168 lines
4.0 KiB
C
168 lines
4.0 KiB
C
|
/*
|
||
|
* arch/sh/boards/st/common/mb705-display.c
|
||
|
*
|
||
|
* Copyright (C) 2008 STMicroelectronics Limited
|
||
|
* Author: Stuart Menefy <stuart.menefy@st.com>
|
||
|
*
|
||
|
* 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 <linux/init.h>
|
||
|
#include <linux/platform_device.h>
|
||
|
#include <asm/processor.h>
|
||
|
#include <mach/common.h>
|
||
|
#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 = (c<count) ? buf[c] : ' ';
|
||
|
epld_write(data, base + (off << 1));
|
||
|
}
|
||
|
|
||
|
spin_unlock(&dd->lock);
|
||
|
|
||
|
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);
|