📄 brooktree848.c
字号:
bt848_ptr_t bt848;#ifdef BROOKTREE_IRQ u_long old_irq, new_irq;#endif vm_offset_t buf; u_long latency; u_long fun; unsigned int rev;#ifdef __FreeBSD__ bktr = &brooktree[unit]; if (unit >= NBKTR) { printf("brooktree%d: attach: only %d units configured.\n", unit, NBKTR); printf("brooktree%d: attach: invalid unit number.\n", unit); return; } bktr->tag = tag; pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &bktr->base, &bktr->phys_base ); fun = pci_conf_read(tag, 0x40); pci_conf_write(tag, 0x40, fun | 1); /* XXX call bt848_i2c dependent attach() routine */ if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc)) printf("bktr%d: i2c_attach: can't attach\n", unit);#ifdef BROOKTREE_IRQ /* from the configuration file */ old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); printf("bktr%d: attach: irq changed from %d to %d\n", unit, (old_irq & 0xff), (new_irq & 0xff));#endif /* setup the interrupt handling routine */ pci_map_int(tag, bktr_intr, (void*) bktr, &net_imask);#endif /* __FreeBSD__ */#ifdef __bsdi__ struct isa_attach_args * const ia = (struct isa_attach_args *)aux; pci_devaddr_t *tag = (pci_devaddr_t *) ia->ia_aux; int unit = bktr->bktr_dev.dv_unit; bktr = (bktr_reg_t *) self; bktr->base = (bt848_ptr_t) bktr_res.pci_vaddr; isa_establish(&bktr->bktr_id, &bktr->bktr_dev); bktr->bktr_ih.ih_fun = bktr_intr_returning_1; bktr->bktr_ih.ih_arg = (void *)bktr; intr_establish(ia->ia_irq, &bktr->bktr_ih, DV_DULL);#endif /* __bsdi__ */ /* * PCI latency timer. 32 is a good value for 4 bus mastering slots, if * you have more than four, then 16 would probably be a better value. */#ifndef BROOKTREE_DEF_LATENCY_VALUE#define BROOKTREE_DEF_LATENCY_VALUE 10#endif latency = pci_conf_read(tag, PCI_LATENCY_TIMER); latency = (latency >> 8) & 0xff; if ( bootverbose ) { if (latency) printf("brooktree%d: PCI bus latency is", unit); else printf("brooktree%d: PCI bus latency was 0 changing to", unit); } if ( !latency ) { latency = BROOKTREE_DEF_LATENCY_VALUE; pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8); } if ( bootverbose ) { printf(" %d.\n", (int) latency); } /* allocate space for dma program */ bktr->dma_prog = get_bktr_mem(unit, DMA_PROG_ALLOC); bktr->odd_dma_prog = get_bktr_mem(unit, DMA_PROG_ALLOC); /* allocate space for pixel buffer */ if ( BROOKTREE_ALLOC ) buf = get_bktr_mem(unit, BROOKTREE_ALLOC); else buf = 0; if ( bootverbose ) { printf("bktr%d: buffer size %d, addr 0x%x\n", unit, BROOKTREE_ALLOC, vtophys(buf)); } bktr->bigbuf = buf; bktr->alloc_pages = BROOKTREE_ALLOC_PAGES; fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2); if ( buf != 0 ) { bzero((caddr_t) buf, BROOKTREE_ALLOC); buf = vtophys(buf); bktr->flags = METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 | METEOR_RGB16; bktr->dma_prog_loaded = FALSE; bktr->cols = 640; bktr->rows = 480; bktr->frames = 1; /* one frame */ bktr->format = METEOR_GEO_RGB16; bktr->pixfmt = oformat_meteor_to_bt( bktr->format ); bktr->pixfmt_compat = TRUE; bt848 = bktr->base; bt848->int_mask = ALL_INTS_DISABLED; bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; } /* read the pci id and determine the card type */ fun = pci_conf_read(tag, PCI_ID_REG); rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff; switch (fun) { case BROOKTREE_848_PCI_ID: if (rev == 0x12) bktr->id = BROOKTREE_848A; else bktr->id = BROOKTREE_848; break; case BROOKTREE_849_PCI_ID: bktr->id = BROOKTREE_849; break; case BROOKTREE_878_PCI_ID: bktr->id = BROOKTREE_878; break; case BROOKTREE_879_PCI_ID: bktr->id = BROOKTREE_879; break; }; bktr->clr_on_start = FALSE; /* defaults for the tuner section of the card */ bktr->tflags = TUNER_INITALIZED; bktr->tuner.frequency = 0; bktr->tuner.channel = 0; bktr->tuner.chnlset = DEFAULT_CHNLSET; bktr->audio_mux_select = 0; bktr->audio_mute_state = FALSE; bktr->bt848_card = -1; bktr->bt848_tuner = -1; bktr->reverse_mute = -1; probeCard( bktr, TRUE ); /* If there is an MSP Audio device, reset it and display the model */ if (bktr->card.msp3400c)msp_reset(bktr); if (bktr->card.msp3400c)msp_read_id(bktr);#ifdef DEVFS /* XXX This just throw away the token, which should probably be fixed when DEVFS is finally made really operational. */ devfs_add_devswf(&bktr_cdevsw, unit, DV_CHR, 0, 0, 0444, "bktr%d", unit); devfs_add_devswf(&bktr_cdevsw, unit+16, DV_CHR, 0, 0, 0444, "tuner%d", unit);#endif /* DEVFS */#if __FreeBSD__ > 2 fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4);#endif}/* * interrupt handling routine complete bktr_read() if using interrupts. */static voidbktr_intr( void *arg ){ bktr_ptr_t bktr; bt848_ptr_t bt848; u_long bktr_status; u_char dstatus; u_long field; u_long w_field; u_long req_field; bktr = (bktr_ptr_t) arg; bt848 = bktr->base; /* * check to see if any interrupts are unmasked on this device. If * none are, then we likely got here by way of being on a PCI shared * interrupt dispatch list. */ if (bt848->int_mask == ALL_INTS_DISABLED) return; /* bail out now, before we do something we shouldn't */ if (!(bktr->flags & METEOR_OPEN)) { bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; bt848->int_mask = ALL_INTS_DISABLED; /* return; ?? */ } /* record and clear the INTerrupt status bits */ bktr_status = bt848->int_stat; bt848->int_stat = bktr_status & ~I2C_BITS; /* don't touch i2c */ /* record and clear the device status register */ dstatus = bt848->dstatus; bt848->dstatus = 0x00;#if defined( STATUS_SUM ) /* add any new device status or INTerrupt status bits */ status_sum |= (bktr_status & ~(BT848_INT_RSV0|BT848_INT_RSV1)); status_sum |= ((dstatus & (BT848_DSTATUS_COF|BT848_DSTATUS_LOF)) << 6);#endif /* STATUS_SUM */ /* printf( " STATUS %x %x %x \n", dstatus, bktr_status, bt848->risc_count ); */ /* if risc was disabled re-start process again */ if ( !(bktr_status & BT848_INT_RISC_EN) || ((bktr_status &(BT848_INT_FBUS | BT848_INT_FTRGT | BT848_INT_FDSR | BT848_INT_PPERR | BT848_INT_RIPERR | BT848_INT_PABORT | BT848_INT_OCERR | BT848_INT_SCERR) ) != 0) || ((bt848->tdec == 0) && (bktr_status & TDEC_BITS)) ) { u_short tdec_save = bt848->tdec; bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; bt848->int_mask = ALL_INTS_DISABLED; /* Reset temporal decimation ctr */ bt848->tdec = 0; bt848->tdec = tdec_save; /* Reset to no-fields captured state */ if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) { switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: bktr->flags |= METEOR_WANT_ODD; break; case METEOR_ONLY_EVEN_FIELDS: bktr->flags |= METEOR_WANT_EVEN; break; default: bktr->flags |= METEOR_WANT_MASK; break; } } bt848->risc_strt_add = vtophys(bktr->dma_prog); bt848->gpio_dma_ctl = FIFO_ENABLED; bt848->gpio_dma_ctl = bktr->capcontrol; bt848->int_mask = BT848_INT_MYSTERYBIT | BT848_INT_RISCI | BT848_INT_VSYNC | BT848_INT_FMTCHG; bt848->cap_ctl = bktr->bktr_cap_ctl; return; } if (!(bktr_status & BT848_INT_RISCI)) return;/** printf( "intr status %x %x %x\n", bktr_status, dstatus, bt848->risc_count ); */ /* * Disable future interrupts if a capture mode is not selected. * This can happen when we are in the process of closing or * changing capture modes, otherwise it shouldn't happen. */ if (!(bktr->flags & METEOR_CAP_MASK)) bt848->cap_ctl = CAPTURE_OFF; /* * Register the completed field * (For dual-field mode, require fields from the same frame) */ field = ( bktr_status & BT848_INT_FIELD ) ? EVEN_F : ODD_F; switch ( bktr->flags & METEOR_WANT_MASK ) { case METEOR_WANT_ODD : w_field = ODD_F ; break; case METEOR_WANT_EVEN : w_field = EVEN_F ; break; default : w_field = (ODD_F|EVEN_F); break; } switch ( bktr->flags & METEOR_ONLY_FIELDS_MASK ) { case METEOR_ONLY_ODD_FIELDS : req_field = ODD_F ; break; case METEOR_ONLY_EVEN_FIELDS : req_field = EVEN_F ; break; default : req_field = (ODD_F|EVEN_F); break; } if (( field == EVEN_F ) && ( w_field == EVEN_F )) bktr->flags &= ~METEOR_WANT_EVEN; else if (( field == ODD_F ) && ( req_field == ODD_F ) && ( w_field == ODD_F )) bktr->flags &= ~METEOR_WANT_ODD; else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) && ( w_field == (ODD_F|EVEN_F) )) bktr->flags &= ~METEOR_WANT_ODD; else if (( field == ODD_F ) && ( req_field == (ODD_F|EVEN_F) ) && ( w_field == ODD_F )) { bktr->flags &= ~METEOR_WANT_ODD; bktr->flags |= METEOR_WANT_EVEN; } else { /* We're out of sync. Start over. */ if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) { switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: bktr->flags |= METEOR_WANT_ODD; break; case METEOR_ONLY_EVEN_FIELDS: bktr->flags |= METEOR_WANT_EVEN; break; default: bktr->flags |= METEOR_WANT_MASK; break; } } return; } /* * If we have a complete frame. */ if (!(bktr->flags & METEOR_WANT_MASK)) { bktr->frames_captured++; /* * post the completion time. */ if (bktr->flags & METEOR_WANT_TS) { struct timeval *ts; if ((u_int) bktr->alloc_pages * PAGE_SIZE <= (bktr->frame_size + sizeof(struct timeval))) { ts =(struct timeval *)bktr->bigbuf + bktr->frame_size; /* doesn't work in synch mode except * for first frame */ /* XXX */ microtime(ts); } } /* * Wake up the user in single capture mode. */ if (bktr->flags & METEOR_SINGLE) { /* stop dma */ bt848->int_mask = ALL_INTS_DISABLED; /* disable risc, leave fifo running */ bt848->gpio_dma_ctl = FIFO_ENABLED; wakeup((caddr_t)bktr); } /* * If the user requested to be notified via signal, * let them know the frame is complete. */ if (bktr->proc && !(bktr->signal & METEOR_SIG_MODE_MASK)) psignal( bktr->proc, bktr->signal&(~METEOR_SIG_MODE_MASK) ); /* * Reset the want flags if in continuous or * synchronous capture mode. *//** XXX NOTE (Luigi):* currently we only support 3 capture modes: odd only, even only,* odd+even interlaced (odd field first). A fourth mode (non interlaced,* either even OR odd) could provide 60 (50 for PAL) pictures per* second, but it would require this routine to toggle the desired frame* each time, and one more different DMA program for the Bt848.* As a consequence, this fourth mode is currently unsupported.*/ if (bktr->flags & (METEOR_CONTIN | METEOR_SYNCAP)) { switch(bktr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: bktr->flags |= METEOR_WANT_ODD; break; case METEOR_ONLY_EVEN_FIELDS: bktr->flags |= METEOR_WANT_EVEN; break; default: bktr->flags |= METEOR_WANT_MASK; break; } } } return;}/*---------------------------------------------------------**** BrookTree 848 character device driver routines****---------------------------------------------------------*/#define VIDEO_DEV 0x00#define TUNER_DEV 0x01/* *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -