📄 led_driver.c
字号:
/* * $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)#endiftypedef 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 = dataSize + PAGE_SIZE - (dataSize%PAGE_SIZE);
DPRINTK(KERN_INFO "LED driver: width(%d),height(%d),depth(%d),datasize(%d)\n",w,h,d,dataSize); data = rvmalloc(dataSize); if (data == NULL) { DPRINTK(KERN_INFO "LED driver: Failed to allocate dma buffer"); return 0; } memset(data, 0, dataSize); screen->datasize = dataSize; screen->vram = data; screen->linestep = bpl; DPRINTK(KERN_INFO "LED driver: SetScreenMemory ok \n" ); return 1;}static void LEDScreen_Enable(){ set_gpio_ctrl(GPIO_LED_EN); set_gpio_ctrl(GPIO_LED_CK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -