/*************************************************************************** * exit_zion_dmaif **************************************************************************/ void exit_zion_dmaif(void) { zion_params_t *zion_params; PINFO("Cleanup ZION DMAIF module ..."); /* get ZION parameters */ zion_params = find_zion (0); if (zion_params == NULL) { return; } /* Check Fireball */ if((zion_params->revision & 0xF000) == 0xF000) { return; } /* Disable backend interrupts */ mbus_writew(0, MBUS_ADDR(zion_params, ZION_MBUS_INTGEN_B)); /* INT Gen B Enable */ zion_disable_mbus_interrupt(zion_params, Dmaif_Int); mbus_writew(0, MBUS_ADDR(zion_params, ZION_MBUS_IOSEL)); /* DMA select */ free_zion_dmaif_private_space(ZION_DMAIF_PARAM (zion_params)); PINFO( "done.\n" ); return; }
void zion_audio_proc_event(zion_params_t *zion_params, int bit, int irq, void *dev_id, u16 pci_status) { u16 int_status_12; u16 int_status_34; /* Read Interrupt Status */ int_status_12 = mbus_readw(MBUS_ADDR(zion_params, DMA12_Interrupt_Status)); int_status_34 = mbus_readw(MBUS_ADDR(zion_params, DMA34_Interrupt_Status)); /* Memorize it ! */ zion_params->interrupt_bits.AUDIO_INT[0] |= int_status_12; zion_params->interrupt_bits.AUDIO_INT[1] |= int_status_34; /* Do Nothing Now... */ /* Clear them */ if(int_status_12) { mbus_writew(int_status_12, MBUS_ADDR(zion_params, DMA12_Interrupt_Clear)); } if(int_status_34) { mbus_writew(int_status_34, MBUS_ADDR(zion_params, DMA34_Interrupt_Clear)); } zion_mbus_int_clear(zion_params, AudioProc_Int); return; }
static int zionvga_image_reflection(int frame) { u16 reg; zion_params_t *params = find_zion(0); if(params == NULL){ return -ENODEV; } reg = mbus_readw(MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); if(frame==0) { reg &= ~(VGA_SEL); } else { reg |= VGA_SEL; } //reg |= (VGA_RSTR_EN|CSC_EN|TRS_ON); #if defined(CONFIG_P2PF_K240) || defined(CONFIG_P2PF_K202) || defined(CONFIG_P2PF_K246A) reg |= (CSC_EN); #else reg |= (CSC_EN|TRS_ON); //VGA_RSTR_EN is supporsed to be set by TX #endif //CONFIG_P2PF_K240 || CONFIG_P2PF_K246A mbus_writew(reg, MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); //Just for assurance reg = mbus_readw(MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); return 0; }
/*************************************************************************** * zion_edma_get_region * @func * Get EDMA buffer addresses * @args * zion_params_t *params [in]: parameters of ZION driver * int dma_ch [in]: channel * int num [in]: buffer number * unsigned long *lower [out]: lower address * unsigned long *upper [out]: upper address * @return * int * 0 : success * -EINVAL : invalid argument * @comment * static function * @author * H. Hoshino **************************************************************************/ static int zion_edma_get_region(zion_params_t * params, int dma_ch, int num, unsigned long *lower, unsigned long *upper) { unsigned short tlower = 0; /* Check channel number */ if (dma_ch >= ZION_EDMA_NR_CH) { PERROR("Invalid EDMA Channel.\n"); return (-EINVAL); } /* Get addresses */ tlower = mbus_readw(MBUS_ADDR(params, ZION_MBUS_EDMA_BUFF_LWR_ADRS(dma_ch, num))); *upper = mbus_readl(MBUS_ADDR(params, ZION_MBUS_EDMA_BUFF_UPR_ADRS(dma_ch, num))); *lower = (unsigned long)( (tlower << 16) & 0x07FF0000L ); /* for DEBUG */ PDEBUG( "[CH%d Buf%d] lower: 0x%08lX, tlower: 0x%04X, upper: 0x%08lX\n", dma_ch, num, *lower, tlower, *upper ); return (0); }
/*************************************************************************** * init_zion_dmaif **************************************************************************/ int init_zion_dmaif(void) { zion_params_t *zion_params; int ret, i; /* get ZION parameters */ zion_params = find_zion(0); if (zion_params == NULL) { return -ENODEV; } /* Check Fireball */ if((zion_params->revision & 0xF000) == 0xF000) { PINFO("This is fireball! ZION DMA IF cannot be used!!\n"); return 0; } /* register fuctions for operation */ for (i = 0; i < ZION_EDMA_PORT; i++) { zion_params->zion_operations[ZION_DMAIF + i] = &zion_dmaif_port_fops; } /* Set Private Data Area */ zion_params->zion_private[ZION_DMAIF] = kmalloc(sizeof(zion_dmaif_params_t), GFP_KERNEL); if (ZION_DMAIF_PARAM(zion_params) == NULL) { PERROR ("Can't get enough space for private data.\n"); return -ENOMEM; } initialize_zion_dmaif_private_space(ZION_DMAIF_PARAM (zion_params)); #ifndef NEO_DEBUG PINFO("ZION DMAIF(EDMA) module ver. %d.%d Installed.\n", DMAIF_MAJORVER, DMAIF_MINORVER); #else /* NEO_DEBUG */ PINFO("ZION DMAIF(EDMA) module ver. %d.%d-DEBUG Installed.\n", DMAIF_MAJORVER, DMAIF_MINORVER); #endif /* !NEO_DEBUG */ /* enable interruption */ mbus_writew(ZION_MBUS_DMASEL_ENB, MBUS_ADDR(zion_params, ZION_MBUS_IOSEL)); /* DMA select */ ret = zion_enable_mbus_interrupt(zion_params, Dmaif_Int, zion_dmaif_event); if (ret) { PERROR ("registering interruption failed.\n"); return -EINVAL; } mbus_writew(ZION_MBUS_INTGB_MPU1ENB, MBUS_ADDR(zion_params, ZION_MBUS_INTGEN_B)); /* INT Gen B Enable */ return 0; }
void debug_print_stts( zion_params_t *params, int ch, char *str ) { unsigned short edma_stts = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_EDMA_STATE(ch)) ); unsigned char sbus_stts = mbus_readb( MBUS_ADDR(params, (ZION_MBUS_EDMA_INT_SBUS_STATE(ch)+1)) ); /* unsigned short sbus_stts */ /* = mbus_readw( MBUS_ADDR(params, (ZION_MBUS_EDMA_INT_SBUS_STATE(ch))) ); */ PDEBUG( "%sCH%d EDMA state: 0x%04X, SBUS state: 0x%02X\n", str, ch ,edma_stts, sbus_stts ); }
static int zionvga_rstr_enable(void) { u16 reg; zion_params_t *params = find_zion(0); if(params == NULL){ return -ENODEV; } reg = mbus_readw(MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); reg |= VGA_RSTR_EN; mbus_writew(reg, MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); reg = mbus_readw(MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); //Just for assurance return 0; }
int zion_common_init(void) { zion_params_t *zion_params; struct proc_dir_entry *pentry; zion_params = find_zion(0); if(zion_params==NULL) { PERROR("ZION : not found\n"); return -ENODEV; } zion_params->zion_operations[ZION_COMMON]=&zion_common_fops; /* Make proc Entry */ pentry = create_proc_entry("zion/pcicreg",0,0); if(pentry) { pentry->read_proc = zion_proc_read; } if(1) { u16 revision = mbus_readw(MBUS_ADDR(zion_params,0)); zion_params->revision = revision; PINFO("ZION detected (Rev. %04X):\n" " Driver(Common Part): Version %s.%s.%s\n", revision, ZIONDRV_MAJOR_VER, ZIONDRV_MINOR_VER, ZIONDRV_PATCH_LEV); } return 0; }
void debug_print_debugstts( zion_params_t *params, int ch, char *str ) { unsigned short extmode = 0; int itr = 0; for ( itr = 0; itr < 3; ++itr ) { /* Disable TestEn all channel */ mbus_writew( 0, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(itr)) ); } /* Test mode 2 */ mbus_writeb( 0x21, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)+1) ); extmode = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)) ); PDEBUG( "%sCH%d ExtMode mode 2: 0x%04X\n", str, ch, extmode ); /* Test mode 5 */ mbus_writeb( 0x51, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)+1) ); extmode = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)) ); PDEBUG( "%sCH%d ExtMode mode 5: 0x%04X\n", str, ch, extmode ); /* Test mode 6 */ mbus_writeb( 0x61, MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)+1) ); extmode = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_EXT_MODE(ch)) ); PDEBUG( "%sCH%d ExtMode mode 6: 0x%04X\n", str, ch, extmode ); }
/*************************************************************************** * zion_edma_timeout * @func * Timedout function of ZION-NEO EDMA * @args * unsigned long *prms [in/out]: parameters of ZION driver * @return * void * @comment * static function * @author * H. Hoshino **************************************************************************/ static void zion_edma_timeout(unsigned long prms) { zion_params_t *params = (zion_params_t *)prms; int ch = 0; zion_edma_params_t *edma_prms = NULL; /* Check argument */ if (NULL == params) { PERROR("Invalid ZION parameters!\n"); return; } /* Print error message */ PERROR("Timedout occured!\n"); for (ch = 0; ch < ZION_EDMA_NR_CH; ++ch) { /* Get EDMA parameters */ edma_prms = &(ZION_DMAIF_PARAM(params)->port_params[ZION_EDMA_DMA_PORTNO(ch)]); /* Clear DMA command */ /* NOTE: Need not write 0 to DmaRun the case of SyncMode = 0 */ mbus_writew(0, MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch))); /* Clear interrupt status: DMA done */ mbus_writew(ZION_MBUS_EDMA_DMADONEINT, MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /* Wake up */ edma_prms->condition = ZION_DMAIF_DISPATCH_TIMEOUT; wake_up(&(edma_prms->zion_dmaif_wait_queue)); } /* for DEBUG XXX */ debug_print_debugstts( params, 0, "" ); debug_print_debugstts( params, 2, "" ); debug_print_stts( params, 0, "" ); debug_print_stts( params, 1, "" ); debug_print_stts( params, 2, "" ); }
/*************************************************************************** * zion_edma_set_region * @func * set EDMA buffer addresses * @args * zion_params_t *params [in]: parameters of ZION driver * int dma_ch [in]: channel * int num [in]: buffer number * unsigned long lower [in]: lower address * unsigned long upper [in]: upper address * @return * int * 0 : success * -EINVAL : invalid argument * @comment * static function * @author * H. Hoshino **************************************************************************/ static int zion_edma_set_region(zion_params_t * params, int dma_ch, int num, unsigned long lower, unsigned long upper) { unsigned short tlower = (unsigned short)( (lower&0x07FF0000L) >> 16 ); /* Check channel number */ if (dma_ch >= ZION_EDMA_NR_CH) { PERROR("Invalid EDMA Channel.\n"); return (-EINVAL); } /* for DEBUG */ PDEBUG( "[CH%d Buf%d] lower: 0x%08lX, tlower: 0x%04X, upper: 0x%08lX\n", dma_ch, num, lower, tlower, upper ); /* Set addresses */ mbus_writew(tlower, MBUS_ADDR(params, ZION_MBUS_EDMA_BUFF_LWR_ADRS(dma_ch, num))); mbus_writel(upper, MBUS_ADDR(params, ZION_MBUS_EDMA_BUFF_UPR_ADRS(dma_ch, num))); return (0); }
/*************************************************************************** * zion_dmaif_port_open **************************************************************************/ int zion_dmaif_port_open(zion_params_t * zion_params, struct inode *inode, struct file *filp) { int zion_minor = MINOR(inode->i_rdev); /* The case of EDMA port opened */ if (is_edma_port(zion_minor)) { int zion_edma_port = zion_minor - ZION_DMAIF; zion_edma_params_t *edma_prms = &(ZION_DMAIF_PARAM(zion_params)->port_params[zion_edma_port]); unsigned long irq_flags = 0; /* Spin lock */ spin_lock_irqsave( &(edma_prms->params_lock), irq_flags ); /* PDEBUG("EDMA port%d opened\n", zion_edma_port); */ /* Initialize EDMA parameters */ edma_prms->ch_no = (int)(zion_edma_port / ZION_EDMA_CH_PORT); edma_prms->condition = ZION_DMAIF_DISPATCH_PENDING; edma_prms->int_status = 0x0000; /* PDEBUG("Initialize EDMA CH%d\n", edma_prms->ch_no); */ /* Use private data of file structure */ filp->private_data = (void *)edma_prms; /* Clear DMA command register */ mbus_writeb( 0, MBUS_ADDR(zion_params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no)+1) ); /** Success **/ /* Unlock spin lock */ spin_unlock_irqrestore( &(edma_prms->params_lock), irq_flags ); // MOD_INC_USE_COUNT; return 0; } /** The case of NOT EDMA port opened **/ PERROR("Minor number is invalid(%d)!\n", zion_minor); return (-ENODEV); }
static int zionvga_init_phase(struct zionvga_phase_arg *phase) { zion_params_t *params = find_zion(0); unsigned short v_phase = phase->v_phase; unsigned short h_phase = phase->h_phase; if(params == NULL){ return -ENODEV; } mbus_writew(v_phase, MBUS_ADDR(params, ZIONVGA_VIDEO_V_PHASE)); mbus_writew(v_phase, MBUS_ADDR(params, ZIONVGA_SYSTEM_V_PHASE)); mbus_writew(h_phase, MBUS_ADDR(params, ZIONVGA_VIDEO_H_PHASE)); mbus_writew(h_phase, MBUS_ADDR(params, ZIONVGA_SYSTEM_H_PHASE)); // Just for Assurance v_phase = mbus_readw(MBUS_ADDR(params, ZIONVGA_VIDEO_V_PHASE)); v_phase = mbus_readw(MBUS_ADDR(params, ZIONVGA_SYSTEM_V_PHASE)); h_phase = mbus_readw(MBUS_ADDR(params, ZIONVGA_VIDEO_H_PHASE)); h_phase = mbus_readw(MBUS_ADDR(params, ZIONVGA_SYSTEM_H_PHASE)); return 0; }
/*************************************************************************** * zion_dmaif_port_ioctl **************************************************************************/ int zion_dmaif_port_ioctl(zion_params_t * params, struct inode *inode, struct file *file, unsigned int function, unsigned long arg) { switch (function) { case ZION_EDMA_IOC_OPEN: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; int rw = -1; unsigned long irq_flags = 0; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Get argument: I/O direction */ if (copy_from_user((void *)&rw, (void *)arg, sizeof(int))) return (-EFAULT); /* Check argument: I/O direction */ if ((ZION_EDMA_READ != rw) && (ZION_EDMA_WRITE != rw)) { PERROR("[CH%d] Invalid I/O direction(%d)!\n", ch, rw); return (-EINVAL); } /* Read EDMA command register */ ucReg = mbus_readb(MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Write EDMA command register: DmaOpen=1 */ ucReg |= (ZION_MBUS_EDMA_OPEN | (rw << 2)) & 0x0F; /* PDEBUG("[CH%d] EDMA open(0x%02X)\n", ch, ucReg); */ mbus_writeb(ucReg, MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Clear interrupt status */ spin_lock_irqsave( &(edma_prms->params_lock), irq_flags ); edma_prms->int_status = 0x0000; spin_unlock_irqrestore( &(edma_prms->params_lock), irq_flags ); break; } case ZION_EDMA_IOC_CLOSE: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Read EDMA command register */ ucReg = mbus_readb( MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); /* Write EDMA command register: DmaOpen=0 */ ucReg &= ZION_MBUS_EDMA_CLOSE & 0x0F; /* PDEBUG("[CH%d] EDMA close(0x%02X)\n", ch, ucReg); */ mbus_writeb( ucReg, MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); /* Success */ break; } case ZION_EDMA_IOC_RUN: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; unsigned short usCmdReg = 0; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Read EDMA command register */ ucReg = mbus_readb(MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Write EDMA command register: DmaRun=1 */ ucReg |= ZION_MBUS_EDMA_RUN; PDEBUG ("[CH%d] EDMA run(0x%02X)\n", ch, ucReg); mbus_writeb(ucReg, MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); #ifdef NEO_WRITEBACK /* for DEBUG -- write back XXX */ usCmdReg = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no)) ); /* PDEBUG( "[CH%d] Write back DMA RUN: 0x%04X\n", */ /* edma_prms->ch_no, usCmdReg ); */ #endif /* NEO_WRITEBACK */ /* Success */ break; } case ZION_EDMA_IOC_STOP: { unsigned char ucReg = 0; zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!\n"); return (-ENODEV); } /* Get and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Read EDMA command register */ ucReg = mbus_readb(MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Write EDMA command register: DmaRun=0 */ ucReg &= ZION_MBUS_EDMA_STOP & 0x0F; /* PDEBUG("[CH%d] EDMA stop(0x%02X)\n", ch, ucReg); */ mbus_writeb(ucReg, MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(ch) + 1)); /* Success */ break; } case ZION_EDMA_IOC_READ: { /* EDMA read */ return (zion_edma_run(params, inode, file, ZION_EDMA_READ)); } case ZION_EDMA_IOC_WRITE: { /* EDMA write */ return (zion_edma_run(params, inode, file, ZION_EDMA_WRITE)); } case ZION_EDMA_IOC_SET_REGION: { struct zion_edma_region s_zion_edma_region; if (copy_from_user((void *)&s_zion_edma_region, (void *)arg, sizeof(struct zion_edma_region))) return (-EFAULT); return zion_edma_set_region(params, s_zion_edma_region.dma_ch, s_zion_edma_region.num, s_zion_edma_region.lower, s_zion_edma_region.upper); } case ZION_EDMA_IOC_GET_REGION: { struct zion_edma_region s_zion_edma_region; if (copy_from_user((void *)&s_zion_edma_region, (void *)arg, sizeof(struct zion_edma_region))) return (-EFAULT); if (zion_edma_get_region(params, s_zion_edma_region.dma_ch, s_zion_edma_region.num, &s_zion_edma_region.lower, &s_zion_edma_region.upper)) return -EINVAL; if (copy_to_user((void *)arg, (void *)&s_zion_edma_region, sizeof(struct zion_edma_region))) return -EFAULT; /* Success */ break; } /* Get interrupt status for poll-select */ case ZION_EDMA_IOC_GET_INTSTTS: { zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; int ch = -1; unsigned long irq_flags = 0; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Invalid ZION EDMA parameters!\n"); return (-ENODEV); } /* Set and check EDMA channel number */ ch = edma_prms->ch_no; if (ch < 0 || ZION_EDMA_NR_CH <= ch) { PERROR("Invalid ZION EDMA channel number(%d)!", ch); return (-ENODEV); } /* Set interrupt status */ if (copy_to_user((void *)arg, (void *)&(edma_prms->int_status), sizeof(unsigned short))) return (-EFAULT); /* Clear interrupt status */ spin_lock_irqsave( &(edma_prms->params_lock), irq_flags ); edma_prms->int_status = 0x0000; spin_unlock_irqrestore( &(edma_prms->params_lock), irq_flags ); /* Success */ break; } default: PERROR("No such Ioctl command!\n"); return (-EINVAL); } /* The end of SWITCH(function) */ return 0; }
/*************************************************************************** * zion_edma_run * @func * Run ZION-NEO EDMA * @args * zion_params_t *params [in/out]: parameters of ZION driver * struct inode *inode [in] : inode * struct file *file [in] : file structure * int rw [in] : command * @return * int * 0 : success * < 0 : error * @comment * * @author * H. Hoshino **************************************************************************/ static int zion_edma_run(zion_params_t * params, struct inode *inode, struct file *file, int rw) { unsigned char ucDmaWnR = 0; #ifdef NEO_WRITEBACK unsigned short usCmdReg = 0; #endif /* NEO_WRITEBACK */ /* Get minor number */ int zion_minor = MINOR(inode->i_rdev); /* Get EDMA parameters */ zion_edma_params_t *edma_prms = (zion_edma_params_t *)file->private_data; /* Check EDMA parameters */ if (NULL == edma_prms) { PERROR("Private data is NULL!(minor:%d)\n", zion_minor); return (-ENODEV); } /* Check argument: rw and set DMA I/O direction */ switch (rw) { case ZION_EDMA_READ: /* for DEBUG */ /* PDEBUG("[CH%d minor%d]EDMA read\n", edma_prms->ch_no, zion_minor); */ ucDmaWnR = ZION_MBUS_EDMA_READ; break; case ZION_EDMA_WRITE: /* for DEBUG */ /* PDEBUG("[CH%d minor%d]EDMA write\n", edma_prms->ch_no, zion_minor); */ ucDmaWnR = ZION_MBUS_EDMA_WRITE; break; default: PERROR("[CH%d minor%d]Invalid I/O direction!(%d)\n", edma_prms->ch_no, zion_minor, rw); return (-EINVAL); } /* end of switch (rw) */ /* Set condition */ edma_prms->condition = ZION_DMAIF_DISPATCH_PENDING; /* Set timed out */ init_timer(&(edma_prms->timer)); edma_prms->timer.function = zion_edma_timeout; edma_prms->timer.data = (unsigned long)params; edma_prms->timer.expires = jiffies + ZION_DMAIF_TIMEOUT; add_timer(&(edma_prms->timer)); /* DMA Run */ mbus_writeb( ((ucDmaWnR | ZION_MBUS_EDMA_RUN | ZION_MBUS_EDMA_OPEN) & 0x0F), MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no) + 1)); #ifdef NEO_WRITEBACK /* for DEBUG -- write back XXX */ usCmdReg = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_DMACMD(edma_prms->ch_no)) ); /* PDEBUG( "[CH%d minor%d] Write back DMA RUN: 0x%04X\n", */ /* edma_prms->ch_no, zion_minor, usCmdReg ); */ #endif /* NEO_WRITEBACK */ /* Sleep */ wait_event(edma_prms->zion_dmaif_wait_queue, (edma_prms->condition != ZION_DMAIF_DISPATCH_PENDING)); /* DMA End -- check timedout */ if (ZION_DMAIF_DISPATCH_TIMEOUT == edma_prms->condition) { PERROR("[CH%d minor%d]ZION EDMA Write Timedout!\n", edma_prms->ch_no, zion_minor); /* for DEBUG XXX */ debug_print_debugstts( params, 0, "" ); debug_print_debugstts( params, 2, "" ); debug_print_stts( params, 0, "" ); debug_print_stts( params, 1, "" ); debug_print_stts( params, 2, "" ); return (-ETIME); } /* Success */ return (0); }
static int zion_common_ioctl(zion_params_t *zion_params, struct inode *inode, struct file *filp, unsigned int function, unsigned long arg) { struct zion_config_byte zion_config_byte = {0}; struct zion_config_word zion_config_word = {0}; struct zion_config_dword zion_config_dword = {0}; struct zion_buf zion_buf; struct ZION_Interrupt_Bits zion_interrupt = {0}; u16 revision; switch(function) { case ZION_MBUS_READ_CONFIG_BYTE: if(copy_from_user((void *)&zion_config_byte, (void *)arg, sizeof(struct zion_config_byte))) return -EFAULT; zion_config_byte.val = (u8) mbus_readb( MBUS_ADDR(zion_params, zion_config_byte.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_byte, sizeof(struct zion_config_byte))) return -EFAULT; break; case ZION_MBUS_READ_CONFIG_WORD: if(copy_from_user((void *)&zion_config_word, (void *)arg, sizeof(struct zion_config_word))) return -EFAULT; zion_config_word.val = (u16) mbus_readw( MBUS_ADDR(zion_params,zion_config_word.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_word, sizeof(struct zion_config_word))) return -EFAULT; break; case ZION_MBUS_READ_CONFIG_DWORD: if(copy_from_user((void *)&zion_config_dword, (void *)arg, sizeof(struct zion_config_dword))) return -EFAULT; zion_config_dword.val = (u32) mbus_readl( MBUS_ADDR(zion_params,zion_config_dword.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_dword, sizeof(struct zion_config_dword))) return -EFAULT; break; case ZION_MBUS_WRITE_CONFIG_BYTE: if(copy_from_user((void *)&zion_config_byte, (void *)arg, sizeof(struct zion_config_byte))) return -EFAULT; mbus_writeb(zion_config_byte.val, MBUS_ADDR(zion_params, zion_config_byte.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_byte, sizeof(struct zion_config_byte))) return -EFAULT; break; case ZION_MBUS_WRITE_CONFIG_WORD: if(copy_from_user((void *)&zion_config_word, (void *)arg, sizeof(struct zion_config_word))) return -EFAULT; mbus_writew(zion_config_word.val, MBUS_ADDR(zion_params, zion_config_word.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_word, sizeof(struct zion_config_word))) return -EFAULT; break; case ZION_MBUS_WRITE_CONFIG_DWORD: if(copy_from_user((void *)&zion_config_dword, (void *)arg, sizeof(struct zion_config_dword))) return -EFAULT; mbus_writel(zion_config_dword.val, MBUS_ADDR(zion_params, zion_config_dword.where) ); if(copy_to_user((void *)arg, (void *)&zion_config_dword, sizeof(struct zion_config_dword))) return -EFAULT; break; case ZION_WRAM_READ: if(copy_from_user((void *)&zion_buf, (void *)arg, sizeof(struct zion_buf))) return -EFAULT; if((zion_buf.size = neo_wram_pio_read(zion_params, zion_buf.addr, zion_buf.buf, zion_buf.size, zion_buf.access_type))==0) return -EINVAL; if(copy_to_user((void *)arg, (void *)&zion_buf, sizeof(struct zion_buf))) return -EFAULT; break; case ZION_WRAM_WRITE: if(copy_from_user((void *)&zion_buf, (void *)arg, sizeof(struct zion_buf))) return -EFAULT; if((zion_buf.size = neo_wram_pio_write(zion_params, zion_buf.addr, zion_buf.buf, zion_buf.size, zion_buf.access_type))==0) return -EINVAL; if(copy_to_user((void *)arg, (void *)&zion_buf, sizeof(struct zion_buf))) return -EFAULT; break; case ZION_WAIT_INTERRUPT: zion_goto_bed(zion_params, &zion_interrupt); /* zion_interrupt.c */ if(copy_to_user((void *)arg, (void *)&zion_interrupt, sizeof(struct ZION_Interrupt_Bits))) return -EFAULT; break; case ZION_WAKE_THREADS_UP: zion_rout_them_up(zion_params); /* zion_interrupt.c */ break; case ZION_SET_ENABLE_BITS: if(copy_from_user((void *)&zion_interrupt, (void *)arg, sizeof(struct ZION_Interrupt_Bits))) return -EFAULT; zion_set_enable_bits(zion_params, &zion_interrupt); /* zion_interrupt.c */ break; case ZION_GET_ENABLE_BITS: zion_get_enable_bits(zion_params, &zion_interrupt); /* zion_interrupt.c */ if(copy_to_user((void *)arg, (void *)&zion_interrupt, sizeof(struct ZION_Interrupt_Bits))) return -EFAULT; break; case ZION_SET_TIMEOUT: zion_params->wait_timeout = arg; /* by jiffies */ break; case ZION_GET_REVISION: revision = zion_params->revision; if(copy_to_user((void *)arg, (void *)&revision, sizeof(u16))) { return -EFAULT; } break; default: PERROR("No such IOCTL.\n"); return -EINVAL; } return 0; }
int init_zion_vga(void) { int ret; zion_params_t *params = find_zion(0); u32 off_addr; if(params == NULL){ return -ENODEV; } PINFO("ZION VGA Frame Buffer Driver Installed.\n"); PDEBUG("compiled "__DATE__" "__TIME__"\n"); //Check Fireball if((params->revision & 0xF000) == 0xF000){ PINFO("This is fireball! ZION VGA cannot be used!!\n"); return 0; } #ifdef CONFIG_ZION_FB_SETUP PINFO("Setting FB Address ... %p and %p\n", (void *)CONFIG_ZION_FB_FIRST_ADDR, (void *)CONFIG_ZION_FB_SECOND_ADDR); mbus_writel(CONFIG_ZION_FB_FIRST_ADDR, MBUS_ADDR(params,ZIONVGA_BUFFER_BASE_ADDRESS_0)); mbus_writel(CONFIG_ZION_FB_SECOND_ADDR, MBUS_ADDR(params,ZIONVGA_BUFFER_BASE_ADDRESS_1)); #endif //CONFIG_ZION_FB_SETUP //Get VGA FB Region off_addr = mbus_readl(MBUS_ADDR(params, ZIONVGA_BUFFER_BASE_ADDRESS_0)); dma_direction[0] = params->whole_sdram_addr + off_addr; PINFO("FB1_BUS_ADDR:%p\n",(void *)dma_direction[0]); off_addr = mbus_readl(MBUS_ADDR(params, ZIONVGA_BUFFER_BASE_ADDRESS_1)); dma_direction[1] = params->whole_sdram_addr + off_addr; PINFO("FB2_BUS_ADDR:%p\n",(void *)dma_direction[1]); memset(&zion_fb_info, 0, sizeof(struct zion_vga_info)); zion_fb_info.ram_address = (unsigned long)__get_free_pages(GFP_KERNEL | __GFP_DMA, ZIONVGA_VRAM_ORDER); if(!zion_fb_info.ram_address){ PERROR("failed get_free_pages(): ram_address\n"); ret = -ENOMEM; goto fail_gfp_fb; } memset((void *)zion_fb_info.ram_address, 0, ZIONVGA_VRAM_SIZE); PDEBUG("ram_address = 0x%08lx (virtual)\n", (unsigned long)zion_fb_info.ram_address); PDEBUG("ram_address = 0x%08lx (physical)\n", virt_to_bus((void *)zion_fb_info.ram_address)); zion_fb_info.fb_info.screen_base = (void __iomem *)zion_fb_info.ram_address; zion_fb_info.fb_info.fbops = &zion_vga_ops; //setup var_screen_info zionvga_encode_var(&default_var); zion_fb_info.fb_info.var = default_var; zionvga_encode_fix(&zion_fb_info.fb_info.fix); zion_fb_info.fb_info.par = &zion_current_par; // This should give a reasonable default video mode ret = fb_alloc_cmap(&zion_fb_info.fb_info.cmap, 256, 0); if(ret){ PERROR( "failed fb_alloc_cmap()\n" ); ret = -ENOMEM; goto fail_alloc_cmap; } if(register_framebuffer(&zion_fb_info.fb_info) < 0){ PERROR("failed register_framebuffer()\n"); ret = -EINVAL; goto fail_reg_fb; } PINFO("fb%d: %s frame buffer device\n", zion_fb_info.fb_info.node, zion_fb_info.fb_info.fix.id); return 0; fail_reg_fb: fb_dealloc_cmap( &zion_fb_info.fb_info.cmap); fail_alloc_cmap: free_pages(zion_fb_info.ram_address, ZIONVGA_VRAM_ORDER); fail_gfp_fb: return ret; }
int zion_set_params(struct zionvga_reset_arg *reset_arg) { u16 reg = 0; int pal_line = reset_arg->pal_line; int spl_line = reset_arg->spl_line; zion_params_t *params = find_zion(0); if(params == NULL){ return -ENODEV; } reg = mbus_readw(MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); reg &= VGA_RSTR_EN; //Don't touch VGA_RSTR_EN bit (It should be set by TX) if(pal_line==576) { reg |= PAL_LINE_SEL; ZIONVGA_Y_RES = 576; } else if(pal_line==480) { reg &= ~PAL_LINE_SEL; ZIONVGA_Y_RES = 480; } else { PERROR("Unsupported VGA SIZE : PAL-Line=%d",pal_line); return -EINVAL; } if(spl_line==720) { reg |= SPL_SEL; ZIONVGA_X_RES = 720; } else if(spl_line==640) { reg &= ~SPL_SEL; ZIONVGA_X_RES = 640; } else { PERROR("Unsupported VGA SIZE : SPL-Line=%d",spl_line); return -EINVAL; } #if defined(CONFIG_P2PF_K240) || defined(CONFIG_P2PF_K202) || defined(CONFIG_P2PF_K246A) reg |= (CSC_EN); #else reg |= (CSC_EN|TRS_ON); #endif //CONFIG_P2PF_K240 || CONFIG_P2PF_K246A mbus_writew(reg, MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); // Just for assurance reg = mbus_readw(MBUS_ADDR(params,ZIONVGA_VGA_SETTING)); zionvga_encode_var( &default_var ); zion_fb_info.fb_info.var = default_var; return 0; }
/*************************************************************************** * zion_dmaif_event * @func * Interruption handler for EDMA * @args * zion_params_t *params [in/out]: parameters of ZION driver * int irq [in] : IRQ number * void *dev_id [in] : Device ID * u16 pci_status[in] : PCI config interrupt status * @return * void * @comment * * @author * H. Hoshino **************************************************************************/ void zion_dmaif_event(zion_params_t * params, int bit, int irq, void *dev_id, u16 pci_status) { unsigned short int_status = 0; unsigned short int_mask = 0; int ch = 0; zion_edma_params_t *edma_prms = NULL; /*** Check EDMA interruption for each channel ***/ for (ch = 0; ch < ZION_EDMA_NR_CH; ++ch) { /* Get interrupt status and mask(enable) */ int_status = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_INTSTTS(ch)) ); int_mask = (unsigned short)mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_INTENB(ch)) ); /* Memorize it ! */ params->interrupt_bits.DMA_INT[ch] |= int_status; /* for DEBUG */ /* PDEBUG( "CH%d int_status: 0x%04X, mask: 0x%04X\n", */ /* ch, int_status, int_mask ); */ /** Check interruptions (Common port) **/ if ( int_status & int_mask ) { /* Get EDMA params */ edma_prms = &(ZION_DMAIF_PARAM(params)->port_params[ZION_EDMA_CMN_PORTNO(ch)]); /* for DEBUG */ /* PDEBUG( "[CH%d port%d] Get interruptions!\n", */ /* ch, ZION_EDMA_CMN_PORTNO(ch) ); */ if ( NULL == edma_prms ) { PERROR( "[CH%d port%d] EDMA params is NULL!!\n", ch, ZION_EDMA_CMN_PORTNO(ch) ); mbus_writew( (ZION_MBUS_EDMA_DMADONEINT | ZION_MBUS_EDMA_SYNCFRMINT | ZION_MBUS_EDMA_BUFFINT_MASK | ZION_MBUS_EDMA_ERRINT_MASK), MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /** Clear interrupt status INT B reg **/ zion_mbus_int_clear(params, Dmaif_Int); return; } /* Set interrupt status */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->int_status |= int_status; /* edma_prms->int_status = int_status; */ spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } /** Check sync frame pulse interruption **/ if ( int_status & int_mask & ZION_MBUS_EDMA_SYNCFRMINT ) { /* Get EDMA params */ edma_prms = &(ZION_DMAIF_PARAM(params)->port_params[ZION_EDMA_FRM_PORTNO(ch)]); /* for DEBUG */ /* PDEBUG( "[CH%d port%d] Sync frame pulse!\n", */ /* ch, ZION_EDMA_FRM_PORTNO(ch) ); */ /* Set interrupt status */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ if ( 0 == edma_prms->int_status ) { edma_prms->int_status = int_status; } else { /* PDEBUG( "[CH%d port%d] int_status is already set(0x%04X, 0x%04X)!\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch), edma_prms->int_status, int_status ); */ } spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Clear interrupt status: sync frame pulse */ mbus_writew(ZION_MBUS_EDMA_SYNCFRMINT, MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } /** Check DMA done interruption **/ if ( int_status & int_mask & ZION_MBUS_EDMA_DMADONEINT ) { /* Get EDMA params */ edma_prms = &(ZION_DMAIF_PARAM(params)->port_params[ZION_EDMA_DMA_PORTNO(ch)]); /* for DEBUG */ PDEBUG( "[CH%d port%d] DMA Done!\n", ch, ZION_EDMA_DMA_PORTNO(ch) ); /* PINFO( "[CH%d port%d] DMA Done!\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch) ); */ /* Stop DMA for G1&G2 transfer mode */ { unsigned char cmd = mbus_readb( MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); mbus_writeb( (cmd & (~0x02)), MBUS_ADDR(params, (ZION_MBUS_EDMA_DMACMD(ch)+1)) ); } /* for DEBUG XXX*/ /* { */ /* unsigned short usPMT = mbus_readw( MBUS_ADDR(params, ZION_MBUS_EDMA_CURRPMT(ch)) ); */ /* PDEBUG( "[CH%d port%d] CurrPMT: 0x%04X\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch), usPMT ); */ /* } */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ /* Set interrupt status */ /* PDEBUG( "[CH%d] int_status: 0x%04X, old: 0x%04X!\n", */ /* ch, int_status, edma_prms->int_status ); */ if ( 0 == edma_prms->int_status ) { edma_prms->int_status = int_status; } else { /* PDEBUG( "[CH%d port%d] int_status is already set(0x%04X, 0x%04X)!\n", */ /* ch, ZION_EDMA_DMA_PORTNO(ch), edma_prms->int_status, int_status ); */ } /* Delete timer */ del_timer_sync(&(edma_prms->timer)); spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Clear interrupt status: DMA done */ mbus_writew(ZION_MBUS_EDMA_DMADONEINT, MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } /** Check error and buffer empty/almost empty/almost full/full interruption **/ if ( int_status & int_mask & (ZION_MBUS_EDMA_BUFFINT_MASK | ZION_MBUS_EDMA_ERRINT_MASK) ) { /* Get EDMA parameters */ edma_prms = &(ZION_DMAIF_PARAM (params)->port_params[ZION_EDMA_BUF_PORTNO(ch)]); /* for DEBUG */ PDEBUG( "[CH%d port%d] Error or warning!\n", ch, ZION_EDMA_BUF_PORTNO(ch) ); /* Set interrupt status */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ /* PDEBUG( "[CH%d] int_status: 0x%04X, old: 0x%04X!\n", */ /* ch, int_status, edma_prms->int_status ); */ if ( 0 == edma_prms->int_status ) { edma_prms->int_status = int_status; } else { /* PDEBUG( "[CH%d port%d] int_status is already set(0x%04X, 0x%04X)!\n", */ /* ch, ZION_EDMA_BUF_PORTNO(ch), edma_prms->int_status, int_status ); */ } spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ /* Clear interrupt status */ mbus_writew((ZION_MBUS_EDMA_BUFFINT_MASK | ZION_MBUS_EDMA_ERRINT_MASK), MBUS_ADDR(params, ZION_MBUS_EDMA_INTCLR(ch))); /* Wake up */ spin_lock( &(edma_prms->params_lock) ); /* Spin lock */ edma_prms->condition = ZION_DMAIF_DISPATCH_DONE; spin_unlock( &(edma_prms->params_lock) ); /* Unlock spin lock */ wake_up(&(edma_prms->zion_dmaif_wait_queue)); } } /* The end of FOR(ch) */ /** Clear interrupt status INT B reg **/ zion_mbus_int_clear(params, Dmaif_Int); /* PDEBUG ("exit %s\n", __FUNCTION__); */ return; }
/** make proc filesystem **/ int zion_proc_read(char *buf, char **start, off_t offset, int length, int *eof, void *data) { zion_params_t *zion_params; int j; u32 val=0; u16 revision; int len=0; zion_params = find_zion(0); if(zion_params==NULL) { return 0; } revision = mbus_readw(MBUS_ADDR(zion_params,0)); len += sprintf(buf+len, "ZION (Rev. %04X):\n" " Base Address:\n" " MBusAddr=0x%X(%d byte) WorkRAM=0x%X(%d byte)\n" " SDRAM=0x%X(%d byte) Partial-SDRAM=0x%X(%d byte)\n" " Resources:\n" " Bus=%d Dev=%d Func=%d IRQ=%d\n" " Driver:\n" " Version: %s.%s.%s\n", revision, zion_params->mbus_addr, zion_params->mbus_size, zion_params->wram_addr, zion_params->wram_size, zion_params->whole_sdram_addr, zion_params->whole_sdram_size, zion_params->partial_sdram_addr, zion_params->partial_sdram_size, (zion_params->dev->bus)->number, (zion_params->dev->devfn) >> 3, (zion_params->dev->devfn) & 0x07,zion_params->dev->irq, ZIONDRV_MAJOR_VER, ZIONDRV_MINOR_VER, ZIONDRV_PATCH_LEV); len += sprintf(buf + len," (VENDOR_ID=%04X,", zion_params->dev->vendor); len += sprintf(buf + len," DEVICE_ID=%04X)\n", zion_params->dev->device); len+= sprintf(buf+len, " PCI Config Regs. : \n"); for (j = 0; j < 256; j += 4) { if ((j % 32) == 0) { len += sprintf(buf + len,"0x%02X : ", j); } pci_read_config_dword(zion_params->dev, j, &val); len += sprintf(buf + len,"%08X ", val); if ((j % 32) == 28) { len += sprintf(buf + len,"\n"); } } len -= offset; if(len < length) { *eof = 1; if(len <= 0) return 0; } else { len = length; } *start = buf + offset; return len; }