drm: Add drm backlight subsystem support
authorDonghwa Lee <dh09.lee@samsung.com>
Thu, 26 Sep 2013 05:31:08 +0000 (14:31 +0900)
committerChanho Park <chanho61.park@samsung.com>
Tue, 18 Nov 2014 02:44:48 +0000 (11:44 +0900)
Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
drivers/gpu/drm/drm_backlight.c [new file with mode: 0644]
drivers/video/backlight/lcd.c
include/drm/drm_backlight.h [new file with mode: 0644]

diff --git a/drivers/gpu/drm/drm_backlight.c b/drivers/gpu/drm/drm_backlight.c
new file mode 100644 (file)
index 0000000..0974bcb
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <drm/drm_backlight.h>
+#include <drm/drm_mode.h>
+
+static DEFINE_MUTEX(drm_bl_mutex);
+static LIST_HEAD(drm_bl_list);
+
+struct drm_bl_data {
+       struct device *dev;
+       struct list_head list;
+       int type;
+};
+
+int drm_bl_register(struct device *dev, int type)
+{
+       struct drm_bl_data *data;
+
+       switch (type) {
+       case BL_BACKLIGHT_CLASS:
+       case BL_LCD_CLASS:
+       case BL_TSP_CLASS:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       data = kzalloc(sizeof(struct drm_bl_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->dev = dev;
+       data->type = type;
+
+       mutex_lock(&drm_bl_mutex);
+       list_add(&data->list, &drm_bl_list);
+       mutex_unlock(&drm_bl_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(drm_bl_register);
+
+void drm_bl_unregister(struct device *dev)
+{
+       struct drm_bl_data *data;
+
+       list_for_each_entry(data, &drm_bl_list, list) {
+               if (data->dev == dev) {
+                       mutex_lock(&drm_bl_mutex);
+                       list_del(&data->list);
+                       mutex_unlock(&drm_bl_mutex);
+                       kfree(data);
+                       break;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(drm_bl_unregister);
+
+/* This is called from dpms function of CRTC or encoder */
+void drm_bl_dpms(int mode)
+{
+       struct drm_bl_data *data;
+       struct backlight_device *bd;
+       struct lcd_device *ld;
+       struct drm_bl_notifier *bl_noti;
+       int blank;
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               blank = FB_BLANK_UNBLANK;
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               /* TODO */
+       default:
+               blank = FB_BLANK_POWERDOWN;
+               break;
+       }
+
+       list_for_each_entry(data, &drm_bl_list, list) {
+               switch (data->type) {
+               case BL_BACKLIGHT_CLASS:
+                       bd = container_of(data->dev, struct backlight_device,
+                                       dev);
+                       bd->props.power = blank;
+                       bd->props.fb_blank = blank;
+                       backlight_update_status(bd);
+                       break;
+               case BL_LCD_CLASS:
+                       ld = container_of(data->dev, struct lcd_device, dev);
+                       if (!ld->ops->set_power)
+                               break;
+                       ld->ops->set_power(ld, blank);
+                       break;
+               case BL_TSP_CLASS:
+                       bl_noti = container_of(data->dev,
+                                       struct drm_bl_notifier, dev);
+                       if (!bl_noti->set_power)
+                               break;
+                       bl_noti->set_power(bl_noti->priv, blank);
+                       break;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(drm_bl_dpms);
index 34fb6bd..3a42b2c 100644 (file)
 #include <linux/fb.h>
 #include <linux/slab.h>
 
+#ifdef CONFIG_DRM
+#include <drm/drm_backlight.h>
+#endif
+
 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
                           defined(CONFIG_LCD_CLASS_DEVICE_MODULE))
 /* This callback gets called when something important happens inside a
@@ -236,6 +240,10 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent,
 
        new_ld->ops = ops;
 
+#ifdef CONFIG_DRM
+       drm_bl_register(&new_ld->dev, BL_LCD_CLASS);
+#endif
+
        return new_ld;
 }
 EXPORT_SYMBOL(lcd_device_register);
@@ -251,6 +259,10 @@ void lcd_device_unregister(struct lcd_device *ld)
        if (!ld)
                return;
 
+#ifdef CONFIG_DRM
+       drm_bl_unregister(&ld->dev);
+#endif
+
        mutex_lock(&ld->ops_lock);
        ld->ops = NULL;
        mutex_unlock(&ld->ops_lock);
diff --git a/include/drm/drm_backlight.h b/include/drm/drm_backlight.h
new file mode 100644 (file)
index 0000000..cbc4380
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+enum drm_bl_class_type {
+       BL_BACKLIGHT_CLASS,
+       BL_LCD_CLASS,
+       BL_TSP_CLASS
+};
+
+struct drm_bl_notifier {
+       struct device dev;
+       void (*set_power)(void *priv, int power);
+       void *priv;
+};
+
+extern int drm_bl_register(struct device *dev, int type);
+extern void drm_bl_unregister(struct device *dev);
+extern void drm_bl_dpms(int mode);