📄 sh7722gfx.c
字号:
/* * SH7722 Graphics Device * * Copyright (C) 2006-2007 IGEL Co.,Ltd * * Written by Denis Oliver Kropp <dok@directfb.org> * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License v2 * as published by the Free Software Foundation. */#include <linux/module.h>#include <linux/version.h>#include <linux/interrupt.h>#include <linux/miscdevice.h>#include <linux/mm.h>#include <linux/sched.h>#include <asm/io.h>#include <asm/uaccess.h>#include <sh7722gfx.h>//#define SH7722GFX_DEBUG//#define SH7722GFX_IRQ_POLLER/**********************************************************************************************************************/#define ENGINE_REG_TOP 0xfd000000#define SH7722_BEU_BASE 0xFE930000#define BEM_REG(x) (*(volatile u32*)((x)+ENGINE_REG_TOP))#define BEU_REG(x) (*(volatile u32*)((x)+SH7722_BEU_BASE))#define BEM_HC_STATUS BEM_REG(0x00000)#define BEM_HC_RESET BEM_REG(0x00004)#define BEM_HC_CLOCK BEM_REG(0x00008)#define BEM_HC_INT_STATUS BEM_REG(0x00020)#define BEM_HC_INT_MASK BEM_REG(0x00024)#define BEM_HC_INT_CLEAR BEM_REG(0x00028)#define BEM_HC_CACHE_FLUSH BEM_REG(0x0002C)#define BEM_HC_DMA_ADR BEM_REG(0x00040)#define BEM_HC_DMA_START BEM_REG(0x00044)#define BEM_HC_DMA_STOP BEM_REG(0x00048)#define BEM_PE_CACHE BEM_REG(0x010B0)#define BEVTR BEU_REG(0x018C)/**********************************************************************************************************************/#ifdef SH7722GFX_DEBUG#define QPRINT(x...) do { \ char buf[128]; \ struct timeval tv; \ do_gettimeofday( &tv ); \ snprintf( buf, sizeof(buf), x ); \ printk( KERN_DEBUG "%ld.%03ld.%03ld - %-17s: %s\n", \ tv.tv_sec - base_time.tv_sec, \ tv.tv_usec / 1000, tv.tv_usec % 1000, __FUNCTION__, buf ); \} while (0)#else#define QPRINT(x...) do {} while (0)#endif#define QDUMP(msg) QPRINT( "%-12s (%s, hw %5d-%5d, next %5d-%5d, %svalid, " \ "HC %07x, INT %06x)", msg, \ shared->hw_running ? "running" : " idle", \ shared->hw_start, \ shared->hw_end, \ shared->next_start, \ shared->next_end, \ shared->next_valid ? " " : "in", \ BEM_HC_STATUS, BEM_HC_INT_STATUS );/**********************************************************************************************************************/static DECLARE_WAIT_QUEUE_HEAD( wait_idle );static DECLARE_WAIT_QUEUE_HEAD( wait_next );static SH7722GfxSharedArea *shared;static struct timeval base_time;#ifndef SHARED_AREA_PHYSstatic struct page *shared_page;static unsigned int shared_order;#endif#ifdef SH7722GFX_IRQ_POLLERstatic int stop_poller;#endif/**********************************************************************************************************************/static intsh7722_reset( SH7722GfxSharedArea *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(SH7722GfxSharedArea) ); shared->buffer_phys = virt_to_phys(&shared->buffer[0]); 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;}static intsh7722_wait_idle( SH7722GfxSharedArea *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_idle++; ret = wait_event_interruptible_timeout( wait_idle, !shared->hw_running, 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 intsh7722_wait_next( SH7722GfxSharedArea *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_tsh7722_beu_irq( int irq, void *ctx ){ BEVTR = 0; /* Nothing here so far. But Vsync could be added. */ return IRQ_HANDLED;}static irqreturn_tsh7722_tdg_irq( int irq, void *ctx ){ SH7722GfxSharedArea *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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -