/* Main Driver file for the ivtv project: * Driver for the iTVC15 chip. * Author: Kevin Thayer (nufan_wfk at yahoo.com) * License: GPL * http://www.sourceforge.net/projects/ivtv/ */ #include "ivtv.h" // Version info #define IVTV_VERSION_NUMBER(name) name##_version_int #define IVTV_VERSION_STRING(name) name##_version_string #define IVTV_VERSION_COMMENT(name) name##_comment_string #define IVTV_DEFINE_VERSION_INTERNAL(name, major, minor, patchlevel, comment) \ unsigned int IVTV_VERSION_NUMBER(name) = ((major << 16) | (minor << 8) | (patchlevel)); \ const char * const IVTV_VERSION_STRING(name) = #major"."#minor"."#patchlevel;\ const char * const IVTV_VERSION_COMMENT(name) = comment; #define IVTV_VERSION_MAJOR(name) (0xFF & (IVTV_VERSION_NUMBER(name) >> 16)) #define IVTV_VERSION_MINOR(name) (0xFF & (IVTV_VERSION_NUMBER(name) >> 8)) #define IVTV_VERSION_PATCHLEVEL(name) (0xFF & (IVTV_VERSION_NUMBER(name))) #define IVTV_DEFINE_VERSION(name, major, minor, patchlevel, comment) IVTV_DEFINE_VERSION_INTERNAL(name, major, minor, patchlevel, comment) IVTV_DEFINE_VERSION(ivtv_rev, IVTV_DRIVER_VERSION_MAJOR, IVTV_DRIVER_VERSION_MINOR, IVTV_DRIVER_VERSION_PATCHLEVEL, ""); /* mini header */ /* var to keep track of the number of array elements in use */ int ivtv_cards_active = 0; /* Master variable for all ivtv info */ struct ivtv ivtv_cards[IVTV_MAX_CARDS]; /* for the global data */ spinlock_t ivtv_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; /* add your revision and whatnot here */ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0,} }; static void ivtv_irq_dec_vsync(struct ivtv* itv); static void ivtv_irq_handler(int irq, void *dev_id, struct pt_regs *regs); static void ivtv_DMA_done(struct ivtv *itv); static void ivtv_sched_DMA(struct ivtv *itv); static void ivtv_dec_DMA_done(struct ivtv *itv); static void ivtv_dec_sched_DMA(struct ivtv *itv); static u32 ivtv_firm_search_id[]= {0x12345678,0x34567812,0x56781234,0x78123456}; /* Parameter declarations */ static int num_devices = IVTV_DEFAULT_NUM_CARDS; static int yuv_buffers = IVTV_DEFAULT_YUV_BUFFERS; static int mpg_buffers = IVTV_DEFAULT_MPG_BUFFERS; static int vbi_buffers = IVTV_DEFAULT_VBI_BUFFERS; static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS; static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS; static int dec_mpg_qlen = IVTV_DEFAULT_DEC_MPG_QLEN; static int dec_yuv_qlen = IVTV_DEFAULT_DEC_YUV_QLEN; #ifdef YUV_FIXUP static int yuv_fixup; #endif int ivtv_pal = 0; /* low debugging by default */ #if 0 int debug = ( IVTV_DEBUG_ERR | IVTV_DEBUG_INFO | IVTV_DEBUG_API | IVTV_DEBUG_DMA | IVTV_DEBUG_IOCTL | IVTV_DEBUG_I2C | IVTV_DEBUG_IRQ ); #endif int ivtv_debug = IVTV_DEBUG_ERR; /* tuner.h tuner type for ivtv card */ int tuner = -1; int errno; #define EXPAND_TO_STRING_INTERNAL(arg) #arg #define EXPAND_TO_STRING(arg) EXPAND_TO_STRING_INTERNAL(arg) #ifdef YUV_FIXUP MODULE_PARM(yuv_fixup, "i"); MODULE_PARM_DESC(yuv_fixup, "\nToggles conversion of Hauppauge Macroblock NV12 to NV12\n"); #endif MODULE_PARM(tuner, "i"); MODULE_PARM_DESC(tuner, "\nTuner type selection, see tuner.h for values"); MODULE_PARM(yuv_buffers, "i"); MODULE_PARM_DESC(yuv_buffers, "\nNumber of 32K buffers for copying YUV.\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_YUV_BUFFERS) ", " "Min: " EXPAND_TO_STRING(IVTV_MIN_YUV_BUFFERS) " " "Max: " EXPAND_TO_STRING(IVTV_MAX_YUV_BUFFERS)); MODULE_PARM(mpg_buffers, "i"); MODULE_PARM_DESC(mpg_buffers, "\nNumber of 32K buffers for copying mpg.\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_MPG_BUFFERS) ", " "Min: " EXPAND_TO_STRING(IVTV_MIN_MPG_BUFFERS) " " "Max: " EXPAND_TO_STRING(IVTV_MAX_MPG_BUFFERS)); MODULE_PARM(vbi_buffers, "i"); MODULE_PARM_DESC(vbi_buffers, "\nNumber of 32K buffers for copying VBI.\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_VBI_BUFFERS) ", " "Min: " EXPAND_TO_STRING(IVTV_MIN_VBI_BUFFERS) " " "Max: " EXPAND_TO_STRING(IVTV_MAX_VBI_BUFFERS)); MODULE_PARM(num_devices, "i"); MODULE_PARM_DESC(num_devices, "\nNumber of supported devices (1-9).\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_NUM_CARDS)); MODULE_PARM(dec_mpg_buffers, "i"); MODULE_PARM_DESC(dec_mpg_buffers, "\nNumber of 32K buffers for decoding MPG.\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_DEC_MPG_BUFFERS) ", " "Min: " EXPAND_TO_STRING(IVTV_MIN_DEC_MPG_BUFFERS) " " "Max: " EXPAND_TO_STRING(IVTV_MAX_DEC_MPG_BUFFERS)); MODULE_PARM(dec_yuv_buffers, "i"); MODULE_PARM_DESC(dec_yuv_buffers, "\nNumber of 32K buffers for decoding YUV.\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_DEC_YUV_BUFFERS) ", " "Min: " EXPAND_TO_STRING(IVTV_MIN_DEC_YUV_BUFFERS) " " "Max: " EXPAND_TO_STRING(IVTV_MAX_DEC_YUV_BUFFERS) ", " "0 to disable"); MODULE_PARM(dec_mpg_qlen, "i"); MODULE_PARM_DESC(dec_mpg_qlen, "\nNumber of 32K buffers to queue before dispatching to decoder\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_DEC_MPG_QLEN) ", " "Min: " EXPAND_TO_STRING(IVTV_MIN_DEC_MPG_QLEN) " " "Max: "); MODULE_PARM(dec_yuv_qlen, "i"); MODULE_PARM_DESC(dec_yuv_qlen, "\nNumber of 32K buffers to queue before dispatching to decoder\n" "Default: " EXPAND_TO_STRING(IVTV_DEFAULT_DEC_YUV_QLEN) ", " "Min: " EXPAND_TO_STRING(IVTV_MIN_DEC_YUV_QLEN) " " "Max: "); MODULE_PARM(ivtv_debug, "i"); MODULE_PARM_DESC(ivtv_debug, "\nDebug level (bitmask), default, errors only\n" "(debug=127 gives full debuging)"); MODULE_PARM(ivtv_pal, "i"); MODULE_PARM_DESC(ivtv_pal, "\nUse PAL as default video mode instead of NTSC"); MODULE_AUTHOR("Kevin Thayer"); MODULE_DESCRIPTION("Alpha iTVC15 driver"); MODULE_SUPPORTED_DEVICE("iTVC15/16 mpg2 encoder (aka WinTV PVR 250/350)"); MODULE_LICENSE("GPL"); static int SGarray_size; static int DSGarray_size; void ivtv_sleep_timeout(int timeout) { int sleep = timeout; do { set_current_state(TASK_INTERRUPTIBLE); sleep = schedule_timeout(sleep); } while (sleep && !signal_pending(current)); set_current_state(TASK_RUNNING); } /* ceiling function for ints.. */ int ivtv_ceil(int x, int y) { int floor = (int)(x/y); if ((floor * y) < x) return floor+1; return floor; } /* Release ioremapped memory */ static void ivtv_iounmap(struct ivtv *itv) { if (itv == NULL) return ; /* Release io memory */ if (itv->io_mem != NULL) { IVTV_DEBUG(IVTV_DEBUG_INFO, "releasing iomem\n"); iounmap(itv->io_mem); itv->io_mem = NULL ; } /* Release registers memory */ if (itv->reg_mem != NULL) { IVTV_DEBUG(IVTV_DEBUG_INFO, "releasing regmem\n"); iounmap(itv->reg_mem); itv->reg_mem = NULL ; } /* Release encoder mailboxes */ if (itv->enc_mbox != NULL) { IVTV_DEBUG(IVTV_DEBUG_INFO, "releasing encmbox\n"); iounmap(itv->enc_mbox); itv->enc_mbox = NULL ; } /* Release decoder mailboxes */ if (itv->dec_mbox != NULL) { IVTV_DEBUG(IVTV_DEBUG_INFO, "releasing decmbox\n"); iounmap(itv->dec_mbox); itv->dec_mbox = NULL ; } } /* must only be used as hints, not as a definitive answer. the answer could * be wrong as soon as we return */ int ivtv_get_free_elements(struct ivtv *itv, struct ivtv_buffer_list *queue) { unsigned long flags; int elements; spin_lock_irqsave(&itv->lock, flags); elements = queue->elements; spin_unlock_irqrestore(&itv->lock, flags); return elements; } inline void __ivtv_enq_buf(struct ivtv_buffer_list *queue, struct ivtv_buffer *buf) { WARN_ON(!list_empty(&buf->list)); list_add_tail(&buf->list, &queue->list); queue->elements++; } /* Adds buffers to the tail, effectively making a queue */ int ivtv_enq_buf(struct ivtv *itv, struct ivtv_buffer_list *queue, struct ivtv_buffer *buf) { unsigned long flags; spin_lock_irqsave(&itv->lock, flags); __ivtv_enq_buf(queue, buf); spin_unlock_irqrestore(&itv->lock, flags); return 0; } inline void __ivtv_del_buf(struct ivtv_buffer_list *queue, struct ivtv_buffer *buffer) { WARN_ON(list_empty(&buffer->list)); list_del_init(&buffer->list); queue->elements--; } /* called to remove the buffer returned by _peek_ functions */ void ivtv_del_buf(struct ivtv *itv, struct ivtv_buffer_list *queue, struct ivtv_buffer *buffer) { unsigned long flags; spin_lock_irqsave(&itv->lock, flags); __ivtv_del_buf(queue, buffer); spin_unlock_irqrestore(&itv->lock, flags); } void ivtv_move_buf(struct ivtv *itv, struct ivtv_buffer_list *from, struct ivtv_buffer_list *to, struct ivtv_buffer *buffer) { unsigned long flags; WARN_ON(list_empty(&buffer->list)); spin_lock_irqsave(&itv->lock, flags); list_move_tail(&buffer->list, &to->list); from->elements--; to->elements++; spin_unlock_irqrestore(&itv->lock, flags); } /* returns first item in queue, doesn't dequeue */ struct ivtv_buffer *__ivtv_deq_peek_head(struct ivtv_buffer_list *queue) { /* make sure list has something to DeQ */ if (!list_empty(&queue->list)) return list_entry(queue->list.next, struct ivtv_buffer, list); IVTV_DEBUG(IVTV_DEBUG_INFO,"DeQ from empty list!\n"); queue->elements = 0; return NULL; } struct ivtv_buffer *ivtv_deq_peek_head(struct ivtv *itv, struct ivtv_buffer_list *queue) { unsigned long flags; struct ivtv_buffer *buffer; spin_lock_irqsave(&itv->lock, flags); buffer = __ivtv_deq_peek_head(queue); spin_unlock_irqrestore(&itv->lock, flags); return buffer; } /* removes buffer from the head */ struct ivtv_buffer *__ivtv_deq_buf(struct ivtv_buffer_list *queue) { struct ivtv_buffer *buf; /* make sure list has something to DeQ */ if (!list_empty(&queue->list)) { buf = list_entry(queue->list.next, struct ivtv_buffer, list); list_del_init(queue->list.next); queue->elements--; return buf; } IVTV_DEBUG(IVTV_DEBUG_INFO,"DeQ from empty list!\n"); queue->elements = 0; return NULL; } struct ivtv_buffer *ivtv_deq_buf(struct ivtv *itv, struct ivtv_buffer_list *queue) { struct ivtv_buffer *buf; unsigned long flags; spin_lock_irqsave(&itv->lock, flags); buf = __ivtv_deq_buf(queue); spin_unlock_irqrestore(&itv->lock, flags); return buf; } struct ivtv_buffer *ivtv_init_buffer(int gfp_mask) { struct ivtv_buffer *ibuf; ibuf = kmalloc(sizeof(struct ivtv_buffer), gfp_mask); if (ibuf == NULL) { IVTV_DEBUG(IVTV_DEBUG_ERR,"No mem on ibuf alloc!\n"); return NULL; } (void *)ibuf->buffer.m.userptr = kmalloc(IVTV_DMA_BUF_SIZE, gfp_mask); if ((void *)ibuf->buffer.m.userptr == NULL) { kfree(ibuf); IVTV_DEBUG(IVTV_DEBUG_ERR,"No mem on buf alloc!\n"); return NULL; } INIT_LIST_HEAD(&ibuf->list); ibuf->buffer.length = IVTV_DMA_BUF_SIZE; ibuf->buffer.bytesused = 0; ibuf->readpos = 0; return ibuf; } #define IVTV_DMA_UNMAPPED ((u32) -1) void ivtv_free_buffer(struct ivtv *itv, struct ivtv_buffer *item) { if (item->dma_handle != IVTV_DMA_UNMAPPED) pci_unmap_single(itv->dev, item->dma_handle, IVTV_DMA_BUF_SIZE, PCI_DMA_TODEVICE); if (item->buffer.m.userptr) { IVTV_DEBUG(IVTV_DEBUG_INFO,"Freeing buf %d!\n", item->buffer.index); kfree((void *)item->buffer.m.userptr); } kfree(item); } int ivtv_free_queue(struct ivtv_buffer_list *queue) { struct ivtv_buffer *item; unsigned long flags; struct ivtv *itv; int x; if (queue == NULL) { IVTV_DEBUG(IVTV_DEBUG_ERR,"Free on NULL list!\n"); return -EINVAL; } spin_lock_irqsave(&ivtv_lock, flags); /* FIXME ugly */ /* verify ivtv before continuing */ itv = NULL; for (x = 0; x < ivtv_cards_active; x++) { if (queue->vdev->priv == &ivtv_cards[x]) { itv = queue->vdev->priv; break; } } spin_unlock_irqrestore(&ivtv_lock, flags); if (itv == NULL) return -ENODEV; while ((item = ivtv_deq_buf(itv, queue))) ivtv_free_buffer(itv, item); return 0; } /* NOTE: This returns the # of buffers allocated */ int ivtv_init_queue(struct ivtv *itv, struct ivtv_buffer_list *queue, int length, enum v4l2_buf_type type) { int x; struct ivtv_buffer *item; /* Just in case */ INIT_LIST_HEAD(&queue->list); for (x=0;x < length; x++) { /* allocate buffer */ item = ivtv_init_buffer(GFP_KERNEL); if (item == NULL) { IVTV_DEBUG(IVTV_DEBUG_ERR,"Buffer alloc failed!\n"); return x; } /* setup buffer */ item->buffer.index = x; item->buffer.type = type; item->buffer.field = V4L2_FIELD_INTERLACED; item->buffer.memory = V4L2_MEMORY_MMAP; /* enqueue buffer */ ivtv_enq_buf(itv, queue, item); } return x; } int ivtv_move_queue(struct ivtv *itv, struct ivtv_buffer_list *src, struct ivtv_buffer_list *dst) { struct ivtv_buffer *buf; unsigned long flags; spin_lock_irqsave(&itv->lock, flags); while ((buf = __ivtv_deq_buf(src))) __ivtv_enq_buf(dst, buf); spin_unlock_irqrestore(&itv->lock, flags); return 0; } static int load_fw_direct(const char *fn, char *mem) { int fd; long l; mm_segment_t fs = get_fs(); set_fs(get_ds()); if ( (fd = open(fn, 0, 0)) == -1) { printk(KERN_INFO "Unable to open '%s'.\n", fn); l = -EINVAL; goto out; } /* the 2 means SEEK_END */ l = lseek(fd, 0L, 2); if (l <= 0 || l > IVTV_FIRM_IMAGE_SIZE) { printk(KERN_INFO "Firmware image too large '%s'\n", fn); l = -ENOMEM; goto out; } /* the 2 means SEEK_SET */ lseek(fd, 0L, 0); if (read(fd, mem, l) != l){ printk(KERN_INFO "Failed to read '%s'.\n", fn); l = -ENOMEM; } out: close(fd); set_fs(fs); return (int) l; } int ivtv_firmware_copy(struct ivtv *itv) { IVTV_DEBUG(IVTV_DEBUG_INFO, "Loading encoder image\n"); if (load_fw_direct(IVTV_FIRM_ENC_FILENAME, (char *)(itv->io_mem + IVTV_ENC_MEM_START)) != IVTV_FIRM_IMAGE_SIZE) { IVTV_DEBUG(IVTV_DEBUG_ERR, "failed loading encoder firmware\n"); return -3; } if (itv->card_type != IVTV_250_V2) { IVTV_DEBUG(IVTV_DEBUG_INFO, "Loading decoder firmware\n"); if (load_fw_direct(IVTV_FIRM_DEC_FILENAME, (char *)(itv->io_mem + IVTV_DEC_MEM_START)) != IVTV_FIRM_IMAGE_SIZE) { IVTV_DEBUG(IVTV_DEBUG_ERR, "failed loading decoder firmware\n"); return -1; } } return 0; } int ivtv_stop_firmware(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; int x = 0; IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping firmware\n"); if (atomic_read(&itv->capturing)) { x = ivtv_stop_all_captures(itv); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 1. Code %d\n",x); } /*Stop decoder_playback */ data[0] = 1; /* 0: render last frame, 1: stop NOW! :) */ data[1] = 0; /* "low 4 bytes of stop index" */ data[2] = 0; /* 0: stop immedeately */ x = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_STOP_PLAYBACK, &result, 3, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 2. Code %d\n",x); /*halt enc firmware */ x = ivtv_api(itv->enc_mbox, &itv->enc_msem, IVTV_API_ENC_HALT_FW, &result, 0, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 3. Code %d\n",x); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); ivtv_sleep_timeout(HZ/100); /*halt dec firmware */ if (IVTV_250_V2 != itv->card_type) { x = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_HALT_FW, &result, 0, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 4. Code %d\n",x); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); ivtv_sleep_timeout(HZ/100); } return 0; } int ivtv_firmware_init(struct ivtv *itv) { int x; /* check that we're not RE-loading firmware */ /* a sucessful load will have detected HW */ /* mailboxes. */ /* FIXME i dont think this will ever get called */ if (NULL != itv->enc_mbox) { IVTV_DEBUG(IVTV_DEBUG_INFO, "readying card for firmware upload\n"); x = ivtv_stop_firmware(itv); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "Error %d, stopping firmware\n", x); } IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping VDM\n"); writel(IVTV_CMD_VDM_STOP, (IVTV_REG_VDM + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping AO\n"); writel(IVTV_CMD_AO_STOP, (IVTV_REG_AO + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "pinging (?) APU\n"); writel(IVTV_CMD_APU_PING, (IVTV_REG_APU + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping VPU\n"); if (IVTV_250_V2 == itv->card_type) { writel(IVTV_CMD_VPU_STOP16, (IVTV_REG_VPU + itv->reg_mem)); } else { writel(IVTV_CMD_VPU_STOP15, (IVTV_REG_VPU + itv->reg_mem)); } IVTV_DEBUG(IVTV_DEBUG_INFO, "Resetting Hw Blocks\n"); writel(IVTV_CMD_HW_BLOCKS_RST, (IVTV_REG_HW_BLOCKS + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping SPU\n"); writel(IVTV_CMD_SPU_STOP, (IVTV_REG_SPU + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); ivtv_sleep_timeout(HZ/100); IVTV_DEBUG(IVTV_DEBUG_INFO, "init Encoder SDRAM pre-charge\n"); writel(IVTV_CMD_SDRAM_PRECHARGE_INIT, (IVTV_REG_ENC_SDRAM_PRECHARGE + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "init Encoder SDRAM refresh to 1us\n"); writel(IVTV_CMD_SDRAM_REFRESH_INIT, (IVTV_REG_ENC_SDRAM_REFRESH + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "init Decoder SDRAM pre-charge\n"); writel(IVTV_CMD_SDRAM_PRECHARGE_INIT, (IVTV_REG_DEC_SDRAM_PRECHARGE + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "init Decoder SDRAM refresh to 1us\n"); writel(IVTV_CMD_SDRAM_REFRESH_INIT, (IVTV_REG_DEC_SDRAM_REFRESH + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for %dms (600 recommended)\n",(int)IVTV_SDRAM_SLEEPTIME); ivtv_sleep_timeout(IVTV_SDRAM_SLEEPTIME); IVTV_DEBUG(IVTV_DEBUG_INFO, "Card ready for firmware!\n"); x = ivtv_firmware_copy(itv); if (x) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error loading firmware!\n"); return x; } /*I guess this is read-modify-write :)*/ writel((readl(itv->reg_mem + IVTV_REG_SPU)&IVTV_MASK_SPU_ENABLE), (IVTV_REG_SPU+itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 1 sec\n"); ivtv_sleep_timeout(HZ); /*I guess this is read-modify-write :)*/ if (IVTV_250_V2 == itv->card_type) { writel((readl(itv->reg_mem + IVTV_REG_VPU)&IVTV_MASK_VPU_ENABLE16), (IVTV_REG_VPU+itv->reg_mem)); } else { writel((readl(itv->reg_mem + IVTV_REG_VPU)&IVTV_MASK_VPU_ENABLE15), (IVTV_REG_VPU+itv->reg_mem)); } IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 1 sec\n"); ivtv_sleep_timeout(HZ); /* FIXME Send Status API commands to encoder and decoder to verify!*/ return 0; } int ivtv_find_firmware_mailbox(struct ivtv *itv) { u32 *searchptr, *result; int match = 0; searchptr = NULL; result = NULL; IVTV_DEBUG(IVTV_DEBUG_INFO, "Searching for encoder mailbox\n"); searchptr =(u32 *)(IVTV_FIRM_SEARCH_ENCODER_START + itv->io_mem); while (searchptr < (u32 *)(IVTV_FIRM_SEARCH_ENCODER_END + itv->io_mem)) { if (ivtv_firm_search_id[match] == readl(searchptr)) { (u32)result = (u32)searchptr+4; /* avoid pointer aritmetic */ match++; while ((match > 0) && (match < 4)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "match: 0x%08x at " "0x%08x. match: %d\n", *result, (u32)result, match); if (ivtv_firm_search_id[match] == readl(result)) { match++; /* FIXME change to just "result++;" ? */ (u32)result = (u32)result + 4; } else match = 0; } } else { IVTV_DEBUG(IVTV_DEBUG_INFO, "."); } if ( 4 == match ) { IVTV_DEBUG(IVTV_DEBUG_INFO, "found encoder mailbox!\n"); itv->enc_mbox = (struct ivtv_mailbox *) result; break; } (u32)searchptr += IVTV_FIRM_SEARCH_STEP; } if (itv->enc_mbox == NULL) IVTV_DEBUG(IVTV_DEBUG_ERR, "Encoder mailbox not found\n"); IVTV_DEBUG(IVTV_DEBUG_INFO, "Searching for decoder mailbox\n"); match = 0; searchptr = (u32 *)(IVTV_FIRM_SEARCH_DECODER_START + itv->io_mem); while (searchptr < (u32 *)(IVTV_FIRM_SEARCH_DECODER_END + itv->io_mem)) { if (ivtv_firm_search_id[match] == readl(searchptr)) { (u32)result = (u32)searchptr+4; /* avoid pointer aritmetic */ match++; while ((match > 0) && (match < 4)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "match: 0x%08x at 0x%08x. match: %d\n", *result, (u32)result, match); if (ivtv_firm_search_id[match] == readl(result)) { match++; /* FIXME change to just "result++;" ? */ (u32)result = (u32)result + 4; } else match = 0; } } else { IVTV_DEBUG(IVTV_DEBUG_INFO, "."); } if ( 4 == match ) { IVTV_DEBUG(IVTV_DEBUG_INFO, "found decoder mailbox!\n"); itv->dec_mbox = (struct ivtv_mailbox *) result; break; } (u32)searchptr += IVTV_FIRM_SEARCH_STEP; } if (itv->dec_mbox == 0) IVTV_DEBUG(IVTV_DEBUG_ERR, "Decoder mailbox not found\n"); return 0; } int ivtv_get_free_mailbox(struct ivtv_mailbox *mbox) { int i = 0; if (NULL == mbox) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Can't get mailbox from NULL\n"); return -ENODEV; } /* FIXME hardcoded cause i'm not sure what changing API_BOXES will do */ //for (i = 0; i < IVTV_MBOX_API_BOXES; i++) { for (i = 0; i < 2; i++) { if (mbox[i].flags & IVTV_MBOX_FIRMWARE_DONE) { switch (mbox[i].cmd) { case IVTV_API_SCHED_DMA_TO_HOST: case IVTV_API_DEC_DMA_FROM_HOST: IVTV_DEBUG(IVTV_DEBUG_API, "recycled mailbox: %d\n", i); writel(IVTV_MBOX_IN_USE, &mbox[i].flags); return i; break; default: IVTV_DEBUG(IVTV_DEBUG_API, "Mailbox %d in use, skipping\n", i); break; } /* FIXME using 'else' may leak mailboxes in some situations */ } else if (!test_and_set_bit(0, &mbox[i].flags)) { IVTV_DEBUG(IVTV_DEBUG_API, "got free mailbox: %d\n", i); return i; } } IVTV_DEBUG(IVTV_DEBUG_ERR, "no free mailboxes!\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "mbox 0: 0x%08x, mbox 1 0x%08x!\n", mbox[0].cmd, mbox[1].cmd); return -ENODEV; } void ivtv_clear_irq_mask(struct ivtv *itv, unsigned long mask) { itv->irqmask &= ~mask; writel(itv->irqmask,(itv->reg_mem + IVTV_REG_IRQMASK)); /* pci posting */ readl(itv->reg_mem + IVTV_REG_IRQMASK); } void ivtv_set_irq_mask(struct ivtv *itv, unsigned long mask) { itv->irqmask |= mask; writel(itv->irqmask,(itv->reg_mem + IVTV_REG_IRQMASK)); /* pci posting */ readl(itv->reg_mem + IVTV_REG_IRQMASK); } /** * Call ivtv api function using given mailbox, without locking sem. */ int __ivtv_api_call(struct ivtv_mailbox *mbox, u32 cmd, int elements, const u32* data) { int x; if (NULL == mbox) { IVTV_DEBUG(IVTV_DEBUG_ERR, "invalid api mailbox\n"); return -ENODEV; } /* "if mailbox is available" */ if ( (mbox->flags & IVTV_MBOX_FIRMWARE_DONE) || (!test_and_set_bit(0, &mbox->flags)) ) { /* I'm too lazy to invert the condition ;) */ } else { IVTV_DEBUG(IVTV_DEBUG_INFO, "Mailbox busy (unexpected)\n"); IVTV_DEBUG(IVTV_DEBUG_INFO, "cmd 0x%08x, m.cmd 0x%08x, fl 0x%08x\n", cmd, mbox->cmd, mbox->flags); IVTV_DEBUG(IVTV_DEBUG_INFO, "d0 0x%08x, d1 0x%08x, d2 0x%08x\n", mbox->data[0], mbox->data[1], mbox->data[2]); return -EBUSY; } readl(&mbox->flags); writel(cmd, &mbox->cmd); writel(IVTV_API_STD_TIMEOUT, &mbox->timeout); for (x = 0; x < IVTV_MBOX_MAX_DATA; x++) { if (x < elements) { writel(data[x], &mbox->data[x]); } else { writel(0, &mbox->data[x]); } } writel((IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_IN_USE), &mbox->flags); readl(&mbox->flags); return 0; } /* This one is for stuff that can't sleep.. irq handlers, etc.. */ int ivtv_api_getresult_nosleep(struct ivtv_mailbox *mbox, u32 *result, u32 data[]) { u32 readdata; int count = 0; if (NULL == mbox) { IVTV_DEBUG(IVTV_DEBUG_ERR, "invalid api mailbox\n"); return -ENODEV; } readdata = readl(&mbox->flags); *result = readl(&mbox->retval); for ( count=0; count < IVTV_MBOX_MAX_DATA; count++) data[count] = readl(&mbox->data[count]); return 0; } int __ivtv_api_getresult(struct ivtv_mailbox *mbox, u32 *result, u32 data[], int api_timeout) { u32 readdata; int count = 0; readdata = readl(&mbox->flags); while (!(readdata & IVTV_MBOX_FIRMWARE_DONE)) { IVTV_DEBUG(IVTV_DEBUG_API, "[%d]result not ready, waiting 1ms\n", count); ivtv_sleep_timeout(HZ/100); readdata = readl(&mbox->flags); if (count++ > api_timeout) { IVTV_DEBUG(IVTV_DEBUG_ERR, "%d ms time out waiting for firmware\n", api_timeout); return -EBUSY; } } *result = readl(&mbox->retval); for ( count=0; count < IVTV_MBOX_MAX_DATA; count++) data[count] = readl(&mbox->data[count]); return 0; } int ivtv_api(struct ivtv_mailbox *mbox, struct semaphore *sem, int cmd, u32 *result, int args, u32 data[]) { int x=0, gotsem=0, needsresult=1; int die=0, api_timeout=100; struct ivtv_mailbox *local_box; IVTV_DEBUG(IVTV_DEBUG_API, "API Call: 0x%08x\n", cmd); local_box = mbox; /* check args */ if (args > IVTV_MBOX_MAX_DATA) return -EINVAL; switch (cmd) { case IVTV_API_SCHED_DMA_TO_HOST: case IVTV_API_DEC_DMA_FROM_HOST: needsresult = 0; if (down_trylock(sem)) { /* box 0 was busy */ gotsem = 0; local_box = &mbox[1]; } else { gotsem = 1; } if (x = __ivtv_api_call(local_box, cmd, args, data)) { if (local_box == mbox) { IVTV_DEBUG(IVTV_DEBUG_API, "Trying alternate mailbox\n"); x = __ivtv_api_call(&mbox[1],cmd,args,data); } } goto ivtv_api_done; break; /* adjust api timeout for these 2 calls */ case IVTV_API_END_CAPTURE: case IVTV_API_EVENT_NOTIFICATION: api_timeout = 1000; default: if (down_interruptible(sem)) return -ERESTARTSYS; gotsem = 1; break; } /* wait 20ms for mailbox to become free */ x = __ivtv_api_call(local_box, cmd, args, data); while ((x == -EBUSY) && (die < 20)) { die++; ivtv_sleep_timeout(HZ/100); x = __ivtv_api_call(local_box, cmd, args, data); IVTV_DEBUG(IVTV_DEBUG_API, "die: %d\n", die); } if (x == -EBUSY) { /* dilemma here: if the command that currently has the mailbox is lost, then it'll never free up the box, and we'll lose our only 'general purpose' box forever. But if it comes back, we run the risk of squishing something important!. */ switch (local_box->cmd) { case IVTV_API_DEC_DMA_FROM_HOST: /* if we got here, it's because the call to xfer the dma was finished, and the command that wants to run has already slept for 20ms. It's probably safe to take over */ IVTV_DEBUG(IVTV_DEBUG_API, "Forcibly freeing mailbox\n"); writel(0x00000000, &mbox->flags); x = __ivtv_api_call(local_box, cmd, args, data); break; default: /* do nothing */ break; } } if (x) { IVTV_DEBUG(IVTV_DEBUG_API,"Error running command 0x%08x\n", cmd); goto ivtv_api_done; } if (needsresult) { x = __ivtv_api_getresult(local_box, result, &data[0], api_timeout); IVTV_DEBUG(IVTV_DEBUG_API, "retval: 0x%08x\n", *result); if(x == -EBUSY) IVTV_DEBUG(IVTV_DEBUG_ERR, "api call 0x%08x\n", cmd); } IVTV_DEBUG(IVTV_DEBUG_API, "Releasing mailbox (before 0x%08x, ", readl(&mbox->flags)); writel(0x00000000, &mbox->flags); IVTV_DEBUG(IVTV_DEBUG_API, "after 0x%08x )\n", readl(&mbox->flags)); ivtv_api_done: if (gotsem) { up(sem); } return x; } int ivtv_firmware_versions(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; int x; /* Encoder */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Getting encoder firmware rev.\n"); x = ivtv_api(itv->enc_mbox, &itv->enc_msem, IVTV_API_ENC_GETVER, &result, 0, &data[0]); if (x) { IVTV_DEBUG(IVTV_DEBUG_ERR, "error getting Encoder firmware version\n"); } else { IVTV_DEBUG(IVTV_DEBUG_ERR, "Encoder revision: 0x%08x\n", data[0]); } if (itv->card_type != IVTV_250_V2) { /* Decoder */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Getting decoder firmware rev.\n"); x = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_GETVER, &result, 0, &data[0]); if (x) { IVTV_DEBUG(IVTV_DEBUG_ERR, "error getting Decoder firmware version\n"); } else { IVTV_DEBUG(IVTV_DEBUG_ERR, "Decoder revision: 0x%08x\n", data[0]); } } return 0; } int ivtv_stop_all_captures(struct ivtv *itv) { struct ivtv_open_id id; int x; id.itv = itv; down(&itv->sem_lock); for (x = 0; x < itv->v4l2.streamcount;x++) { if (test_bit(IVTV_F_S_CAP, &itv->v4l2.streams[x].s_flags)) { id.type=x; ivtv_stop_capture(&id); } } up(&itv->sem_lock); return 0; } int ivtv_stop_capture(struct ivtv_open_id *id) { struct ivtv *itv=id->itv; u32 data[IVTV_MBOX_MAX_DATA], result; DECLARE_WAITQUEUE(wait, current); int type,subtype; int x; /* sem_lock must be held */ IVTV_ASSERT(ivtv_sem_count(&itv->sem_lock) <= 0); /* FIXME set 'die' ?? */ type = id->type; if (type == 1) { subtype = 3; //FIXME temp } else { subtype = 3; } /* only run these if we're shutting down the last cap */ if (atomic_read(&itv->capturing) == 0) { /* event notification (off)*/ data[0] = 0; /*type: 0 = refresh */ data[1] = 0; /*on/off: 0 = off */ data[2] = 0x10000000; /*intr_bit: 0x10000000 = digitizer */ data[3] = -1; /*mbox_id: -1: none */ x = ivtv_api(itv->enc_mbox, &itv->enc_msem, IVTV_API_EVENT_NOTIFICATION, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopcap error 1. Code %d\n",x); } /* end_capture */ data[0] = 0; /*when: 0 = end of GOP */ data[1] = type; /*type: 0 = mpeg */ data[2] = subtype; /*subtype: 3 = video+audio */ x = ivtv_api(itv->enc_mbox, &itv->enc_msem, IVTV_API_END_CAPTURE, &result, 3, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopcap error 2. Code %d\n",x); x = 0; add_wait_queue(&itv->v4l2.streams[type].waitq, &wait); do { set_current_state(TASK_UNINTERRUPTIBLE); /* check if DMA is pending */ if (!test_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags)) break; IVTV_DEBUG(IVTV_DEBUG_INFO, "dma still pending!\n"); schedule_timeout(HZ/100); if (x++ > 100) { IVTV_DEBUG(IVTV_DEBUG_ERR, "giving up waiting for DMA pending clear\n"); break; } } while (1); set_current_state(TASK_RUNNING); remove_wait_queue(&itv->v4l2.streams[type].waitq, &wait); /* only run these if we're shutting down the last cap */ if (atomic_read(&itv->capturing) == 0) { int eos_count = 0; add_wait_queue(&itv->cap_w, &wait); set_current_state(TASK_UNINTERRUPTIBLE); /* wait 1s for EOS interrupt */ if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) schedule_timeout(HZ); while((!test_bit(IVTV_F_I_EOS, &itv->i_flags))) { if(eos_count > HZ) break; eos_count++; schedule_timeout(HZ/100); } if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "EOS interrupt not received! stopping anyway.\n"); } else if(eos_count > 0) { IVTV_DEBUG(IVTV_DEBUG_INFO, "EOS interrupt took %d ms to occur.\n", (eos_count+HZ)); } set_current_state(TASK_RUNNING); remove_wait_queue(&itv->cap_w, &wait); } if (atomic_read(&itv->capturing)) return 0; clear_bit(IVTV_F_S_OVERFLOW, &itv->v4l2.streams[type].s_flags); /*Set the following Interrupt mask bits: 0xd8000000 */ ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); IVTV_DEBUG(IVTV_DEBUG_IRQ, "IRQ Mask is now: 0x%08x\n", itv->irqmask); ivtv_move_queue(itv, &itv->v4l2.streams[type].full_q, &itv->v4l2.streams[type].free_q); ivtv_move_queue(itv, &itv->v4l2.streams[type].dma_q, &itv->v4l2.streams[type].free_q); return 0; } int ivtv_stop_decode(struct ivtv_open_id *id) { struct ivtv *itv=id->itv; u32 data[IVTV_MBOX_MAX_DATA], result; struct ivtv_buffer *buf; int x; /* sem_lock must be held */ IVTV_ASSERT(ivtv_sem_count(&itv->sem_lock) <= 0); /* FIXME set 'die' ?? */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Decoder stop.\n"); /* only run these if we're shutting down the last cap */ if (atomic_read(&itv->decoding) == 0) { #if 0 /* event notification (off)*/ data[0] = 0; /* Event: 0 = audio change between stereo and mono */ data[1] = 0; /* Enable/Disable: 0 = disabled, 1 = enabled */ data[2] = 0x00010000; /* Bit: interrupt bit to fire */ data[3] = -1; /* Mailbox to use: -1 = no mailbox needed */ x = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_EVENT_NOTIFICATION, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopDEC error 1. Code %d\n",x); #endif /* end_capture */ data[0] = itv->dec_options.hide_last_frame; /* 0 = last frame, 1 = black */ data[1] = itv->dec_options.pts_low; /* when: pts low */ data[2] = itv->dec_options.pts_hi; /* when: pts hi */ x = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_STOP_PLAYBACK, &result, 3, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopDEC error 2. Code %d\n",x); } /* FIXME turn off relevant irqmask here */ ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE); /* stop decoder interrupt timeout */ del_timer_sync(&itv->dec_timeout); /* clean up queues */ /* move free_q to full_q to clean up partially-filled buffers */ while ((buf = ivtv_deq_buf(itv, &itv->v4l2.streams[id->type].free_q))) { buf->buffer.bytesused=0; buf->readpos=0; ivtv_enq_buf(itv, &itv->v4l2.streams[id->type].full_q, buf); } while ((buf = ivtv_deq_buf(itv, &itv->v4l2.streams[id->type].full_q))) { buf->buffer.bytesused=0; buf->readpos=0; ivtv_enq_buf(itv, &itv->v4l2.streams[id->type].free_q, buf); } while ((buf = ivtv_deq_buf(itv, &itv->v4l2.streams[id->type].dma_q))) { buf->buffer.bytesused=0; buf->readpos=0; ivtv_enq_buf(itv, &itv->v4l2.streams[id->type].free_q, buf); } if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[id->type].s_flags)) IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: clearing dma_pending\n"); /* Clean up some possibly loose-ends */ wake_up(&itv->dec_master_w); clear_bit(IVTV_F_I_BUSY, &itv->i_flags); return 0; } void ivtv_dec_timeout(unsigned long arg) { struct ivtv *itv = (struct ivtv *)arg; /* FIXME mpg only :/ */ struct ivtv_v4l2_stream *stream = &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG]; unsigned long flags; if (!test_bit(IVTV_F_S_DMAP, &stream->s_flags)) return; IVTV_DEBUG(IVTV_DEBUG_ERR, "ivtv_dec_timeout: lost IRQ; resetting...\n"); spin_lock_irqsave(&itv->lock, flags); ivtv_dec_DMA_done(itv); /* kick it off again! */ set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); ivtv_dec_sched_DMA(itv); spin_unlock_irqrestore(&itv->lock, flags); } #if 0 static void ivtv_show_irq_status(struct ivtv* itv, u32 irqstat, u32 irqmask, u32 dmastat) { struct ivtv_mailbox* mbox8 = &itv->dec_mbox[8]; struct ivtv_mailbox* mbox9 = &itv->dec_mbox[9]; #if 0 // Make it less verbose... if ((irqstat & ~4) == IVTV_IRQ_DEC_VSYNC) return; #endif printk("ivtv: irqstat [ " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s], " "frame %d, pts %d, scr %d, type %d, offset %08x, max %d, full %d\n", (irqstat & IVTV_IRQ_ENC_START_CAP) ? "StartCap " : "", (irqstat & IVTV_IRQ_ENC_EOS) ? "EndOfStream " : "", (irqstat & IVTV_IRQ_ENC_VBI_CAP) ? "VBICap " : "", (irqstat & IVTV_IRQ_ENC_VIM_RST) ? "VIMReset " : "", (irqstat & IVTV_IRQ_ENC_DMA_COMPLETE) ? "EncDMAComplete " : "", (irqstat & (1<<26)) ? "26 " : "", (irqstat & IVTV_IRQ_DEC_COPY_PROTECT) ? "CopyProt " : "", (irqstat & IVTV_IRQ_DEC_AUD_MODE_CHG) ? "AudioMode " : "", (irqstat & (1<<23)) ? "23 " : "", (irqstat & IVTV_IRQ_DEC_DATA_REQ) ? "DecDataReq " : "", (irqstat & IVTV_IRQ_DEC_IFRAME_DONE) ? "IFrameDone " : "", (irqstat & IVTV_IRQ_DEC_DMA_COMPLETE) ? "DecDMAComplete " : "", (irqstat & IVTV_IRQ_DEC_VBI_RE_INSERT) ? "VBIReInsert " : "", (irqstat & IVTV_IRQ_DEC_DMA_ERR) ? "DecDMAError " : "", (irqstat & (1<<17)) ? "17 " : "", (irqstat & (1<<16)) ? "16 " : "", (irqstat & (1<<15)) ? "15 " : "", (irqstat & (1<<14)) ? "14 " : "", (irqstat & (1<<13)) ? "13 " : "", (irqstat & (1<<12)) ? "12 " : "", (irqstat & (1<<11)) ? "11 " : "", (irqstat & IVTV_IRQ_DEC_VSYNC) ? "DecVSync " : "", (irqstat & (1<<9)) ? "9 " : "", (irqstat & (1<<8)) ? "8 " : "", (irqstat & (1<<7)) ? "7 " : "", (irqstat & (1<<6)) ? "6 " : "", (irqstat & (1<<5)) ? "5 " : "", (irqstat & (1<<4)) ? "4 " : "", (irqstat & (1<<3)) ? "3 " : "", (irqstat & (1<<2)) ? "2 " : "", (irqstat & (1<<1)) ? "1 " : "", (irqstat & (1<<0)) ? "0 " : "", readl(&mbox8->data[0]), readl(&mbox8->data[1]), readl(&mbox8->data[3]), readl(&mbox9->data[0]), readl(&mbox9->data[1]), readl(&mbox9->data[2]), readl(&mbox9->data[3])); } #endif static void ivtv_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { u32 stat = 0; u32 combo = 0; struct ivtv *itv=(struct ivtv *)dev_id; spin_lock(&itv->lock); /* get contents of irq status register*/ stat = readl(itv->reg_mem + IVTV_REG_IRQSTATUS); combo=~itv->irqmask & stat; if (0 == combo) { /* wasn't for us*/ spin_unlock(&itv->lock); return; } /* ivtv_show_irq_status(itv, stat, itv->irqmask, readl(itv->reg_mem + IVTV_REG_DMASTATUS)); */ IVTV_DEBUG(IVTV_DEBUG_IRQ, "======= valid IRQ bits: 0x%08x ======\n", combo); writel(combo, (itv->reg_mem + IVTV_REG_IRQSTATUS)); if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) { ivtv_DMA_done(itv); IVTV_DEBUG(IVTV_DEBUG_IRQ, "Processed DMA-complete\n"); } if (combo & IVTV_IRQ_ENC_START_CAP) { ivtv_sched_DMA(itv); IVTV_DEBUG(IVTV_DEBUG_IRQ, "Processed enc-startcap\n"); } if (combo & IVTV_IRQ_ENC_EOS) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "Encoder End Of Stream\n"); set_bit(IVTV_F_I_EOS, &itv->i_flags); wake_up(&itv->cap_w); } if (combo & IVTV_IRQ_ENC_VBI_CAP) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "deb3\n"); } if (combo & IVTV_IRQ_ENC_VIM_RST) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "VIM Restart\n"); } if (combo & IVTV_IRQ_DEC_COPY_PROTECT) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "deb6\n"); } if (combo & IVTV_IRQ_DEC_AUD_MODE_CHG) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "deb7\n"); } if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "Decoder DMA Done\n"); ivtv_dec_DMA_done(itv); } if (combo & IVTV_IRQ_DEC_DATA_REQ) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "Decoder Data Request\n"); set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); ivtv_dec_sched_DMA(itv); } if (combo & IVTV_IRQ_DEC_IFRAME_DONE) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "deb9\n"); } if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "deb11\n"); } if (combo & IVTV_IRQ_DEC_DMA_ERR) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "deb12\n"); } if (combo & IVTV_IRQ_DEC_VSYNC) { ivtv_irq_dec_vsync(itv); } /* stat = readl(itv->reg_mem + IVTV_REG_IRQSTATUS); IVTV_DEBUG(IVTV_DEBUG_IRQ, "IVTV IRQ STATUS REG AFTER INTERRUPT 0x%08x", stat); if (combo & ~IVTV_IRQ_DEBUG_KLUGE) { IVTV_DEBUG(IVTV_DEBUG_ERR, "unknown irq 0x%08x, mask:0x%08x, combo:0x%08x\n", stat, itv->irqmask, combo); } */ spin_unlock(&itv->lock); } static void ivtv_irq_dec_vsync(struct ivtv* itv) { u32* data = itv->dec_mbox[IVTV_MBOX_FIELD_DISPLAYED].data; u32 newframe = readl(&data[0]); u64 newpts = ((u64)readl(&data[2]) << 32) | (u64)(readl(&data[1])); u64 newscr = ((u64)readl(&data[4]) << 32) | (u64)(readl(&data[3])); itv->dec_timestamp.pts = newpts; itv->dec_timestamp.scr = newscr; if (newframe != itv->dec_timestamp.frame) { itv->dec_timestamp.frame = newframe; wake_up(&itv->vsync_w); } IVTV_DEBUG(IVTV_DEBUG_IRQ, "ivtv_irq_dec_vsync: frames %d, pts %ld, scr %ld\n", itv->dec_timestamp.frame, (long int)itv->dec_timestamp.pts, (long int)itv->dec_timestamp.scr); } static void ivtv_show_debug_flags(struct ivtv *itv) { int y; printk(KERN_DEBUG "ivtv: i_flags=%lx", itv->i_flags); for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) printk(", %d s_sflags=%lx", y, itv->v4l2.streams[y].s_flags); printk("\n"); } static void ivtv_DMA_done(struct ivtv *itv) { u32 result; int y,stmtype=-1; struct ivtv_v4l2_stream *stream=NULL; struct ivtv_buffer *buf; IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA Done tasklet\n"); for (y=0; y < itv->v4l2.streamcount; y++) { if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[y].s_flags)) { stmtype = y; break; } } if (stmtype < 0) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Got DMA-done, but not expecting one\n"); ivtv_show_debug_flags(itv); return; } stream = &itv->v4l2.streams[stmtype]; /* check DMA status register */ result = readl(itv->reg_mem + IVTV_REG_DMASTATUS); if (!(result & IVTV_DMA_SUCCESS)) { if (result & IVTV_DMA_WRITE_ERR) IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA write error. Result=0x%08x\n", result); if (result & IVTV_DMA_READ_ERR) IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA read error. Result=0x%08x\n",result); return; } /* DMA was fine if we made it this far */ /* remove from dma_pending queue */ while ((buf = __ivtv_deq_buf(&stream->dma_q))) { IVTV_ASSERT(buf->dma_handle != IVTV_DMA_UNMAPPED); pci_unmap_single(itv->dev, buf->dma_handle, IVTV_DMA_BUF_SIZE, PCI_DMA_TODEVICE); buf->dma_handle = IVTV_DMA_UNMAPPED; /* byteswap ABCD -> DCBA for MPG data*/ if (stmtype == 0) { for (y = 0; y < buf->buffer.bytesused; y += 4) { swab32s( (u32 *)((u32)buf->buffer.m.userptr + y)); } } /* put in the 'done' queue */ __ivtv_enq_buf(&stream->full_q, buf); } /*wake up client*/ wake_up(&stream->waitq); } /* must hold itv->lock */ static int ivtv_ignore_DMA_req(struct ivtv *itv, u32 type) { u32 data[IVTV_MBOX_MAX_DATA], result; int ret = 0; data[0] = 0; data[1] = 0; /* ACK the DMA and continue */ data[2] = type; // AEW - API docs say type goes here if (ivtv_api(itv->enc_mbox, &itv->enc_msem, IVTV_API_SCHED_DMA_TO_HOST, &result, 3, &data[0])) { IVTV_DEBUG(IVTV_DEBUG_ERR, "error sending DMA info\n"); ret = -EIO; } if (!ret) set_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags); return ret; } /* FIXME this function is getting too long. split it up? */ static void ivtv_sched_DMA(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; u32 type, size, offset; u32 UVsize=0, UVoffset=0, pts_stamp=0; struct ivtv_v4l2_stream *st; int x, bufs_needed; int uvflag=0; struct ivtv_buffer *buf; LIST_HEAD(free_list); long sequence; IVTV_DEBUG(IVTV_DEBUG_INFO, "Sched DMA tasklet\n"); /* Get DMA destination and size arguments from card*/ x = ivtv_api_getresult_nosleep(&itv->enc_mbox[9], &result, &data[0]); if (x) { IVTV_DEBUG(IVTV_DEBUG_ERR, "error:%d getting DMA info\n", x); return; } type = data[0]; /* FIXME should check for null on the stream element */ if (itv->v4l2.streamcount <= type) { IVTV_DEBUG(IVTV_DEBUG_ERR,"No stream handler for type %d\n", type); ivtv_ignore_DMA_req(itv, type); return; } switch (type) { case 0: /* MPEG */ offset = data[1]; size = data[2]; IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA/MPG type 0x%08x,size 0x%08x,offset 0x%08x\n", type, size, offset); bufs_needed = ivtv_ceil(size, IVTV_DMA_BUF_SIZE); break; case 1: /* YUV */ offset = data[1]; size = data[2]; UVoffset = data[3]; UVsize = data[4]; pts_stamp = data[6]; IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA/YUV type 0x%08x,Ysize 0x%08x,Yoffset 0x%08x," "UVsize 0x%08x,UVoffset 0x%08x,PTS 0x%08x\n", type, size, offset, UVsize, UVoffset, pts_stamp); bufs_needed = ivtv_ceil(size, IVTV_DMA_BUF_SIZE); bufs_needed += ivtv_ceil(UVsize, IVTV_DMA_BUF_SIZE); break; case 2: /* PCM (audio) */ offset = data[1]; size = data[2]; pts_stamp = data[6]; IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA/PCM type 0x%08x,size 0x%08x,offset 0x%08x " "PTS 0x%08x\n", type, size, offset, pts_stamp); bufs_needed = ivtv_ceil(size, IVTV_DMA_BUF_SIZE); ivtv_ignore_DMA_req(itv, type); return; case 3: /* VBI */ offset = data[1]; size = data[2]; bufs_needed = ivtv_ceil(size, IVTV_DMA_BUF_SIZE); IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA/VBI type 0x%08x, size 0x%08x, offset 0x%08x" "EXPERIMENTAL\n", type, size, offset); break; default: IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA/UNKNOWN type 0x%08x, NOT SUPPORTED\n", type); ivtv_ignore_DMA_req(itv, type); return; } if (bufs_needed > SGarray_size) { IVTV_DEBUG(IVTV_DEBUG_ERR, "INTERNAL ERROR: ivtv_sched_DMA_tasklet: " "bufs_needed = %d but SGarray_size = %d\n", bufs_needed, SGarray_size); return; } st = &itv->v4l2.streams[type]; /* gather the needed buffers first, so we don't have to bail * in mid-air. put them on a list on the stack */ for (x = 0; x < bufs_needed; x++) { buf = __ivtv_deq_buf(&st->free_q); if (!buf) break; list_add_tail(&buf->list, &free_list); } /* damn, failed */ if (x < bufs_needed) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA buffer DeQueue failed! got %d, want %d\n", x + 1, bufs_needed + 1); IVTV_DEBUG(IVTV_DEBUG_INFO, "SCHED: free_q: %d elements\n", st->free_q.elements); IVTV_DEBUG(IVTV_DEBUG_INFO, "SCHED: dma_q: %d elements\n", st->dma_q.elements); IVTV_DEBUG(IVTV_DEBUG_INFO, "SCHED: full_q: %d elements\n", st->full_q.elements); while (!list_empty(&free_list)) { buf = list_entry(free_list.next, struct ivtv_buffer, list); list_del_init(&buf->list); __ivtv_enq_buf(&st->free_q, buf); } /* mark overflow condition, next free will restart dma req */ set_bit(IVTV_F_S_OVERFLOW, &st->s_flags); return; } /* increment the sequence # */ sequence = ++st->seq; for (x = 0; x < bufs_needed; x++) { IVTV_DEBUG(IVTV_DEBUG_INFO, "size: %d 0x%08x\n", size, size); if ((size == 0) && (type == 1) && (uvflag == 0)) { /* YUV */ /* process the UV section */ offset = UVoffset; size = UVsize; uvflag = 1; } /* extract the buffers we procured earlier */ buf = list_entry(free_list.next, struct ivtv_buffer, list); list_del_init(&buf->list); buf->readpos = 0; buf->buffer.index = x; buf->buffer.sequence = sequence; buf->ts = jiffies; if (size < (IVTV_DMA_BUF_SIZE & 0xffffff00)) { buf->buffer.bytesused = size; /* bytecount must be multiple of 0x100 (256) */ itv->SGarray[x].size = (0xffffff00 & (buf->buffer.bytesused + 0xFF)); size = 0; } else { buf->buffer.bytesused = IVTV_DMA_BUF_SIZE; itv->SGarray[x].size = IVTV_DMA_BUF_SIZE; size -= IVTV_DMA_BUF_SIZE; } itv->SGarray[x].src = offset; offset += buf->buffer.bytesused; /* unfortunately the pci dma api wasn't properly defined * for handling mapping errors (running out of iommu space, * for instance). 0 can be a valid bus address. */ buf->dma_handle = pci_map_single(itv->dev, (void *)buf->buffer.m.userptr, buf->buffer.bytesused, PCI_DMA_FROMDEVICE); itv->SGarray[x].dst = buf->dma_handle; /* FIXME need to add pts stuff, index, etc. */ __ivtv_enq_buf(&st->dma_q, buf); } /* This should wrap gracefully */ /* FIXME obselete? */ itv->trans_id++; itv->SGarray[bufs_needed-1].size |= 0x80000000; /*FIXME unlock */ data[0] = itv->SG_handle; /* 3 elements * 4 bytes per element * num_elements */ data[1] = (3 * 4 * bufs_needed); data[2] = type; data[3] = 0x0; for (x = 0; x < bufs_needed; x++) IVTV_DEBUG(IVTV_DEBUG_INFO, "SGarray[%d]: 0x%08x, 0x%08x 0x%08x\n", x, itv->SGarray[x].src, itv->SGarray[x].dst, itv->SGarray[x].size); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sched dma: addr: 0x%08x, array_size 0x%08x," " type 0x%08x\n", data[0], data[1], data[2]); set_bit(IVTV_F_S_DMAP, &st->s_flags); ivtv_api(itv->enc_mbox, &itv->enc_msem, IVTV_API_SCHED_DMA_TO_HOST, &result, 4, &data[0]); } static void ivtv_sched_DMA_tasklet(unsigned long arg) { struct ivtv *itv = (struct ivtv *) arg; unsigned long flags; spin_lock_irqsave(&itv->lock, flags); ivtv_sched_DMA(itv); spin_unlock_irqrestore(&itv->lock, flags); } /* FIXME this function does way more than it should */ static int __devinit ivtv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { int retval=0; unsigned char pci_latency; struct ivtv *itv; struct video_channel v; unsigned long freq; u16 cmd; IVTV_DEBUG(IVTV_DEBUG_INFO, "Found card #%d\n", ivtv_cards_active); spin_lock_irq(&ivtv_lock); /* Make sure we've got a place for this card */ if (ivtv_cards_active == IVTV_MAX_CARDS) { IVTV_DEBUG(IVTV_DEBUG_ERR, ":Maximum # of cards already detected (%d).\n", ivtv_cards_active); spin_unlock_irq(&ivtv_lock); return -ENOMEM; } itv = &ivtv_cards[ivtv_cards_active]; itv->dev = dev; itv->num = ivtv_cards_active; ivtv_cards_active++; spin_unlock_irq(&ivtv_lock); /* always remember what you think the irq mask should be */ itv->irqmask = 0; #ifdef YUV_FIXUP itv->options.yuv_fixup = yuv_fixup; #endif itv->options.dec_yuv_buffers = dec_yuv_buffers; itv->options.dec_mpg_buffers = mpg_buffers; itv->options.yuv_buffers = yuv_buffers; itv->options.mpg_buffers = mpg_buffers; itv->options.vbi_buffers = vbi_buffers; itv->options.num_devices = num_devices; itv->options.dec_mpg_qlen = dec_mpg_qlen; itv->options.dec_yuv_qlen = dec_yuv_qlen; /* Set FrameBuffer-ID to invalid */ itv->fb_id = -1; switch (dev->subsystem_device) { case IVTV_PCI_ID_250_V2: IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an iTVC16 based chip\n"); itv->card_type = IVTV_250_V2; break; case IVTV_PCI_ID_350_V1: IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an iTVC15 based chip\n"); itv->card_type = IVTV_350_V1; break; case IVTV_PCI_ID_250_V1: IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an iTVC15 based chip\n"); itv->card_type = IVTV_250_V1; break; default: /* Default to 250 v1 style */ IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an unknown chip, treating it like an iTVC15\n"); itv->card_type = IVTV_250_V1; break; } init_MUTEX(&itv->enc_msem); init_MUTEX(&itv->dec_msem); init_MUTEX(&itv->sem_lock); spin_lock_init(&itv->lock); itv->base_addr=pci_resource_start(dev,0); itv->enc_mbox = NULL; itv->dec_mbox = NULL; itv->io_mem = NULL; itv->reg_mem = NULL; itv->i_flags = 0; atomic_set(&itv->capturing, 0); atomic_set(&itv->decoding, 0); itv->user_dma_to_device_state = NULL; /* Prepare list for action! */ INIT_LIST_HEAD(&itv->client_list); init_waitqueue_head(&itv->cap_w); init_waitqueue_head(&itv->vsync_w); init_waitqueue_head(&itv->dec_master_w); init_timer(&itv->dec_timeout); itv->dec_timeout.function = ivtv_dec_timeout; itv->dec_timeout.data = (unsigned long)itv; tasklet_init(&itv->dma_sched_tq, ivtv_sched_DMA_tasklet, (unsigned long) itv); IVTV_DEBUG(IVTV_DEBUG_INFO, "base addr: 0x%08x\n", itv->base_addr); IVTV_DEBUG(IVTV_DEBUG_INFO, "Enabling pci device\n"); if (pci_enable_device(dev)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Can't enable device %d!\n",itv->num); retval = -EIO; goto err; } if (pci_set_dma_mask(dev, 0xffffffff)) { IVTV_DEBUG(IVTV_DEBUG_ERR, KERN_WARNING "No suitable DMA available on card %d.\n", itv->num); retval = -EIO; goto err; } if (!request_mem_region(pci_resource_start(dev,0), IVTV_IOREMAP_SIZE, IVTV_DEVNAME )) { retval = -EIO; goto err; } /* Check for bus mastering */ pci_read_config_word(dev, PCI_COMMAND, &cmd); if (! (cmd & PCI_COMMAND_MASTER)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Bus Mastering is not enabled\n"); retval = -ENXIO; goto free_mem; } else { IVTV_DEBUG(IVTV_DEBUG_INFO, "Bus Mastering Enabled."); } pci_read_config_byte(dev, PCI_CLASS_REVISION, &itv->card_rev); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); IVTV_DEBUG(IVTV_DEBUG_INFO, "%d (rev %d) at %02x:%02x.%x, ", itv->dev->device, itv->card_rev, dev->bus->number, PCI_SLOT(dev->devfn),PCI_FUNC(dev->devfn)); IVTV_DEBUG(IVTV_DEBUG_INFO, " irq: %d, latency: %d, memory: 0x%lx\n", itv->dev->irq, pci_latency, (unsigned long)itv->base_addr); /*map io memory*/ IVTV_DEBUG(IVTV_DEBUG_INFO, "attempting ioremap at 0x%08x len 0x%08x\n", itv->base_addr, IVTV_ENCDEC_SIZE); itv->io_mem = ioremap_nocache(itv->base_addr,IVTV_ENCDEC_SIZE); if (!itv->io_mem) { IVTV_DEBUG(IVTV_DEBUG_ERR, IVTV_IOREMAP_ERROR); retval = -ENOMEM; goto free_mem; } /*map registers memory*/ IVTV_DEBUG(IVTV_DEBUG_INFO, "attempting ioremap at 0x%08x len 0x%08x\n", itv->base_addr+IVTV_REG_OFFSET, IVTV_REG_SIZE); itv->reg_mem = ioremap_nocache(itv->base_addr+IVTV_REG_OFFSET,IVTV_REG_SIZE); if (!itv->reg_mem) { IVTV_DEBUG(IVTV_DEBUG_ERR, IVTV_IOREMAP_ERROR); retval = -ENOMEM; goto free_io; } IVTV_DEBUG(IVTV_DEBUG_IRQ, "Masking interrupts\n"); /* clear interrupt mask, effectively disabling interrupts */ ivtv_set_irq_mask(itv, 0xffffffff); retval = request_irq(itv->dev->irq, ivtv_irq_handler, SA_SHIRQ | SA_INTERRUPT,IVTV_DEVNAME,(void *)itv); if (retval) { IVTV_DEBUG(IVTV_DEBUG_ERR, "failed to register irq %d\n", retval); goto free_io; } /* save itv in the pci struct for later use*/ pci_set_drvdata(dev,itv); /* active i2c */ itv->i2c_command=(I2C_TIMING); IVTV_DEBUG(IVTV_DEBUG_INFO, "activating i2c..\n"); if (init_ivtv_i2c(itv)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "i2c died! unloading\n"); goto free_irq; } IVTV_DEBUG(IVTV_DEBUG_INFO, "Active card count: %d.\n", ivtv_cards_active); /*write firmware */ retval = ivtv_firmware_init(itv); if (retval) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error initializing.\n"); retval = -ENOMEM; goto free_i2c; } /*search for encoder/decoder mailboxes*/ IVTV_DEBUG(IVTV_DEBUG_INFO, "About to search for mailboxes\n"); ivtv_find_firmware_mailbox(itv); if ((itv->enc_mbox == NULL) && (itv->dec_mbox ==NULL)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error locating firmware.\n"); retval = -ENOMEM; goto free_i2c; } /*releasing unneeded iomapped memory (encoder+decoder)*/ //iounmap(itv->io_mem); /*remapping only needed io memory (mailboxes) */ itv->enc_mbox = ioremap(itv->base_addr+((u8 *)itv->enc_mbox - (u8 *)itv->io_mem), IVTV_MBOX_MAX_BOXES * IVTV_MBOX_SIZE); itv->dec_mbox = ioremap(itv->base_addr+((u8 *)itv->dec_mbox - (u8 *)itv->io_mem), IVTV_MBOX_MAX_BOXES * IVTV_MBOX_SIZE); /* clearing pointers */ //itv->io_mem = NULL ; /*Try and get firmware versions */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Getting firmware version..\n"); retval = ivtv_firmware_versions(itv); if (retval) { IVTV_DEBUG(IVTV_DEBUG_ERR, "error %d getting version #!\n", retval); goto free_i2c; } /* Allocate scatter-gather arrays*/ //++MTY NASTY little bug!!! If user changes dec_mpg_buffers, // memory corruption results with the old way! /* encoder */ itv->SGarray = (struct ivtv_SG_element *) kmalloc(sizeof(struct ivtv_SG_element) * SGarray_size, GFP_KERNEL); if (!(itv->SGarray)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error allocating SGarray[].\n"); retval = -ENOMEM; goto free_i2c; } itv->SG_handle = pci_map_single(itv->dev, (void *)&itv->SGarray[0], (sizeof(struct ivtv_SG_element) * SGarray_size), PCI_DMA_TODEVICE); if (itv->card_type == IVTV_350_V1) { /* decoder */ itv->DSGarray = (struct ivtv_SG_element *) kmalloc(sizeof(struct ivtv_SG_element) * DSGarray_size, GFP_KERNEL); if (!(itv->DSGarray)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error allocating DSGarray[].\n"); retval = -ENOMEM; goto free_sg; } itv->DSG_handle = pci_map_single(itv->dev, (void *)&itv->DSGarray[0], (sizeof(struct ivtv_SG_element) * DSGarray_size), PCI_DMA_TODEVICE); } /* FIXME -temporary- setup tuner */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Setting Tuner\n"); if( tuner > -1 ) { ivtv_call_i2c_client(itv, IVTV_TUNER_I2C_ADDR, TUNER_SET_TYPE, &tuner ); } /* set the standard */ if (!ivtv_pal) v.norm = VIDEO_MODE_NTSC; else v.norm = VIDEO_MODE_PAL; ivtv_call_i2c_client(itv,IVTV_TUNER_I2C_ADDR, VIDIOCSCHAN,&v); if (!ivtv_pal) { /* set the channel */ freq = 1076; /* ch. 4 67250*16/1000 */ ivtv_call_i2c_client(itv,IVTV_TUNER_I2C_ADDR,VIDIOCSFREQ,&freq); } retval = ivtv_v4l2_setup(itv); if (retval) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Problem starting v4l2\n"); goto ivtv_v4l2_fail; } return 0; ivtv_v4l2_fail: pci_unmap_single(itv->dev, itv->DSG_handle, (sizeof(struct ivtv_SG_element) * DSGarray_size), PCI_DMA_TODEVICE); kfree(itv->DSGarray); free_sg: pci_unmap_single(itv->dev, itv->SG_handle, (sizeof(struct ivtv_SG_element) * SGarray_size), PCI_DMA_TODEVICE); kfree(itv->SGarray); free_i2c: exit_ivtv_i2c(itv); free_irq: free_irq(itv->dev->irq, (void *)itv); free_io: ivtv_iounmap(itv); free_mem: release_mem_region(pci_resource_start(itv->dev,0), IVTV_IOREMAP_SIZE); err: IVTV_DEBUG(IVTV_DEBUG_ERR, "Error %d on init\n", retval); spin_lock_irq(&ivtv_lock); ivtv_cards_active--; spin_unlock_irq(&ivtv_lock); return retval; } static void ivtv_remove(struct pci_dev *pci_dev) { struct ivtv *itv=pci_get_drvdata(pci_dev); int x = 0; IVTV_DEBUG(IVTV_DEBUG_INFO, "Disabling interrupts!\n"); ivtv_set_irq_mask(itv, 0xffffffff); IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping thread\n"); atomic_set(&itv->decoding, 0); IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping card parts\n"); x = ivtv_stop_firmware(itv); IVTV_DEBUG(IVTV_DEBUG_INFO, "Freeing buffers\n"); for (x = 0; x < itv->v4l2.streamcount; x++) { IVTV_DEBUG(IVTV_DEBUG_INFO,"Freeing stream %d!\n", x); ivtv_free_queue(&itv->v4l2.streams[x].free_q); ivtv_free_queue(&itv->v4l2.streams[x].full_q); ivtv_free_queue(&itv->v4l2.streams[x].dma_q); } IVTV_DEBUG(IVTV_DEBUG_INFO, "Unregistering v4l devices!\n"); ivtv_v4l2_cleanup(itv); IVTV_DEBUG(IVTV_DEBUG_INFO, "Freeing dma resources\n"); pci_unmap_single(itv->dev, itv->SG_handle, (sizeof(struct ivtv_SG_element) * SGarray_size), PCI_DMA_TODEVICE); kfree(itv->SGarray); pci_unmap_single(itv->dev, itv->DSG_handle, (sizeof(struct ivtv_SG_element) * DSGarray_size), PCI_DMA_TODEVICE); kfree(itv->DSGarray); exit_ivtv_i2c(itv); IVTV_DEBUG(IVTV_DEBUG_INFO, "releasing irq\n"); free_irq(itv->dev->irq, (void *)itv); if (itv->dev) { ivtv_iounmap(itv); } IVTV_DEBUG(IVTV_DEBUG_INFO, "releasing mem\n"); if (itv) release_mem_region(pci_resource_start(itv->dev,0), IVTV_IOREMAP_SIZE); /* FIXME free v4l2 stuff! */ /* FIXME am i leaking kernel mem? */ } /* define a pci_driver for card detection */ static struct pci_driver ivtv_pci_driver = { name: "ivtv: iTVC15/16 mpg2 encoder card", id_table: ivtv_pci_tbl, probe: ivtv_probe, remove: ivtv_remove, }; #ifdef YUV_FIXUP static int ivtv_YUV_fixup(struct ivtv_v4l2_stream *st, int count, char *ubuf, struct ivtv_buffer *buf) { /* * int count = # of bytes to transfer to client * st->ubytes = # of bytes written this frame * ubuf = buffer to write to (user's buffer) * buf = read buffer * */ int src_width=720; /* all known formats have src width of 720 */ int Hoff, Voff; /* collectors for offsets to read position */ int width, height; /* resolution of the capture stream */ int curline; /* vertical line currently being processed */ int maxline; /* height of combined frame */ int cur_m_block; /* current horizontal offset of working mblock in this row */ int maxblock; /* # of macroblocks in a row */ int Hbytes; /* # of bytes to write to user this time around */ int retval=0; /* accumulator for total bytes written */ int start; /* position in buf to read from */ int buf_start; /* byte offset of first byte in this *buf */ height = st->format.fmt.pix.height; width = st->format.fmt.pix.width; maxblock = (width + 0xf) >> 4; maxline = (int)(1.5 * height); /* 1 for Y, .5 for UV */ /* Offset is always bufsize * buffer index buf_start = (st->ubytes - buf->readpos); tested/works */ buf_start = IVTV_DMA_BUF_SIZE * buf->buffer.index; /* FIXME it may not be possible to get YUV width > 720 */ // if (width > src_width) src_width=width; curline = (int) (st->ubytes / width); while (curline < maxline) { // printk(" cl: %d, ml: %d\n", curline, maxline); Voff = 16 * (curline & 0xf) + /* Voffset within MBlock */ ((curline & 0xfff0) * src_width); /* Voffset of Mblock */ cur_m_block = (st->ubytes - (curline * width)) >> 4; /* printk("voff %d, macroVoff %d, Voff %d, cmb %d\n", (16 * (curline & 0xf)), ((curline & 0xff0) * src_width), Voff, cur_m_block); */ while ((cur_m_block < maxblock) && (count > 0)) { Hoff = (cur_m_block * 256) + /* mblock offset within line */ /* Hoffset within mblock, usually 0 */ ((st->ubytes - (curline * width)) & 0xf); Hbytes = 16 - ((st->ubytes - (curline * width)) & 0xf); if (Hbytes > count) Hbytes = count; start = Hoff + Voff; if (copy_to_user((char *)((u32)ubuf + retval), (u32 *)((u32)buf->buffer.m.userptr + (start - buf_start)), Hbytes)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "copy to user failed\n"); return -EFAULT; } count -= Hbytes; retval += Hbytes; st->ubytes += Hbytes; cur_m_block++; } /* if user can't handle anymore data or buffer empty */ curline++; if ((count == 0) ) /*|| ((curline * src_width) % IVTV_DMA_BUF_SIZE) == 0)*/ return retval; } /* FIXME i don't think you should ever get here */ IVTV_DEBUG(IVTV_DEBUG_ERR, "You've just sailed off the edge of this function\n"); return retval; } #endif long ivtv_read(struct ivtv_open_id *id, char *ubuf, size_t count, int block) { int x, sleepctr, datalen, retval=0, freed=0; struct ivtv *itv = id->itv; size_t newcount; unsigned long tid; struct ivtv_buffer *buf; struct ivtv_v4l2_stream *st=&itv->v4l2.streams[id->type]; DECLARE_WAITQUEUE(wait, current); IVTV_DEBUG(IVTV_DEBUG_INFO, " Read stream.. \n"); if (atomic_read(&itv->capturing) == 0) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Stream not initialized before read(shouldn't happen)\n"); return -EIO; } /* FIXME find a way to gracefully exit capture */ sleepctr = retval = 0; buf = NULL; add_wait_queue(&st->waitq, &wait); do { if ((itv->trans_id == 0) && (sleepctr >= IVTV_MAX_DATA_SLEEP)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Timeout waiting for data!\n"); retval = -EIO; break; } set_current_state(TASK_INTERRUPTIBLE); buf = ivtv_deq_peek_head(itv, &st->full_q); if (buf) break; if (!block) { retval = -EAGAIN; break; } ivtv_sleep_timeout(IVTV_SLEEP_WAIT); if (signal_pending(current)) retval = -ERESTARTSYS; sleepctr++; } while (!retval); __set_current_state(TASK_RUNNING); remove_wait_queue(&st->waitq, &wait); /* an error (or signal) occured */ if (retval) return retval; /* Skip the first 4 bytes of mpg streams to help out * finicky decoders.. but not for iTVC16 */ if ((id->type == 0) && (itv->first_read == 1) && (itv->card_type != IVTV_250_V2)) { for( x = 0; x < buf->buffer.bytesused-4; x++ ) { unsigned char *p; itv->first_read = 0; p = (unsigned char *) buf->buffer.m.userptr + buf->readpos + x; if( !p[0] && !p[1] && p[2] == 1 ) { IVTV_DEBUG(IVTV_DEBUG_INFO, "Stripping first 4 bytes\n"); buf->buffer.bytesused -= x; buf->readpos += x; break; } } } /* data ready */ /* copy it to the client */ while ((count > 0) && (buf->buffer.bytesused > 0)) { newcount = count; datalen = buf->buffer.bytesused; IVTV_DEBUG(IVTV_DEBUG_INFO, "datalen 0x%08x\n", datalen); if (newcount > datalen) newcount = datalen; #ifdef YUV_FIXUP if ((id->type == 1) && (itv->options.yuv_fixup)) { newcount = ivtv_YUV_fixup(st,newcount,ubuf+retval,buf); if (newcount < 0) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error fixing up YUV!\n"); return newcount; } } else { #endif if (copy_to_user((char *)((u32)ubuf+retval), (u32 *)((u32)buf->buffer.m.userptr + buf->readpos), newcount)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "copy to user failed\n"); return -EFAULT; } #ifdef YUV_FIXUP } #endif buf->readpos += newcount; retval += newcount; count -= newcount; buf->buffer.bytesused -= newcount; IVTV_DEBUG(IVTV_DEBUG_INFO, "new datalen 0x%08x\n", buf->buffer.bytesused); /* if buffer is empty or we've read the whole frame */ if ((buf->buffer.bytesused == 0)) { ivtv_move_buf(itv, &st->full_q, &st->free_q, buf); freed++; buf = ivtv_deq_peek_head(itv, &st->full_q); if (buf) { tid = buf->buffer.sequence; if (buf->buffer.sequence != tid) { /* end of frame! */ st->ubytes = 0; break; } } else { /* user wanted more than we had. Since * queues are filled in irq time, * that means end of frame */ st->ubytes = 0; break; } } } /* end of while */ /* if we put some buffers back in the free queue, kick off dma * scheduling if card was stopped due to overflow before */ if (freed && test_and_clear_bit(IVTV_F_S_OVERFLOW, &st->s_flags)) { spin_lock_irq(&itv->lock); ivtv_sched_DMA(itv); spin_unlock_irq(&itv->lock); } /*FIXME unlock */ if (retval != 0) { IVTV_DEBUG(IVTV_DEBUG_INFO, "Returning %d\n", retval); return retval; } /* Shouldn't ever get here */ IVTV_DEBUG(IVTV_DEBUG_ERR, "Something's weird. You shouldn't be here\n"); return -EIO; } static void ivtv_swap_copy(const char *buf, const char *ubuf, size_t count) { u32 *src,*dst; src=(u32 *)ubuf; dst=(u32 *)buf; #ifdef CONFIG_X86 while ((u32)src <= (u32)ubuf + count) { /* byteswap while copying */ __asm__ __volatile__ ("bswap %0" : "=r" (*dst) : "0" (*src) ); src++;dst++; } #else { int y; /* Old slow memcpy then swab */ memcpy((void *)buf,(void *)ubuf,count); for (y = 0; y < count; y += 4) { swab32s( (u32 *)((u32)buf + y)); } } #endif } static int ivtv_fill_dec_buffers(struct ivtv_open_id *id, const char *ubuf, size_t count) { struct ivtv *itv = id->itv; struct ivtv_v4l2_stream *stream=&itv->v4l2.streams[id->type]; struct ivtv_buffer *buf; int copybytes=0, bytesread=0, retval=0; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_fill_dec_buffers, %d bytes\n", count); /* Read what the user gives us. queue it for DMA after each buffer * also enqueue partly-full buffers. */ IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: free_q: %d elements\n", stream->free_q.elements); IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: dma_q: %d elements\n", stream->dma_q.elements); IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: full_q: %d elements\n", stream->full_q.elements); /* FIXME will only do one write. Has underlying code to handle more * than one, just need loop control logic for it, if it's * deemed necessary. */ while (bytesread == 0) { DECLARE_WAITQUEUE(wait, current); unsigned long flags; buf = NULL; add_wait_queue(&stream->waitq, &wait); do { set_current_state(TASK_INTERRUPTIBLE); buf = ivtv_deq_peek_head(itv, &stream->free_q); if (buf) break; schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } spin_lock_irqsave(&itv->lock, flags); ivtv_dec_sched_DMA(id->itv); spin_unlock_irqrestore(&itv->lock, flags); } while (!buf); set_current_state(TASK_RUNNING); remove_wait_queue(&stream->waitq, &wait); if (retval) return retval; /* bytes left to send > free bytes in current buffer */ if ((count - bytesread) > (IVTV_DMA_DEC_BUF_SIZE - buf->buffer.bytesused)) { copybytes = IVTV_DMA_DEC_BUF_SIZE - buf->buffer.bytesused; } else { copybytes = count - bytesread; } /* copy data */ /* FIXME */ IVTV_DEBUG(IVTV_DEBUG_INFO, "copying %d bytes to 0x%08x" " (buffer free = %d)\n", copybytes,(int)(buf->buffer.m.userptr + buf->buffer.bytesused), (int)(IVTV_DMA_DEC_BUF_SIZE - buf->buffer.bytesused)); ivtv_swap_copy((char *)(buf->buffer.m.userptr+buf->buffer.bytesused), (char *)((u32)ubuf + bytesread),copybytes); bytesread += copybytes; buf->buffer.bytesused += copybytes; /* enq buffer when full */ if (buf->buffer.bytesused == IVTV_DMA_DEC_BUF_SIZE) ivtv_move_buf(itv,&stream->free_q,&stream->full_q,buf); } return bytesread; } /* * Schedule host -> hardware DMA of one buffer from the stream (MPEG or YUV) * with the most recent request for more data, but only if dec->dec_needs_data * is set. * * This code can be called from both interrupt context as well as userspace; * it does the right things in either case. If called from userspace, it may * block only when the same call is in progress in interupt context (since * interrupt context is not allowed to block.) * * @returns 0 if the buffer was queued to dma_q and the DMA was initiated. * * -EAGAIN if either the full_q queue is empty or the function is * already in progress in interrupt context. * * -ENOSPC if there is no space remaining in the hardware's buffer. * This should never happen if proper flow control is used. * * -EINVAL if the most recent "data needed" interrupt requested an * unknown stream type (should really never happen!) * * -EBUSY if a DMA on the same queue is already in progress (should * never happen) * */ static void ivtv_dec_sched_DMA(struct ivtv *itv) { int ret=0, x=0, bytes_written=0, type=0, max=2; struct ivtv_buffer *buf; struct ivtv_v4l2_stream *stream=NULL; u32 data[IVTV_MBOX_MAX_DATA], result; u32 mem_offset, mem_size, hw_stream_type, buffer_bytes; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_DMA\n"); /* fancy way of saying "if (ivtv->dec_needs_data == 0)" */ if (!test_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: no data needed\n"); return; } /* Get Card Mem Dst address from mailbox 10 */ ret = ivtv_api_getresult_nosleep(&itv->dec_mbox[9], &result, &data[0]); IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: Mailbox 10: 0x%08x 0x%08x 0x%08x 0x%08x\n", data[0],data[1],data[2],data[3]); hw_stream_type = data[0]; switch(hw_stream_type) { case 0: /* MPG */ type = IVTV_DEC_STREAM_TYPE_MPG; IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: mpg data\n"); break; case 2: /* YUV */ type = IVTV_DEC_STREAM_TYPE_YUV; IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: yuv data\n"); break; default: IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: unknown stream type %d\n", data[0]); max = 0; return; } stream = &itv->v4l2.streams[type]; if (test_bit(IVTV_F_I_BUSY, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: decoder busy, delaying\n"); set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); return; } /* If we got this far, we have data to send and it wants it */ clear_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); /* Get card mem addr and size from data array */ mem_offset = data[1]; mem_size = data[2]; buffer_bytes = data[3]; /* # bytes in card's buffer */ while ((max > x) && (mem_size > bytes_written)) { /* send a maximum of 'max' buffers */ buf = __ivtv_deq_peek_head(&stream->full_q); if (buf == NULL) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: No more buffers to send\n"); break; } #if 1 if (mem_size < buf->buffer.bytesused) { itv->DSGarray[x].size = mem_size; } else { itv->DSGarray[x].size = buf->buffer.bytesused; } #else /* just send the whole buffer */ itv->DSGarray[x].size = buf->buffer.bytesused; #endif buf->dma_handle = pci_map_single(itv->dev, (void *)(buf->buffer.m.userptr + buf->readpos), itv->DSGarray[x].size, PCI_DMA_TODEVICE); itv->DSGarray[x].src = buf->dma_handle; itv->DSGarray[x].dst = (mem_offset + bytes_written + IVTV_FIRM_SEARCH_DECODER_START); buf->readpos += itv->DSGarray[x].size; bytes_written += itv->DSGarray[x].size; buf->buffer.bytesused -= itv->DSGarray[x].size; IVTV_DEBUG(IVTV_DEBUG_INFO, "1st 32bits of buffer %d are 0x%08x\n", buf->buffer.index, *(u32 *)buf->buffer.m.userptr); IVTV_DEBUG(IVTV_DEBUG_INFO, "DSGarray[%d]: 0x%08x, 0x%08x 0x%08x\n", x, itv->DSGarray[x].src, itv->DSGarray[x].dst, itv->DSGarray[x].size); /* buffer is empty? */ if (buf->buffer.bytesused == 0) { __ivtv_del_buf(&stream->full_q, buf); __ivtv_enq_buf(&stream->dma_q, buf); } x++; } if (x == 0) { /* no full buffers */ IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: Nothing to send\n"); set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); return; } //Set Last Element Bit itv->DSGarray[x-1].size |= 0x80000000; //Schedule DMA XFER data[0] = itv->DSG_handle; data[1] = bytes_written; data[2] = hw_stream_type; /* note that we're DMA'ing */ mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); set_bit(IVTV_F_S_DMAP, &stream->s_flags); set_bit(IVTV_F_I_BUSY, &itv->i_flags); ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_DMA_FROM_HOST, &result, 3, &data[0]); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sched DEC dma: addr: 0x%08x, array_size 0x%08x, type 0x%08x\n", data[0], data[1], data[2]); } static void ivtv_dec_DMA_done(struct ivtv *itv) { struct ivtv_v4l2_stream *stream=NULL; struct ivtv_buffer *buf; int y, stmtype=-1, freed=0; IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: DMA Done tasklet\n"); if (!test_and_clear_bit(IVTV_F_I_BUSY, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DMAP not set\n"); ivtv_show_debug_flags(itv); return; } #if 0 del_timer(&itv->dec_timeout); #else mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); #endif for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) { if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[y].s_flags)) { stmtype = y; break; } } /* Handle OSD DMA */ if (test_and_clear_bit(IVTV_F_I_OSD_DMA, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "OSD: DMA Done\n"); /* wake all the normal streams, in case they fell asleep */ for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) { wake_up(&itv->v4l2.streams[y].waitq); } wake_up(&itv->dec_master_w); return; } if (stmtype < 0) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: Got DMA-done, not expecting one\n"); ivtv_show_debug_flags(itv); return; } IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: Stream %d dma-done\n", y); stream = &itv->v4l2.streams[y]; while ((buf = __ivtv_deq_buf(&stream->dma_q)) != NULL) { IVTV_ASSERT(buf->dma_handle != IVTV_DMA_UNMAPPED); pci_unmap_single(itv->dev, buf->dma_handle, IVTV_DMA_DEC_BUF_SIZE, PCI_DMA_TODEVICE); buf->dma_handle = IVTV_DMA_UNMAPPED; buf->buffer.bytesused = 0; buf->readpos = 0; /* put in the 'done' queue */ __ivtv_enq_buf(&stream->free_q, buf); freed++; } /* if we put some buffers back in the free queue, kick off dma * scheduling if card was stopped due to overflow before */ if (freed && test_and_clear_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) ivtv_sched_DMA(itv); /* wake up queue filler */ wake_up(&stream->waitq); wake_up(&itv->dec_master_w); } int ivtv_get_timing_info(struct ivtv *itv, struct ivtv_ioctl_framesync *info) { u32 ret, result, data[IVTV_MBOX_MAX_DATA]; int suicidecounter = 0; memset(info, 0x00, sizeof(struct ivtv_ioctl_framesync)); /* Occasionally, we'll get a wierd, invalid number for * frames played. fortunately, it sets the SCR timestamp to 0 * in that case, which it never is otherwise. cool, huh */ while (info->scr == 0) { /* eliminate bogus values, FIXME ugly */ ret = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_TIMING_INFO,&result,0,&data[0]); if (ret) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: err sending timing info\n"); return ret; } info->frame = data[0]; info->pts = ((u64)data[2] << 32) | (u64)data[1]; info->scr = ((u64)data[4] << 32) | (u64)data[3]; if (suicidecounter++ > 10) { /* endless loops are bad! */ IVTV_DEBUG(IVTV_DEBUG_ERR,"Timeout getting frames played\n"); return -1; } if (info->scr == 0) ivtv_sleep_timeout(HZ/50); } return 0; } ssize_t ivtv_write(struct ivtv_open_id *id, const char *ubuf, size_t count) { int bytes_written=0, ret; unsigned long flags; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_write\n"); while (bytes_written < count) { /* completely use up user data * before returning */ /* buffer the data - this may block waiting on free buffers */ ret = ivtv_fill_dec_buffers(id, ubuf + bytes_written, (count - bytes_written)); if (ret < 0) { break; } else { bytes_written += ret; } /* send it! it'll return right away if no data needed */ spin_lock_irqsave(&id->itv->lock, flags); ivtv_dec_sched_DMA(id->itv); spin_unlock_irqrestore(&id->itv->lock, flags); } IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: returning %d\n", bytes_written); return bytes_written; } unsigned int ivtv_dec_poll(struct file *filp, poll_table *wait) { struct ivtv_open_id *id = filp->private_data; unsigned int mask = 0; /* add stream's waitq to the poll list */ poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait); #if 0 if (down_interruptible(&id->itv->sem_lock)) return -ERESTARTSYS; if (ivtv_get_free_elements(id->itv, &id->itv->v4l2.streams[id->type].free_q)) mask |= POLLOUT | POLLWRNORM; /* Writable */ up(&id->itv->sem_lock); #else mask |= POLLOUT | POLLWRNORM; #endif return mask; } unsigned int ivtv_poll(struct file *filp, poll_table *wait) { struct ivtv_open_id *id = filp->private_data; unsigned int mask = 0; /* add stream's waitq to the poll list */ poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait); #if 0 if (down_interruptible(&id->itv->sem_lock)) return -ERESTARTSYS; if (ivtv_get_free_elements(id->itv, &id->itv->v4l2.streams[id->type].full_q)) mask |= POLLIN | POLLRDNORM; /* readable */ up(&id->itv->sem_lock); #else mask |= POLLIN | POLLRDNORM; #endif return mask; } #if 0 static void ivtv_print_boxes(struct ivtv_mailbox *mbox) { int x,y; IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); ivtv_sleep_timeout(HZ/100); if (NULL == mbox) { IVTV_DEBUG(IVTV_DEBUG_IOCTL, "Mailboxes not initialized!\n"); return; } for (x = 0; x <= IVTV_MBOX_MAX_BOXES; x++) { IVTV_DEBUG(IVTV_DEBUG_IOCTL, "mbox: 0x%08x, # %d\n", (u32)mbox, x); IVTV_DEBUG(IVTV_DEBUG_IOCTL, "flags: 0x%08x ",(u32)readl(&mbox->flags)); IVTV_DEBUG(IVTV_DEBUG_IOCTL, "cmd: 0x%08x\n", readl(&mbox->cmd)); IVTV_DEBUG(IVTV_DEBUG_IOCTL, "result: 0x%08x ", readl(&mbox->retval)); IVTV_DEBUG(IVTV_DEBUG_IOCTL, "timeout: 0x%08x\n", readl(&mbox->timeout)); IVTV_DEBUG(IVTV_DEBUG_IOCTL, "Data:\n"); for (y = 0; y < IVTV_MBOX_MAX_DATA; y++) { IVTV_DEBUG(IVTV_DEBUG_IOCTL, "[%02d]0x%08x, ", y, readl(&mbox->data[y])); if (2 == y%3) IVTV_DEBUG(IVTV_DEBUG_IOCTL, "\n"); } /*Since mbox has type ptr, this should step it up*/ /* to the start of the next mbox */ mbox++; IVTV_DEBUG(IVTV_DEBUG_IOCTL, "\n"); } } #endif int ivtv_close(struct ivtv_open_id *id) { struct ivtv *itv=id->itv; /* sem_lock must be held */ IVTV_ASSERT(ivtv_sem_count(&itv->sem_lock) <= 0); if( (id->type != IVTV_DEC_STREAM_TYPE_MPG) && (id->type != IVTV_DEC_STREAM_TYPE_YUV)) { if (atomic_read(&itv->capturing)) { atomic_dec(&itv->capturing); return ivtv_stop_capture(id); } } if( (id->type == IVTV_DEC_STREAM_TYPE_MPG) || (id->type == IVTV_DEC_STREAM_TYPE_YUV)) { if (atomic_read(&itv->decoding)) { atomic_dec(&itv->decoding); return ivtv_stop_decode(id); } } return 0; } static int module_start(void) { int loop_a; printk("ivtv: version %s (%s) loading\n", IVTV_VERSION_STRING(ivtv_rev), IVTV_VERSION_COMMENT(ivtv_rev)); memset(ivtv_cards, 0, sizeof(ivtv_cards)); /* Validate parameters */ if (((yuv_buffers > IVTV_MAX_YUV_BUFFERS) || (yuv_buffers < IVTV_MIN_YUV_BUFFERS)) && (yuv_buffers != 0)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! yuv_buffers must be between 40 and 500\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } #ifdef YUV_FIXUP if ((yuv_fixup != 0) && (yuv_fixup != 1)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! yuv_fixup must be 0 or 1\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } #endif if ((dec_mpg_buffers > IVTV_MAX_DEC_MPG_BUFFERS) || (dec_mpg_buffers < IVTV_MIN_DEC_MPG_BUFFERS)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! dec_mpg_buffers must be between 5 and 100\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } if (((dec_yuv_buffers > IVTV_MAX_DEC_YUV_BUFFERS) || (dec_yuv_buffers < IVTV_MIN_DEC_YUV_BUFFERS)) && (dec_yuv_buffers != 0)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! dec_yuv_buffers must be between 17 and 500\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } if ((mpg_buffers > IVTV_MAX_MPG_BUFFERS) || (mpg_buffers < IVTV_MIN_MPG_BUFFERS)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! mpg_buffers must be between 15 and 100\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } if ((dec_yuv_qlen > dec_yuv_buffers) || (dec_yuv_qlen < IVTV_MIN_DEC_YUV_QLEN)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! dec_yuv_qlen must be between %d and %d\n", IVTV_MIN_DEC_YUV_QLEN, dec_yuv_buffers); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } if ((dec_mpg_qlen > dec_mpg_buffers) || (dec_mpg_qlen < IVTV_MIN_DEC_MPG_QLEN)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! dec_mpg_qlen must be between %d and %d\n", IVTV_MIN_DEC_MPG_QLEN, dec_mpg_buffers); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } if ((vbi_buffers > IVTV_MAX_VBI_BUFFERS) || (vbi_buffers < IVTV_MIN_VBI_BUFFERS)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! vbi_buffers must be between 3 and 100\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } if ((num_devices > IVTV_MAX_CARDS) || (num_devices < 1)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error! num_devices must be between 1 and 9 (not working yet)\n"); IVTV_DEBUG(IVTV_DEBUG_ERR, "Exiting..\n"); return -1; } if (ivtv_debug < 0) IVTV_DEBUG(IVTV_DEBUG_ERR, "debug value must be >= 0!\n"); IVTV_DEBUG(IVTV_DEBUG_INFO, "Loading, I'll try to detect %d devices!\n", num_devices); IVTV_DEBUG(IVTV_DEBUG_INFO, " .. running on kernel %s\n", UTS_RELEASE); IVTV_DEBUG(IVTV_DEBUG_INFO, "Setting some variables to invalid for detection\n"); for (loop_a = 0; loop_a < IVTV_MAX_CARDS; loop_a++) { ivtv_cards[loop_a].num = -1; ivtv_cards[loop_a].dev = NULL; } SGarray_size = (mpg_buffers + yuv_buffers + vbi_buffers) * 2; DSGarray_size = (dec_mpg_buffers + dec_yuv_buffers) * 2; IVTV_DEBUG(IVTV_DEBUG_ERR, "SGarray_size = %d, DSGarray_size = %d\n", SGarray_size, DSGarray_size); IVTV_DEBUG(IVTV_DEBUG_INFO, "Scanning PCI bus..\n"); if (pci_module_init(&ivtv_pci_driver)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error detecting PCI card\n"); return -ENODEV; } printk("ivtv: loaded\n"); return 0; } static void module_cleanup(void) { pci_unregister_driver(&ivtv_pci_driver); IVTV_DEBUG(IVTV_DEBUG_ERR, "You've not seen the last of willy!\n"); #ifdef AEW_DEBUG DUMP_BAD_ALLOC_TABLE; #endif // AEW_DEBUG } module_init(module_start); module_exit(module_cleanup);