LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* two patches - request for comments
@ 2004-05-28 21:20 Andrew Zabolotny
  2004-05-28 21:59 ` Todd Poynor
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Andrew Zabolotny @ 2004-05-28 21:20 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg KH

[-- Attachment #1: Type: text/plain, Size: 1003 bytes --]

Hello!

I'm going to submit the class_find_device() patch (attached for your
convenience) as a pre-requisite for the backlight/lcd device class patch
(also included so that you can take at it as well) via Russel King (the
backlight/lcd patch is needed for our ARM-based handhelds framebuffer
devices). Any comments/objections are welcome.

The LCD and backlight device classes were implemented with the following in
mind:

a) Allow user-mode code to control backlight and lcd (notably for
handhelds this is a must). This is done via sysfs (/sys/class/backlight/XXX/
and /sys/class/lcd/XXX/ where XXX is something like mq1100fb0).

b) Allow framebuffer devices to find and contact the respective backlight and
lcd devices (they are using the same name as the framebuffer device). This is
needed to implement the respective calls to backlight and lcd devices for
power management.

--
Greetings,
   Andrew

P.S. I've posted a similar message on linux-fbdev mailing listt; forgive me if
you seen it twice.

[-- Attachment #2: class.diff --]
[-- Type: application/octet-stream, Size: 2520 bytes --]

--- linux-2.6.6/drivers/base/class.c	2004-05-10 06:33:21.000000000 +0400
+++ linux-2.6.6-hh0/drivers/base/class.c	2004-05-25 15:17:57.000000000 +0400
@@ -359,7 +359,7 @@
 	class_device_put(class_dev);
 }
 
-int class_device_rename(struct class_device *class_dev, char *new_name)
+int class_device_rename(struct class_device *class_dev, const char *new_name)
 {
 	class_dev = class_device_get(class_dev);
 	if (!class_dev)
@@ -377,6 +377,33 @@
 	return 0;
 }
 
+/**
+ * class_device_find - find a struct class_device in a specific class
+ * @class: the class to search
+ * @class_id: the class_id to search for
+ *
+ * Iterates through the list of all class devices registered to a class. If
+ * the class_id is found, its reference count is incremented and returned to
+ * the caller. If the class_id does not match any existing struct class_device
+ * registered to this struct class, then NULL is returned.
+ */
+struct class_device * class_device_find(struct class *class, const char *class_id)
+{
+	struct class_device *class_dev;
+	struct class_device *found = NULL;
+
+	down_read(&class->subsys.rwsem);
+	list_for_each_entry(class_dev, &class->children, node) {
+		if (strcmp(class_dev->class_id, class_id) == 0) {
+			found = class_device_get(class_dev);
+			break;
+		}
+	}
+	up_read(&class->subsys.rwsem);
+
+	return found;
+}
+
 struct class_device * class_device_get(struct class_device *class_dev)
 {
 	if (class_dev)
@@ -389,7 +416,6 @@
 	kobject_put(&class_dev->kobj);
 }
 
-
 int class_interface_register(struct class_interface *class_intf)
 {
 	struct class * parent;
@@ -468,6 +494,8 @@
 EXPORT_SYMBOL(class_device_put);
 EXPORT_SYMBOL(class_device_create_file);
 EXPORT_SYMBOL(class_device_remove_file);
+EXPORT_SYMBOL(class_device_rename);
+EXPORT_SYMBOL(class_device_find);
 
 EXPORT_SYMBOL(class_interface_register);
 EXPORT_SYMBOL(class_interface_unregister);
--- linux-2.6.6/include/linux/device.h	2004-05-10 06:33:19.000000000 +0400
+++ linux-2.6.6-hh0/include/linux/device.h	2004-05-25 01:54:30.000000000 +0400
@@ -212,8 +212,9 @@
 extern int class_device_add(struct class_device *);
 extern void class_device_del(struct class_device *);
 
-extern int class_device_rename(struct class_device *, char *);
+extern int class_device_rename(struct class_device *, const char *);
 
+extern struct class_device * class_device_find(struct class *class, const char *class_id);
 extern struct class_device * class_device_get(struct class_device *);
 extern void class_device_put(struct class_device *);
 

[-- Attachment #3: bl-lcd.diff --]
[-- Type: application/octet-stream, Size: 23553 bytes --]

--- linux-2.6.6/include/linux/lcd.h	1970-01-01 03:00:00.000000000 +0300
+++ linux-2.6.6-hh0/include/linux/lcd.h	2004-05-27 22:48:18.000000000 +0400
@@ -0,0 +1,60 @@
+/*
+ * LCD Lowlevel Control Abstraction
+ * 
+ * Copyright (C) 2003,2004 Hewlett-Packard Company
+ * 
+ */
+
+#ifndef _LINUX_LCD_H
+#define _LINUX_LCD_H
+
+#include <linux/device.h>
+
+struct lcd_device;
+
+/* This structure defines all the properties of a LCD flat panel. */
+struct lcd_properties {
+	/* Owner module */
+	struct module *owner;
+	/* Get the power enabled status (0/1) */
+	int (*get_power) (struct lcd_device *);
+	/* Enable or disable power to the LCD */
+	int (*set_power) (struct lcd_device *, int power);
+	/* Get the LCD controller enabled status (0/1) */
+	int (*get_enable) (struct lcd_device *);
+	/* Enable or disable the LCD controller */
+	int (*set_enable) (struct lcd_device *, int enable);
+	/* The maximum value for contrast (read-only) */
+	int max_contrast;
+	/* Get the current contrast setting (0-max_contrast) */
+	int (*get_contrast) (struct lcd_device *);
+	/* Set LCD panel contrast */
+	int (*set_contrast) (struct lcd_device *, int contrast);
+};
+
+struct lcd_device {
+	/* This protects the 'props' field. If 'props' is NULL, the driver that
+	   registered this device has been unloaded, and if class_devdata()
+	   points to something in the body of that driver, it is also invalid. */
+	struct semaphore sem;
+	/* If this is NULL, the backing module is unloaded */
+	struct lcd_properties *props;
+	/* The class device structure */
+	struct class_device class_dev;
+};
+
+extern int lcd_device_register(const char *name, void *devdata,
+	struct lcd_properties *lp);
+extern void lcd_device_unregister(const char *name);
+
+extern struct lcd_device *lcd_device_find(const char *name);
+extern struct lcd_device *lcd_device_get(struct lcd_device *ld);
+extern void lcd_device_put(struct lcd_device *ld);
+
+#define to_lcd_device(obj) container_of(obj, struct lcd_device, class_dev)
+
+/* The registered clients of this notifier chain will be called every time
+   a new lcd class_device is registered */
+extern struct notifier_block *lcd_device_chain;
+
+#endif
--- linux-2.6.6/include/linux/backlight.h	1970-01-01 03:00:00.000000000 +0300
+++ linux-2.6.6-hh0/include/linux/backlight.h	2004-05-27 22:48:27.000000000 +0400
@@ -0,0 +1,57 @@
+/*
+ * Backlight Lowlevel Control Abstraction
+ * 
+ * Copyright (C) 2003,2004 Hewlett-Packard Company
+ * 
+ */
+
+#ifndef _LINUX_BACKLIGHT_H
+#define _LINUX_BACKLIGHT_H
+
+#include <linux/device.h>
+
+struct backlight_device;
+
+/* This structure defines all the properties of a backlight
+   (usually attached to a LCD). */
+struct backlight_properties {
+	/* Owner module */
+	struct module *owner;
+	/* Get the power enabled status (0/1) */
+	int (*get_power) (struct backlight_device *);
+	/* Enable or disable power to the LCD */
+	int (*set_power) (struct backlight_device *, int power);
+	/* Maximal value for brightness (read-only) */
+	int max_brightness;
+	/* Get current backlight brightness */
+	int (*get_brightness) (struct backlight_device *);
+	/* Set backlight brightness (0..max_brightness) */
+	int (*set_brightness) (struct backlight_device *, int brightness);
+};
+
+struct backlight_device {
+	/* This protects the 'props' field. If 'props' is NULL, the driver that
+	   registered this device has been unloaded, and if class_devdata()
+	   points to something in the body of that driver, it is also invalid. */
+	struct semaphore sem;
+	/* If this is NULL, the backing module is unloaded */
+	struct backlight_properties *props;
+	/* The class device structure */
+	struct class_device class_dev;
+};
+
+extern int backlight_device_register(const char *name, void *devdata,
+				     struct backlight_properties *bp);
+extern void backlight_device_unregister(const char *name);
+
+extern struct backlight_device *backlight_device_find(const char *name);
+extern struct backlight_device *backlight_device_get(struct backlight_device *bd);
+extern void backlight_device_put(struct backlight_device *bd);
+
+#define to_backlight_device(obj) container_of(obj, struct backlight_device, class_dev)
+
+/* The registered clients of this notifier chain will be called every time
+   a new backlight class_device is registered */
+extern struct notifier_block *backlight_device_chain;
+
+#endif
--- linux-2.6.6/drivers/video/lcd.c	1970-01-01 03:00:00.000000000 +0300
+++ linux-2.6.6-hh0/drivers/video/lcd.c	2004-05-29 01:00:52.000000000 +0400
@@ -0,0 +1,339 @@
+/*
+ * LCD Lowlevel Control Abstraction
+ * 
+ * Copyright (C) 2003,2004 Hewlett-Packard Company
+ * 
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/lcd.h>
+#include <linux/notifier.h>
+#include <linux/ctype.h>
+#include <asm/bug.h>
+
+struct notifier_block *lcd_device_chain;
+EXPORT_SYMBOL (lcd_device_chain);
+
+static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
+{
+	int rc;
+	struct lcd_device *ld = to_lcd_device(cdev);
+
+	down (&ld->sem);
+	if (likely (ld->props && ld->props->get_power))
+		rc = sprintf (buf, "%d\n", ld->props->get_power (ld));
+	else
+		rc = -ENXIO;
+	up (&ld->sem);
+
+	return rc;
+}
+
+static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_t count)
+{
+	int rc, power;
+	char *endp;
+	struct lcd_device *ld = to_lcd_device(cdev);
+
+	power = simple_strtoul(buf, &endp, 0);
+	if (*endp && !isspace (*endp))
+		return -EINVAL;
+
+	down (&ld->sem);
+	if (likely (ld->props && ld->props->set_power)) {
+		pr_debug("lcd: set power to %d\n", power);
+		ld->props->set_power(ld, power);
+		rc = count;
+	} else
+		rc = -ENXIO;
+	up (&ld->sem);
+
+	return rc;
+}
+
+static ssize_t lcd_show_enable(struct class_device *cdev, char *buf)
+{
+	int rc;
+	struct lcd_device *ld = to_lcd_device(cdev);
+
+	down (&ld->sem);
+	if (likely(ld->props && ld->props->get_enable))
+		rc = sprintf (buf, "%d\n", ld->props->get_enable(ld));
+	else
+		rc = -ENXIO;
+	up (&ld->sem);
+
+	return rc;
+}
+
+static ssize_t lcd_store_enable(struct class_device *cdev, const char *buf, size_t count)
+{
+	int rc, enable;
+	char *endp;
+	struct lcd_device *ld = to_lcd_device(cdev);
+
+	enable = simple_strtoul(buf, &endp, 0);
+	if (*endp && !isspace (*endp))
+		return -EINVAL;
+
+	down (&ld->sem);
+	if (likely (ld->props && ld->props->set_enable)) {
+		pr_debug("lcd: set enable to %d\n", enable);
+		ld->props->set_enable(ld, enable);
+		rc = count;
+	} else
+		rc = -ENXIO;
+	up (&ld->sem);
+
+	return rc;
+}
+
+static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
+{
+	int rc;
+	struct lcd_device *ld = to_lcd_device(cdev);
+
+	down (&ld->sem);
+	if (likely (ld->props && ld->props->get_contrast))
+		rc = sprintf (buf, "%d\n", ld->props->get_contrast(ld));
+	else
+		rc = -ENXIO;
+	up (&ld->sem);
+
+	return rc;
+}
+
+static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, size_t count)
+{
+	int rc, contrast;
+	char *endp;
+	struct lcd_device *ld = to_lcd_device(cdev);
+
+	contrast = simple_strtoul(buf, &endp, 0);
+	if (*endp && !isspace (*endp))
+		return -EINVAL;
+
+	down (&ld->sem);
+	if (likely (ld->props && ld->props->set_contrast)) {
+		pr_debug("lcd: set contrast to %d\n", contrast);
+		ld->props->set_contrast(ld, contrast);
+		rc = count;
+	} else
+		rc = -ENXIO;
+	up (&ld->sem);
+
+	return rc;
+}
+
+static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf)
+{
+	int rc;
+	struct lcd_device *ld = to_lcd_device(cdev);
+
+	down (&ld->sem);
+	if (likely (ld->props))
+		rc = sprintf (buf, "%d\n", ld->props->max_contrast);
+	else
+		rc = -ENXIO;
+	up (&ld->sem);
+
+	return rc;
+}
+
+static void lcd_class_release(struct class_device *dev)
+{
+	struct lcd_device *ld = to_lcd_device (dev);
+	kfree (ld);
+}
+
+struct class lcd_class = {
+	.name = "lcd",
+	.release = lcd_class_release,
+};
+
+#define DECLARE_ATTR(_name,_mode,_show,_store)			\
+{							 	\
+	.attr	= { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
+	.show	= _show,					\
+	.store	= _store,					\
+}
+
+static struct class_device_attribute lcd_class_device_attributes[] = {
+	DECLARE_ATTR (power, 0644, lcd_show_power, lcd_store_power),
+	DECLARE_ATTR (enable, 0644, lcd_show_enable, lcd_store_enable),
+	DECLARE_ATTR (contrast, 0644, lcd_show_contrast, lcd_store_contrast),
+	DECLARE_ATTR (max_contrast, 0444, lcd_show_max_contrast, NULL),
+};
+
+/**
+ * lcd_device_register - register a new object of lcd_device class.
+ * @name: the name of the new object (must be the same as the name of the
+ *   respective framebuffer device).
+ * @devdata: an optional pointer to be stored in the class_device. The
+ *   methods may retrieve it by using class_get_devdata (ld->class_dev).
+ * @lp: the lcd properties structure.
+ *
+ * Creates a new lcd class_device and copies data from the received ld
+ * structure into the new object. Returns after registering the new object.
+ */
+int lcd_device_register (const char *name, void *devdata,
+			 struct lcd_properties *lp)
+{
+	int i, rc;
+	struct lcd_device *new_ld;
+
+	pr_debug("lcd_device_register: name=%s\n", name);
+
+	new_ld = kmalloc (sizeof (struct lcd_device), GFP_KERNEL);
+	if (unlikely (!new_ld))
+		return -ENOMEM;
+
+	init_MUTEX (&new_ld->sem);
+	new_ld->props = lp;
+	new_ld->class_dev.class = &lcd_class;
+	strlcpy (new_ld->class_dev.class_id, name, KOBJ_NAME_LEN);
+	class_set_devdata (&new_ld->class_dev, devdata);
+	rc = class_device_register (&new_ld->class_dev);
+	if (unlikely (rc)) {
+		kfree (new_ld);
+		return rc;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++) {
+		rc = class_device_create_file(&new_ld->class_dev,
+					      &lcd_class_device_attributes[i]);
+		if (unlikely (rc)) {
+			while (--i >= 0)
+				class_device_remove_file(&new_ld->class_dev,
+							 &lcd_class_device_attributes[i]);
+			class_device_unregister(&new_ld->class_dev);
+			return rc;
+		}
+	}
+
+	notifier_call_chain (&lcd_device_chain, 0, new_ld);
+
+	return 0;
+}
+EXPORT_SYMBOL(lcd_device_register);
+
+/**
+ * lcd_device_unregister - unregisters a object of lcd_device class.
+ * @name: the name of the object (must be the same as the name of the
+ *   respective framebuffer device).
+ *
+ * Unregisters a previously registered via lcd_device_register object.
+ */
+void lcd_device_unregister(const char *name)
+{
+	int i;
+	struct lcd_device *ld;
+	struct class_device *class_dev =
+		class_device_find (&lcd_class, name);
+
+	if (!class_dev)
+		return;
+
+	pr_debug("lcd_device_unregister: name=%s\n", name);
+
+	for (i = 0; i < ARRAY_SIZE (lcd_class_device_attributes); i++)
+		class_device_remove_file (class_dev,
+					  &lcd_class_device_attributes[i]);
+
+	ld = to_lcd_device (class_dev);
+	down (&ld->sem);
+	ld->props = NULL;
+	up (&ld->sem);
+
+	class_device_unregister(class_dev);
+	/* We got the reference counter incremented by class_device_find() */
+	class_device_put(class_dev);
+}
+EXPORT_SYMBOL(lcd_device_unregister);
+
+/**
+ * lcd_device_find - find a LCD device by name.
+ * @name: the name of the LCD object to find.
+ *
+ * The reference counter of the returned object as well as on the module
+ * that implements the backlight functions are incremented.
+ */
+struct lcd_device *lcd_device_find(const char *name)
+{
+	struct lcd_device *ld;
+	struct class_device *class_dev =
+		class_device_find (&lcd_class, name);
+
+	if (unlikely (!class_dev))
+		return NULL;
+
+	ld = lcd_device_get (to_lcd_device (class_dev));
+	class_device_put (class_dev);
+	return ld;
+}
+EXPORT_SYMBOL(lcd_device_find);
+
+/**
+ * lcd_device_get - increment reference counter of a LCD device
+ *   and on the module that implements the LCD device methods.
+ * @ld: the LCD device object.
+ *
+ * Increments the reference counter on both the LCD device and on the
+ * module that implements this LCD device.
+ */
+struct lcd_device *lcd_device_get(struct lcd_device *ld)
+{
+	struct class_device *class_dev = class_device_get (&ld->class_dev);
+
+	if (likely (class_dev)) {
+		down (&ld->sem);
+		if (likely (ld->props && try_module_get (ld->props->owner))) {
+			up (&ld->sem);
+			return ld;
+		}
+		up (&ld->sem);
+
+		class_device_put(class_dev);
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(lcd_device_get);
+
+/**
+ * lcd_device_put - decrement reference counter of a LCD device.
+ * @ld: the LCD device object.
+ *
+ * Decrements the reference counter on both the LCD device and on the
+ * module that implements this LCD device.
+ */
+void lcd_device_put(struct lcd_device *ld)
+{
+	if (ld) {
+		down (&ld->sem);
+		if (ld->props)
+			module_put(ld->props->owner);
+		up (&ld->sem);
+		class_device_put (&ld->class_dev);
+	}
+}
+EXPORT_SYMBOL(lcd_device_put);
+
+static void __exit lcd_class_exit(void)
+{
+	class_unregister(&lcd_class);
+}
+
+static int __init lcd_class_init(void)
+{
+	return class_register(&lcd_class);
+}
+
+/*
+ * if this is compiled into the kernel, we need to ensure that the
+ * class is registered before users of the class try to register lcd's
+ */
+postcore_initcall(lcd_class_init);
+module_exit(lcd_class_exit);
--- linux-2.6.6/drivers/video/backlight.c	1970-01-01 03:00:00.000000000 +0300
+++ linux-2.6.6-hh0/drivers/video/backlight.c	2004-05-29 00:56:53.000000000 +0400
@@ -0,0 +1,301 @@
+/*
+ * Backlight Lowlevel Control Abstraction
+ * 
+ * Copyright (C) 2003,2004 Hewlett-Packard Company
+ * 
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/notifier.h>
+#include <linux/ctype.h>
+#include <asm/bug.h>
+
+struct notifier_block *backlight_device_chain;
+EXPORT_SYMBOL (backlight_device_chain);
+
+static ssize_t backlight_show_power (struct class_device *cdev, char *buf)
+{
+	int rc;
+	struct backlight_device *bd = to_backlight_device (cdev);
+
+	down (&bd->sem);
+	if (likely (bd->props && bd->props->get_power))
+		rc = sprintf (buf, "%d\n", bd->props->get_power (bd));
+	else
+		rc = -ENXIO;
+	up (&bd->sem);
+
+	return rc;
+}
+
+static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
+{
+	int rc, power;
+	char *endp;
+	struct backlight_device *bd = to_backlight_device (cdev);
+
+	power = simple_strtoul (buf, &endp, 0);
+	if (*endp && !isspace (*endp))
+		return -EINVAL;
+
+	down (&bd->sem);
+	if (likely (bd->props && bd->props->set_power)) {
+		pr_debug("backlight: set power to %d\n", power);
+		bd->props->set_power(bd, power);
+		rc = count;
+	} else
+		rc = -ENXIO;
+	up (&bd->sem);
+
+	return rc;
+}
+
+static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
+{
+	int rc;
+	struct backlight_device *bd = to_backlight_device (cdev);
+
+	down (&bd->sem);
+	if (likely (bd->props && bd->props->get_brightness))
+		rc = sprintf (buf, "%d\n", bd->props->get_brightness (bd));
+	else
+		rc = -ENXIO;
+	up (&bd->sem);
+
+	return rc;
+}
+
+static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
+{
+	int rc, brightness;
+	char *endp;
+	struct backlight_device *bd = to_backlight_device (cdev);
+
+	brightness = simple_strtoul (buf, &endp, 0);
+	if (*endp && !isspace (*endp))
+		return -EINVAL;
+
+	down (&bd->sem);
+	if (likely (bd->props && bd->props->set_brightness)) {
+		pr_debug("backlight: set brightness to %d\n", brightness);
+		bd->props->set_brightness(bd, brightness);
+		rc = count;
+	} else
+		rc = -ENXIO;
+	up (&bd->sem);
+
+	return rc;
+}
+
+static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf)
+{
+	int rc;
+	struct backlight_device *bd = to_backlight_device (cdev);
+
+	down (&bd->sem);
+	if (likely (bd->props))
+		rc = sprintf(buf, "%d\n", bd->props->max_brightness);
+	else
+		rc = -ENXIO;
+	up (&bd->sem);
+
+	return rc;
+}
+
+static void backlight_class_release(struct class_device *dev)
+{
+	struct backlight_device *bd = to_backlight_device (dev);
+	kfree (bd);
+}
+
+struct class backlight_class = {
+	.name = "backlight",
+	.release = backlight_class_release,
+};
+
+#define DECLARE_ATTR(_name,_mode,_show,_store)			\
+{							 	\
+	.attr	= { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
+	.show	= _show,					\
+	.store	= _store,					\
+}
+
+static struct class_device_attribute bl_class_device_attributes[] = {
+	DECLARE_ATTR (power, 0644, backlight_show_power, backlight_store_power),
+	DECLARE_ATTR (brightness, 0644, backlight_show_brightness, backlight_store_brightness),
+	DECLARE_ATTR (max_brightness, 0444, backlight_show_max_brightness, NULL),
+};
+
+/**
+ * backlight_device_register - register a new object of backlight_device class.
+ * @name: the name of the new object (must be the same as the name of the
+ *   respective framebuffer device).
+ * @devdata: an optional pointer to be stored in the class_device. The
+ *   methods may retrieve it by using class_get_devdata (&bd->class_dev).
+ * @bp: the backlight properties structure.
+ *
+ * Creates a new backlight class_device. Returns after registering the
+ * new object.
+ */
+int backlight_device_register(const char *name, void *devdata,
+			      struct backlight_properties *bp)
+{
+	int i, rc;
+	struct backlight_device *new_bd;
+
+	pr_debug("backlight_device_register: name=%s\n", name);
+
+	new_bd = kmalloc (sizeof (struct backlight_device), GFP_KERNEL);
+	if (unlikely (!new_bd))
+		return -ENOMEM;
+
+	init_MUTEX (&new_bd->sem);
+	new_bd->props = bp;
+	new_bd->class_dev.class = &backlight_class;
+	strlcpy (new_bd->class_dev.class_id, name, KOBJ_NAME_LEN);
+	class_set_devdata (&new_bd->class_dev, devdata);
+	rc = class_device_register (&new_bd->class_dev);
+	if (unlikely (rc)) {
+		kfree (new_bd);
+		return rc;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++) {
+		rc = class_device_create_file(&new_bd->class_dev,
+					      &bl_class_device_attributes[i]);
+		if (unlikely (rc)) {
+			while (--i >= 0)
+				class_device_remove_file(&new_bd->class_dev,
+							 &bl_class_device_attributes[i]);
+			class_device_unregister(&new_bd->class_dev);
+			return rc;
+		}
+	}
+
+	notifier_call_chain (&backlight_device_chain, 0, new_bd);
+
+	return 0;
+}
+EXPORT_SYMBOL(backlight_device_register);
+
+/**
+ * backlight_device_unregister - unregisters a object of backlight_device class.
+ * @name: the name of the object (must be the same as the name of the
+ *   respective framebuffer device).
+ *
+ * Unregisters a previously registered via backlight_device_register object.
+ */
+void backlight_device_unregister(const char *name)
+{
+	int i;
+	struct backlight_device *bd;
+	struct class_device *class_dev =
+		class_device_find (&backlight_class, name);
+
+	if (!class_dev)
+		return;
+
+	pr_debug("backlight_device_unregister: name=%s\n", name);
+
+	for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++)
+		class_device_remove_file (class_dev,
+                                          &bl_class_device_attributes[i]);
+
+	bd = to_backlight_device (class_dev);
+	down (&bd->sem);
+	bd->props = NULL;
+	up (&bd->sem);
+
+	class_device_unregister(class_dev);
+	/* We got the reference counter incremented by class_device_find() */
+	class_device_put(class_dev);
+}
+EXPORT_SYMBOL(backlight_device_unregister);
+
+/**
+ * backlight_device_find - find a backlight device by name.
+ * @name: the name of the backlight object to find.
+ *
+ * The reference counter of the returned object as well as on the module
+ * that implements the backlight functions are incremented.
+ */
+struct backlight_device *backlight_device_find(const char *name)
+{
+	struct backlight_device *bd;
+	struct class_device *class_dev =
+		class_device_find (&backlight_class, name);
+
+	if (unlikely (!class_dev))
+		return NULL;
+
+	bd = backlight_device_get (to_backlight_device (class_dev));
+	class_device_put (class_dev);
+	return bd;
+}
+EXPORT_SYMBOL(backlight_device_find);
+
+/**
+ * backlight_device_get - increment reference counter of a backlight device
+ *   and on the module that implements the backlight device methods.
+ * @bd: the backlight device object.
+ *
+ * Increments the reference counter on both the backlight device and on the
+ * module that implements this backlight device.
+ */
+struct backlight_device *backlight_device_get(struct backlight_device *bd)
+{
+	struct class_device *class_dev = class_device_get (&bd->class_dev);
+
+	if (likely (class_dev)) {
+		down (&bd->sem);
+		if (likely (bd->props && try_module_get (bd->props->owner))) {
+			up (&bd->sem);
+			return bd;
+		}
+                up (&bd->sem);
+
+		class_device_put(class_dev);
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(backlight_device_get);
+
+/**
+ * backlight_device_put - decrement reference counter of a backlight device.
+ * @ld: the backlight device object.
+ *
+ * Decrements the reference counter on both the backlight device and on the
+ * module that implements this backlight device.
+ */
+void backlight_device_put(struct backlight_device *bd)
+{
+	if (bd) {
+		down (&bd->sem);
+		if (bd->props)
+			module_put(bd->props->owner);
+		up (&bd->sem);
+		class_device_put (&bd->class_dev);
+	}
+}
+EXPORT_SYMBOL(backlight_device_put);
+
+static void __exit backlight_class_exit(void)
+{
+	class_unregister(&backlight_class);
+}
+
+static int __init backlight_class_init(void)
+{
+	return class_register(&backlight_class);
+}
+
+/*
+ * if this is compiled into the kernel, we need to ensure that the
+ * class is registered before users of the class try to register lcd's
+ */
+postcore_initcall(backlight_class_init);
+module_exit(backlight_class_exit);
--- linux-2.6.6/drivers/video/Kconfig	2004-05-10 06:31:59.000000000 +0400
+++ replacement/drivers/video/Kconfig	2004-05-28 23:19:45.000000000 +0400
@@ -38,6 +38,38 @@
 	  (e.g. an accelerated X server) and that are not frame buffer
 	  device-aware may cause unexpected results. If unsure, say N.
 
+config LCD_CLASS_DEVICE
+        tristate "Lowlevel LCD controls"
+	depends on FB
+	help
+	  This framework adds support for low-level control of LCD.
+	  Some framebuffer devices connect to platform-specific LCD modules
+	  in order to have a platform-specific way to control the flat panel
+	  (contrast and applying power to the LCD (not to the backlight!)).
+
+	  To have support for your specific LCD panel you will have to
+	  select the proper drivers which depend on this option.
+
+config LCD_DEVICE
+	bool
+	depends on LCD_CLASS_DEVICE
+	default FB
+
+config BACKLIGHT_CLASS_DEVICE
+        tristate "Lowlevel Backlight controls"
+	depends on FB
+	help
+	  This framework adds support for low-level control of the LCD
+          backlight. This includes support for brightness and power.
+
+	  To have support for your specific LCD panel you will have to
+	  select the proper drivers which depend on this option.
+
+config BACKLIGHT_DEVICE
+	bool
+	depends on BACKLIGHT_CLASS_DEVICE
+	default FB
+
 config FB_CIRRUS
 	tristate "Cirrus Logic support"
 	depends on FB && (AMIGA || PCI) && BROKEN
--- linux-2.6.6/drivers/video/Makefile	2004-05-10 06:32:00.000000000 +0400
+++ replacement/drivers/video/Makefile	2004-05-25 21:29:26.000000000 +0400
@@ -13,6 +13,9 @@
 obj-$(CONFIG_PPC)                 += macmodes.o
 endif
 
+obj-$(CONFIG_LCD_DEVICE)          += lcd.o
+obj-$(CONFIG_BACKLIGHT_DEVICE)    += backlight.o
+
 obj-$(CONFIG_FB_ACORN)            += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
 obj-$(CONFIG_FB_PM2)              += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-05-28 21:20 two patches - request for comments Andrew Zabolotny
@ 2004-05-28 21:59 ` Todd Poynor
  2004-05-29  8:10   ` Andrew Zabolotny
  2004-05-28 22:10 ` Greg KH
  2004-05-29 13:46 ` Denis Vlasenko
  2 siblings, 1 reply; 15+ messages in thread
From: Todd Poynor @ 2004-05-28 21:59 UTC (permalink / raw)
  To: Andrew Zabolotny; +Cc: linux-kernel, Greg KH

Hi, you're adding new interfaces for power management of LCD and 
backlight devices.  Since there's already LDM/sysfs interfaces for 
reading and writing power state of generic devices, is it necessary to 
add ones particular to these devices or device classes?  In other words, 
is /sys/devices/<bus>/<device>/power/state not suitable for these purposes?

And if a PM interface for device classes is needed that ties into the 
device driver suspend/resume callbacks, perhaps it can be modeled more 
closely on the existing interfaces?  These new interfaces seem to be 
intended to define: 0 == power off, 1 ==  power on.  The existing 
ACPI-inspired interfaces use: 0 == power on/full-power, 1/2/3/4 == 
low-power/off state.

New files don't have GPL license comments.

-- 
Todd

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-05-28 21:20 two patches - request for comments Andrew Zabolotny
  2004-05-28 21:59 ` Todd Poynor
@ 2004-05-28 22:10 ` Greg KH
  2004-05-29  8:44   ` Andrew Zabolotny
  2004-05-29 13:46 ` Denis Vlasenko
  2 siblings, 1 reply; 15+ messages in thread
From: Greg KH @ 2004-05-28 22:10 UTC (permalink / raw)
  To: Andrew Zabolotny; +Cc: linux-kernel

On Sat, May 29, 2004 at 01:20:30AM +0400, Andrew Zabolotny wrote:
> Hello!
> 
> I'm going to submit the class_find_device() patch (attached for your
> convenience) as a pre-requisite for the backlight/lcd device class patch
> (also included so that you can take at it as well) via Russel King (the
> backlight/lcd patch is needed for our ARM-based handhelds framebuffer
> devices). Any comments/objections are welcome.
> 
> The LCD and backlight device classes were implemented with the following in
> mind:

Becides the comments that Todd had about the power management stuff, I
have the following comments:
	- please inline your patches, I can't quote them :(
	- you create the DEVICE_ATTR macro, why not use the one already
	  created for you (CLASS_DEVICE_ATTR will work I think.)
	- Don't do a unregister function by passing a string to it.
	  Explicitly pass the pointer of the object that you want to
	  unregister, like all other kernel interfaces do.  With that
	  change you no longer need the class_find_device() patch,
	  right?
	- How about some drivers that actually use this interface?
	  Again, you are creating interfaces with no examples of users
	  of the interface, which isn't acceptable.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-05-28 21:59 ` Todd Poynor
@ 2004-05-29  8:10   ` Andrew Zabolotny
  2004-06-01 20:09     ` Todd Poynor
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Zabolotny @ 2004-05-29  8:10 UTC (permalink / raw)
  To: Todd Poynor; +Cc: linux-kernel, greg

On Fri, 28 May 2004 14:59:53 -0700
Todd Poynor <tpoynor@mvista.com> wrote:

> Hi, you're adding new interfaces for power management of LCD and 
> backlight devices.  Since there's already LDM/sysfs interfaces for 
> reading and writing power state of generic devices, is it necessary to 
> add ones particular to these devices or device classes?  In other words, 
> is /sys/devices/<bus>/<device>/power/state not suitable for these purposes?
Well, first liquid crystal displays and backlight are not connected to any
specific bus. They could, on some platforms, and could not on other. For
example, on some PDAs backlight is controlled via the programmed I/O CPU pins
(GPIO), on other they are connected to some weird companion chips, on third
they could be controlled via the PCI bus (on large PCs, I mean) and so on. So
there will be no easy way for an application to find the backlight devices
and control them. In our case that's easy: opendir ("/sys/class/backlight")
and you found all of them.

On the other hand, the lcd and backlight modules will be used by the
framebuffer device, which in most cases will be itself on a certain bus. And
when the framebuffer device will be powered off, it contacts the corresponding
lcd and backlight devices to power them off as well.

On the third hand (:-) the lcd device class, for example, actually has *two*
power switches: the 'power' and the 'enable' attribute. The first powers off
the liquid crystal display, and seconds powers off the lcd controller. These
are different things and it would be wise to leave them apart, as having finer
grained control is always better. Also they have attributes that are in no way
part of power management: contrast, brightness etc. So these attributes would
have to be spreaded out across the entire sysfs.

On the fourth hand (oh no), what would be the code sequence for a framebuffer
device to find the corresponding lcd and backlight devices? For now that's
done by searching the 'backlight' and 'lcd' device classes for a device with
the same name as the framebuffer device; if we place every device on its own
bus, the framebuffer device will have to search all the buses in the system.
Not speaking that the code will be substantially larger (current code is
already 2-3k for each class, which is alot if we're speaking of embedded
systems).

> And if a PM interface for device classes is needed that ties into the 
> device driver suspend/resume callbacks, perhaps it can be modeled more 
> closely on the existing interfaces?  These new interfaces seem to be 
> intended to define: 0 == power off, 1 ==  power on.  The existing 
> ACPI-inspired interfaces use: 0 == power on/full-power, 1/2/3/4 == 
> low-power/off state.
Um, well, this could be implemented. Although I don't see much reason for a
backlight to be in a "semi-enabled state"; besides if it will remain a
separate class device, it doesn't matter much. But if someone cares, it could
be changed now since there is not much code which depends on that.

> New files don't have GPL license comments.
Indeed, I forgot to add them. Initially they weren't designed to be compiled
as modules.

--
Greetings,
   Andrew

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-05-28 22:10 ` Greg KH
@ 2004-05-29  8:44   ` Andrew Zabolotny
  2004-06-01 21:23     ` Jeff Garzik
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Zabolotny @ 2004-05-29  8:44 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel

On Fri, 28 May 2004 15:10:06 -0700
Greg KH <greg@kroah.com> wrote:

> 	- you create the DEVICE_ATTR macro, why not use the one already
> 	  created for you (CLASS_DEVICE_ATTR will work I think.)
Because it would involve unneeded extra garbage into data segment. See:

CLASS_DEVICE_ATTR(_name,_mode,_show,_store) is:
struct class_device_attribute class_device_attr_##_name = {
  ...
}

DECLARE_ATTR is just:
{ ... }

This way, I cannot use CLASS_DEVICE_ATTR for things like:

static struct class_device_attribute bl_class_device_attributes[] = {
	DECLARE_ATTR(...),
	DECLARE_ATTR(...),
	...
};

Instead, I must declare it this way:

CLASS_DEVICE_ATTR(blah1)
CLASS_DEVICE_ATTR(blah2)
CLASS_DEVICE_ATTR(blah3)

and after that:

struct class_device_attribut *blah_ptr [] = {
	blah1, blah2, blah3
};

The second array is absolutely unneeded here (one garbage pointer for every
device attribute plus alignment), since the array is absolutely static. And
even worse, the array cannot be declared __initdata since devices can
register and unregister at any time.

> 	- Don't do a unregister function by passing a string to it.
> 	  Explicitly pass the pointer of the object that you want to
> 	  unregister, like all other kernel interfaces do.  With that
> 	  change you no longer need the class_find_device() patch,
> 	  right?
No. class_find_device was written for lcd_find_device() and
backlight_find_device() (framebuffer devices use them). On the other hand,
the driver that registers the backlight device doesn't have a pointer to the
class device (well, the lcd_register_device could return it). Since the
lcd/backlight names are unique anyway, I don't see any problems with that, and
moreover, it is *registered* by giving it a name, why it should be
unregistered in a different way?

In any case, if you have strong objections against that, this could be changed
of course. But again, it will result in more useless code/data (the driver
will have to store somewhere the device it has registered, or alternatively,
use lcd/backlight_device_find()).

> 	- How about some drivers that actually use this interface?
> 	  Again, you are creating interfaces with no examples of users
> 	  of the interface, which isn't acceptable.
There are already four drivers that implement the lcd/backlight devices (for
Dell Axim X5, iPAQ 2210, Jornada 560, Rover P5), and three framebuffer devices
that were modified to use it (sa1100fb, pxafb and mq1100fb). I would paste
them here but they are quite large, and I wouldn't like to pollute this list,
it's so high-traffic already.

Instead, you can download them from
http://zap.eltrast.ru/data/backlight-lcd-class-devices.tar.bz2 (~33k).

The full sources are in handhelds.org' public CVS
(:pserver:anoncvs@cvs.handhelds.org:/cvs, repository linux/kernel26).

--
Greetings,
   Andrew

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-05-28 21:20 two patches - request for comments Andrew Zabolotny
  2004-05-28 21:59 ` Todd Poynor
  2004-05-28 22:10 ` Greg KH
@ 2004-05-29 13:46 ` Denis Vlasenko
  2 siblings, 0 replies; 15+ messages in thread
From: Denis Vlasenko @ 2004-05-29 13:46 UTC (permalink / raw)
  To: Andrew Zabolotny, linux-kernel; +Cc: Greg KH

On Saturday 29 May 2004 00:20, Andrew Zabolotny wrote:
> Hello!
>
> I'm going to submit the class_find_device() patch (attached for your
> convenience) as a pre-requisite for the backlight/lcd device class patch
> (also included so that you can take at it as well) via Russel King (the

Danger Will Robinson. Try to do the same to Rusty Russell and you're toast ;)
--
vda


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-05-29  8:10   ` Andrew Zabolotny
@ 2004-06-01 20:09     ` Todd Poynor
  2004-06-01 21:00       ` Andrew Zabolotny
  0 siblings, 1 reply; 15+ messages in thread
From: Todd Poynor @ 2004-06-01 20:09 UTC (permalink / raw)
  To: Andrew Zabolotny; +Cc: linux-kernel, greg

Andrew Zabolotny wrote:
> On Fri, 28 May 2004 14:59:53 -0700
> Todd Poynor <tpoynor@mvista.com> wrote:
> 
> 
>>Hi, you're adding new interfaces for power management of LCD and 
>>backlight devices.  Since there's already LDM/sysfs interfaces for 
>>reading and writing power state of generic devices, is it necessary to 
>>add ones particular to these devices or device classes?  In other words, 
>>is /sys/devices/<bus>/<device>/power/state not suitable for these purposes?
> 
> Well, first liquid crystal displays and backlight are not connected to any
> specific bus. They could, on some platforms, and could not on other. For
> example, on some PDAs backlight is controlled via the programmed I/O CPU pins
> (GPIO), on other they are connected to some weird companion chips, on third
> they could be controlled via the PCI bus (on large PCs, I mean) and so on. So
> there will be no easy way for an application to find the backlight devices
> and control them. In our case that's easy: opendir ("/sys/class/backlight")
> and you found all of them.

I'm not questioning the usefulness of the other aspects of the patch, 
such as adding an LCD/backlight class for framebuffer access and adding 
attributes for the unique features of LCD/backlight devices.  My 
questions are specific to the power management interfaces, since there's 
already interfaces for this, with different semantics than the new class 
interfaces, and there's some value in sticking with a single consistent 
interface for it.

If I understand correctly, the LCD device is registered on a bus (either 
a platform-specific bus or the generic "platform" bus), and the device 
therefore already has a power/state attribute; the class entry could 
refer back to that device if needed.  So I'm interested in discussing 
whether the existing PM interface suffices for LCD/backlight devices, or 
if not, should the existing interfaces be improved (rather than working 
around deficiencies via device-specific interfaces)?

 > [...]
> On the third hand (:-) the lcd device class, for example, actually has *two*
> power switches: the 'power' and the 'enable' attribute. The first powers off
> the liquid crystal display, and seconds powers off the lcd controller. These
> are different things and it would be wise to leave them apart, as having finer
> grained control is always better. [...]

But it also sounds like the single LDM registration for an LCD device 
could be better handled by registering the LCD display, LCD controller, 
and backlight as separate devices (which they probably are), allowing 
individual control through the standard interfaces.

>>And if a PM interface for device classes is needed that ties into the 
>>device driver suspend/resume callbacks, perhaps it can be modeled more 
>>closely on the existing interfaces?  These new interfaces seem to be 
>>intended to define: 0 == power off, 1 ==  power on.  The existing 
>>ACPI-inspired interfaces use: 0 == power on/full-power, 1/2/3/4 == 
>>low-power/off state.
> 
> Um, well, this could be implemented. Although I don't see much reason for a
> backlight to be in a "semi-enabled state"; besides if it will remain a
> separate class device, it doesn't matter much. 

The main problem is that existing interfaces write zero for on and 
non-zero for off, while the new interface reverses things.  I realize 
that multiple power states are not implemented by all devices; if 
there's interest in tailoring device states to more closely match the 
hardware capabilities of non-ACPI systems then I'd be happy to talk more 
about that.

So none of my objections are terribly crucial, and if Greg et al don't 
have a problem with device-class-specific PM interfaces that have 
different semantics and/or capabilities than those of the device 
power/state attributes then I don't have much of a problem with it 
either.  Just seems worthwhile to check whether there's improvements 
needed in the existing PM interfaces instead.


-- 
Todd

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-06-01 20:09     ` Todd Poynor
@ 2004-06-01 21:00       ` Andrew Zabolotny
  2004-06-02 17:15         ` Greg KH
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Zabolotny @ 2004-06-01 21:00 UTC (permalink / raw)
  To: Todd Poynor; +Cc: linux-kernel, greg

On Tue, 01 Jun 2004 13:09:46 -0700
Todd Poynor <tpoynor@mvista.com> wrote:

> I'm not questioning the usefulness of the other aspects of the patch, 
> such as adding an LCD/backlight class for framebuffer access and adding 
> attributes for the unique features of LCD/backlight devices.  My 
> questions are specific to the power management interfaces, since there's 
> already interfaces for this, with different semantics than the new class 
> interfaces, and there's some value in sticking with a single consistent 
> interface for it.
Well, after thinking awhile, I have changed it so that 0 means power on,
1..3 intermediate values (although for now they are interpreted as poweroff by
existing drivers since there are no intermediate states) and 4 is 'off for
real'. Indeed, there is no much reason to have them use different semantics.

> If I understand correctly, the LCD device is registered on a bus (either 
> a platform-specific bus or the generic "platform" bus)
No, they are registered just as a class device. There is no corresponding
device on any other bus, this would mean a lot of unneeded overhead.

> therefore already has a power/state attribute; the class entry could 
> refer back to that device if needed.  So I'm interested in discussing 
> whether the existing PM interface suffices for LCD/backlight devices, or 
> if not, should the existing interfaces be improved (rather than working 
> around deficiencies via device-specific interfaces)?
Um, well, the LCD device actually has two power controls, like I said
before: one toggles the power to the LCD itself, another one (the 'enable'
attribute) controls power to the LCD controller. Not that this explicit
separate control is required very much, but it would be nice to have a degree
of freedom close to that allowed by hardware.

In theory, if we would use the standard power interface, it could use the
different levels of power saving, e.g. 0 - controller and LCD on, 1,2 - LCD
off, controller on, 3,4 - both off.

> But it also sounds like the single LDM registration for an LCD device 
> could be better handled by registering the LCD display, LCD controller, 
> and backlight as separate devices (which they probably are), allowing 
> individual control through the standard interfaces.
Well, the LCD panel is controllable only through the LCD controller, so for
the most part they are the same. The only thing is that the LCD controller has
a one-bit switch to disable the power to the panel. I don't think it makes
sense to separate that bit into a separate device.

> So none of my objections are terribly crucial, and if Greg et al don't 
> have a problem with device-class-specific PM interfaces that have 
> different semantics and/or capabilities than those of the device 
> power/state attributes then I don't have much of a problem with it 
> either.  Just seems worthwhile to check whether there's improvements 
> needed in the existing PM interfaces instead.
Well, the power interface under drivers/ is available for framebuffer.
If it would handle it properly (the framebuffer drivers I've tried
don't, alas), they would toggle the attached (to the framebuffer) LCD
and backlight power state according to its own state (which is not so fine
grained, but is logical). In any case, one of reasons this backlight/lcd patch
has been written was to avoid that mess with callbacks that lately begun to
appear in ARM-specific framebuffer devices (and I shudder at the thought that
MIPS people should be doing something similar).

--
Greetings,
   Andrew

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-05-29  8:44   ` Andrew Zabolotny
@ 2004-06-01 21:23     ` Jeff Garzik
  2004-06-01 21:57       ` Andrew Zabolotny
  0 siblings, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2004-06-01 21:23 UTC (permalink / raw)
  To: Andrew Zabolotny; +Cc: Greg KH, linux-kernel

Andrew Zabolotny wrote:
> No. class_find_device was written for lcd_find_device() and
> backlight_find_device() (framebuffer devices use them). On the other hand,
> the driver that registers the backlight device doesn't have a pointer to the
> class device (well, the lcd_register_device could return it). Since the
> lcd/backlight names are unique anyway, I don't see any problems with that, and
> moreover, it is *registered* by giving it a name, why it should be
> unregistered in a different way?


Typical Linux usage to an item being registered is

	ptr = alloc_foo()
	register_foo(ptr)
	unregister_foo(ptr)
	free_foo()

It is quite unusual to unregister based on name.  Pointers are far more 
likely to be unique, and the programmer is far less likely to screw up 
the unregister operation.

	Jeff



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-06-01 21:23     ` Jeff Garzik
@ 2004-06-01 21:57       ` Andrew Zabolotny
  2004-06-02 17:12         ` Greg KH
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Zabolotny @ 2004-06-01 21:57 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: greg, linux-kernel

On Tue, 01 Jun 2004 17:23:11 -0400
Jeff Garzik <jgarzik@pobox.com> wrote:

> Typical Linux usage to an item being registered is
> 	ptr = alloc_foo()
> 	register_foo(ptr)
> 	unregister_foo(ptr)
> 	free_foo()
In this case it is:

register_lcd_device("foo", ...);
...
unregister_lcd_device("foo");

The name is guaranteed to be unique by sysfs design during the whole
device lifetime, and calling unregister_xxx() outside the lifetime brackets
is clearly an error.

> It is quite unusual to unregister based on name.  Pointers are far more 
> likely to be unique, and the programmer is far less likely to screw up 
> the unregister operation.
I understand this, I see why it looks unusual. I'll fix this if it matters.
It'll be something like:

lcd_device = register_lcd_device ("foo", ...);
...
unregister_lcd_device (lcd_device);

However, this extra pointer will take some memory; not much of course.

--
Greetings,
   Andrew

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-06-01 21:57       ` Andrew Zabolotny
@ 2004-06-02 17:12         ` Greg KH
  0 siblings, 0 replies; 15+ messages in thread
From: Greg KH @ 2004-06-02 17:12 UTC (permalink / raw)
  To: Andrew Zabolotny; +Cc: Jeff Garzik, linux-kernel

On Wed, Jun 02, 2004 at 01:57:40AM +0400, Andrew Zabolotny wrote:
> On Tue, 01 Jun 2004 17:23:11 -0400
> Jeff Garzik <jgarzik@pobox.com> wrote:
> 
> > Typical Linux usage to an item being registered is
> > 	ptr = alloc_foo()
> > 	register_foo(ptr)
> > 	unregister_foo(ptr)
> > 	free_foo()
> In this case it is:
> 
> register_lcd_device("foo", ...);
> ...
> unregister_lcd_device("foo");
> 
> The name is guaranteed to be unique by sysfs design during the whole
> device lifetime, and calling unregister_xxx() outside the lifetime brackets
> is clearly an error.
> 
> > It is quite unusual to unregister based on name.  Pointers are far more 
> > likely to be unique, and the programmer is far less likely to screw up 
> > the unregister operation.
> I understand this, I see why it looks unusual. I'll fix this if it matters.

It matters, please fix it.

> It'll be something like:
> 
> lcd_device = register_lcd_device ("foo", ...);
> ...
> unregister_lcd_device (lcd_device);

What about:
	lcd_device = alloc_lcd_device("foo", ...);
	error = register_lcd_device(lcd_device);
	...
	unregister_lcd_device(lcd_device);

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-06-01 21:00       ` Andrew Zabolotny
@ 2004-06-02 17:15         ` Greg KH
  2004-06-02 21:25           ` Andrew Zabolotny
  2004-06-02 21:32           ` Russell King
  0 siblings, 2 replies; 15+ messages in thread
From: Greg KH @ 2004-06-02 17:15 UTC (permalink / raw)
  To: Andrew Zabolotny; +Cc: Todd Poynor, linux-kernel

On Wed, Jun 02, 2004 at 01:00:36AM +0400, Andrew Zabolotny wrote:
> 
> In theory, if we would use the standard power interface, it could use the
> different levels of power saving, e.g. 0 - controller and LCD on, 1,2 - LCD
> off, controller on, 3,4 - both off.

Please use the standard power interface, and use the standard levels of
power state.  That's why we _have_ this driver model in the first
place...

> > So none of my objections are terribly crucial, and if Greg et al don't 
> > have a problem with device-class-specific PM interfaces that have 
> > different semantics and/or capabilities than those of the device 
> > power/state attributes then I don't have much of a problem with it 
> > either.  Just seems worthwhile to check whether there's improvements 
> > needed in the existing PM interfaces instead.

I do have a problem with device-class-specific PM interfaces that have
different semantics from the whole rest of the system.

> Well, the power interface under drivers/ is available for framebuffer.
> If it would handle it properly (the framebuffer drivers I've tried
> don't, alas)

Then they need to be fixed to do so.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-06-02 17:15         ` Greg KH
@ 2004-06-02 21:25           ` Andrew Zabolotny
  2004-06-02 21:32           ` Russell King
  1 sibling, 0 replies; 15+ messages in thread
From: Andrew Zabolotny @ 2004-06-02 21:25 UTC (permalink / raw)
  To: Greg KH; +Cc: tpoynor, linux-kernel

On Wed, 2 Jun 2004 10:15:42 -0700
Greg KH <greg@kroah.com> wrote:

> > In theory, if we would use the standard power interface, it could use the
> > different levels of power saving, e.g. 0 - controller and LCD on, 1,2 -
> > LCD off, controller on, 3,4 - both off.
> Please use the standard power interface, and use the standard levels of
> power state.  That's why we _have_ this driver model in the first
> place...
The problem is that I cannot use the standard power interface because I don't
know how. The patch in question implements class devices, not regular devices.
Class devices don't use the standard power management scheme. Here:

/sys # ls devices/platform/
detach_state    power           pxa2xx_udc0
mq11xx0         pxa2xx-pcmcia0  pxafb0
mq11xx_udc0     pxa2xx_serial0  pxamci0

None of the above devices implement the backlight and LCD; they use bits from
different devices; in my case several GPIO pins from the mq11xx0 device, a
couple of CPU' GPIO pins (which aren't present in sysfs at all).

Now the mq11xx0 device (which is a System-On-Chip, e.g. a single chip
encomprising a lot of somehow-independent-functions) has a lot of subdevices:

/sys # ls devices/platform/mq11xx0/
detach_state  mq11xx_i2s0   mq11xx_spi0   mq11xx_uhc0
mq11xx_fb0    mq11xx_lcd0   mq11xx_udc0   power

The backlight is controlled by a few spare bits from the mq11xx_spi0 device
(which is a SPI bus controller). I don't think it makes sense to create the
backlight device node under /sys/devices/platform/mq11xx0/mq11xx_spi0/;
besides that's on my PDA; on other PDAs they could be located anywhere else,
thus the software will have a major headache to find the backlight/lcd power
controls.

Right now it works this way:

/sys # ls class/backlight/mq11xx_fb0/
brightness      max_brightness  power
/sys # ls class/lcd/mq11xx_fb0/
contrast      enable        max_contrast  power

I could unify lcd's 'power' and 'enable' attributes into one (they already use
the 'standard' 0-4 power levels), like I stated in one of my previous
messages, but it anyways would be quite different from the current power
management structure.

> > Well, the power interface under drivers/ is available for framebuffer.
> > If it would handle it properly (the framebuffer drivers I've tried
> > don't, alas)
> Then they need to be fixed to do so.
Doh, you don't want me to fix the whole kernel in one patch, don't you? :-)

--
Greetings,
   Andrew

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-06-02 17:15         ` Greg KH
  2004-06-02 21:25           ` Andrew Zabolotny
@ 2004-06-02 21:32           ` Russell King
  2004-06-04 20:43             ` Greg KH
  1 sibling, 1 reply; 15+ messages in thread
From: Russell King @ 2004-06-02 21:32 UTC (permalink / raw)
  To: Greg KH; +Cc: Andrew Zabolotny, Todd Poynor, linux-kernel

On Wed, Jun 02, 2004 at 10:15:42AM -0700, Greg KH wrote:
> On Wed, Jun 02, 2004 at 01:00:36AM +0400, Andrew Zabolotny wrote:
> > 
> > In theory, if we would use the standard power interface, it could use the
> > different levels of power saving, e.g. 0 - controller and LCD on, 1,2 - LCD
> > off, controller on, 3,4 - both off.
> 
> Please use the standard power interface, and use the standard levels of
> power state.  That's why we _have_ this driver model in the first
> place...

It /doesn't/ make any sense to in this case.  We're talking effectively
about the LCD panel attributes, not a device as such.

IOW:
- LCD backlight brightness
- LCD backlight on/off
- LCD panel power on/off

Typically, the last item needs to be closely controlled in relation to
the LCD controller itself, and it just does not make sense to separate
the LCD panel power control from the controller itself in the device
model.  In fact, exposing the LCD panel power control independent of
the LCD controller state can lead to cases where you end up destroying
your LCD panel - there is a very defined sequence to power up/down
these things to avoid degredation.

However, the issue is that all of the three things can be handled
god-knows-which-way on any platform, even when they're using the
same LCD controllers.  So we need a way for platform/machine specific
code to provide the information so that the LCD controller can
correctly handle these settings on blank, etc.

Hope this provides some extra reasoning why using the device model
for these attributes is wrong.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 PCMCIA      - http://pcmcia.arm.linux.org.uk/
                 2.6 Serial core

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: two patches - request for comments
  2004-06-02 21:32           ` Russell King
@ 2004-06-04 20:43             ` Greg KH
  0 siblings, 0 replies; 15+ messages in thread
From: Greg KH @ 2004-06-04 20:43 UTC (permalink / raw)
  To: Andrew Zabolotny, Todd Poynor, linux-kernel

On Wed, Jun 02, 2004 at 10:32:19PM +0100, Russell King wrote:
> On Wed, Jun 02, 2004 at 10:15:42AM -0700, Greg KH wrote:
> > On Wed, Jun 02, 2004 at 01:00:36AM +0400, Andrew Zabolotny wrote:
> > > 
> > > In theory, if we would use the standard power interface, it could use the
> > > different levels of power saving, e.g. 0 - controller and LCD on, 1,2 - LCD
> > > off, controller on, 3,4 - both off.
> > 
> > Please use the standard power interface, and use the standard levels of
> > power state.  That's why we _have_ this driver model in the first
> > place...
> 
> It /doesn't/ make any sense to in this case.  We're talking effectively
> about the LCD panel attributes, not a device as such.

<snip>

> Hope this provides some extra reasoning why using the device model
> for these attributes is wrong.

Ok, this makes more sense now, thanks for explaining it.

greg k-h

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2004-06-04 22:48 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-05-28 21:20 two patches - request for comments Andrew Zabolotny
2004-05-28 21:59 ` Todd Poynor
2004-05-29  8:10   ` Andrew Zabolotny
2004-06-01 20:09     ` Todd Poynor
2004-06-01 21:00       ` Andrew Zabolotny
2004-06-02 17:15         ` Greg KH
2004-06-02 21:25           ` Andrew Zabolotny
2004-06-02 21:32           ` Russell King
2004-06-04 20:43             ` Greg KH
2004-05-28 22:10 ` Greg KH
2004-05-29  8:44   ` Andrew Zabolotny
2004-06-01 21:23     ` Jeff Garzik
2004-06-01 21:57       ` Andrew Zabolotny
2004-06-02 17:12         ` Greg KH
2004-05-29 13:46 ` Denis Vlasenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).