/*
* $Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi Exp $
* Copyright (C) 2000 YAEGASHI Takeshi
* Generic scan keyboard driver
GPIO EXT Direct LED PIN
----------------------------------------------------------------------------------
EINT9/GPG1 6 output A
EINT16/GPG8 7 output B
EINT17/GPG9 8 output C
nSS1/EINT11/GPG3 9 output D
SPICLK1/EINT15/GPG7 10 output ST
SPIMISI1/EINT14/GPG6 11 output EN
SPIMISO1/EINT13/GPG5 12 output CK
TXD1/GPH4 13 output R1
RXD1/GPH5 14 output G1
nRTS1/TXD2/GPH6 15 output R2
nCTS01/RXD2/GPH7 16 output G2
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/major.h>
#include <linux/string.h>
//#include <linux/tty.h>
#include <linux/signal.h>
#include <linux/timer.h>
#include <asm/hardware.h>
#include "led_driver.h"
#define DEBUG 1
#ifdef DPRINTK
#undef DPRINTK
#endif
#ifdef DEBUG
#define DPRINTK(x... ) printk( ##x )
#else
#define DPRINTK(x... )
#endif
#define TWH 10
#define TWL 10
#define TCS 15
#define TCH 20
#define TCR 30
#define TCKS 20
#define TCKH 20
#define TDS 50
#define TDH 50
#define TRD 25
#define TRZ 10
#define TRF 20
#define TPHL 60
#define TPHZ 50
#define TSU 30
#define TH 10
#define GPIO_LED_A (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G1)
#define GPIO_LED_B (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G8)
#define GPIO_LED_C (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G9)
#define GPIO_LED_D (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G3)
#define GPIO_LED_ST (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G7)
#define GPIO_LED_EN (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G6)
#define GPIO_LED_CK (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G5)
#define GPIO_LED_R1 (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_H4)
#define GPIO_LED_G1 (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_H5)
#define GPIO_LED_R2 (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_H6)
#define GPIO_LED_G2 (GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_H7)
#define ENABLE 1
#define DISABLE 0
#define SCANHZ (HZ/2)
#ifndef virt_to_page
#define virt_to_page(x) MAP_NR(x)
#endif
#ifndef vmalloc_32
#define vmalloc_32(x) vmalloc(x)
#endif
typedef struct led_screen_para {
u16 screenwidth;
u16 screenheight;
u8 depth;
u8 scanline;
u8 pages;
u16 linestep;
u16 datasize;
void* vram;
} LED_SCREEN_PARA;
static int scan_jiffies=0;
struct timer_list scan_timer;
static int disp_frame = 0;
static devfs_handle_t devfs_handle;
static LED_SCREEN_PARA *ledscreens;
static u32 RED_GPIO[2] = {GPIO_LED_R1, GPIO_LED_R2};
static u32 GREEN_GPIO[2] = {GPIO_LED_G1, GPIO_LED_G2};
static int LEDScreen_open(struct inode *minode, struct file *mfile);
static int LEDScreen_release(struct inode *minode, struct file *mfile);
static int LEDScreen_mmap(struct file *file, struct vm_area_struct *vma);
static int LEDScreen_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
static int SetScreenMemory(LED_SCREEN_PARA *screen);
static void LEDScreen_Enable(void);
static void LED_Disable(LED_SCREEN_PARA *screen);
static void write_pixel(LED_SCREEN_PARA *screen, int frame, int x, int y);
static void write_frame(LED_SCREEN_PARA *screen, int frame);
static int LEDScreen_starttimer(void);
static struct file_operations device_fops = {
owner: THIS_MODULE,
ioctl: LEDScreen_ioctl,
mmap: LEDScreen_mmap,
open: LEDScreen_open,
release: LEDScreen_release,
};
/*******************************/
/* Memory management functions */
/*******************************/
#define MDEBUG(x) do { } while(0) /* Debug memory management */
/* [DaveM] I've recoded most of this so that:
* 1) It's easier to tell what is happening
* 2) It's more portable, especially for translating things
* out of vmalloc mapped areas in the kernel.
* 3) Less unnecessary translations happen.
*
* The code used to assume that the kernel vmalloc mappings
* existed in the page tables of every process, this is simply
* not guaranteed. We now use pgd_offset_k which is the
* defined way to get at the kernel page tables.
*/
/* Given PGD from the address space's page table, return the kernel
* virtual mapping of the physical memory mapped at ADR.
*/
static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
{
unsigned long ret = 0UL;
pmd_t *pmd;
pte_t *ptep, pte;
if (!pgd_none(*pgd)) {
pmd = pmd_offset(pgd, adr);
if (!pmd_none(*pmd)) {
ptep = pte_offset(pmd, adr);
pte = *ptep;
if(pte_present(pte)) {
ret = (unsigned long)
page_address(pte_page(pte));
ret |= (adr & (PAGE_SIZE - 1));
}
}
}
MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
return ret;
}
static inline unsigned long uvirt_to_bus(unsigned long adr)
{
unsigned long kva, ret;
kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
ret = virt_to_bus((void *)kva);
MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
return ret;
}
static inline unsigned long kvirt_to_bus(unsigned long adr)
{
unsigned long va, kva, ret;
va = VMALLOC_VMADDR(adr);
kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = virt_to_bus((void *)kva);
MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
return ret;
}
/* Here we want the physical address of the memory.
* This is used when initializing the contents of the
* area and marking the pages as reserved.
*/
static inline unsigned long kvirt_to_pa(unsigned long adr)
{
unsigned long va, kva, ret;
va = VMALLOC_VMADDR(adr);
kva = uvirt_to_kva(pgd_offset_k(va), va);
ret = __pa(kva);
MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
return ret;
}
static void * rvmalloc(unsigned long size)
{
void * mem;
unsigned long adr, page;
mem=vmalloc_32(size);
if (mem)
{
memset(mem, 0, size); /* Clear the ram out,
no junk to the user */
adr=(unsigned long) mem;
while (size > 0)
{
page = kvirt_to_pa(adr);
mem_map_reserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
}
return mem;
}
static void rvfree(void * mem, unsigned long size)
{
unsigned long adr, page;
if (mem)
{
adr=(unsigned long) mem;
while (size > 0)
{
page = kvirt_to_pa(adr);
mem_map_unreserve(virt_to_page(__va(page)));
adr+=PAGE_SIZE;
size-=PAGE_SIZE;
}
vfree(mem);
}
}
/* End of code taken from bttv.c */
static int SetScreenMemory(LED_SCREEN_PARA *screen)
{
int w, h, d;
int bpl, dataSize;
unsigned char *data;
w = screen->screenwidth;
h = screen->screenheight;
d = screen->depth;
if ( d == 1 )
bpl = (w*d+7)/8;
else
bpl = ((w*d+31)/32)*4;
dataSize = bpl * h;
if (dataSize%PAGE_SIZE)
dataSize
评论0