static int pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv) { int ret = 0; QDUMP("Waiting for free..."); /* Does not need to be atomic. There's a lock in user space, * but anyhow, this is just for statistics. */ priv->shared->num_wait_free++; while (!priv->free) { u32 rbexhr = gc_readl(priv, REG_GCRBEXHR); ret = wait_event_interruptible_timeout(priv->wait_free, priv->free, HZ*4); if (ret < 0) break; if (ret > 0) continue; if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) { QERROR("TIMEOUT"); ret = -ETIMEDOUT; break; } } QDUMP("done"); return ret; }
static int pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv) { int ret = 0; QDUMP("Waiting for idle..."); /* Does not need to be atomic. There's a lock in user space, * but anyhow, this is just for statistics. */ priv->shared->num_wait_idle++; while (priv->shared->hw_running) { int num = priv->shared->num_interrupts; u32 rbexhr = gc_readl(priv, REG_GCRBEXHR); ret = wait_event_interruptible_timeout(priv->wait_idle, !priv->shared->hw_running, HZ*4); if (ret != 0) break; if (gc_readl(priv, REG_GCRBEXHR) == rbexhr && priv->shared->num_interrupts == num) { QERROR("TIMEOUT"); ret = -ETIMEDOUT; break; } } QDUMP("done"); return ret; }
static int sh7722_wait_next( SH772xGfxSharedArea *shared ) { int ret; QDUMP( "Waiting....." ); /* Does not need to be atomic. There's a lock in user space, * but anyhow, this is just for statistics. */ shared->num_wait_next++; ret = wait_event_interruptible_timeout( wait_next, !shared->hw_running || shared->next_start == shared->next_end, 42*HZ ); if (!ret) { printk( KERN_ERR "%s: TIMEOUT! (%srunning, hw %d-%d, next %d-%d - %svalid, " "STATUS 0x%08x, INT_STATUS 0x%08x)\n", __FUNCTION__, shared->hw_running ? "" : "not ", shared->hw_start, shared->hw_end, shared->next_start, shared->next_end, shared->next_valid ? "" : "not ", BEM_HC_STATUS, BEM_HC_INT_STATUS ); } QDUMP( "........done" ); return (ret > 0) ? 0 : (ret < 0) ? ret : -ETIMEDOUT; }
static irqreturn_t pxa3xx_gcu_handle_irq(int irq, void *ctx) { struct pxa3xx_gcu_priv *priv = ctx; struct pxa3xx_gcu_shared *shared = priv->shared; u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL; QDUMP("-Interrupt"); if (!status) return IRQ_NONE; spin_lock(&priv->spinlock); shared->num_interrupts++; if (status & IE_EEOB) { QDUMP(" [EEOB]"); flush_running(priv); wake_up_all(&priv->wait_free); if (priv->ready) { run_ready(priv); } else { /* There is no more data prepared by the userspace. * Set hw_running = 0 and wait for the next userspace * kick-off */ shared->num_idle++; shared->hw_running = 0; QDUMP(" '-> Idle."); /* set ring buffer length to zero */ gc_writel(priv, REG_GCRBLR, 0); wake_up_all(&priv->wait_idle); } shared->num_done++; } else { QERROR(" [???]"); dump_whole_state(priv); } /* Clear the interrupt */ gc_writel(priv, REG_GCISCR, status); spin_unlock(&priv->spinlock); return IRQ_HANDLED; }
static void run_ready(struct pxa3xx_gcu_priv *priv) { unsigned int num = 0; struct pxa3xx_gcu_shared *shared = priv->shared; struct pxa3xx_gcu_batch *ready = priv->ready; QDUMP("Start"); BUG_ON(!ready); shared->buffer[num++] = 0x05000000; while (ready) { shared->buffer[num++] = 0x00000001; shared->buffer[num++] = ready->phys; ready = ready->next; } shared->buffer[num++] = 0x05000000; priv->running = priv->ready; priv->ready = priv->ready_last = NULL; gc_writel(priv, REG_GCRBLR, 0); shared->hw_running = 1; /* ring base address */ gc_writel(priv, REG_GCRBBR, shared->buffer_phys); /* ring tail address */ gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4); /* ring length */ gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4); }
static void pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv) { QDUMP("RESET"); /* disable interrupts */ gc_writel(priv, REG_GCIECR, 0); /* reset hardware */ gc_writel(priv, REG_GCCR, GCCR_ABORT); gc_writel(priv, REG_GCCR, 0); memset(priv->shared, 0, SHARED_SIZE); priv->shared->buffer_phys = priv->shared_phys; priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC; do_gettimeofday(&priv->base_time); /* set up the ring buffer pointers */ gc_writel(priv, REG_GCRBLR, 0); gc_writel(priv, REG_GCRBBR, priv->shared_phys); gc_writel(priv, REG_GCRBTR, priv->shared_phys); /* enable all IRQs except EOB */ gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB); }
void DHMWindow::onAddDAS(const QString &das) { QDUMP(das); if (dasset_.find(das) != dasset_.end()) { messages_->append(QString("%1 found in DHM list").arg(das)); return; } daslist_->addItem(das); dasset_.insert(das); messages_->append(QString("%1 inserted into DHM list").arg(das)); }
static void dump_whole_state(struct pxa3xx_gcu_priv *priv) { struct pxa3xx_gcu_shared *sh = priv->shared; u32 base = gc_readl(priv, REG_GCRBBR); QDUMP("DUMP"); printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n" "%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n", sh->hw_running ? "running" : "idle ", gc_readl(priv, REG_GCISCR), gc_readl(priv, REG_GCRBBR), gc_readl(priv, REG_GCRBLR), (gc_readl(priv, REG_GCRBEXHR) - base) / 4, (gc_readl(priv, REG_GCRBHR) - base) / 4, (gc_readl(priv, REG_GCRBTR) - base) / 4); }
void DHMWindow::onRemoveDAS(const QString &das) { QDUMP(das); if (dasset_.find(das) == dasset_.end()) { messages_->append(QString("%1 NOT found in DHM list").arg(das)); return; } QList<QListWidgetItem*> removelist = daslist_->findItems(das, Qt::MatchExactly); QList<QListWidgetItem*>::Iterator rit = removelist.begin(); QList<QListWidgetItem*>::Iterator ritend = removelist.end(); for ( ; rit != ritend; ++rit) { int row = daslist_->row(*rit); daslist_->takeItem(row); dasset_.remove(das); } messages_->append(QString("%1 removed from DHM list").arg(das)); }
static int sh7722_reset( SH772xGfxSharedArea *shared ) { int i; do_gettimeofday( &base_time ); QPRINT( "Resetting hardware..." ); BEM_HC_CLOCK = 0; for (i=0; i<30000; i++); BEM_HC_CLOCK = 0x1111; BEM_HC_RESET = 0x1111; for (i=0; i<30000; i++); BEM_HC_RESET = 0; QPRINT( "Initializing shared area..." ); memset( (void*) shared, 0, sizeof(SH772xGfxSharedArea) ); shared->buffer_phys = virt_to_phys(&shared->buffer[0]); shared->jpeg_phys = virt_to_phys(jpeg_area); shared->magic = SH7722GFX_SHARED_MAGIC; QPRINT( "Clearing interrupts..." ); BEM_HC_INT_CLEAR = 0x111111; BEM_HC_INT_MASK = 0x110011; BEM_HC_CACHE_FLUSH = 0; QDUMP( "Ready" ); return 0; }
void DHMWindow::onStatusMessage(const QString &message) { QDUMP(message); }
static irqreturn_t sh7722_tdg_irq( int irq, void *ctx ) { SH772xGfxSharedArea *shared = ctx; u32 status = BEM_HC_INT_STATUS; if (! (status & 0x111111)) { #ifndef SH7722GFX_IRQ_POLLER printk( KERN_WARNING "%s: bogus interrupt, INT_STATUS 0x%08x!\n", __FUNCTION__, status ); #endif return IRQ_NONE; } if (status & ~0x100) QDUMP( "-Interrupt" ); if (status & ~0x101100) printk( KERN_ERR "%s: error! INT_STATUS 0x%08x!\n", __FUNCTION__, status ); shared->num_interrupts++; /* Clear the interrupt. */ BEM_HC_INT_CLEAR = status; if (status & 0x100010) { if (!shared->hw_running) printk( KERN_WARNING "%s: hw not running? INT_STATUS 0x%08x!\n", __FUNCTION__, status ); if (status & 0x10) { printk( KERN_ERR "%s: RUNAWAY! (%srunning, hw %d-%d, next %d-%d - %svalid, " "STATUS 0x%08x, INT_STATUS 0x%08x)\n", __FUNCTION__, shared->hw_running ? "" : "not ", shared->hw_start, shared->hw_end, shared->next_start, shared->next_end, shared->next_valid ? "" : "not ", BEM_HC_STATUS, status ); BEM_HC_RESET = 0x1111; } /* Next valid means user space is not in the process of extending the buffer. */ if (shared->next_valid && shared->next_start != shared->next_end) { shared->hw_start = shared->next_start; shared->hw_end = shared->next_end; shared->next_start = shared->next_end = (shared->hw_end + 1 + 3) & ~3; shared->next_valid = 0; shared->num_words += shared->hw_end - shared->hw_start; shared->num_starts++; QDUMP( " '-> Start!" ); BEM_HC_DMA_ADR = shared->buffer_phys + shared->hw_start*4; BEM_HC_DMA_START = 1; wake_up_all( &wait_next ); } else { shared->num_idle++; QDUMP( " '-> Idle." ); BEM_PE_CACHE = 1; shared->hw_running = 0; wake_up_all( &wait_next ); wake_up_all( &wait_idle ); } shared->num_done++; } return IRQ_HANDLED; }