static struct list_head main_display_device_list;
static struct list_head aux_display_device_list;
-static ssize_t display_show_name(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
}
-static ssize_t display_show_type(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(name);
+
+static ssize_t type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
}
-static ssize_t display_show_property(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(type);
+
+static ssize_t property_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", dsp->property);
}
-static ssize_t display_show_enable(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(property);
+
+static ssize_t enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
int enable;
return snprintf(buf, PAGE_SIZE, "%d\n", enable);
}
-static ssize_t display_store_enable(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
+static ssize_t enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
int enable;
return size;
}
-static ssize_t display_show_connect(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RW(enable);
+
+static ssize_t connect_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
int connect;
return snprintf(buf, PAGE_SIZE, "%d\n", connect);
}
+static DEVICE_ATTR_RO(connect);
+
static int mode_string(char *buf, unsigned int offset,
const struct fb_videomode *mode)
{
}
if (mode->xres == 0 && mode->yres == 0)
return snprintf(&buf[offset], PAGE_SIZE - offset, "auto\n");
-/*
- if (mode->flag & FB_MODE_IS_DETAILED)
- m = 'D';
- if (mode->flag & FB_MODE_IS_VESA)
- m = 'V';
- if (mode->flag & FB_MODE_IS_STANDARD)
- m = 'S';
-*/
if (mode->vmode & FB_VMODE_INTERLACED)
v = 'i';
if (mode->vmode & FB_VMODE_DOUBLE)
mode->xres, mode->yres, v, mode->refresh);
}
-static ssize_t display_show_modes(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t modes_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
struct list_head *modelist, *pos;
const struct fb_videomode *mode;
int i;
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->getmodelist) {
- if (dsp->ops->getmodelist(dsp, &modelist))
+ if (dsp->ops->getmodelist(dsp, &modelist)) {
+ mutex_unlock(&dsp->lock);
return -EINVAL;
+ }
} else {
+ mutex_unlock(&dsp->lock);
return 0;
}
i = 0;
mode = &display_modelist->mode;
i += mode_string(buf, i, mode);
}
+ mutex_unlock(&dsp->lock);
return i;
}
-static ssize_t display_show_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(modes);
+
+static ssize_t mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
struct fb_videomode mode;
return 0;
}
-static ssize_t display_store_mode(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
char mstr[100];
struct fb_videomode *mode;
size_t i;
+ mutex_lock(&dsp->lock);
if (!memcmp(buf, "auto", 4)) {
if (dsp->ops && dsp->ops->setmode)
dsp->ops->setmode(dsp, NULL);
+ mutex_unlock(&dsp->lock);
return count;
}
if (dsp->ops && dsp->ops->getmodelist) {
if (dsp->ops && dsp->ops->getmodelist) {
- if (dsp->ops->getmodelist(dsp, &modelist))
+ if (dsp->ops->getmodelist(dsp, &modelist)) {
+ mutex_unlock(&dsp->lock);
return -EINVAL;
+ }
}
list_for_each(pos, modelist) {
display_modelist = list_entry(pos,
if (strncmp(mstr, buf, max(count, i)) == 0) {
if (dsp->ops && dsp->ops->setmode)
dsp->ops->setmode(dsp, mode);
+ mutex_unlock(&dsp->lock);
return count;
}
}
}
+ mutex_unlock(&dsp->lock);
return -EINVAL;
}
-static ssize_t display_show_scale(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static DEVICE_ATTR_RW(mode);
+
+static ssize_t scale_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
int xscale, yscale;
return -EINVAL;
}
-static ssize_t display_store_scale(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t scale_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
int scale = 100;
return -EINVAL;
}
-static ssize_t display_show_3dmode(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RW(scale);
+
+static ssize_t mode3d_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
struct list_head *modelist, *pos;
char mode_str[128];
int mode_strlen, format_3d;
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->getmodelist) {
- if (dsp->ops->getmodelist(dsp, &modelist))
+ if (dsp->ops->getmodelist(dsp, &modelist)) {
+ mutex_unlock(&dsp->lock);
return -EINVAL;
+ }
} else {
+ mutex_unlock(&dsp->lock);
return 0;
}
if (dsp->ops && dsp->ops->getmode) {
- if (dsp->ops->getmode(dsp, &mode))
+ if (dsp->ops->getmode(dsp, &mode)) {
+ mutex_unlock(&dsp->lock);
return -EINVAL;
+ }
} else {
+ mutex_unlock(&dsp->lock);
return 0;
}
display_modelist = list_entry(pos,
struct display_modelist,
list);
- if (fb_mode_is_equal(&mode, &display_modelist->mode))
- break;
- else
+ if (!fb_mode_is_equal(&mode, &display_modelist->mode))
display_modelist = NULL;
+ else
+ break;
}
if (display_modelist)
i = snprintf(buf, PAGE_SIZE, "3dmodes=%d\n",
struct display_modelist,
list);
mode_strlen = mode_string(mode_str, 0,
- &(display_modelist->mode));
- mode_str[mode_strlen-1] = 0;
+ &display_modelist->mode);
+ mode_str[mode_strlen - 1] = 0;
format_3d = display_modelist->format_3d;
- i += snprintf(buf+i, PAGE_SIZE, "%s,%d\n",
+ i += snprintf(buf + i, PAGE_SIZE, "%s,%d\n",
mode_str, format_3d);
}
+ mutex_unlock(&dsp->lock);
return i;
}
-static ssize_t display_store_3dmode(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t mode3d_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
int mode;
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->set3dmode) {
if (!kstrtoint(buf, 0, &mode))
dsp->ops->set3dmode(dsp, mode);
+ mutex_unlock(&dsp->lock);
return count;
}
+ mutex_unlock(&dsp->lock);
return -EINVAL;
}
-static ssize_t display_show_color(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RW(mode3d);
+
+static ssize_t color_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
+ int ret = 0;
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->getcolor)
- return dsp->ops->getcolor(dsp, buf);
- else
- return 0;
+ ret = dsp->ops->getcolor(dsp, buf);
+ mutex_unlock(&dsp->lock);
+ return ret;
}
-static ssize_t display_store_color(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t color_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->setcolor) {
- if (!dsp->ops->setcolor(dsp, buf, count))
+ if (!dsp->ops->setcolor(dsp, buf, count)) {
+ mutex_unlock(&dsp->lock);
return count;
+ }
}
+ mutex_unlock(&dsp->lock);
return -EINVAL;
}
-static ssize_t display_show_sinkaudioinfo(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static DEVICE_ATTR_RW(color);
+
+static ssize_t audioinfo_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
char audioinfo[200];
int ret = 0;
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->getedidaudioinfo) {
ret = dsp->ops->getedidaudioinfo(dsp, audioinfo, 200);
- if (!ret)
+ if (!ret) {
+ mutex_unlock(&dsp->lock);
return snprintf(buf, PAGE_SIZE, "%s\n", audioinfo);
+ }
}
+ mutex_unlock(&dsp->lock);
return -EINVAL;
}
-static ssize_t display_show_monspecs(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(audioinfo);
+
+static ssize_t monspecs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
struct fb_monspecs monspecs;
int ret = 0;
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->getmonspecs) {
ret = dsp->ops->getmonspecs(dsp, &monspecs);
if (!ret) {
+ mutex_unlock(&dsp->lock);
memcpy(buf, &monspecs, sizeof(struct fb_monspecs));
return sizeof(struct fb_monspecs);
}
}
+ mutex_unlock(&dsp->lock);
return -EINVAL;
}
-static ssize_t display_show_debug(struct device *dev,
- struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(monspecs);
+
+static ssize_t debug_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
+ int ret = -EINVAL;
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->getdebug)
- return dsp->ops->getdebug(dsp, buf);
- else
- return -EINVAL;
+ ret = dsp->ops->getdebug(dsp, buf);
+ mutex_unlock(&dsp->lock);
+ return ret;
}
-static ssize_t display_store_debug(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t debug_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- int cmd;
+ int cmd, ret = -EINVAL;
struct rk_display_device *dsp = dev_get_drvdata(dev);
+ mutex_lock(&dsp->lock);
if (dsp->ops && dsp->ops->setdebug) {
if (kstrtoint(buf, 0, &cmd) == 0)
dsp->ops->setdebug(dsp, cmd);
- return count;
+ ret = count;
}
- return -EINVAL;
+ mutex_unlock(&dsp->lock);
+ return ret;
}
-static struct device_attribute display_attrs[] = {
- __ATTR(name, S_IRUGO, display_show_name, NULL),
- __ATTR(type, S_IRUGO, display_show_type, NULL),
- __ATTR(property, S_IRUGO, display_show_property, NULL),
- __ATTR(enable, 0666, display_show_enable, display_store_enable),
- __ATTR(connect, S_IRUGO, display_show_connect, NULL),
- __ATTR(modes, S_IRUGO, display_show_modes, NULL),
- __ATTR(mode, 0666, display_show_mode, display_store_mode),
- __ATTR(scale, 0666, display_show_scale, display_store_scale),
- __ATTR(3dmode, 0666, display_show_3dmode, display_store_3dmode),
- __ATTR(color, 0666, display_show_color, display_store_color),
- __ATTR(audioinfo, S_IRUGO, display_show_sinkaudioinfo, NULL),
- __ATTR(monspecs, S_IRUGO, display_show_monspecs, NULL),
- __ATTR(debug, 0664, display_show_debug, display_store_debug),
- __ATTR_NULL
+static DEVICE_ATTR_RW(debug);
+
+static ssize_t prop_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rk_display_device *dsp = dev_get_drvdata(dev);
+ int ret = -EINVAL;
+
+ mutex_lock(&dsp->lock);
+ if (dsp->ops && dsp->ops->getvrinfo)
+ ret = dsp->ops->getvrinfo(dsp, buf);
+ mutex_unlock(&dsp->lock);
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(prop);
+
+static struct attribute *display_device_attrs[] = {
+ &dev_attr_name.attr,
+ &dev_attr_type.attr,
+ &dev_attr_property.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_connect.attr,
+ &dev_attr_modes.attr,
+ &dev_attr_mode.attr,
+ &dev_attr_scale.attr,
+ &dev_attr_mode3d.attr,
+ &dev_attr_color.attr,
+ &dev_attr_audioinfo.attr,
+ &dev_attr_monspecs.attr,
+ &dev_attr_debug.attr,
+ &dev_attr_prop.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(display_device);
+
static int display_suspend(struct device *dev, pm_message_t state)
{
struct rk_display_device *dsp = dev_get_drvdata(dev);
dev_enabled = dev;
}
/* If no device is connected, enable highest priority device. */
- if (dev_enable == NULL) {
+ if (!dev_enable) {
dev->ops->setenable(dev, 1);
return;
}
mutex_unlock(&allocated_dsp_lock);
if (new_dev->idx >= 0) {
- new_dev->dev =
- device_create(display_class, parent,
- MKDEV(0, 0), new_dev,
- "%s", new_dev->type);
+ struct list_head *pos, *head;
+ struct rk_display_device *dev;
+ int i = 0;
+
+ head = &main_display_device_list;
+ list_for_each_entry(dev, head, list) {
+ if (strcmp(dev->type, new_dev->type) == 0)
+ i++;
+ }
+ head = &aux_display_device_list;
+ list_for_each_entry(dev, head, list) {
+ if (strcmp(dev->type, new_dev->type) == 0)
+ i++;
+ }
+ if (i == 0)
+ new_dev->dev =
+ device_create(display_class, parent,
+ MKDEV(0, 0), new_dev,
+ "%s", new_dev->type);
+ else
+ new_dev->dev =
+ device_create(display_class, parent,
+ MKDEV(0, 0), new_dev,
+ "%s%d", new_dev->type, i);
+
if (!IS_ERR(new_dev->dev)) {
new_dev->parent = parent;
new_dev->driver = driver;
new_dev->dev->driver = parent->driver;
mutex_init(&new_dev->lock);
/* Add new device to display device list. */
- {
- struct list_head *pos, *head;
- struct rk_display_device *dev;
-
if (new_dev->property == DISPLAY_MAIN)
head = &main_display_device_list;
else
}
list_add_tail(&new_dev->list, pos);
return new_dev;
- }
}
mutex_lock(&allocated_dsp_lock);
idr_remove(&allocated_dsp, new_dev->idx);
mutex_lock(&ddev->lock);
device_unregister(ddev->dev);
mutex_unlock(&ddev->lock);
- /* Mark device index as avaliable */
+ /* Mark device index as available */
mutex_lock(&allocated_dsp_lock);
idr_remove(&allocated_dsp, ddev->idx);
mutex_unlock(&allocated_dsp_lock);
display_class = NULL;
return -EINVAL;
}
- display_class->dev_attrs = display_attrs;
+ display_class->dev_groups = display_device_groups;
display_class->suspend = display_suspend;
display_class->resume = display_resume;
mutex_init(&allocated_dsp_lock);
subsys_initcall(rk_display_class_init);
module_exit(rk_display_class_exit);
-
MODULE_AUTHOR("zhengyang@rock-chips.com");
MODULE_DESCRIPTION("Driver for rk display device");
MODULE_LICENSE("GPL");