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 display_device_list;
10 static ssize_t display_show_name(struct device *dev,
11 struct device_attribute *attr, char *buf)
13 struct rk_display_device *dsp = dev_get_drvdata(dev);
14 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
17 static ssize_t display_show_type(struct device *dev,
18 struct device_attribute *attr, char *buf)
20 struct rk_display_device *dsp = dev_get_drvdata(dev);
21 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
24 static ssize_t display_show_enable(struct device *dev,
25 struct device_attribute *attr, char *buf)
27 struct rk_display_device *dsp = dev_get_drvdata(dev);
29 if(dsp->ops && dsp->ops->getenable)
30 enable = dsp->ops->getenable(dsp);
33 return snprintf(buf, PAGE_SIZE, "%d\n", enable);
36 static ssize_t display_store_enable(struct device *dev,
37 struct device_attribute *attr,
38 const char *buf, size_t size)
40 struct rk_display_device *dsp = dev_get_drvdata(dev);
43 sscanf(buf, "%d", &enable);
44 if(dsp->ops && dsp->ops->setenable)
45 dsp->ops->setenable(dsp, enable);
49 static ssize_t display_show_connect(struct device *dev,
50 struct device_attribute *attr, char *buf)
52 struct rk_display_device *dsp = dev_get_drvdata(dev);
54 if(dsp->ops && dsp->ops->getstatus)
55 connect = dsp->ops->getstatus(dsp);
58 return snprintf(buf, PAGE_SIZE, "%d\n", connect);
61 static int mode_string(char *buf, unsigned int offset,
62 const struct fb_videomode *mode)
67 // if (mode->flag & FB_MODE_IS_DETAILED)
69 // if (mode->flag & FB_MODE_IS_VESA)
71 // if (mode->flag & FB_MODE_IS_STANDARD)
74 if (mode->vmode & FB_VMODE_INTERLACED)
76 if (mode->vmode & FB_VMODE_DOUBLE)
79 return snprintf(&buf[offset], PAGE_SIZE - offset, "%dx%d%c-%d\n",
80 mode->xres, mode->yres, v, mode->refresh);
82 static ssize_t display_show_modes(struct device *dev,
83 struct device_attribute *attr, char *buf)
85 struct rk_display_device *dsp = dev_get_drvdata(dev);
86 struct list_head *modelist, *pos;
87 struct fb_modelist *fb_modelist;
88 const struct fb_videomode *mode;
90 if(dsp->ops && dsp->ops->getmodelist)
92 if(dsp->ops->getmodelist(dsp, &modelist))
99 list_for_each(pos, modelist) {
100 fb_modelist = list_entry(pos, struct fb_modelist, list);
101 mode = &fb_modelist->mode;
102 i += mode_string(buf, i, mode);
107 static ssize_t display_show_mode(struct device *dev,
108 struct device_attribute *attr, char *buf)
110 struct rk_display_device *dsp = dev_get_drvdata(dev);
111 struct fb_videomode mode;
113 if(dsp->ops && dsp->ops->getmode)
114 if(dsp->ops->getmode(dsp, &mode) == 0)
115 return mode_string(buf, 0, &mode);
119 static ssize_t display_store_mode(struct device *dev,
120 struct device_attribute *attr,
121 const char *buf, size_t count)
123 struct rk_display_device *dsp = dev_get_drvdata(dev);
125 struct list_head *modelist, *pos;
126 struct fb_modelist *fb_modelist;
127 struct fb_videomode *mode;
130 if(dsp->ops && dsp->ops->getmodelist)
132 if(dsp->ops && dsp->ops->getmodelist)
134 if(dsp->ops->getmodelist(dsp, &modelist))
137 list_for_each(pos, modelist) {
138 fb_modelist = list_entry(pos, struct fb_modelist, list);
139 mode = &fb_modelist->mode;
140 i = mode_string(mstr, 0, mode);
141 if (strncmp(mstr, buf, max(count, i)) == 0) {
142 if(dsp->ops && dsp->ops->setmode)
143 dsp->ops->setmode(dsp, mode);
151 static ssize_t display_show_scale(struct device *dev,
152 struct device_attribute *attr, char *buf)
154 struct rk_display_device *dsp = dev_get_drvdata(dev);
157 if(dsp->ops && dsp->ops->getscale) {
158 xscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_X);
159 yscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_Y);
161 return snprintf(buf, PAGE_SIZE, "xscale=%d yscale=%d\n", xscale, yscale);
166 static ssize_t display_store_scale(struct device *dev,
167 struct device_attribute *attr,
168 const char *buf, size_t count)
170 struct rk_display_device *dsp = dev_get_drvdata(dev);
173 if(dsp->ops && dsp->ops->setscale) {
174 if(!strncmp(buf, "xscale", 6)) {
175 sscanf(buf, "xscale=%d", &scale);
176 dsp->ops->setscale(dsp, DISPLAY_SCALE_X, scale);
178 else if(!strncmp(buf, "yscale", 6)) {
179 sscanf(buf, "yscale=%d", &scale);
180 dsp->ops->setscale(dsp, DISPLAY_SCALE_Y, scale);
183 sscanf(buf, "%d", &scale);
184 dsp->ops->setscale(dsp, DISPLAY_SCALE_X, scale);
185 dsp->ops->setscale(dsp, DISPLAY_SCALE_Y, scale);
192 static ssize_t display_show_debug(struct device *dev,
193 struct device_attribute *attr, char *buf)
198 static ssize_t display_store_debug(struct device *dev,
199 struct device_attribute *attr,
200 const char *buf, size_t count)
203 struct rk_display_device *dsp = dev_get_drvdata(dev);
205 if(dsp->ops && dsp->ops->setdebug) {
206 sscanf(buf, "%d", &cmd);
207 dsp->ops->setdebug(dsp, cmd);
213 static ssize_t display_show_sinkaudioinfo(struct device *dev,
214 struct device_attribute *attr, char *buf)
216 struct rk_display_device *dsp = dev_get_drvdata(dev);
220 if(dsp->ops && dsp->ops->getedidaudioinfo) {
221 ret = dsp->ops->getedidaudioinfo(dsp, audioinfo, 200);
223 return snprintf(buf, PAGE_SIZE, "%s\n", audioinfo);
231 static ssize_t display_show_monspecs(struct device *dev,
232 struct device_attribute *attr, char *buf)
234 struct rk_display_device *dsp = dev_get_drvdata(dev);
235 struct fb_monspecs monspecs;
237 if(dsp->ops && dsp->ops->getmonspecs) {
238 ret = dsp->ops->getmonspecs(dsp,&monspecs);
240 memcpy(buf, &monspecs, sizeof(struct fb_monspecs));
241 return sizeof(struct fb_monspecs);//snprintf(buf, PAGE_SIZE, "%s\n", monspecs.monitor);
248 static struct device_attribute display_attrs[] = {
249 __ATTR(name, S_IRUGO, display_show_name, NULL),
250 __ATTR(type, S_IRUGO, display_show_type, NULL),
251 __ATTR(enable, 0664, display_show_enable, display_store_enable),
252 __ATTR(connect, S_IRUGO, display_show_connect, NULL),
253 __ATTR(modes, S_IRUGO, display_show_modes, NULL),
254 __ATTR(mode, 0664, display_show_mode, display_store_mode),
255 __ATTR(scale, 0664, display_show_scale, display_store_scale),
256 __ATTR(debug, 0664, display_show_debug, display_store_debug),
257 __ATTR(audioinfo, S_IRUGO, display_show_sinkaudioinfo, NULL),
258 __ATTR(monspecs, S_IRUGO, display_show_monspecs, NULL),
262 static int display_suspend(struct device *dev, pm_message_t state)
264 struct rk_display_device *dsp = dev_get_drvdata(dev);
266 mutex_lock(&dsp->lock);
267 if (likely(dsp->driver->suspend))
268 dsp->driver->suspend(dsp, state);
269 mutex_unlock(&dsp->lock);
273 static int display_resume(struct device *dev)
275 struct rk_display_device *dsp = dev_get_drvdata(dev);
277 mutex_lock(&dsp->lock);
278 if (likely(dsp->driver->resume))
279 dsp->driver->resume(dsp);
280 mutex_unlock(&dsp->lock);
284 void rk_display_device_enable(struct rk_display_device *ddev)
286 //#ifndef CONFIG_DISPLAY_AUTO_SWITCH
289 struct list_head *pos, *head = &display_device_list;
290 struct rk_display_device *dev = NULL, *dev_enabled = NULL, *dev_enable = NULL;
291 int enable = 0,connect;
293 list_for_each(pos, head) {
294 dev = list_entry(pos, struct rk_display_device, list);
295 enable = dev->ops->getenable(dev);
296 connect = dev->ops->getstatus(dev);
302 // If no device is connected, enable highest priority device.
303 if(dev_enable == NULL) {
304 dev->ops->setenable(dev, 1);
308 if(dev_enable == dev_enabled) {
309 if(dev_enable != ddev)
310 ddev->ops->setenable(ddev, 0);
314 dev_enabled->ops->setenable(dev_enabled, 0);
315 dev_enable->ops->setenable(dev_enable, 1);
321 EXPORT_SYMBOL(rk_display_device_enable);
323 void rk_display_device_enable_other(struct rk_display_device *ddev)
325 #ifndef CONFIG_DISPLAY_AUTO_SWITCH
328 struct list_head *pos, *head = &display_device_list;
329 struct rk_display_device *dev;
332 list_for_each_prev(pos, head) {
333 dev = list_entry(pos, struct rk_display_device, list);
336 connect = dev->ops->getstatus(dev);
339 dev->ops->setenable(dev, 1);
346 EXPORT_SYMBOL(rk_display_device_enable_other);
348 void rk_display_device_disable_other(struct rk_display_device *ddev)
350 #ifndef CONFIG_DISPLAY_AUTO_SWITCH
353 struct list_head *pos, *head = &display_device_list;
354 struct rk_display_device *dev;
357 list_for_each(pos, head) {
358 dev = list_entry(pos, struct rk_display_device, list);
361 enable = dev->ops->getenable(dev);
363 dev->ops->setenable(dev, 0);
366 ddev->ops->setenable(ddev, 1);
369 EXPORT_SYMBOL(rk_display_device_disable_other);
371 void rk_display_device_select(int priority)
373 struct list_head *pos, *head = &display_device_list;
374 struct rk_display_device *dev;
375 int enable, found = 0;
377 list_for_each(pos, head) {
378 dev = list_entry(pos, struct rk_display_device, list);
379 if(dev->priority == priority)
385 printk("[%s] select display interface %d not exist\n", __FUNCTION__, priority);
389 list_for_each(pos, head) {
390 dev = list_entry(pos, struct rk_display_device, list);
391 enable = dev->ops->getenable(dev);
392 if(dev->priority == priority)
395 dev->ops->setenable(dev, 1);
398 dev->ops->setenable(dev, 0);
401 EXPORT_SYMBOL(rk_display_device_select);
402 static struct mutex allocated_dsp_lock;
403 static DEFINE_IDR(allocated_dsp);
404 static struct class *display_class;
406 struct rk_display_device *rk_display_device_register(struct rk_display_driver *driver,
407 struct device *parent, void *devdata)
409 struct rk_display_device *new_dev = NULL;
412 if (unlikely(!driver))
415 new_dev = kzalloc(sizeof(struct rk_display_device), GFP_KERNEL);
416 if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
417 // Reserve the index for this display
418 mutex_lock(&allocated_dsp_lock);
419 new_dev->idx = idr_alloc(&allocated_dsp, new_dev, 0, 0, GFP_KERNEL);
420 mutex_unlock(&allocated_dsp_lock);
422 if (new_dev->idx >= 0) {
423 new_dev->dev = device_create(display_class, parent,
424 MKDEV(0, 0), new_dev,
425 "%s", new_dev->type);
426 if (!IS_ERR(new_dev->dev)) {
427 new_dev->parent = parent;
428 new_dev->driver = driver;
430 new_dev->dev->driver = parent->driver;
431 mutex_init(&new_dev->lock);
432 // Add new device to display device list.
434 struct list_head *pos, *head = &display_device_list;
435 struct rk_display_device *dev;
437 list_for_each(pos, head) {
438 dev = list_entry(pos, struct rk_display_device, list);
439 if(dev->priority > new_dev->priority)
442 list_add_tail(&new_dev->list, pos);
446 mutex_lock(&allocated_dsp_lock);
447 idr_remove(&allocated_dsp, new_dev->idx);
448 mutex_unlock(&allocated_dsp_lock);
455 EXPORT_SYMBOL(rk_display_device_register);
457 void rk_display_device_unregister(struct rk_display_device *ddev)
462 mutex_lock(&ddev->lock);
463 device_unregister(ddev->dev);
464 mutex_unlock(&ddev->lock);
465 // Mark device index as avaliable
466 mutex_lock(&allocated_dsp_lock);
467 idr_remove(&allocated_dsp, ddev->idx);
468 mutex_unlock(&allocated_dsp_lock);
469 list_del(&ddev->list);
472 EXPORT_SYMBOL(rk_display_device_unregister);
474 static int __init rk_display_class_init(void)
476 display_class = class_create(THIS_MODULE, "display");
477 if (IS_ERR(display_class)) {
478 printk(KERN_ERR "Failed to create display class\n");
479 display_class = NULL;
482 display_class->dev_attrs = display_attrs;
483 display_class->suspend = display_suspend;
484 display_class->resume = display_resume;
485 mutex_init(&allocated_dsp_lock);
486 INIT_LIST_HEAD(&display_device_list);
490 static void __exit rk_display_class_exit(void)
492 class_destroy(display_class);
495 subsys_initcall(rk_display_class_init);
496 module_exit(rk_display_class_exit);
499 MODULE_AUTHOR("zhengyang@rock-chips.com");
500 MODULE_DESCRIPTION("Driver for rk display device");
501 MODULE_LICENSE("GPL");