All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kristoffer Ericson <kristoffer.ericson@gmail.com>
To: Russell King - ARM Linux <linux@arm.linux.org.uk>
Cc: Kristoffer Ericson <kristoffer.ericson@gmail.com>,
	Roel Kluin <12o3l@tiscali.nl>,
	rpurdie@openedhand.com,
	Linux-arm <linux-arm-kernel@lists.arm.linux.org.uk>,
	linux-main <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH/HP7XX] - Add combined LCD / BL driver for platform HP Jornada 7xx handhelds
Date: Wed, 6 Feb 2008 20:21:28 +0100	[thread overview]
Message-ID: <20080206202128.06fbcafa.Kristoffer.ericson@gmail.com> (raw)
In-Reply-To: <20080206164435.GC32245@flint.arm.linux.org.uk>

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

Attempt #3 :
Changes :
---------
* removed JORN.. prefixes except from functions.
* removed file location in head
* fixed (hope) indent issues
* do not exceed 80 chars per line
* added extra checks if driver allocation fails
* return -1 instead of (MAX + 1)
...and probably alot more.

Patch:
* builds
* passes checkpatch.pl (only complaining about signoff-tag)

Oh, and thanks for all the feedback people! (and for doing it nicely)
Only thing not adress so far is richards mdelay question, need to do a quick test before I can answer that.

/Kristoffer

diff --git a/drivers/video/backlight/jornada720_bllcd.c b/drivers/video/backlight/jornada720_bllcd.c
new file mode 100644
index 0000000..0adbc49
--- /dev/null
+++ b/drivers/video/backlight/jornada720_bllcd.c
@@ -0,0 +1,287 @@
+/*
+ *
+ * Backlight and LCD Driver for HP Jornada 720
+ * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * or any later version as published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/device.h>
+#include <asm/hardware.h>
+#include <asm/arch/jornada720.h>
+#include <video/s1d13xxxfb.h>
+
+MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
+MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight/LCD Driver");
+MODULE_LICENSE("GPL");
+
+/* Contrast */
+#define LCD_MAX_CONTR	0xff
+#define LCD_DEF_CONTR	0x80
+/* Brightness */
+#define BL_MAX_BRIGHT	0xff
+#define BL_DEF_BRIGHT	0x19
+
+struct bllcd_device {
+	struct backlight_device *bl_device;
+	struct lcd_device *lcd_device;
+};
+
+/*
+ * BACKLIGHT HANDLING ROUTINES
+ */
+static int jornada_bl_get_brightness(struct backlight_device *dev)
+{
+	int ret;
+
+	/* check if backlight is on */
+	if (!(PPSR & PPC_LDD1))
+		return BL_MAX_BRIGHT;
+
+	jornada_ssp_start();
+	if (jornada_ssp_inout(GETBRIGHTNESS) == -ETIMEDOUT) {
+		printk(KERN_ERR "bl :get brightness timeout\n");
+		ret = -1;
+	} else
+		ret = jornada_ssp_inout(TXDUMMY);
+
+	jornada_ssp_end();
+
+	/* 0 is max brightness */
+	return BL_MAX_BRIGHT - ret;
+}
+
+static int jornada_bl_update_status(struct backlight_device *dev)
+{
+	int ret = 0;
+	int value;
+
+	jornada_ssp_start();
+
+	if (dev->props.power != FB_BLANK_UNBLANK ||
+	dev->props.fb_blank != FB_BLANK_UNBLANK) {
+		ret = jornada_ssp_inout(BRIGHTNESSOFF);
+		if (ret == -ETIMEDOUT) {
+			printk(KERN_ERR "bl : brightness off timeout\n");
+			/* backlight off */
+			PPSR &= ~PPC_LDD1;
+			PPDR |= PPC_LDD1;
+		}
+	} else { /* backlight on */
+		PPSR |= PPC_LDD1;
+		/* send setbrightness cmd */
+		ret = jornada_ssp_inout(SETBRIGHTNESS);
+		if (ret != TXDUMMY) {
+			printk(KERN_ERR "bl :set brightness timeout\n");
+		} else {
+			/* cmd accepted */
+			value = BL_MAX_BRIGHT - dev->props.brightness;
+			if (jornada_ssp_byte(value) == TXDUMMY)
+				ret = value;
+			else
+				printk(KERN_ERR "bl :set brightness failed\n");
+		}
+	}
+
+	jornada_ssp_end();
+
+	return ret;
+}
+
+/*
+ * LCD HANDLING FUNCTIONS
+ */
+static int jornada_lcd_set_contrast(struct lcd_device *pdev, int contrast)
+{
+	int ret = 0;
+
+	jornada_ssp_start();
+
+	ret = jornada_ssp_inout(SETCONTRAST);
+
+	if (ret == -ETIMEDOUT)
+		printk(KERN_ERR "lcd :set contrast timeout\n");
+	else
+		ret = jornada_ssp_byte(contrast);
+
+	jornada_ssp_end();
+
+	return ret;
+}
+
+static int jornada_lcd_set_power(struct lcd_device  *pdev, int power)
+{
+	if (power != FB_BLANK_UNBLANK) {
+		/* turn off LCD */
+		PPSR &= ~PPC_LDD2;
+		PPDR |= PPC_LDD2;
+	} else {
+		/* turn on LCD */
+		PPSR |= PPC_LDD2;
+	}
+
+	return 0;
+}
+
+static int jornada_lcd_get_power(struct lcd_device *pdev)
+{
+	if (PPSR & PPC_LDD2)
+		return FB_BLANK_UNBLANK;
+	else
+		return FB_BLANK_POWERDOWN;
+}
+
+static int jornada_lcd_get_contrast(struct lcd_device *pdev)
+{
+	int ret;
+
+	/* Don't set contrast on off powerd LCD */
+	if (jornada_lcd_get_power(pdev) != FB_BLANK_UNBLANK)
+		return 0;
+
+	jornada_ssp_start();
+
+	ret = jornada_ssp_inout(GETCONTRAST);
+	if (ret != -ETIMEDOUT)
+		ret = jornada_ssp_inout(TXDUMMY);
+	else {
+		printk(KERN_ERR "lcd :get contrast timeout\n");
+		ret = -1;
+	}
+
+	jornada_ssp_end();
+
+	return ret;
+}
+
+static struct backlight_ops jornada_bl_ops = {
+	.get_brightness = jornada_bl_get_brightness,
+	.update_status = jornada_bl_update_status,
+};
+
+static struct lcd_ops jornada_lcd_ops = {
+	.get_contrast = jornada_lcd_get_contrast,
+	.set_contrast = jornada_lcd_set_contrast,
+	.get_power = jornada_lcd_get_power,
+	.set_power = jornada_lcd_set_power,
+};
+
+static int jornada_bl_probe(struct platform_device *pdev)
+{
+	struct bllcd_device *bllcd;
+
+	bllcd = kzalloc(sizeof(*bllcd), GFP_KERNEL);
+	if (bllcd == NULL)
+		return -ENOMEM;
+
+	/* bl driver - name must match fb driver name */
+	bllcd->bl_device = backlight_device_register(S1D_DEVICENAME,
+	&pdev->dev, NULL, &jornada_bl_ops);
+
+	if (IS_ERR(bllcd->bl_device)) {
+		kfree(bllcd);
+		printk(KERN_ERR "bl :failed to register device\n");
+		return -ENODEV;
+	}
+
+	/* lcd driver */
+	bllcd->lcd_device = lcd_device_register(S1D_DEVICENAME,
+				&pdev->dev, NULL, &jornada_lcd_ops);
+	if (IS_ERR(bllcd->lcd_device)) {
+		backlight_device_unregister(bllcd->bl_device);
+		kfree(bllcd);
+		printk(KERN_ERR "lcd :failed to register device\n");
+		return -ENODEV;
+	}
+
+	jornada_lcd_set_contrast(bllcd->lcd_device, LCD_DEF_CONTR);
+	jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_UNBLANK);
+
+	msleep(100);
+
+	bllcd->bl_device->props.power = FB_BLANK_UNBLANK;
+	bllcd->bl_device->props.brightness = BL_DEF_BRIGHT;
+	jornada_bl_update_status(bllcd->bl_device);
+
+	platform_set_drvdata(pdev, bllcd);
+	printk(KERN_INFO "HP Jornada 7xx Backlight/LCD driver activated\n");
+
+	return 0;
+}
+
+static int jornada_bl_remove(struct platform_device *pdev)
+{
+	struct bllcd_device *bllcd = platform_get_drvdata(pdev);
+
+	bllcd->bl_device->props.power = FB_BLANK_POWERDOWN;
+	bllcd->bl_device->props.brightness = 0;
+	bllcd->bl_device->props.max_brightness = 0;
+
+	backlight_device_unregister(bllcd->bl_device);
+	lcd_device_unregister(bllcd->lcd_device);
+
+	return 0;
+}
+
+static int jornada_bl_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct bllcd_device *bllcd = platform_get_drvdata(pdev);
+
+	bllcd->bl_device->props.power = FB_BLANK_POWERDOWN;
+	bllcd->bl_device->props.brightness = 0;
+	bllcd->bl_device->props.max_brightness = 0;
+	jornada_bl_update_status(bllcd->bl_device);
+
+	jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_POWERDOWN);
+
+	return 0;
+}
+
+static int jornada_bl_resume(struct platform_device *pdev)
+{
+	struct bllcd_device *bllcd = platform_get_drvdata(pdev);
+
+	bllcd->bl_device->props.power = FB_BLANK_UNBLANK;
+	bllcd->bl_device->props.brightness = BL_DEF_BRIGHT;
+	bllcd->bl_device->props.max_brightness = BL_MAX_BRIGHT;
+	jornada_bl_update_status(bllcd->bl_device);
+
+	jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_UNBLANK);
+
+	return 0;
+}
+
+static struct platform_driver jornada_bl_driver = {
+	.probe	= jornada_bl_probe,
+	.remove	= jornada_bl_remove,
+#ifdef CONFIG_PM
+	.suspend = jornada_bl_suspend,
+	.resume = jornada_bl_resume,
+#endif
+	.driver = {
+	    .name = "jornada_bllcd",
+	},
+};
+
+static int __init jornada_bl_init(void)
+{
+	return platform_driver_register(&jornada_bl_driver);
+}
+
+static void __exit jornada_bl_exit(void)
+{
+	platform_driver_unregister(&jornada_bl_driver);
+}
+
+module_init(jornada_bl_init);
+module_exit(jornada_bl_exit);





On Wed, 6 Feb 2008 16:44:36 +0000
Russell King - ARM Linux <linux@arm.linux.org.uk> wrote:

> On Wed, Feb 06, 2008 at 05:33:41PM +0100, Kristoffer Ericson wrote:
> > Oki, here is attempt #2 (btw, new mail or just keep thread?)
> 
> Probably better to keep the thread.  More comments 8)
> 
> > +struct jornada_bllcd_device {
> > +	struct backlight_device *jorn_backlight_device;
> > +	struct lcd_device *jorn_lcd_device;
> 
> We're inside a jornada file.  Do these "jorn_" prefixes add anything
> useful that the reader doesn't already know?
> 
> > +static int jornada_bl_update_status(struct backlight_device *dev)
> > +{
> > +	int ret = 0;
> > +
> > +	jornada_ssp_start();
> > +
> > +	if (dev->props.power != FB_BLANK_UNBLANK ||
> > +		dev->props.fb_blank != FB_BLANK_UNBLANK) {
> > +		ret = jornada_ssp_inout(BRIGHTNESSOFF);
> > +		if (ret == -ETIMEDOUT)
> > +			printk(KERN_ERR "jornada720_bl:	\
> > +				BrightnessOff timeout\n");
> > +			/* backlight off */
> > +			PPSR &= ~PPC_LDD1;
> > +			PPDR |= PPC_LDD1;
> 
> Look at the above 5 lines.  What are your expectations if ret != -ETIMEDOUT?
> If C were python you'd have one behaviour due to the indent...
> 
> > +
> > +	} else	{	/* backlight on */
> 
> Too many spaces.
> 
> > +			PPSR |= PPC_LDD1;
> > +			if ((jornada_ssp_inout(SETBRIGHTNESS)) == TXDUMMY) {
> > +			    /* send brightness value (0 is max, 255 lowest) */
> > +				if (jornada_ssp_byte(JORNADA_BL_MAX_BRIGHTNESS -
> > +					 dev->props.brightness) != -ETIMEDOUT)
> > +				ret = (JORNADA_BL_MAX_BRIGHTNESS -
> > +					dev->props.brightness);
> > +			} else
> > +				printk(KERN_ERR "jornada720_bl:	\
> > +					SetBrightness timeout\n");
> > +		}
> 
> If this corresponds with the "} else {" line, it should have one tab.  Plus
> the above indented code section should probably have one less indentation.
> 
> > +	jornada_ssp_end();
> > +
> > +	return ret;
> > +}
> > +
> > +/*
> > + * LCD HANDLING FUNCTIONS
> > + */
> > +static int jornada_lcd_set_contrast(struct lcd_device *pdev, int contrast)
> > +{
> > +	int ret = 0;
> > +
> > +	jornada_ssp_start();
> > +
> > +	ret = jornada_ssp_inout(SETCONTRAST);
> > +
> > +	if (ret == -ETIMEDOUT)
> > +		printk(KERN_ERR "jornada_lcd: failure to set contrast\n");
> > +	 else
> 
> Space before 'else' not required.
> 
> > +		ret = jornada_ssp_byte(contrast);
> > +
> > +	jornada_ssp_end();
> > +
> > +	return ret;
> > +}
> > +
> > +static int jornada_lcd_set_power(struct lcd_device  *pdev, int power)
> > +{
> > +	if (power != FB_BLANK_UNBLANK) {
> > +		/* turn off LCD */
> > +		PPSR &= ~PPC_LDD2;
> > +		PPDR |= PPC_LDD2;
> > +	} else {
> > +		/* turn on LCD */
> > +		PPSR |= PPC_LDD2;
> > +		}
> 
> Wrongly placed }
> 
> > +
> > +	return 0;
> > +}
> > +
> > +static int jornada_lcd_get_power(struct lcd_device *pdev)
> > +{
> > +	if (PPSR & PPC_LDD2)
> > +		return FB_BLANK_UNBLANK;
> > +	else
> > +		return FB_BLANK_POWERDOWN;
> > +}
> > +
> > +static int jornada_lcd_get_contrast(struct lcd_device *pdev)
> > +{
> > +	int ret;
> > +
> > +	/* Don't set contrast on off powerd LCD */
> > +	if (jornada_lcd_get_power(pdev) != FB_BLANK_UNBLANK)
> > +		return 0;
> > +
> > +	jornada_ssp_start();
> > +
> > +	ret = jornada_ssp_inout(GETCONTRAST);
> > +	if (ret != -ETIMEDOUT)
> > +		ret = jornada_ssp_inout(TXDUMMY);
> > +	else {
> > +		printk(KERN_ERR "jornada_lcd: getcontrast failed!\n");
> > +		ret = JORNADA_BL_MAX_BRIGHTNESS + 1;
> > +	}
> > +
> > +	jornada_ssp_end();
> > +
> > +	return ret;
> > +}
> > +
> > +static struct backlight_ops jornada_bl_ops = {
> > +	.get_brightness = jornada_bl_get_brightness,
> > +	.update_status = jornada_bl_update_status,
> > +};
> > +
> > +static struct lcd_ops jornada_lcd_ops = {
> > +	.get_contrast = jornada_lcd_get_contrast,
> > +	.set_contrast = jornada_lcd_set_contrast,
> > +	.get_power = jornada_lcd_get_power,
> > +	.set_power = jornada_lcd_set_power,
> > +};
> > +
> > +static int jornada_bl_probe(struct platform_device *pdev)
> > +{
> > +	struct jornada_bllcd_device *bllcd;
> > +
> > +	bllcd = kzalloc(sizeof(*bllcd), GFP_KERNEL);
> > +	if (bllcd == NULL)
> > +		return -ENOMEM;
> > +
> > +	/* bl driver - name must match fb driver name */
> > +	bllcd->jorn_backlight_device = backlight_device_register(S1D_DEVICENAME,
> > +		&pdev->dev, NULL, &jornada_bl_ops);
> > +
> > +	if (IS_ERR(bllcd->jorn_backlight_device)) {
> > +		kfree(bllcd);
> > +		return PTR_ERR(bllcd->jorn_backlight_device);
> 
> Access after free.  Bad bad bad.
> 
> > +	}
> > +
> > +	/* lcd driver */
> > +	bllcd->jorn_lcd_device = lcd_device_register(S1D_DEVICENAME,
> > +				&pdev->dev, NULL, &jornada_lcd_ops);
> > +	if (IS_ERR(bllcd->jorn_lcd_device)) {
> > +		kfree(bllcd);
> > +		return PTR_ERR(bllcd->jorn_lcd_device);
> 
> Access after free.  Bad bad bad.
> 
> > +	}
> > +
> > +	jornada_lcd_set_contrast(bllcd->jorn_lcd_device,
> > +			JORNADA_LCD_DEFAULT_CONTRAST);
> > +	jornada_lcd_set_power(bllcd->jorn_lcd_device,
> > +			FB_BLANK_UNBLANK);
> > +
> > +	msleep(100);
> > +
> > +	bllcd->jorn_backlight_device->props.power
> > +		= FB_BLANK_UNBLANK;
> > +	bllcd->jorn_backlight_device->props.brightness
> > +		= JORNADA_BL_DEFAULT_BRIGHTNESS;
> 
> If you get rid of the "jorn_" prefix, can these be on one line?
> 
> > +	jornada_bl_update_status(bllcd->jorn_backlight_device);
> > +
> > +	platform_set_drvdata(pdev, bllcd);
> > +	printk(KERN_INFO "HP Jornada 7xx Backlight/LCD driver activated\n");
> > +
> > +	return 0;
> > +}
> > +
> > +static int jornada_bl_remove(struct platform_device *pdev)
> > +{
> > +	struct jornada_bllcd_device *bllcd = platform_get_drvdata(pdev);
> > +
> > +	bllcd->jorn_backlight_device->props.power = FB_BLANK_POWERDOWN;
> > +	bllcd->jorn_backlight_device->props.brightness = 0;
> > +	bllcd->jorn_backlight_device->props.max_brightness = 0;
> > +
> > +	backlight_device_unregister(bllcd->jorn_backlight_device);
> > +	lcd_device_unregister(bllcd->jorn_lcd_device);
> 
> Leaves bllcd allocated - memory leak.
> 
> > +
> > +	return 0;
> > +}
> > +
> > +static int jornada_bl_suspend(struct platform_device *pdev, pm_message_t state)
> > +{
> > +	struct jornada_bllcd_device *bllcd = platform_get_drvdata(pdev);
> > +
> > +	bllcd->jorn_backlight_device->props.power = FB_BLANK_POWERDOWN;
> > +	bllcd->jorn_backlight_device->props.brightness = 0;
> > +	bllcd->jorn_backlight_device->props.max_brightness = 0;
> > +	jornada_bl_update_status(bllcd->jorn_backlight_device);
> > +
> > +	jornada_lcd_set_power(bllcd->jorn_lcd_device, FB_BLANK_POWERDOWN);
> > +
> > +	return 0;
> > +}
> > +
> > +static int jornada_bl_resume(struct platform_device *pdev)
> > +{
> > +	struct jornada_bllcd_device *bllcd = platform_get_drvdata(pdev);
> > +
> > +	bllcd->jorn_backlight_device->props.power
> > +		= FB_BLANK_UNBLANK;
> > +	bllcd->jorn_backlight_device->props.brightness
> > +		= JORNADA_BL_DEFAULT_BRIGHTNESS;
> > +	bllcd->jorn_backlight_device->props.max_brightness
> > +		= JORNADA_BL_MAX_BRIGHTNESS;
> > +	jornada_bl_update_status(bllcd->jorn_backlight_device);
> > +
> > +	jornada_lcd_set_power(bllcd->jorn_lcd_device, FB_BLANK_UNBLANK);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct platform_driver jornada_bl_driver = {
> > +	.probe	= jornada_bl_probe,
> > +	.remove	= jornada_bl_remove,
> > +#ifdef CONFIG_PM
> > +	.suspend = jornada_bl_suspend,
> > +	.resume = jornada_bl_resume,
> > +#endif
> > +	.driver = {
> > +	    .name = "jornada_bllcd",
> 
> a tab, not 4 spaces.
> 

[-- Attachment #2: jornada720_bllcd.patch --]
[-- Type: application/octet-stream, Size: 7202 bytes --]

diff --git a/drivers/video/backlight/jornada720_bllcd.c b/drivers/video/backlight/jornada720_bllcd.c
new file mode 100644
index 0000000..0adbc49
--- /dev/null
+++ b/drivers/video/backlight/jornada720_bllcd.c
@@ -0,0 +1,287 @@
+/*
+ *
+ * Backlight and LCD Driver for HP Jornada 720
+ * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * or any later version as published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/device.h>
+#include <asm/hardware.h>
+#include <asm/arch/jornada720.h>
+#include <video/s1d13xxxfb.h>
+
+MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
+MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight/LCD Driver");
+MODULE_LICENSE("GPL");
+
+/* Contrast */
+#define LCD_MAX_CONTR	0xff
+#define LCD_DEF_CONTR	0x80
+/* Brightness */
+#define BL_MAX_BRIGHT	0xff
+#define BL_DEF_BRIGHT	0x19
+
+struct bllcd_device {
+	struct backlight_device *bl_device;
+	struct lcd_device *lcd_device;
+};
+
+/*
+ * BACKLIGHT HANDLING ROUTINES
+ */
+static int jornada_bl_get_brightness(struct backlight_device *dev)
+{
+	int ret;
+
+	/* check if backlight is on */
+	if (!(PPSR & PPC_LDD1))
+		return BL_MAX_BRIGHT;
+
+	jornada_ssp_start();
+	if (jornada_ssp_inout(GETBRIGHTNESS) == -ETIMEDOUT) {
+		printk(KERN_ERR "bl :get brightness timeout\n");
+		ret = -1;
+	} else
+		ret = jornada_ssp_inout(TXDUMMY);
+
+	jornada_ssp_end();
+
+	/* 0 is max brightness */
+	return BL_MAX_BRIGHT - ret;
+}
+
+static int jornada_bl_update_status(struct backlight_device *dev)
+{
+	int ret = 0;
+	int value;
+
+	jornada_ssp_start();
+
+	if (dev->props.power != FB_BLANK_UNBLANK ||
+	dev->props.fb_blank != FB_BLANK_UNBLANK) {
+		ret = jornada_ssp_inout(BRIGHTNESSOFF);
+		if (ret == -ETIMEDOUT) {
+			printk(KERN_ERR "bl : brightness off timeout\n");
+			/* backlight off */
+			PPSR &= ~PPC_LDD1;
+			PPDR |= PPC_LDD1;
+		}
+	} else { /* backlight on */
+		PPSR |= PPC_LDD1;
+		/* send setbrightness cmd */
+		ret = jornada_ssp_inout(SETBRIGHTNESS);
+		if (ret != TXDUMMY) {
+			printk(KERN_ERR "bl :set brightness timeout\n");
+		} else {
+			/* cmd accepted */
+			value = BL_MAX_BRIGHT - dev->props.brightness;
+			if (jornada_ssp_byte(value) == TXDUMMY)
+				ret = value;
+			else
+				printk(KERN_ERR "bl :set brightness failed\n");
+		}
+	}
+
+	jornada_ssp_end();
+
+	return ret;
+}
+
+/*
+ * LCD HANDLING FUNCTIONS
+ */
+static int jornada_lcd_set_contrast(struct lcd_device *pdev, int contrast)
+{
+	int ret = 0;
+
+	jornada_ssp_start();
+
+	ret = jornada_ssp_inout(SETCONTRAST);
+
+	if (ret == -ETIMEDOUT)
+		printk(KERN_ERR "lcd :set contrast timeout\n");
+	else
+		ret = jornada_ssp_byte(contrast);
+
+	jornada_ssp_end();
+
+	return ret;
+}
+
+static int jornada_lcd_set_power(struct lcd_device  *pdev, int power)
+{
+	if (power != FB_BLANK_UNBLANK) {
+		/* turn off LCD */
+		PPSR &= ~PPC_LDD2;
+		PPDR |= PPC_LDD2;
+	} else {
+		/* turn on LCD */
+		PPSR |= PPC_LDD2;
+	}
+
+	return 0;
+}
+
+static int jornada_lcd_get_power(struct lcd_device *pdev)
+{
+	if (PPSR & PPC_LDD2)
+		return FB_BLANK_UNBLANK;
+	else
+		return FB_BLANK_POWERDOWN;
+}
+
+static int jornada_lcd_get_contrast(struct lcd_device *pdev)
+{
+	int ret;
+
+	/* Don't set contrast on off powerd LCD */
+	if (jornada_lcd_get_power(pdev) != FB_BLANK_UNBLANK)
+		return 0;
+
+	jornada_ssp_start();
+
+	ret = jornada_ssp_inout(GETCONTRAST);
+	if (ret != -ETIMEDOUT)
+		ret = jornada_ssp_inout(TXDUMMY);
+	else {
+		printk(KERN_ERR "lcd :get contrast timeout\n");
+		ret = -1;
+	}
+
+	jornada_ssp_end();
+
+	return ret;
+}
+
+static struct backlight_ops jornada_bl_ops = {
+	.get_brightness = jornada_bl_get_brightness,
+	.update_status = jornada_bl_update_status,
+};
+
+static struct lcd_ops jornada_lcd_ops = {
+	.get_contrast = jornada_lcd_get_contrast,
+	.set_contrast = jornada_lcd_set_contrast,
+	.get_power = jornada_lcd_get_power,
+	.set_power = jornada_lcd_set_power,
+};
+
+static int jornada_bl_probe(struct platform_device *pdev)
+{
+	struct bllcd_device *bllcd;
+
+	bllcd = kzalloc(sizeof(*bllcd), GFP_KERNEL);
+	if (bllcd == NULL)
+		return -ENOMEM;
+
+	/* bl driver - name must match fb driver name */
+	bllcd->bl_device = backlight_device_register(S1D_DEVICENAME,
+	&pdev->dev, NULL, &jornada_bl_ops);
+
+	if (IS_ERR(bllcd->bl_device)) {
+		kfree(bllcd);
+		printk(KERN_ERR "bl :failed to register device\n");
+		return -ENODEV;
+	}
+
+	/* lcd driver */
+	bllcd->lcd_device = lcd_device_register(S1D_DEVICENAME,
+				&pdev->dev, NULL, &jornada_lcd_ops);
+	if (IS_ERR(bllcd->lcd_device)) {
+		backlight_device_unregister(bllcd->bl_device);
+		kfree(bllcd);
+		printk(KERN_ERR "lcd :failed to register device\n");
+		return -ENODEV;
+	}
+
+	jornada_lcd_set_contrast(bllcd->lcd_device, LCD_DEF_CONTR);
+	jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_UNBLANK);
+
+	msleep(100);
+
+	bllcd->bl_device->props.power = FB_BLANK_UNBLANK;
+	bllcd->bl_device->props.brightness = BL_DEF_BRIGHT;
+	jornada_bl_update_status(bllcd->bl_device);
+
+	platform_set_drvdata(pdev, bllcd);
+	printk(KERN_INFO "HP Jornada 7xx Backlight/LCD driver activated\n");
+
+	return 0;
+}
+
+static int jornada_bl_remove(struct platform_device *pdev)
+{
+	struct bllcd_device *bllcd = platform_get_drvdata(pdev);
+
+	bllcd->bl_device->props.power = FB_BLANK_POWERDOWN;
+	bllcd->bl_device->props.brightness = 0;
+	bllcd->bl_device->props.max_brightness = 0;
+
+	backlight_device_unregister(bllcd->bl_device);
+	lcd_device_unregister(bllcd->lcd_device);
+
+	return 0;
+}
+
+static int jornada_bl_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct bllcd_device *bllcd = platform_get_drvdata(pdev);
+
+	bllcd->bl_device->props.power = FB_BLANK_POWERDOWN;
+	bllcd->bl_device->props.brightness = 0;
+	bllcd->bl_device->props.max_brightness = 0;
+	jornada_bl_update_status(bllcd->bl_device);
+
+	jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_POWERDOWN);
+
+	return 0;
+}
+
+static int jornada_bl_resume(struct platform_device *pdev)
+{
+	struct bllcd_device *bllcd = platform_get_drvdata(pdev);
+
+	bllcd->bl_device->props.power = FB_BLANK_UNBLANK;
+	bllcd->bl_device->props.brightness = BL_DEF_BRIGHT;
+	bllcd->bl_device->props.max_brightness = BL_MAX_BRIGHT;
+	jornada_bl_update_status(bllcd->bl_device);
+
+	jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_UNBLANK);
+
+	return 0;
+}
+
+static struct platform_driver jornada_bl_driver = {
+	.probe	= jornada_bl_probe,
+	.remove	= jornada_bl_remove,
+#ifdef CONFIG_PM
+	.suspend = jornada_bl_suspend,
+	.resume = jornada_bl_resume,
+#endif
+	.driver = {
+	    .name = "jornada_bllcd",
+	},
+};
+
+static int __init jornada_bl_init(void)
+{
+	return platform_driver_register(&jornada_bl_driver);
+}
+
+static void __exit jornada_bl_exit(void)
+{
+	platform_driver_unregister(&jornada_bl_driver);
+}
+
+module_init(jornada_bl_init);
+module_exit(jornada_bl_exit);

  reply	other threads:[~2008-02-06 19:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-05 18:53 [PATCH/HP7XX] - Add combined LCD / BL driver for platform HP Jornada 7xx handhelds Kristoffer Ericson
2008-02-06 12:34 ` Roel Kluin
2008-02-06 12:38   ` Roel Kluin
2008-02-06 16:33     ` Kristoffer Ericson
2008-02-06 16:44       ` Russell King - ARM Linux
2008-02-06 19:21         ` Kristoffer Ericson [this message]
2008-02-06 19:31           ` Russell King - ARM Linux
2008-02-06 19:43             ` Kristoffer Ericson
2008-02-06 19:45               ` Russell King - ARM Linux
2008-02-07  7:19                 ` Uwe Kleine-König
2008-02-06 19:49             ` Kristoffer Ericson
2008-02-06 17:04       ` Roel Kluin
2008-02-06 17:22       ` Sam Ravnborg
2008-02-06 17:25       ` Richard Purdie
2008-02-06 16:26   ` Kristoffer Ericson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080206202128.06fbcafa.Kristoffer.ericson@gmail.com \
    --to=kristoffer.ericson@gmail.com \
    --cc=12o3l@tiscali.nl \
    --cc=linux-arm-kernel@lists.arm.linux.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=rpurdie@openedhand.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.