1 #include <linux/module.h>
2 #include <linux/ctype.h>
5 #include <linux/kdev_t.h>
6 #include <linux/display-sys.h>
8 static struct list_head main_display_device_list;
9 static struct list_head aux_display_device_list;
11 static ssize_t display_show_name(struct device *dev,
12 struct device_attribute *attr, char *buf)
14 struct rk_display_device *dsp = dev_get_drvdata(dev);
16 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
19 static ssize_t display_show_type(struct device *dev,
20 struct device_attribute *attr, char *buf)
22 struct rk_display_device *dsp = dev_get_drvdata(dev);
24 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
27 static ssize_t display_show_property(struct device *dev,
28 struct device_attribute *attr, char *buf)
30 struct rk_display_device *dsp = dev_get_drvdata(dev);
32 return snprintf(buf, PAGE_SIZE, "%d\n", dsp->property);
35 static ssize_t display_show_enable(struct device *dev,
36 struct device_attribute *attr, char *buf)
38 struct rk_display_device *dsp = dev_get_drvdata(dev);
41 if (dsp->ops && dsp->ops->getenable)
42 enable = dsp->ops->getenable(dsp);
45 return snprintf(buf, PAGE_SIZE, "%d\n", enable);
48 static ssize_t display_store_enable(struct device *dev,
49 struct device_attribute *attr,
50 const char *buf, size_t size)
52 struct rk_display_device *dsp = dev_get_drvdata(dev);
55 if (kstrtoint(buf, 0, &enable))
57 if (dsp->ops && dsp->ops->setenable)
58 dsp->ops->setenable(dsp, enable);
62 static ssize_t display_show_connect(struct device *dev,
63 struct device_attribute *attr, char *buf)
65 struct rk_display_device *dsp = dev_get_drvdata(dev);
68 if (dsp->ops && dsp->ops->getstatus)
69 connect = dsp->ops->getstatus(dsp);
72 return snprintf(buf, PAGE_SIZE, "%d\n", connect);
75 static int mode_string(char *buf, unsigned int offset,
76 const struct fb_videomode *mode)
81 pr_err("%s parameter error\n", __func__);
84 if (mode->xres == 0 && mode->yres == 0)
85 return snprintf(&buf[offset], PAGE_SIZE - offset, "auto\n");
87 if (mode->flag & FB_MODE_IS_DETAILED)
89 if (mode->flag & FB_MODE_IS_VESA)
91 if (mode->flag & FB_MODE_IS_STANDARD)
94 if (mode->vmode & FB_VMODE_INTERLACED)
96 if (mode->vmode & FB_VMODE_DOUBLE)
99 return snprintf(&buf[offset], PAGE_SIZE - offset,
100 "%dx%d%c-%d(YCbCr420)\n",
101 mode->xres, mode->yres, v, mode->refresh);
103 return snprintf(&buf[offset], PAGE_SIZE - offset,
105 mode->xres, mode->yres, v, mode->refresh);
108 static ssize_t display_show_modes(struct device *dev,
109 struct device_attribute *attr, char *buf)
111 struct rk_display_device *dsp = dev_get_drvdata(dev);
112 struct list_head *modelist, *pos;
113 struct display_modelist *display_modelist;
114 const struct fb_videomode *mode;
117 mutex_lock(&dsp->lock);
118 if (dsp->ops && dsp->ops->getmodelist) {
119 if (dsp->ops->getmodelist(dsp, &modelist)) {
120 mutex_unlock(&dsp->lock);
124 mutex_unlock(&dsp->lock);
128 if (dsp->priority == DISPLAY_PRIORITY_HDMI)
129 i += snprintf(buf, PAGE_SIZE, "auto\n");
131 list_for_each(pos, modelist) {
132 display_modelist = list_entry(pos,
133 struct display_modelist,
135 mode = &display_modelist->mode;
136 i += mode_string(buf, i, mode);
138 mutex_unlock(&dsp->lock);
142 static ssize_t display_show_mode(struct device *dev,
143 struct device_attribute *attr, char *buf)
145 struct rk_display_device *dsp = dev_get_drvdata(dev);
146 struct fb_videomode mode;
148 if (dsp->ops && dsp->ops->getmode)
149 if (dsp->ops->getmode(dsp, &mode) == 0)
150 return mode_string(buf, 0, &mode);
154 static ssize_t display_store_mode(struct device *dev,
155 struct device_attribute *attr,
156 const char *buf, size_t count)
158 struct rk_display_device *dsp = dev_get_drvdata(dev);
160 struct list_head *modelist, *pos;
161 struct display_modelist *display_modelist;
162 struct fb_videomode *mode;
165 if (!memcmp(buf, "auto", 4)) {
166 if (dsp->ops && dsp->ops->setmode)
167 dsp->ops->setmode(dsp, NULL);
171 if (dsp->ops && dsp->ops->getmodelist) {
172 if (dsp->ops && dsp->ops->getmodelist) {
173 if (dsp->ops->getmodelist(dsp, &modelist))
176 list_for_each(pos, modelist) {
177 display_modelist = list_entry(pos,
178 struct display_modelist,
180 mode = &display_modelist->mode;
181 i = mode_string(mstr, 0, mode);
182 if (strncmp(mstr, buf, max(count, i)) == 0) {
183 if (dsp->ops && dsp->ops->setmode)
184 dsp->ops->setmode(dsp, mode);
192 static ssize_t display_show_scale(struct device *dev,
193 struct device_attribute *attr,
196 struct rk_display_device *dsp = dev_get_drvdata(dev);
199 if (dsp->ops && dsp->ops->getscale) {
200 xscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_X);
201 yscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_Y);
202 if (xscale && yscale)
203 return snprintf(buf, PAGE_SIZE,
204 "xscale=%d yscale=%d\n",
210 static ssize_t display_store_scale(struct device *dev,
211 struct device_attribute *attr,
212 const char *buf, size_t count)
214 struct rk_display_device *dsp = dev_get_drvdata(dev);
217 if (dsp->ops && dsp->ops->setscale) {
218 if (!strncmp(buf, "xscale", 6)) {
219 if (!kstrtoint(buf, 0, &scale))
220 dsp->ops->setscale(dsp,
223 } else if (!strncmp(buf, "yscale", 6)) {
224 if (!kstrtoint(buf, 0, &scale))
225 dsp->ops->setscale(dsp,
229 if (!kstrtoint(buf, 0, &scale)) {
230 dsp->ops->setscale(dsp,
233 dsp->ops->setscale(dsp,
243 static ssize_t display_show_3dmode(struct device *dev,
244 struct device_attribute *attr, char *buf)
246 struct rk_display_device *dsp = dev_get_drvdata(dev);
247 struct list_head *modelist, *pos;
248 struct display_modelist *display_modelist;
249 struct fb_videomode mode;
250 int i = 0, cur_3d_mode = -1;
252 int mode_strlen, format_3d;
254 if (dsp->ops && dsp->ops->getmodelist) {
255 if (dsp->ops->getmodelist(dsp, &modelist))
261 if (dsp->ops && dsp->ops->getmode) {
262 if (dsp->ops->getmode(dsp, &mode))
268 list_for_each(pos, modelist) {
269 display_modelist = list_entry(pos,
270 struct display_modelist,
272 if (fb_mode_is_equal(&mode, &display_modelist->mode))
275 display_modelist = NULL;
277 if (display_modelist)
278 i = snprintf(buf, PAGE_SIZE, "3dmodes=%d\n",
279 display_modelist->format_3d);
281 i = snprintf(buf, PAGE_SIZE, "3dmodes=0\n");
283 if (dsp->ops && dsp->ops->get3dmode)
284 cur_3d_mode = dsp->ops->get3dmode(dsp);
285 i += snprintf(buf + i, PAGE_SIZE - i, "cur3dmode=%d\n", cur_3d_mode);
287 list_for_each(pos, modelist) {
288 display_modelist = list_entry(pos,
289 struct display_modelist,
291 mode_strlen = mode_string(mode_str, 0,
292 &(display_modelist->mode));
293 mode_str[mode_strlen-1] = 0;
294 format_3d = display_modelist->format_3d;
295 i += snprintf(buf+i, PAGE_SIZE, "%s,%d\n",
296 mode_str, format_3d);
301 static ssize_t display_store_3dmode(struct device *dev,
302 struct device_attribute *attr,
303 const char *buf, size_t count)
305 struct rk_display_device *dsp = dev_get_drvdata(dev);
308 if (dsp->ops && dsp->ops->set3dmode) {
309 if (!kstrtoint(buf, 0, &mode))
310 dsp->ops->set3dmode(dsp, mode);
316 static ssize_t display_show_color(struct device *dev,
317 struct device_attribute *attr, char *buf)
319 struct rk_display_device *dsp = dev_get_drvdata(dev);
321 if (dsp->ops && dsp->ops->getcolor)
322 return dsp->ops->getcolor(dsp, buf);
327 static ssize_t display_store_color(struct device *dev,
328 struct device_attribute *attr,
329 const char *buf, size_t count)
331 struct rk_display_device *dsp = dev_get_drvdata(dev);
333 if (dsp->ops && dsp->ops->setcolor) {
334 if (!dsp->ops->setcolor(dsp, buf, count))
340 static ssize_t display_show_sinkaudioinfo(struct device *dev,
341 struct device_attribute *attr,
344 struct rk_display_device *dsp = dev_get_drvdata(dev);
348 if (dsp->ops && dsp->ops->getedidaudioinfo) {
349 ret = dsp->ops->getedidaudioinfo(dsp, audioinfo, 200);
351 return snprintf(buf, PAGE_SIZE, "%s\n", audioinfo);
356 static ssize_t display_show_monspecs(struct device *dev,
357 struct device_attribute *attr, char *buf)
359 struct rk_display_device *dsp = dev_get_drvdata(dev);
360 struct fb_monspecs monspecs;
363 if (dsp->ops && dsp->ops->getmonspecs) {
364 ret = dsp->ops->getmonspecs(dsp, &monspecs);
366 memcpy(buf, &monspecs, sizeof(struct fb_monspecs));
367 return sizeof(struct fb_monspecs);
373 static ssize_t display_show_debug(struct device *dev,
374 struct device_attribute *attr, char *buf)
376 struct rk_display_device *dsp = dev_get_drvdata(dev);
378 if (dsp->ops && dsp->ops->getdebug)
379 return dsp->ops->getdebug(dsp, buf);
384 static ssize_t display_store_debug(struct device *dev,
385 struct device_attribute *attr,
386 const char *buf, size_t count)
389 struct rk_display_device *dsp = dev_get_drvdata(dev);
391 if (dsp->ops && dsp->ops->setdebug) {
392 if (kstrtoint(buf, 0, &cmd) == 0)
393 dsp->ops->setdebug(dsp, cmd);
399 static struct device_attribute display_attrs[] = {
400 __ATTR(name, S_IRUGO, display_show_name, NULL),
401 __ATTR(type, S_IRUGO, display_show_type, NULL),
402 __ATTR(property, S_IRUGO, display_show_property, NULL),
403 __ATTR(enable, 0666, display_show_enable, display_store_enable),
404 __ATTR(connect, S_IRUGO, display_show_connect, NULL),
405 __ATTR(modes, S_IRUGO, display_show_modes, NULL),
406 __ATTR(mode, 0666, display_show_mode, display_store_mode),
407 __ATTR(scale, 0666, display_show_scale, display_store_scale),
408 __ATTR(3dmode, 0666, display_show_3dmode, display_store_3dmode),
409 __ATTR(color, 0666, display_show_color, display_store_color),
410 __ATTR(audioinfo, S_IRUGO, display_show_sinkaudioinfo, NULL),
411 __ATTR(monspecs, S_IRUGO, display_show_monspecs, NULL),
412 __ATTR(debug, 0664, display_show_debug, display_store_debug),
416 static int display_suspend(struct device *dev, pm_message_t state)
418 struct rk_display_device *dsp = dev_get_drvdata(dev);
420 mutex_lock(&dsp->lock);
421 if (likely(dsp->driver->suspend))
422 dsp->driver->suspend(dsp, state);
423 mutex_unlock(&dsp->lock);
427 static int display_resume(struct device *dev)
429 struct rk_display_device *dsp = dev_get_drvdata(dev);
431 mutex_lock(&dsp->lock);
432 if (likely(dsp->driver->resume))
433 dsp->driver->resume(dsp);
434 mutex_unlock(&dsp->lock);
438 int display_add_videomode(const struct fb_videomode *mode,
439 struct list_head *head)
441 struct list_head *pos;
442 struct display_modelist *modelist;
443 struct fb_videomode *m;
446 list_for_each(pos, head) {
447 modelist = list_entry(pos, struct display_modelist, list);
449 if (fb_mode_is_equal(m, mode)) {
455 modelist = kmalloc(sizeof(*modelist),
460 modelist->mode = *mode;
461 list_add(&modelist->list, head);
466 void rk_display_device_enable(struct rk_display_device *ddev)
468 struct list_head *pos, *head;
469 struct rk_display_device *dev = NULL, *dev_enabled = NULL;
470 struct rk_display_device *dev_enable = NULL;
471 int enable = 0, connect;
473 if (ddev->property == DISPLAY_MAIN)
474 head = &main_display_device_list;
476 head = &aux_display_device_list;
478 list_for_each(pos, head) {
479 dev = list_entry(pos, struct rk_display_device, list);
480 enable = dev->ops->getenable(dev);
481 connect = dev->ops->getstatus(dev);
487 /* If no device is connected, enable highest priority device. */
488 if (dev_enable == NULL) {
489 dev->ops->setenable(dev, 1);
493 if (dev_enable == dev_enabled) {
494 if (dev_enable != ddev)
495 ddev->ops->setenable(ddev, 0);
498 dev_enabled->priority != DISPLAY_PRIORITY_HDMI)
499 dev_enabled->ops->setenable(dev_enabled, 0);
500 dev_enable->ops->setenable(dev_enable, 1);
503 EXPORT_SYMBOL(rk_display_device_enable);
505 void rk_display_device_enable_other(struct rk_display_device *ddev)
507 #ifndef CONFIG_DISPLAY_AUTO_SWITCH
510 struct list_head *pos, *head;
511 struct rk_display_device *dev;
514 if (ddev->property == DISPLAY_MAIN)
515 head = &main_display_device_list;
517 head = &aux_display_device_list;
519 list_for_each_prev(pos, head) {
520 dev = list_entry(pos, struct rk_display_device, list);
522 connect = dev->ops->getstatus(dev);
524 dev->ops->setenable(dev, 1);
531 EXPORT_SYMBOL(rk_display_device_enable_other);
533 void rk_display_device_disable_other(struct rk_display_device *ddev)
535 #ifndef CONFIG_DISPLAY_AUTO_SWITCH
538 struct list_head *pos, *head;
539 struct rk_display_device *dev;
542 if (ddev->property == DISPLAY_MAIN)
543 head = &main_display_device_list;
545 head = &aux_display_device_list;
547 list_for_each(pos, head) {
548 dev = list_entry(pos, struct rk_display_device, list);
550 enable = dev->ops->getenable(dev);
552 dev->ops->setenable(dev, 0);
555 ddev->ops->setenable(ddev, 1);
558 EXPORT_SYMBOL(rk_display_device_disable_other);
560 void rk_display_device_select(int property, int priority)
562 struct list_head *pos, *head;
563 struct rk_display_device *dev;
564 int enable, found = 0;
566 if (property == DISPLAY_MAIN)
567 head = &main_display_device_list;
569 head = &aux_display_device_list;
571 list_for_each(pos, head) {
572 dev = list_entry(pos, struct rk_display_device, list);
573 if (dev->priority == priority)
578 pr_err("[%s] select display interface %d not exist\n",
583 list_for_each(pos, head) {
584 dev = list_entry(pos, struct rk_display_device, list);
585 enable = dev->ops->getenable(dev);
586 if (dev->priority == priority) {
588 dev->ops->setenable(dev, 1);
590 dev->ops->setenable(dev, 0);
594 EXPORT_SYMBOL(rk_display_device_select);
595 static struct mutex allocated_dsp_lock;
596 static DEFINE_IDR(allocated_dsp);
597 static struct class *display_class;
599 struct rk_display_device
600 *rk_display_device_register(struct rk_display_driver *driver,
601 struct device *parent, void *devdata)
603 struct rk_display_device *new_dev = NULL;
606 if (unlikely(!driver))
609 new_dev = kzalloc(sizeof(*new_dev), GFP_KERNEL);
610 if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
611 /* Reserve the index for this display */
612 mutex_lock(&allocated_dsp_lock);
613 new_dev->idx = idr_alloc(&allocated_dsp, new_dev,
615 mutex_unlock(&allocated_dsp_lock);
617 if (new_dev->idx >= 0) {
619 device_create(display_class, parent,
620 MKDEV(0, 0), new_dev,
621 "%s", new_dev->type);
622 if (!IS_ERR(new_dev->dev)) {
623 new_dev->parent = parent;
624 new_dev->driver = driver;
626 new_dev->dev->driver = parent->driver;
627 mutex_init(&new_dev->lock);
628 /* Add new device to display device list. */
630 struct list_head *pos, *head;
631 struct rk_display_device *dev;
633 if (new_dev->property == DISPLAY_MAIN)
634 head = &main_display_device_list;
636 head = &aux_display_device_list;
638 list_for_each(pos, head) {
641 struct rk_display_device,
643 if (dev->priority > new_dev->priority)
646 list_add_tail(&new_dev->list, pos);
650 mutex_lock(&allocated_dsp_lock);
651 idr_remove(&allocated_dsp, new_dev->idx);
652 mutex_unlock(&allocated_dsp_lock);
659 EXPORT_SYMBOL(rk_display_device_register);
661 void rk_display_device_unregister(struct rk_display_device *ddev)
666 mutex_lock(&ddev->lock);
667 device_unregister(ddev->dev);
668 mutex_unlock(&ddev->lock);
669 /* Mark device index as avaliable */
670 mutex_lock(&allocated_dsp_lock);
671 idr_remove(&allocated_dsp, ddev->idx);
672 mutex_unlock(&allocated_dsp_lock);
673 list_del(&ddev->list);
676 EXPORT_SYMBOL(rk_display_device_unregister);
678 static int __init rk_display_class_init(void)
680 display_class = class_create(THIS_MODULE, "display");
681 if (IS_ERR(display_class)) {
682 pr_err("Failed to create display class\n");
683 display_class = NULL;
686 display_class->dev_attrs = display_attrs;
687 display_class->suspend = display_suspend;
688 display_class->resume = display_resume;
689 mutex_init(&allocated_dsp_lock);
690 INIT_LIST_HEAD(&main_display_device_list);
691 INIT_LIST_HEAD(&aux_display_device_list);
695 static void __exit rk_display_class_exit(void)
697 class_destroy(display_class);
700 subsys_initcall(rk_display_class_init);
701 module_exit(rk_display_class_exit);
704 MODULE_AUTHOR("zhengyang@rock-chips.com");
705 MODULE_DESCRIPTION("Driver for rk display device");
706 MODULE_LICENSE("GPL");