/* * 7 Segment LED routines * Based on RBTX49xx patch from CELF patch archive. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * (C) Copyright TOSHIBA CORPORATION 2005-2007 * All Rights Reserved. */ #include <linux/device.h> #include <linux/slab.h> #include <linux/map_to_7segment.h> #include <asm/txx9/generic.h> static unsigned int tx_7segled_num; static void (*tx_7segled_putc)(unsigned int pos, unsigned char val); void __init txx9_7segled_init(unsigned int num, void (*putc)(unsigned int pos, unsigned char val)) { tx_7segled_num = num; tx_7segled_putc = putc; } static SEG7_CONVERSION_MAP(txx9_seg7map, MAP_ASCII7SEG_ALPHANUM_LC); int txx9_7segled_putc(unsigned int pos, char c) { if (pos >= tx_7segled_num) return -EINVAL; c = map_to_seg7(&txx9_seg7map, c); if (c < 0) return c; tx_7segled_putc(pos, c); return 0; } static ssize_t ascii_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { unsigned int ch = dev->id; txx9_7segled_putc(ch, buf[0]); return size; } static ssize_t raw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { unsigned int ch = dev->id; tx_7segled_putc(ch, buf[0]); return size; } static DEVICE_ATTR(ascii, 0200, NULL, ascii_store); static DEVICE_ATTR(raw, 0200, NULL, raw_store); static ssize_t map_seg7_show(struct device *dev, struct device_attribute *attr, char *buf) { memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map)); return sizeof(txx9_seg7map); } static ssize_t map_seg7_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { if (size != sizeof(txx9_seg7map)) return -EINVAL; memcpy(&txx9_seg7map, buf, size); return size; } static DEVICE_ATTR(map_seg7, 0600, map_seg7_show, map_seg7_store); static struct bus_type tx_7segled_subsys = { .name = "7segled", .dev_name = "7segled", }; static void tx_7segled_release(struct device *dev) { kfree(dev); } static int __init tx_7segled_init_sysfs(void) { int error, i; if (!tx_7segled_num) return -ENODEV; error = subsys_system_register(&tx_7segled_subsys, NULL); if (error) return error; error = device_create_file(tx_7segled_subsys.dev_root, &dev_attr_map_seg7); if (error) return error; for (i = 0; i < tx_7segled_num; i++) { struct device *dev; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { error = -ENODEV; break; } dev->id = i; dev->bus = &tx_7segled_subsys; dev->release = &tx_7segled_release; error = device_register(dev); if (error) { put_device(dev); return error; } device_create_file(dev, &dev_attr_ascii); device_create_file(dev, &dev_attr_raw); } return error; } device_initcall(tx_7segled_init_sysfs);