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)
80 if (mode->xres == 0 && mode->yres == 0)
81 return snprintf(&buf[offset], PAGE_SIZE - offset, "auto\n");
83 if (mode->flag & FB_MODE_IS_DETAILED)
85 if (mode->flag & FB_MODE_IS_VESA)
87 if (mode->flag & FB_MODE_IS_STANDARD)
90 if (mode->vmode & FB_VMODE_INTERLACED)
92 if (mode->vmode & FB_VMODE_DOUBLE)
95 return snprintf(&buf[offset], PAGE_SIZE - offset,
96 "%dx%d%c-%d(YCbCr420)\n",
97 mode->xres, mode->yres, v, mode->refresh);
99 return snprintf(&buf[offset], PAGE_SIZE - offset,
101 mode->xres, mode->yres, v, mode->refresh);
104 static ssize_t display_show_modes(struct device *dev,
105 struct device_attribute *attr, char *buf)
107 struct rk_display_device *dsp = dev_get_drvdata(dev);
108 struct list_head *modelist, *pos;
109 struct display_modelist *display_modelist;
110 const struct fb_videomode *mode;
113 if (dsp->ops && dsp->ops->getmodelist) {
114 if (dsp->ops->getmodelist(dsp, &modelist))
120 if (dsp->priority == DISPLAY_PRIORITY_HDMI)
121 i += snprintf(buf, PAGE_SIZE, "auto\n");
123 list_for_each(pos, modelist) {
124 display_modelist = list_entry(pos,
125 struct display_modelist,
127 mode = &display_modelist->mode;
128 i += mode_string(buf, i, mode);
133 static ssize_t display_show_mode(struct device *dev,
134 struct device_attribute *attr, char *buf)
136 struct rk_display_device *dsp = dev_get_drvdata(dev);
137 struct fb_videomode mode;
139 if (dsp->ops && dsp->ops->getmode)
140 if (dsp->ops->getmode(dsp, &mode) == 0)
141 return mode_string(buf, 0, &mode);
145 static ssize_t display_store_mode(struct device *dev,
146 struct device_attribute *attr,
147 const char *buf, size_t count)
149 struct rk_display_device *dsp = dev_get_drvdata(dev);
151 struct list_head *modelist, *pos;
152 struct display_modelist *display_modelist;
153 struct fb_videomode *mode;
156 if (!memcmp(buf, "auto", 4)) {
157 if (dsp->ops && dsp->ops->setmode)
158 dsp->ops->setmode(dsp, NULL);
162 if (dsp->ops && dsp->ops->getmodelist) {
163 if (dsp->ops && dsp->ops->getmodelist) {
164 if (dsp->ops->getmodelist(dsp, &modelist))
167 list_for_each(pos, modelist) {
168 display_modelist = list_entry(pos,
169 struct display_modelist,
171 mode = &display_modelist->mode;
172 i = mode_string(mstr, 0, mode);
173 if (strncmp(mstr, buf, max(count, i)) == 0) {
174 if (dsp->ops && dsp->ops->setmode)
175 dsp->ops->setmode(dsp, mode);
183 static ssize_t display_show_scale(struct device *dev,
184 struct device_attribute *attr,
187 struct rk_display_device *dsp = dev_get_drvdata(dev);
190 if (dsp->ops && dsp->ops->getscale) {
191 xscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_X);
192 yscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_Y);
193 if (xscale && yscale)
194 return snprintf(buf, PAGE_SIZE,
195 "xscale=%d yscale=%d\n",
201 static ssize_t display_store_scale(struct device *dev,
202 struct device_attribute *attr,
203 const char *buf, size_t count)
205 struct rk_display_device *dsp = dev_get_drvdata(dev);
208 if (dsp->ops && dsp->ops->setscale) {
209 if (!strncmp(buf, "xscale", 6)) {
210 if (!kstrtoint(buf, 0, &scale))
211 dsp->ops->setscale(dsp,
214 } else if (!strncmp(buf, "yscale", 6)) {
215 if (!kstrtoint(buf, 0, &scale))
216 dsp->ops->setscale(dsp,
220 if (!kstrtoint(buf, 0, &scale)) {
221 dsp->ops->setscale(dsp,
224 dsp->ops->setscale(dsp,
234 static ssize_t display_show_3dmode(struct device *dev,
235 struct device_attribute *attr, char *buf)
237 struct rk_display_device *dsp = dev_get_drvdata(dev);
238 struct list_head *modelist, *pos;
239 struct display_modelist *display_modelist;
240 struct fb_videomode mode;
241 int i = 0, cur_3d_mode = -1;
243 int mode_strlen, format_3d;
245 if (dsp->ops && dsp->ops->getmodelist) {
246 if (dsp->ops->getmodelist(dsp, &modelist))
252 if (dsp->ops && dsp->ops->getmode) {
253 if (dsp->ops->getmode(dsp, &mode))
259 list_for_each(pos, modelist) {
260 display_modelist = list_entry(pos,
261 struct display_modelist,
263 if (fb_mode_is_equal(&mode, &display_modelist->mode))
266 display_modelist = NULL;
268 if (display_modelist)
269 i = snprintf(buf, PAGE_SIZE, "3dmodes=%d\n",
270 display_modelist->format_3d);
272 i = snprintf(buf, PAGE_SIZE, "3dmodes=0\n");
274 if (dsp->ops && dsp->ops->get3dmode)
275 cur_3d_mode = dsp->ops->get3dmode(dsp);
276 i += snprintf(buf + i, PAGE_SIZE - i, "cur3dmode=%d\n", cur_3d_mode);
278 list_for_each(pos, modelist) {
279 display_modelist = list_entry(pos,
280 struct display_modelist,
282 mode_strlen = mode_string(mode_str, 0,
283 &(display_modelist->mode));
284 mode_str[mode_strlen-1] = 0;
285 format_3d = display_modelist->format_3d;
286 i += snprintf(buf+i, PAGE_SIZE, "%s,%d\n",
287 mode_str, format_3d);
292 static ssize_t display_store_3dmode(struct device *dev,
293 struct device_attribute *attr,
294 const char *buf, size_t count)
296 struct rk_display_device *dsp = dev_get_drvdata(dev);
299 if (dsp->ops && dsp->ops->set3dmode) {
300 if (!kstrtoint(buf, 0, &mode))
301 dsp->ops->set3dmode(dsp, mode);
307 static ssize_t display_show_color(struct device *dev,
308 struct device_attribute *attr, char *buf)
310 struct rk_display_device *dsp = dev_get_drvdata(dev);
312 if (dsp->ops && dsp->ops->getcolor)
313 return dsp->ops->getcolor(dsp, buf);
318 static ssize_t display_store_color(struct device *dev,
319 struct device_attribute *attr,
320 const char *buf, size_t count)
322 struct rk_display_device *dsp = dev_get_drvdata(dev);
324 if (dsp->ops && dsp->ops->setcolor) {
325 if (!dsp->ops->setcolor(dsp, buf, count))
331 static ssize_t display_show_sinkaudioinfo(struct device *dev,
332 struct device_attribute *attr,
335 struct rk_display_device *dsp = dev_get_drvdata(dev);
339 if (dsp->ops && dsp->ops->getedidaudioinfo) {
340 ret = dsp->ops->getedidaudioinfo(dsp, audioinfo, 200);
342 return snprintf(buf, PAGE_SIZE, "%s\n", audioinfo);
347 static ssize_t display_show_monspecs(struct device *dev,
348 struct device_attribute *attr, char *buf)
350 struct rk_display_device *dsp = dev_get_drvdata(dev);
351 struct fb_monspecs monspecs;
354 if (dsp->ops && dsp->ops->getmonspecs) {
355 ret = dsp->ops->getmonspecs(dsp, &monspecs);
357 memcpy(buf, &monspecs, sizeof(struct fb_monspecs));
358 return sizeof(struct fb_monspecs);
364 static ssize_t display_show_debug(struct device *dev,
365 struct device_attribute *attr, char *buf)
367 struct rk_display_device *dsp = dev_get_drvdata(dev);
369 if (dsp->ops && dsp->ops->getdebug)
370 return dsp->ops->getdebug(dsp, buf);
375 static ssize_t display_store_debug(struct device *dev,
376 struct device_attribute *attr,
377 const char *buf, size_t count)
380 struct rk_display_device *dsp = dev_get_drvdata(dev);
382 if (dsp->ops && dsp->ops->setdebug) {
383 if (kstrtoint(buf, 0, &cmd) == 0)
384 dsp->ops->setdebug(dsp, cmd);
390 static struct device_attribute display_attrs[] = {
391 __ATTR(name, S_IRUGO, display_show_name, NULL),
392 __ATTR(type, S_IRUGO, display_show_type, NULL),
393 __ATTR(property, S_IRUGO, display_show_property, NULL),
394 __ATTR(enable, 0666, display_show_enable, display_store_enable),
395 __ATTR(connect, S_IRUGO, display_show_connect, NULL),
396 __ATTR(modes, S_IRUGO, display_show_modes, NULL),
397 __ATTR(mode, 0666, display_show_mode, display_store_mode),
398 __ATTR(scale, 0666, display_show_scale, display_store_scale),
399 __ATTR(3dmode, 0666, display_show_3dmode, display_store_3dmode),
400 __ATTR(color, 0666, display_show_color, display_store_color),
401 __ATTR(audioinfo, S_IRUGO, display_show_sinkaudioinfo, NULL),
402 __ATTR(monspecs, S_IRUGO, display_show_monspecs, NULL),
403 __ATTR(debug, 0664, display_show_debug, display_store_debug),
407 static int display_suspend(struct device *dev, pm_message_t state)
409 struct rk_display_device *dsp = dev_get_drvdata(dev);
411 mutex_lock(&dsp->lock);
412 if (likely(dsp->driver->suspend))
413 dsp->driver->suspend(dsp, state);
414 mutex_unlock(&dsp->lock);
418 static int display_resume(struct device *dev)
420 struct rk_display_device *dsp = dev_get_drvdata(dev);
422 mutex_lock(&dsp->lock);
423 if (likely(dsp->driver->resume))
424 dsp->driver->resume(dsp);
425 mutex_unlock(&dsp->lock);
429 int display_add_videomode(const struct fb_videomode *mode,
430 struct list_head *head)
432 struct list_head *pos;
433 struct display_modelist *modelist;
434 struct fb_videomode *m;
437 list_for_each(pos, head) {
438 modelist = list_entry(pos, struct display_modelist, list);
440 if (fb_mode_is_equal(m, mode)) {
446 modelist = kmalloc(sizeof(*modelist),
451 modelist->mode = *mode;
452 list_add(&modelist->list, head);
457 void rk_display_device_enable(struct rk_display_device *ddev)
459 struct list_head *pos, *head;
460 struct rk_display_device *dev = NULL, *dev_enabled = NULL;
461 struct rk_display_device *dev_enable = NULL;
462 int enable = 0, connect;
464 if (ddev->property == DISPLAY_MAIN)
465 head = &main_display_device_list;
467 head = &aux_display_device_list;
469 list_for_each(pos, head) {
470 dev = list_entry(pos, struct rk_display_device, list);
471 enable = dev->ops->getenable(dev);
472 connect = dev->ops->getstatus(dev);
478 /* If no device is connected, enable highest priority device. */
479 if (dev_enable == NULL) {
480 dev->ops->setenable(dev, 1);
484 if (dev_enable == dev_enabled) {
485 if (dev_enable != ddev)
486 ddev->ops->setenable(ddev, 0);
489 dev_enabled->priority != DISPLAY_PRIORITY_HDMI)
490 dev_enabled->ops->setenable(dev_enabled, 0);
491 dev_enable->ops->setenable(dev_enable, 1);
494 EXPORT_SYMBOL(rk_display_device_enable);
496 void rk_display_device_enable_other(struct rk_display_device *ddev)
498 #ifndef CONFIG_DISPLAY_AUTO_SWITCH
501 struct list_head *pos, *head;
502 struct rk_display_device *dev;
505 if (ddev->property == DISPLAY_MAIN)
506 head = &main_display_device_list;
508 head = &aux_display_device_list;
510 list_for_each_prev(pos, head) {
511 dev = list_entry(pos, struct rk_display_device, list);
513 connect = dev->ops->getstatus(dev);
515 dev->ops->setenable(dev, 1);
522 EXPORT_SYMBOL(rk_display_device_enable_other);
524 void rk_display_device_disable_other(struct rk_display_device *ddev)
526 #ifndef CONFIG_DISPLAY_AUTO_SWITCH
529 struct list_head *pos, *head;
530 struct rk_display_device *dev;
533 if (ddev->property == DISPLAY_MAIN)
534 head = &main_display_device_list;
536 head = &aux_display_device_list;
538 list_for_each(pos, head) {
539 dev = list_entry(pos, struct rk_display_device, list);
541 enable = dev->ops->getenable(dev);
543 dev->ops->setenable(dev, 0);
546 ddev->ops->setenable(ddev, 1);
549 EXPORT_SYMBOL(rk_display_device_disable_other);
551 void rk_display_device_select(int property, int priority)
553 struct list_head *pos, *head;
554 struct rk_display_device *dev;
555 int enable, found = 0;
557 if (property == DISPLAY_MAIN)
558 head = &main_display_device_list;
560 head = &aux_display_device_list;
562 list_for_each(pos, head) {
563 dev = list_entry(pos, struct rk_display_device, list);
564 if (dev->priority == priority)
569 pr_err("[%s] select display interface %d not exist\n",
574 list_for_each(pos, head) {
575 dev = list_entry(pos, struct rk_display_device, list);
576 enable = dev->ops->getenable(dev);
577 if (dev->priority == priority) {
579 dev->ops->setenable(dev, 1);
581 dev->ops->setenable(dev, 0);
585 EXPORT_SYMBOL(rk_display_device_select);
586 static struct mutex allocated_dsp_lock;
587 static DEFINE_IDR(allocated_dsp);
588 static struct class *display_class;
590 struct rk_display_device
591 *rk_display_device_register(struct rk_display_driver *driver,
592 struct device *parent, void *devdata)
594 struct rk_display_device *new_dev = NULL;
597 if (unlikely(!driver))
600 new_dev = kzalloc(sizeof(*new_dev), GFP_KERNEL);
601 if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
602 /* Reserve the index for this display */
603 mutex_lock(&allocated_dsp_lock);
604 new_dev->idx = idr_alloc(&allocated_dsp, new_dev,
606 mutex_unlock(&allocated_dsp_lock);
608 if (new_dev->idx >= 0) {
609 if (new_dev->property == DISPLAY_MAIN)
611 device_create(display_class, parent,
612 MKDEV(0, 0), new_dev,
613 "%s", new_dev->type);
616 device_create(display_class, parent,
617 MKDEV(0, 0), new_dev,
621 if (!IS_ERR(new_dev->dev)) {
622 new_dev->parent = parent;
623 new_dev->driver = driver;
625 new_dev->dev->driver = parent->driver;
626 mutex_init(&new_dev->lock);
627 /* Add new device to display device list. */
629 struct list_head *pos, *head;
630 struct rk_display_device *dev;
632 if (new_dev->property == DISPLAY_MAIN)
633 head = &main_display_device_list;
635 head = &aux_display_device_list;
637 list_for_each(pos, head) {
640 struct rk_display_device,
642 if (dev->priority > new_dev->priority)
645 list_add_tail(&new_dev->list, pos);
649 mutex_lock(&allocated_dsp_lock);
650 idr_remove(&allocated_dsp, new_dev->idx);
651 mutex_unlock(&allocated_dsp_lock);
658 EXPORT_SYMBOL(rk_display_device_register);
660 void rk_display_device_unregister(struct rk_display_device *ddev)
665 mutex_lock(&ddev->lock);
666 device_unregister(ddev->dev);
667 mutex_unlock(&ddev->lock);
668 /* Mark device index as avaliable */
669 mutex_lock(&allocated_dsp_lock);
670 idr_remove(&allocated_dsp, ddev->idx);
671 mutex_unlock(&allocated_dsp_lock);
672 list_del(&ddev->list);
675 EXPORT_SYMBOL(rk_display_device_unregister);
677 static int __init rk_display_class_init(void)
679 display_class = class_create(THIS_MODULE, "display");
680 if (IS_ERR(display_class)) {
681 pr_err("Failed to create display class\n");
682 display_class = NULL;
685 display_class->dev_attrs = display_attrs;
686 display_class->suspend = display_suspend;
687 display_class->resume = display_resume;
688 mutex_init(&allocated_dsp_lock);
689 INIT_LIST_HEAD(&main_display_device_list);
690 INIT_LIST_HEAD(&aux_display_device_list);
694 static void __exit rk_display_class_exit(void)
696 class_destroy(display_class);
699 subsys_initcall(rk_display_class_init);
700 module_exit(rk_display_class_exit);
703 MODULE_AUTHOR("zhengyang@rock-chips.com");
704 MODULE_DESCRIPTION("Driver for rk display device");
705 MODULE_LICENSE("GPL");