📄 saa1064.c
字号:
/* Copyright (C) 2006 NXP B.V. All Rights Reserved. This source code and any compilation or derivative thereof is the proprietary information of NXP B.V. and is confidential in nature. Under no circumstances is this software to be exposed to or placed under an Open Source License of any type without the expressed written permission of NXP B.V.*//** @file saa1064.c @brief Linux implementation of the saa1064 driver. @b Module: saa1064 driver.*//* This is the Linux implementation of the saa1064 LED driver.Rev Date Author Comments--------------------------------------------------------------------------------001 20061123 neill Original002 20061130 neill Set up an initial message to display003 20070112 steel Update for 2.6.19 kernel004 20070625 neill Start with static display-------------------------------------------------------------------------------- For consistency and standardisation retain the Section Separators.*/#define __SAA1064_C__#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/kmod.h>#include <linux/miscdevice.h>#include <linux/interrupt.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/i2c.h>#include <linux/i2c-dev.h>// ----------------------- SAA1064 MODULE Local Headers --------------------#include "saa1064.h"// ----------------------- SAA1064 MODULE Generic Decriptions ----------------#define THIS_MODULE_DESCRIPTION SAA1064_MODULE_DESCRIPTIONMODULE_DESCRIPTION(THIS_MODULE_DESCRIPTION);MODULE_AUTHOR("Mike Neill");MODULE_LICENSE("Proprietary");// ----------------------- SAA1064 MODULE Debug Level ------------------------static int debug = 0;module_param(debug, int, 0);MODULE_PARM_DESC(debug, "Debug level (0-1)");#define MAX_MESSAGE 256static int scroll_enable = 0;module_param(scroll_enable, int, 0);MODULE_PARM_DESC(scroll_enable, "Enable scrolling (0-1)");static int scroll_forwards = 1;module_param(scroll_forwards, int, 0);MODULE_PARM_DESC(scroll_forwards, "Scroll forwards (0-1)");static int scroll_delay = 500;module_param(scroll_delay, int, 0);MODULE_PARM_DESC(scroll_delay, "Scroll delay in milliseconds");static int display_brightness = 4;module_param(display_brightness, int, 0);MODULE_PARM_DESC(display_brightness, "Display brightness (0 - 7)");static int scrollPosition = 0;static int restartMessage = 0;static int messageLength = 0;static unsigned char messageStore[MAX_MESSAGE];static struct timer_list timer;static wait_queue_head_t waitQueue;static int updateWakeup = 0;static int updateExit = 0;// ----------------------- saa1064 Kernel Debug --------------------------------#ifdef __SAA1064_C__#undef dprintk#define dprintk(num, format, args...) \ do { \ if (debug >= num) printk(format, ##args); \ } while (0)#endif//------------------------------------------------------------------------------// FORWARD FUNCTIONS DECLARATION//------------------------------------------------------------------------------// ----------------------- SAA1064 MODULE Forward Functions Declarations ----static int saa1064_attachAdapter (struct i2c_adapter *adapter );static int saa1064_detachClient (struct i2c_client *client );static ssize_t saa1064_write(struct file *file, const char __user *buf, size_t count, loff_t *pos);static int saa1064_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);// ****************************************************************************// * *// * M O D U L E S T R U C T U R E S *// * *// ****************************************************************************// ----------------------- SAA1064 MODULE Operations Structure ----------------static struct file_operations saa1064_fops = { .write = saa1064_write, .ioctl = saa1064_ioctl};static struct miscdevice saa1064_MiscDev = { .minor = MISC_DYNAMIC_MINOR, .name = "saa1064", .fops = &saa1064_fops};/* Number to LED segment conversion */static unsigned char numbers[10] = { 0xbd, 0x09, 0x75, 0x6d, 0xc9, 0xec, 0xfc, 0x0d, 0xfd, 0xcd};/* Lower case character to LED segment conversion */static unsigned char lower_case_characters[26] = { /* a b c d e f g h i j */ 0xdd, 0xf8, 0x70, 0x79, 0xf4, 0xd4, 0xed, 0xd8, 0x08, 0x29, /* k l m n o p q r s t */ 0xd9, 0x09, 0x6d, 0x58, 0x78, 0xd5, 0xcd, 0x50, 0xec, 0xf0, /* u v w x y z */ 0x38, 0x38, 0xf4, 0xd9, 0xe9, 0x75};/* Upper case character to LED segment conversion */static unsigned char upper_case_characters[26] = { /* a b c d e f g h i j */ 0xdd, 0xfd, 0xb4, 0xbd, 0xf4, 0xd4, 0xfc, 0xd9, 0x09, 0x29, /* k l m n o p q r s t */ 0xd9, 0xb0, 0x6d, 0x58, 0xbd, 0xd5, 0xcd, 0xdd, 0xec, 0xf0, /* u v w x y z */ 0xb9, 0xb9, 0xf4, 0xd9, 0xe9, 0x75};/* Character position to LED position conversion */static const unsigned char messageMap[5] = { 1, 4, 2, 3};// ****************************************************************************// * *// * I 2 C S T R U C T U R E S *// * *// ****************************************************************************#define I2C_SAA1064 0x70#define I2C_NAME(s) (s)->name#define MESSAGE_LENGTH 4// -----------------------------------------------------------------------------// I2C Support Structures// -----------------------------------------------------------------------------// Generic i2c probe ... addresses: i2c wants 7 bit (without the r/w bit), so '>>1'static unsigned short normal_i2c [ ] = { I2C_SAA1064 >> 1,I2C_CLIENT_END};static unsigned short probe [2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short ignore [2] = { I2C_CLIENT_END, I2C_CLIENT_END };static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = probe, .ignore = ignore};static int saa1064_present = 0;static struct i2c_client *saa1064_client = NULL;static struct i2c_driver i2c_driver_saa1064 = { .driver = { .name = "SAA1064", }, .id = I2C_DRIVERID_SAA1064, .attach_adapter = saa1064_attachAdapter, .detach_client = saa1064_detachClient,};// ****************************************************************************// * *// * I 2 C S E C T I O N *// * *// ****************************************************************************// -----------------------------------------------------------------------------// I2C Support Functions// -----------------------------------------------------------------------------static int saa1064_sendI2C ( struct i2c_client* client, const u8* data, unsigned char reg, unsigned int len){ int ret = -1; if (client == NULL) { return 0; } while(len--) { if ((ret = i2c_smbus_write_byte_data(client, reg++, *data++)) < 0) { break; } } return ret;}// ****************************************************************************// * *// * M O D U L E S E C T I O N *// * *// ****************************************************************************static int saa1064_calculateUpdateTime(void){ return (scroll_delay * HZ)/1000;}static void saa1064_updateDisplay(void){ int writePosition = 0; int readPosition = scrollPosition; unsigned char displayMessage[1]; displayMessage[0] = (display_brightness << 4) | 0x07; saa1064_sendI2C ( saa1064_client, displayMessage, 0, 1); while(writePosition < MESSAGE_LENGTH) { dprintk(1, "sending : %02x to LED %d (%d)\n", messageStore[readPosition], writePosition, messageMap[writePosition]); saa1064_sendI2C ( saa1064_client, &messageStore[readPosition], messageMap[writePosition], 1); readPosition++; readPosition %= messageLength; writePosition++; }}static int saa1064_updateShouldWakeup(void){ if (updateWakeup || updateExit) { updateWakeup = 0; return 1; } return 0;}static void saa1064_updateWakeup(void){ updateWakeup = 1; wake_up_interruptible(&waitQueue);}static int saa1064_updateDisplay_thread (void *data){ while (1) { wait_event_interruptible(waitQueue, saa1064_updateShouldWakeup()); if (updateExit) { break; } saa1064_updateDisplay(); } updateExit = 0; return 0;}static void saa1064_dumpMessageStore(void){ int readPosition = 0; while(readPosition < messageLength) { dprintk(1, "0x%02X ", messageStore[readPosition]); readPosition++; } dprintk(1, "\n");}static void saa1064_updateTimer (unsigned long data){ unsigned long newTimeout = jiffies + saa1064_calculateUpdateTime(); if (restartMessage) { scrollPosition = 0; saa1064_updateWakeup(); restartMessage = 0; } else if (scroll_enable) { if (messageLength) { if (scroll_forwards) { scrollPosition++; if (scrollPosition >= messageLength) { scrollPosition = 0; } } else { scrollPosition--; if (scrollPosition < 0) { scrollPosition = (messageLength-1); } } saa1064_updateWakeup(); } } mod_timer(&timer, newTimeout);}static int saa1064_startScrolling(void){ int result = 0; if (scroll_enable == 0) { init_timer(&timer); timer.expires = jiffies + saa1064_calculateUpdateTime(); timer.data = 0; timer.function = saa1064_updateTimer; add_timer(&timer); init_waitqueue_head (&waitQueue); result = kernel_thread (saa1064_updateDisplay_thread, 0, 0); if (result < 0) { printk(KERN_WARNING "%s: Can't start display update thread!\n", THIS_MODULE->name); scroll_enable = 0; } else { scroll_enable = 1; } } return result;}static void saa1064_stopScrolling(void){ if (scroll_enable) { del_timer(&timer); updateExit = 1; saa1064_updateWakeup(); while(updateExit) { msleep(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -