/* * arch/sh/boards/st/common/mb705-display.c * * Copyright (C) 2008 STMicroelectronics Limited * Author: Stuart Menefy * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. * * Driver for the two HDSP-253x display modules on the mb705. */ #include #include #include #include #include "mb705-epld.h" /* HDSP-253x display register offsets */ /* All offsets must be shifted by 1 to allow for shifted address lines. */ #define UDC_ADDRESS_OFF (0<<4) #define UDC_RAM_OFF (1<<4) #define CHAR_RAM_OFF (3<<4) struct display_data { spinlock_t lock; }; static struct device_attribute dev_attr_udef[]; static ssize_t store_text(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct display_data *dd = dev_get_drvdata(dev); int c; spin_lock(&dd->lock); for (c=0; c<16; c++) { int base = ((c<8) ? EPLD_TS_DISPLAY1_BASE : EPLD_TS_DISPLAY0_BASE) + CHAR_RAM_OFF; int off = c & 7; int data = (clock); return count; } static DEVICE_ATTR(text, S_IWUSR, NULL, store_text); static ssize_t store_udef(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct display_data *dd = dev_get_drvdata(dev); int code = attr - dev_attr_udef; int display; spin_lock(&dd->lock); for (display=0; display < 2; display++) { int base = (display == 0) ? EPLD_TS_DISPLAY0_BASE : EPLD_TS_DISPLAY1_BASE; int i; epld_write(code, base + UDC_ADDRESS_OFF); for (i=0; (i < 7) && (i < count); i++) epld_write(buf[i], base + UDC_RAM_OFF + (i << 1)); } spin_unlock(&dd->lock); return count; } static struct device_attribute dev_attr_udef[16] = { __ATTR(udef0, S_IWUSR, NULL, store_udef), __ATTR(udef1, S_IWUSR, NULL, store_udef), __ATTR(udef2, S_IWUSR, NULL, store_udef), __ATTR(udef3, S_IWUSR, NULL, store_udef), __ATTR(udef4, S_IWUSR, NULL, store_udef), __ATTR(udef5, S_IWUSR, NULL, store_udef), __ATTR(udef6, S_IWUSR, NULL, store_udef), __ATTR(udef7, S_IWUSR, NULL, store_udef), __ATTR(udef8, S_IWUSR, NULL, store_udef), __ATTR(udef9, S_IWUSR, NULL, store_udef), __ATTR(udef10, S_IWUSR, NULL, store_udef), __ATTR(udef11, S_IWUSR, NULL, store_udef), __ATTR(udef12, S_IWUSR, NULL, store_udef), __ATTR(udef13, S_IWUSR, NULL, store_udef), __ATTR(udef14, S_IWUSR, NULL, store_udef), __ATTR(udef15, S_IWUSR, NULL, store_udef) }; static int __init mb705_display_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int res; struct display_data *dd; int i; char string[17]; int string_len; dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL); if (dd == NULL) return -ENOMEM; spin_lock_init(&dd->lock); platform_set_drvdata(pdev, dd); res = device_create_file(dev, &dev_attr_text); if (res) return res; for (i=0; i<16; i++) { if (device_create_file(dev, &dev_attr_udef[i])) { dev_warn(dev, "%s: failed to create udef sysfs entry\n", __func__); } } /* notFL signal is controlled by DisplayCtrlReg[0] */ epld_write(1, EPLD_TS_DISPLAY_CTRL_REG); string_len = scnprintf(string, sizeof(string), "MB705%c", mb705_rev); store_text(dev, NULL, string, string_len); return 0; } static int __exit mb705_display_remove(struct platform_device *pdev) { int i; device_remove_file(&pdev->dev, &dev_attr_text); for (i=0; i<4; i++) { device_remove_file(&pdev->dev, &dev_attr_udef[i]); } return 0; } static struct platform_driver mb705_display_driver = { .remove = __exit_p(mb705_display_remove), .driver = { .name = "mb705-display", .owner = THIS_MODULE, }, }; static int __init mb705_display_init(void) { return platform_driver_probe(&mb705_display_driver, mb705_display_probe); } static void __exit mb705_display_exit(void) { platform_driver_unregister(&mb705_display_driver); } module_init(mb705_display_init); module_exit(mb705_display_exit);