1/* 2 * 7 Segment LED routines 3 * Based on RBTX49xx patch from CELF patch archive. 4 * 5 * This file is subject to the terms and conditions of the GNU General Public 6 * License. See the file "COPYING" in the main directory of this archive 7 * for more details. 8 * 9 * (C) Copyright TOSHIBA CORPORATION 2005-2007 10 * All Rights Reserved. 11 */ 12#include <linux/device.h> 13#include <linux/slab.h> 14#include <linux/map_to_7segment.h> 15#include <asm/txx9/generic.h> 16 17static unsigned int tx_7segled_num; 18static void (*tx_7segled_putc)(unsigned int pos, unsigned char val); 19 20void __init txx9_7segled_init(unsigned int num, 21 void (*putc)(unsigned int pos, unsigned char val)) 22{ 23 tx_7segled_num = num; 24 tx_7segled_putc = putc; 25} 26 27static SEG7_CONVERSION_MAP(txx9_seg7map, MAP_ASCII7SEG_ALPHANUM_LC); 28 29int txx9_7segled_putc(unsigned int pos, char c) 30{ 31 if (pos >= tx_7segled_num) 32 return -EINVAL; 33 c = map_to_seg7(&txx9_seg7map, c); 34 if (c < 0) 35 return c; 36 tx_7segled_putc(pos, c); 37 return 0; 38} 39 40static ssize_t ascii_store(struct device *dev, 41 struct device_attribute *attr, 42 const char *buf, size_t size) 43{ 44 unsigned int ch = dev->id; 45 txx9_7segled_putc(ch, buf[0]); 46 return size; 47} 48 49static ssize_t raw_store(struct device *dev, 50 struct device_attribute *attr, 51 const char *buf, size_t size) 52{ 53 unsigned int ch = dev->id; 54 tx_7segled_putc(ch, buf[0]); 55 return size; 56} 57 58static DEVICE_ATTR(ascii, 0200, NULL, ascii_store); 59static DEVICE_ATTR(raw, 0200, NULL, raw_store); 60 61static ssize_t map_seg7_show(struct device *dev, 62 struct device_attribute *attr, 63 char *buf) 64{ 65 memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map)); 66 return sizeof(txx9_seg7map); 67} 68 69static ssize_t map_seg7_store(struct device *dev, 70 struct device_attribute *attr, 71 const char *buf, size_t size) 72{ 73 if (size != sizeof(txx9_seg7map)) 74 return -EINVAL; 75 memcpy(&txx9_seg7map, buf, size); 76 return size; 77} 78 79static DEVICE_ATTR(map_seg7, 0600, map_seg7_show, map_seg7_store); 80 81static struct bus_type tx_7segled_subsys = { 82 .name = "7segled", 83 .dev_name = "7segled", 84}; 85 86static void tx_7segled_release(struct device *dev) 87{ 88 kfree(dev); 89} 90 91static int __init tx_7segled_init_sysfs(void) 92{ 93 int error, i; 94 if (!tx_7segled_num) 95 return -ENODEV; 96 error = subsys_system_register(&tx_7segled_subsys, NULL); 97 if (error) 98 return error; 99 error = device_create_file(tx_7segled_subsys.dev_root, &dev_attr_map_seg7); 100 if (error) 101 return error; 102 for (i = 0; i < tx_7segled_num; i++) { 103 struct device *dev; 104 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 105 if (!dev) { 106 error = -ENODEV; 107 break; 108 } 109 dev->id = i; 110 dev->bus = &tx_7segled_subsys; 111 dev->release = &tx_7segled_release; 112 error = device_register(dev); 113 if (error) { 114 put_device(dev); 115 return error; 116 } 117 device_create_file(dev, &dev_attr_ascii); 118 device_create_file(dev, &dev_attr_raw); 119 } 120 return error; 121} 122 123device_initcall(tx_7segled_init_sysfs); 124