Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: Gethering power management/policy hw drivers under drivers/power/? (Re: [RFC][PATCH v3 1/3] runt
From: Rafael J. Wysocki @ 2012-07-30 20:59 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Alex Courbot, Jean Pihet, Greg Kroah-Hartman, David Woodhouse,
	Stephen Warren, Thierry Reding, Simon Glass, Grant Likely,
	Rob Herring, Mark Brown, Arnd Bergmann,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	Liam Girdwood, MyungJoo Ham, linux-pm-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20120730024049.GA10442@lizard>

On Monday, July 30, 2012, Anton Vorontsov wrote:
> On Mon, Jul 30, 2012 at 10:51:42AM +0900, Alex Courbot wrote:
> [...]
> > On the other hand I have just noticed that the apparently unrelated
> > Adaptive Voltage Scaling driver just appeared in drivers/power/avs.
> > So if Anton and David are ok with this, maybe I could put the power
> > sequences code in its own subdirectory within drivers/power.
> 
> Well, currently drivers/power/ is indeed just for power supply class
> subsystem and drivers. But if the trend is to gather power management
> ("policy") stuff under one directory, i.e.
> 
> drivers/
>   power/
>     supplies/    <- former "power supply class and drivers"
>     regulators/
>     idle/
>     cpuidle/
>     cpufreq/
>     devfreq/
>     avs/
>     ...
> 
> That would probably make sense, we could easily see the big picture.
> But if we're not going to do this long-term,

Yes, we may do this eventually, but surely not right now.

Thanks,
Rafael

^ permalink raw reply

* Re: [PATCH 1/7] HID: picoLCD: split driver code
From: Bruno Prémont @ 2012-07-30 19:59 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: linux-fbdev
In-Reply-To: <20120730213828.6c78f8f3@neptune.home>

In order to make code maintenance easier, split the vairous
functions into individial files (this removes a bunch of #ifdefs).

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---



WARNING: this is a mangled resend of this patch (removed the payload of
hunk that deletes drivers/hid/hid-picolcd.c to halve the patch's size)
as resulting mail is otherwise too big for vger (unless bless by list owner)...

If needed, please ask for off-list resending of this patch, though dropping
the first (and mangled) hunk before attempting to apply and then manually
removing the file should do.



 drivers/hid/hid-picolcd.c           | 2752 -----------------------------------
 drivers/hid/Kconfig                 |    8 +
 drivers/hid/Makefile                |   20 +
 drivers/hid/hid-picolcd.h           |  306 ++++
 drivers/hid/hid-picolcd_backlight.c |  121 ++
 drivers/hid/hid-picolcd_cir.c       |   61 +
 drivers/hid/hid-picolcd_core.c      |  704 +++++++++
 drivers/hid/hid-picolcd_debugfs.c   |  898 ++++++++++++
 drivers/hid/hid-picolcd_fb.c        |  673 +++++++++
 drivers/hid/hid-picolcd_lcd.c       |  106 ++
 drivers/hid/hid-picolcd_leds.c      |  172 +++
 11 files changed, 3069 insertions(+), 2752 deletions(-)
 delete mode 100644 drivers/hid/hid-picolcd.c
 create mode 100644 drivers/hid/hid-picolcd.h
 create mode 100644 drivers/hid/hid-picolcd_backlight.c
 create mode 100644 drivers/hid/hid-picolcd_cir.c
 create mode 100644 drivers/hid/hid-picolcd_core.c
 create mode 100644 drivers/hid/hid-picolcd_debugfs.c
 create mode 100644 drivers/hid/hid-picolcd_fb.c
 create mode 100644 drivers/hid/hid-picolcd_lcd.c
 create mode 100644 drivers/hid/hid-picolcd_leds.c

diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
deleted file mode 100644
index 45c3433..0000000
--- a/drivers/hid/hid-picolcd.c
+++ /dev/null
@@ -1,2752 +0,0 @@


<dropped as otherwise patch is too big>



diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 3fda8c8..1d806d0 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -491,6 +491,14 @@ config HID_PICOLCD_LEDS
 	---help---
 	  Provide access to PicoLCD's GPO pins via leds class.
 
+config HID_PICOLCD_CIR
+	bool "CIR via RC class" if EXPERT
+	default !EXPERT
+	depends on HID_PICOLCD
+	depends on HID_PICOLCD=RC_CORE || RC_CORE=y
+	---help---
+	  Provide access to PicoLCD's CIR interface via remote control (LIRC).
+
 config HID_PRIMAX
 	tristate "Primax non-fully HID-compliant devices"
 	depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index ca6cc9f..8b7a9b6 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -66,6 +66,26 @@ obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
+hid-picolcd-y			+= hid-picolcd_core.o
+ifdef CONFIG_HID_PICOLCD_FB
+hid-picolcd-y			+= hid-picolcd_fb.o
+endif
+ifdef CONFIG_HID_PICOLCD_BACKLIGHT
+hid-picolcd-y			+= hid-picolcd_backlight.o
+endif
+ifdef CONFIG_HID_PICOLCD_LCD
+hid-picolcd-y			+= hid-picolcd_lcd.o
+endif
+ifdef CONFIG_HID_PICOLCD_LEDS
+hid-picolcd-y			+= hid-picolcd_leds.o
+endif
+ifdef CONFIG_HID_PICOLCD_CIR
+hid-picolcd-y			+= hid-picolcd_cir.o
+endif
+ifdef CONFIG_DEBUG_FS
+hid-picolcd-y			+= hid-picolcd_debugfs.o
+endif
+
 obj-$(CONFIG_HID_PRIMAX)	+= hid-primax.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o hid-roccat-common.o \
 	hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
diff --git a/drivers/hid/hid-picolcd.h b/drivers/hid/hid-picolcd.h
new file mode 100644
index 0000000..4ddb318
--- /dev/null
+++ b/drivers/hid/hid-picolcd.h
@@ -0,0 +1,306 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#define PICOLCD_NAME "PicoLCD (graphic)"
+
+/* Report numbers */
+#define REPORT_ERROR_CODE      0x10 /* LCD: IN[16]  */
+#define   ERR_SUCCESS            0x00
+#define   ERR_PARAMETER_MISSING  0x01
+#define   ERR_DATA_MISSING       0x02
+#define   ERR_BLOCK_READ_ONLY    0x03
+#define   ERR_BLOCK_NOT_ERASABLE 0x04
+#define   ERR_BLOCK_TOO_BIG      0x05
+#define   ERR_SECTION_OVERFLOW   0x06
+#define   ERR_INVALID_CMD_LEN    0x07
+#define   ERR_INVALID_DATA_LEN   0x08
+#define REPORT_KEY_STATE       0x11 /* LCD: IN[2]   */
+#define REPORT_IR_DATA         0x21 /* LCD: IN[63]  */
+#define REPORT_EE_DATA         0x32 /* LCD: IN[63]  */
+#define REPORT_MEMORY          0x41 /* LCD: IN[63]  */
+#define REPORT_LED_STATE       0x81 /* LCD: OUT[1]  */
+#define REPORT_BRIGHTNESS      0x91 /* LCD: OUT[1]  */
+#define REPORT_CONTRAST        0x92 /* LCD: OUT[1]  */
+#define REPORT_RESET           0x93 /* LCD: OUT[2]  */
+#define REPORT_LCD_CMD         0x94 /* LCD: OUT[63] */
+#define REPORT_LCD_DATA        0x95 /* LCD: OUT[63] */
+#define REPORT_LCD_CMD_DATA    0x96 /* LCD: OUT[63] */
+#define	REPORT_EE_READ         0xa3 /* LCD: OUT[63] */
+#define REPORT_EE_WRITE        0xa4 /* LCD: OUT[63] */
+#define REPORT_ERASE_MEMORY    0xb2 /* LCD: OUT[2]  */
+#define REPORT_READ_MEMORY     0xb3 /* LCD: OUT[3]  */
+#define REPORT_WRITE_MEMORY    0xb4 /* LCD: OUT[63] */
+#define REPORT_SPLASH_RESTART  0xc1 /* LCD: OUT[1]  */
+#define REPORT_EXIT_KEYBOARD   0xef /* LCD: OUT[2]  */
+#define REPORT_VERSION         0xf1 /* LCD: IN[2],OUT[1]    Bootloader: IN[2],OUT[1]   */
+#define REPORT_BL_ERASE_MEMORY 0xf2 /*                      Bootloader: IN[36],OUT[4]  */
+#define REPORT_BL_READ_MEMORY  0xf3 /*                      Bootloader: IN[36],OUT[4]  */
+#define REPORT_BL_WRITE_MEMORY 0xf4 /*                      Bootloader: IN[36],OUT[36] */
+#define REPORT_DEVID           0xf5 /* LCD: IN[5], OUT[1]   Bootloader: IN[5],OUT[1]   */
+#define REPORT_SPLASH_SIZE     0xf6 /* LCD: IN[4], OUT[1]   */
+#define REPORT_HOOK_VERSION    0xf7 /* LCD: IN[2], OUT[1]   */
+#define REPORT_EXIT_FLASHER    0xff /*                      Bootloader: OUT[2]         */
+
+/* Description of in-progress IO operation, used for operations
+ * that trigger response from device */
+struct picolcd_pending {
+	struct hid_report *out_report;
+	struct hid_report *in_report;
+	struct completion ready;
+	int raw_size;
+	u8 raw_data[64];
+};
+
+
+#define PICOLCD_KEYS 17
+
+/* Per device data structure */
+struct picolcd_data {
+	struct hid_device *hdev;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debug_reset;
+	struct dentry *debug_eeprom;
+	struct dentry *debug_flash;
+	struct mutex mutex_flash;
+	int addr_sz;
+#endif
+	u8 version[2];
+	unsigned short opmode_delay;
+	/* input stuff */
+	u8 pressed_keys[2];
+	struct input_dev *input_keys;
+	struct input_dev *input_cir;
+	unsigned short keycode[PICOLCD_KEYS];
+
+#ifdef CONFIG_HID_PICOLCD_FB
+	/* Framebuffer stuff */
+	u8 fb_update_rate;
+	u8 fb_bpp;
+	u8 fb_force;
+	u8 *fb_vbitmap;		/* local copy of what was sent to PicoLCD */
+	u8 *fb_bitmap;		/* framebuffer */
+	struct fb_info *fb_info;
+	struct fb_deferred_io fb_defio;
+#endif /* CONFIG_HID_PICOLCD_FB */
+#ifdef CONFIG_HID_PICOLCD_LCD
+	struct lcd_device *lcd;
+	u8 lcd_contrast;
+#endif /* CONFIG_HID_PICOLCD_LCD */
+#ifdef CONFIG_HID_PICOLCD_BACKLIGHT
+	struct backlight_device *backlight;
+	u8 lcd_brightness;
+	u8 lcd_power;
+#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
+#ifdef CONFIG_HID_PICOLCD_LEDS
+	/* LED stuff */
+	u8 led_state;
+	struct led_classdev *led[8];
+#endif /* CONFIG_HID_PICOLCD_LEDS */
+
+	/* Housekeeping stuff */
+	spinlock_t lock;
+	struct mutex mutex;
+	struct picolcd_pending *pending;
+	int status;
+#define PICOLCD_BOOTLOADER 1
+#define PICOLCD_FAILED 2
+#define PICOLCD_READY_FB 4
+};
+
+
+/* Find a given report */
+#define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT)
+#define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT)
+
+struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir);
+
+#ifdef CONFIG_DEBUG_FS
+void picolcd_debug_out_report(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report);
+#define usbhid_submit_report(a, b, c) \
+	do { \
+		picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
+		usbhid_submit_report(a, b, c); \
+	} while (0)
+
+void picolcd_debug_raw_event(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size);
+
+void picolcd_init_devfs(struct picolcd_data *data,
+		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
+		struct hid_report *flash_r, struct hid_report *flash_w,
+		struct hid_report *reset);
+
+void picolcd_exit_devfs(struct picolcd_data *data);
+#else
+static inline void picolcd_debug_raw_event(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size)
+{
+}
+static inline void picolcd_init_devfs(struct picolcd_data *data,
+		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
+		struct hid_report *flash_r, struct hid_report *flash_w,
+		struct hid_report *reset)
+{
+}
+static inline void picolcd_exit_devfs(struct picolcd_data *data)
+{
+}
+static inline void picolcd_debug_raw_event(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+
+#ifdef CONFIG_HID_PICOLCD_FB
+int picolcd_fb_reset(struct picolcd_data *data, int clear);
+
+int picolcd_init_framebuffer(struct picolcd_data *data);
+
+void picolcd_exit_framebuffer(struct picolcd_data *data);
+
+void picolcd_fb_unload(void);
+
+void picolcd_fb_refresh(struct picolcd_data *data);
+#define picolcd_fbinfo(d) ((d)->fb_info)
+#else
+static inline int picolcd_fb_reset(struct picolcd_data *data, int clear)
+{
+	return 0;
+}
+static inline int picolcd_init_framebuffer(struct picolcd_data *data)
+{
+	return 0;
+}
+static inline void picolcd_exit_framebuffer(struct picolcd_data *data)
+{
+}
+static inline void picolcd_fb_unload(void)
+{
+}
+static inline void picolcd_fb_refresh(struct picolcd_data *data)
+{
+}
+#define picolcd_fbinfo(d) NULL
+#endif /* CONFIG_HID_PICOLCD_FB */
+
+
+#ifdef CONFIG_HID_PICOLCD_BACKLIGHT
+int picolcd_init_backlight(struct picolcd_data *data,
+		struct hid_report *report);
+
+void picolcd_exit_backlight(struct picolcd_data *data);
+
+int picolcd_resume_backlight(struct picolcd_data *data);
+
+void picolcd_suspend_backlight(struct picolcd_data *data);
+#else
+static inline int picolcd_init_backlight(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_backlight(struct picolcd_data *data)
+{
+}
+static inline int picolcd_resume_backlight(struct picolcd_data *data)
+{
+	return 0;
+}
+static inline void picolcd_suspend_backlight(struct picolcd_data *data)
+{
+}
+
+#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
+
+
+#ifdef CONFIG_HID_PICOLCD_LCD
+int picolcd_init_lcd(struct picolcd_data *data,
+		struct hid_report *report);
+
+void picolcd_exit_lcd(struct picolcd_data *data);
+
+int picolcd_resume_lcd(struct picolcd_data *data);
+#else
+static inline int picolcd_init_lcd(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_lcd(struct picolcd_data *data)
+{
+}
+static inline int picolcd_resume_lcd(struct picolcd_data *data)
+{
+	return 0;
+}
+#endif /* CONFIG_HID_PICOLCD_LCD */
+
+
+#ifdef CONFIG_HID_PICOLCD_LEDS
+int picolcd_init_leds(struct picolcd_data *data,
+		struct hid_report *report);
+
+void picolcd_exit_leds(struct picolcd_data *data);
+
+void picolcd_leds_set(struct picolcd_data *data);
+#else
+static inline int picolcd_init_leds(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_leds(struct picolcd_data *data)
+{
+}
+static inline void picolcd_leds_set(struct picolcd_data *data)
+{
+}
+#endif /* CONFIG_HID_PICOLCD_LEDS */
+
+
+#ifdef CONFIG_HID_PICOLCD_CIR
+int picolcd_raw_cir(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size);
+
+int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report);
+
+void picolcd_exit_cir(struct picolcd_data *data);
+#else
+static inline int picolcd_raw_cir(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	return 1;
+}
+static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_cir(struct picolcd_data *data)
+{
+}
+#endif /* CONFIG_HID_PICOLCD_LIRC */
+
+int picolcd_reset(struct hid_device *hdev);
+struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
+			int report_id, const u8 *raw_data, int size);
diff --git a/drivers/hid/hid-picolcd_backlight.c b/drivers/hid/hid-picolcd_backlight.c
new file mode 100644
index 0000000..cd1ccd7
--- /dev/null
+++ b/drivers/hid/hid-picolcd_backlight.c
@@ -0,0 +1,121 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/backlight.h>
+
+#include "hid-picolcd.h"
+
+static int picolcd_get_brightness(struct backlight_device *bdev)
+{
+	struct picolcd_data *data = bl_get_data(bdev);
+	return data->lcd_brightness;
+}
+
+static int picolcd_set_brightness(struct backlight_device *bdev)
+{
+	struct picolcd_data *data = bl_get_data(bdev);
+	struct hid_report *report = picolcd_out_report(REPORT_BRIGHTNESS, data->hdev);
+	unsigned long flags;
+
+	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
+		return -ENODEV;
+
+	data->lcd_brightness = bdev->props.brightness & 0x0ff;
+	data->lcd_power      = bdev->props.power;
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, data->lcd_power = FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
+	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+static int picolcd_check_bl_fb(struct backlight_device *bdev, struct fb_info *fb)
+{
+	return fb && fb = picolcd_fbinfo((struct picolcd_data *)bl_get_data(bdev));
+}
+
+static const struct backlight_ops picolcd_blops = {
+	.update_status  = picolcd_set_brightness,
+	.get_brightness = picolcd_get_brightness,
+	.check_fb       = picolcd_check_bl_fb,
+};
+
+int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report)
+{
+	struct device *dev = &data->hdev->dev;
+	struct backlight_device *bdev;
+	struct backlight_properties props;
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
+			report->field[0]->report_size != 8) {
+		dev_err(dev, "unsupported BRIGHTNESS report");
+		return -EINVAL;
+	}
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 0xff;
+	bdev = backlight_device_register(dev_name(dev), dev, data,
+			&picolcd_blops, &props);
+	if (IS_ERR(bdev)) {
+		dev_err(dev, "failed to register backlight\n");
+		return PTR_ERR(bdev);
+	}
+	bdev->props.brightness     = 0xff;
+	data->lcd_brightness       = 0xff;
+	data->backlight            = bdev;
+	picolcd_set_brightness(bdev);
+	return 0;
+}
+
+void picolcd_exit_backlight(struct picolcd_data *data)
+{
+	struct backlight_device *bdev = data->backlight;
+
+	data->backlight = NULL;
+	if (bdev)
+		backlight_device_unregister(bdev);
+}
+
+int picolcd_resume_backlight(struct picolcd_data *data)
+{
+	if (!data->backlight)
+		return 0;
+	return picolcd_set_brightness(data->backlight);
+}
+
+#ifdef CONFIG_PM
+void picolcd_suspend_backlight(struct picolcd_data *data)
+{
+	int bl_power = data->lcd_power;
+	if (!data->backlight)
+		return;
+
+	data->backlight->props.power = FB_BLANK_POWERDOWN;
+	picolcd_set_brightness(data->backlight);
+	data->lcd_power = data->backlight->props.power = bl_power;
+}
+#endif /* CONFIG_PM */
+
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
new file mode 100644
index 0000000..dc632c3
--- /dev/null
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -0,0 +1,61 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include <linux/input.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <linux/leds.h>
+
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+
+int picolcd_raw_cir(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	/* Need understanding of CIR data format to implement ... */
+	return 1;
+}
+
+/* initialize CIR input device */
+int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
+{
+	/* support not implemented yet */
+	return 0;
+}
+
+void picolcd_exit_cir(struct picolcd_data *data)
+{
+}
+
diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
new file mode 100644
index 0000000..36e7548
--- /dev/null
+++ b/drivers/hid/hid-picolcd_core.c
@@ -0,0 +1,704 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include <linux/input.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+
+/* Input device
+ *
+ * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys
+ * and header for 4x4 key matrix. The built-in keys are part of the matrix.
+ */
+static const unsigned short def_keymap[PICOLCD_KEYS] = {
+	KEY_RESERVED,	/* none */
+	KEY_BACK,	/* col 4 + row 1 */
+	KEY_HOMEPAGE,	/* col 3 + row 1 */
+	KEY_RESERVED,	/* col 2 + row 1 */
+	KEY_RESERVED,	/* col 1 + row 1 */
+	KEY_SCROLLUP,	/* col 4 + row 2 */
+	KEY_OK,		/* col 3 + row 2 */
+	KEY_SCROLLDOWN,	/* col 2 + row 2 */
+	KEY_RESERVED,	/* col 1 + row 2 */
+	KEY_RESERVED,	/* col 4 + row 3 */
+	KEY_RESERVED,	/* col 3 + row 3 */
+	KEY_RESERVED,	/* col 2 + row 3 */
+	KEY_RESERVED,	/* col 1 + row 3 */
+	KEY_RESERVED,	/* col 4 + row 4 */
+	KEY_RESERVED,	/* col 3 + row 4 */
+	KEY_RESERVED,	/* col 2 + row 4 */
+	KEY_RESERVED,	/* col 1 + row 4 */
+};
+
+
+/* Find a given report */
+struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir)
+{
+	struct list_head *feature_report_list = &hdev->report_enum[dir].report_list;
+	struct hid_report *report = NULL;
+
+	list_for_each_entry(report, feature_report_list, list) {
+		if (report->id = id)
+			return report;
+	}
+	hid_warn(hdev, "No report with id 0x%x found\n", id);
+	return NULL;
+}
+
+/* Submit a report and wait for a reply from device - if device fades away
+ * or does not respond in time, return NULL */
+struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
+		int report_id, const u8 *raw_data, int size)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	struct picolcd_pending *work;
+	struct hid_report *report = picolcd_out_report(report_id, hdev);
+	unsigned long flags;
+	int i, j, k;
+
+	if (!report || !data)
+		return NULL;
+	if (data->status & PICOLCD_FAILED)
+		return NULL;
+	work = kzalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		return NULL;
+
+	init_completion(&work->ready);
+	work->out_report = report;
+	work->in_report  = NULL;
+	work->raw_size   = 0;
+
+	mutex_lock(&data->mutex);
+	spin_lock_irqsave(&data->lock, flags);
+	for (i = k = 0; i < report->maxfield; i++)
+		for (j = 0; j < report->field[i]->report_count; j++) {
+			hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0);
+			k++;
+		}
+	data->pending = work;
+	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
+	spin_lock_irqsave(&data->lock, flags);
+	data->pending = NULL;
+	spin_unlock_irqrestore(&data->lock, flags);
+	mutex_unlock(&data->mutex);
+	return work;
+}
+
+/*
+ * input class device
+ */
+static int picolcd_raw_keypad(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	/*
+	 * Keypad event
+	 * First and second data bytes list currently pressed keys,
+	 * 0x00 means no key and at most 2 keys may be pressed at same time
+	 */
+	int i, j;
+
+	/* determine newly pressed keys */
+	for (i = 0; i < size; i++) {
+		unsigned int key_code;
+		if (raw_data[i] = 0)
+			continue;
+		for (j = 0; j < sizeof(data->pressed_keys); j++)
+			if (data->pressed_keys[j] = raw_data[i])
+				goto key_already_down;
+		for (j = 0; j < sizeof(data->pressed_keys); j++)
+			if (data->pressed_keys[j] = 0) {
+				data->pressed_keys[j] = raw_data[i];
+				break;
+			}
+		input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]);
+		if (raw_data[i] < PICOLCD_KEYS)
+			key_code = data->keycode[raw_data[i]];
+		else
+			key_code = KEY_UNKNOWN;
+		if (key_code != KEY_UNKNOWN) {
+			dbg_hid(PICOLCD_NAME " got key press for %u:%d",
+					raw_data[i], key_code);
+			input_report_key(data->input_keys, key_code, 1);
+		}
+		input_sync(data->input_keys);
+key_already_down:
+		continue;
+	}
+
+	/* determine newly released keys */
+	for (j = 0; j < sizeof(data->pressed_keys); j++) {
+		unsigned int key_code;
+		if (data->pressed_keys[j] = 0)
+			continue;
+		for (i = 0; i < size; i++)
+			if (data->pressed_keys[j] = raw_data[i])
+				goto key_still_down;
+		input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]);
+		if (data->pressed_keys[j] < PICOLCD_KEYS)
+			key_code = data->keycode[data->pressed_keys[j]];
+		else
+			key_code = KEY_UNKNOWN;
+		if (key_code != KEY_UNKNOWN) {
+			dbg_hid(PICOLCD_NAME " got key release for %u:%d",
+					data->pressed_keys[j], key_code);
+			input_report_key(data->input_keys, key_code, 0);
+		}
+		input_sync(data->input_keys);
+		data->pressed_keys[j] = 0;
+key_still_down:
+		continue;
+	}
+	return 1;
+}
+
+static int picolcd_check_version(struct hid_device *hdev)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	struct picolcd_pending *verinfo;
+	int ret = 0;
+
+	if (!data)
+		return -ENODEV;
+
+	verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0);
+	if (!verinfo) {
+		hid_err(hdev, "no version response from PicoLCD\n");
+		return -ENODEV;
+	}
+
+	if (verinfo->raw_size = 2) {
+		data->version[0] = verinfo->raw_data[1];
+		data->version[1] = verinfo->raw_data[0];
+		if (data->status & PICOLCD_BOOTLOADER) {
+			hid_info(hdev, "PicoLCD, bootloader version %d.%d\n",
+				 verinfo->raw_data[1], verinfo->raw_data[0]);
+		} else {
+			hid_info(hdev, "PicoLCD, firmware version %d.%d\n",
+				 verinfo->raw_data[1], verinfo->raw_data[0]);
+		}
+	} else {
+		hid_err(hdev, "confused, got unexpected version response from PicoLCD\n");
+		ret = -EINVAL;
+	}
+	kfree(verinfo);
+	return ret;
+}
+
+/*
+ * Reset our device and wait for answer to VERSION request
+ */
+int picolcd_reset(struct hid_device *hdev)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev);
+	unsigned long flags;
+	int error;
+
+	if (!data || !report || report->maxfield != 1)
+		return -ENODEV;
+
+	spin_lock_irqsave(&data->lock, flags);
+	if (hdev->product = USB_DEVICE_ID_PICOLCD_BOOTLOADER)
+		data->status |= PICOLCD_BOOTLOADER;
+
+	/* perform the reset */
+	hid_set_field(report->field[0], 0, 1);
+	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	error = picolcd_check_version(hdev);
+	if (error)
+		return error;
+
+	picolcd_resume_lcd(data);
+	picolcd_resume_backlight(data);
+	picolcd_fb_refresh(data);
+	picolcd_leds_set(data);
+	return 0;
+}
+
+/*
+ * The "operation_mode" sysfs attribute
+ */
+static ssize_t picolcd_operation_mode_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+
+	if (data->status & PICOLCD_BOOTLOADER)
+		return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n");
+	else
+		return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n");
+}
+
+static ssize_t picolcd_operation_mode_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	struct hid_report *report = NULL;
+	size_t cnt = count;
+	int timeout = data->opmode_delay;
+	unsigned long flags;
+
+	if (cnt >= 3 && strncmp("lcd", buf, 3) = 0) {
+		if (data->status & PICOLCD_BOOTLOADER)
+			report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev);
+		buf += 3;
+		cnt -= 3;
+	} else if (cnt >= 10 && strncmp("bootloader", buf, 10) = 0) {
+		if (!(data->status & PICOLCD_BOOTLOADER))
+			report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev);
+		buf += 10;
+		cnt -= 10;
+	}
+	if (!report)
+		return -EINVAL;
+
+	while (cnt > 0 && (buf[cnt-1] = '\n' || buf[cnt-1] = '\r'))
+		cnt--;
+	if (cnt != 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, timeout & 0xff);
+	hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
+	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return count;
+}
+
+static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show,
+		picolcd_operation_mode_store);
+
+/*
+ * The "operation_mode_delay" sysfs attribute
+ */
+static ssize_t picolcd_operation_mode_delay_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay);
+}
+
+static ssize_t picolcd_operation_mode_delay_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	unsigned u;
+	if (sscanf(buf, "%u", &u) != 1)
+		return -EINVAL;
+	if (u > 30000)
+		return -EINVAL;
+	else
+		data->opmode_delay = u;
+	return count;
+}
+
+static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show,
+		picolcd_operation_mode_delay_store);
+
+/*
+ * Handle raw report as sent by device
+ */
+static int picolcd_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	unsigned long flags;
+	int ret = 0;
+
+	if (!data)
+		return 1;
+
+	if (report->id = REPORT_KEY_STATE) {
+		if (data->input_keys)
+			ret = picolcd_raw_keypad(data, report, raw_data+1, size-1);
+	} else if (report->id = REPORT_IR_DATA) {
+		if (data->input_cir)
+			ret = picolcd_raw_cir(data, report, raw_data+1, size-1);
+	} else {
+		spin_lock_irqsave(&data->lock, flags);
+		/*
+		 * We let the caller of picolcd_send_and_wait() check if the
+		 * report we got is one of the expected ones or not.
+		 */
+		if (data->pending) {
+			memcpy(data->pending->raw_data, raw_data+1, size-1);
+			data->pending->raw_size  = size-1;
+			data->pending->in_report = report;
+			complete(&data->pending->ready);
+		}
+		spin_unlock_irqrestore(&data->lock, flags);
+	}
+
+	picolcd_debug_raw_event(data, hdev, report, raw_data, size);
+	return 1;
+}
+
+#ifdef CONFIG_PM
+static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
+{
+	if (PMSG_IS_AUTO(message))
+		return 0;
+
+	picolcd_suspend_backlight(hid_get_drvdata(hdev));
+	dbg_hid(PICOLCD_NAME " device ready for suspend\n");
+	return 0;
+}
+
+static int picolcd_resume(struct hid_device *hdev)
+{
+	int ret;
+	ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
+	return 0;
+}
+
+static int picolcd_reset_resume(struct hid_device *hdev)
+{
+	int ret;
+	ret = picolcd_reset(hdev);
+	if (ret)
+		dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret);
+	ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0);
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret);
+	ret = picolcd_resume_lcd(hid_get_drvdata(hdev));
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret);
+	ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
+	picolcd_leds_set(hid_get_drvdata(hdev));
+	return 0;
+}
+#endif
+
+/* initialize keypad input device */
+static int picolcd_init_keys(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	struct hid_device *hdev = data->hdev;
+	struct input_dev *idev;
+	int error, i;
+
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 2 ||
+			report->field[0]->report_size != 8) {
+		hid_err(hdev, "unsupported KEY_STATE report\n");
+		return -EINVAL;
+	}
+
+	idev = input_allocate_device();
+	if (idev = NULL) {
+		hid_err(hdev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+	input_set_drvdata(idev, hdev);
+	memcpy(data->keycode, def_keymap, sizeof(def_keymap));
+	idev->name = hdev->name;
+	idev->phys = hdev->phys;
+	idev->uniq = hdev->uniq;
+	idev->id.bustype = hdev->bus;
+	idev->id.vendor  = hdev->vendor;
+	idev->id.product = hdev->product;
+	idev->id.version = hdev->version;
+	idev->dev.parent = hdev->dev.parent;
+	idev->keycode     = &data->keycode;
+	idev->keycodemax  = PICOLCD_KEYS;
+	idev->keycodesize = sizeof(data->keycode[0]);
+	input_set_capability(idev, EV_MSC, MSC_SCAN);
+	set_bit(EV_REP, idev->evbit);
+	for (i = 0; i < PICOLCD_KEYS; i++)
+		input_set_capability(idev, EV_KEY, data->keycode[i]);
+	error = input_register_device(idev);
+	if (error) {
+		hid_err(hdev, "error registering the input device\n");
+		input_free_device(idev);
+		return error;
+	}
+	data->input_keys = idev;
+	return 0;
+}
+
+static void picolcd_exit_keys(struct picolcd_data *data)
+{
+	struct input_dev *idev = data->input_keys;
+
+	data->input_keys = NULL;
+	if (idev)
+		input_unregister_device(idev);
+}
+
+static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data)
+{
+	int error;
+
+	error = picolcd_check_version(hdev);
+	if (error)
+		return error;
+
+	if (data->version[0] != 0 && data->version[1] != 3)
+		hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
+			 dev_name(&hdev->dev));
+
+	/* Setup keypad input device */
+	error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev));
+	if (error)
+		goto err;
+
+	/* Setup CIR input device */
+	error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev));
+	if (error)
+		goto err;
+
+	/* Set up the framebuffer device */
+	error = picolcd_init_framebuffer(data);
+	if (error)
+		goto err;
+
+	/* Setup lcd class device */
+	error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev));
+	if (error)
+		goto err;
+
+	/* Setup backlight class device */
+	error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev));
+	if (error)
+		goto err;
+
+	/* Setup the LED class devices */
+	error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev));
+	if (error)
+		goto err;
+
+	picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev),
+			picolcd_out_report(REPORT_EE_WRITE, hdev),
+			picolcd_out_report(REPORT_READ_MEMORY, hdev),
+			picolcd_out_report(REPORT_WRITE_MEMORY, hdev),
+			picolcd_out_report(REPORT_RESET, hdev));
+	return 0;
+err:
+	picolcd_exit_leds(data);
+	picolcd_exit_backlight(data);
+	picolcd_exit_lcd(data);
+	picolcd_exit_framebuffer(data);
+	picolcd_exit_cir(data);
+	picolcd_exit_keys(data);
+	return error;
+}
+
+static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data)
+{
+	int error;
+
+	error = picolcd_check_version(hdev);
+	if (error)
+		return error;
+
+	if (data->version[0] != 1 && data->version[1] != 0)
+		hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
+			 dev_name(&hdev->dev));
+
+	picolcd_init_devfs(data, NULL, NULL,
+			picolcd_out_report(REPORT_BL_READ_MEMORY, hdev),
+			picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL);
+	return 0;
+}
+
+static int picolcd_probe(struct hid_device *hdev,
+		     const struct hid_device_id *id)
+{
+	struct picolcd_data *data;
+	int error = -ENOMEM;
+
+	dbg_hid(PICOLCD_NAME " hardware probe...\n");
+
+	/*
+	 * Let's allocate the picolcd data structure, set some reasonable
+	 * defaults, and associate it with the device
+	 */
+	data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL);
+	if (data = NULL) {
+		hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n");
+		error = -ENOMEM;
+		goto err_no_cleanup;
+	}
+
+	spin_lock_init(&data->lock);
+	mutex_init(&data->mutex);
+	data->hdev = hdev;
+	data->opmode_delay = 5000;
+	if (hdev->product = USB_DEVICE_ID_PICOLCD_BOOTLOADER)
+		data->status |= PICOLCD_BOOTLOADER;
+	hid_set_drvdata(hdev, data);
+
+	/* Parse the device reports and start it up */
+	error = hid_parse(hdev);
+	if (error) {
+		hid_err(hdev, "device report parse failed\n");
+		goto err_cleanup_data;
+	}
+
+	/* We don't use hidinput but hid_hw_start() fails if nothing is
+	 * claimed. So spoof claimed input. */
+	hdev->claimed = HID_CLAIMED_INPUT;
+	error = hid_hw_start(hdev, 0);
+	hdev->claimed = 0;
+	if (error) {
+		hid_err(hdev, "hardware start failed\n");
+		goto err_cleanup_data;
+	}
+
+	error = hid_hw_open(hdev);
+	if (error) {
+		hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n");
+		goto err_cleanup_hid_hw;
+	}
+
+	error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
+	if (error) {
+		hid_err(hdev, "failed to create sysfs attributes\n");
+		goto err_cleanup_hid_ll;
+	}
+
+	error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
+	if (error) {
+		hid_err(hdev, "failed to create sysfs attributes\n");
+		goto err_cleanup_sysfs1;
+	}
+
+	if (data->status & PICOLCD_BOOTLOADER)
+		error = picolcd_probe_bootloader(hdev, data);
+	else
+		error = picolcd_probe_lcd(hdev, data);
+	if (error)
+		goto err_cleanup_sysfs2;
+
+	dbg_hid(PICOLCD_NAME " activated and initialized\n");
+	return 0;
+
+err_cleanup_sysfs2:
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
+err_cleanup_sysfs1:
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
+err_cleanup_hid_ll:
+	hid_hw_close(hdev);
+err_cleanup_hid_hw:
+	hid_hw_stop(hdev);
+err_cleanup_data:
+	kfree(data);
+err_no_cleanup:
+	hid_set_drvdata(hdev, NULL);
+
+	return error;
+}
+
+static void picolcd_remove(struct hid_device *hdev)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	unsigned long flags;
+
+	dbg_hid(PICOLCD_NAME " hardware remove...\n");
+	spin_lock_irqsave(&data->lock, flags);
+	data->status |= PICOLCD_FAILED;
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	picolcd_exit_devfs(data);
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
+	hid_hw_close(hdev);
+	hid_hw_stop(hdev);
+	hid_set_drvdata(hdev, NULL);
+
+	/* Shortcut potential pending reply that will never arrive */
+	spin_lock_irqsave(&data->lock, flags);
+	if (data->pending)
+		complete(&data->pending->ready);
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* Cleanup LED */
+	picolcd_exit_leds(data);
+	/* Clean up the framebuffer */
+	picolcd_exit_backlight(data);
+	picolcd_exit_lcd(data);
+	picolcd_exit_framebuffer(data);
+	/* Cleanup input */
+	picolcd_exit_cir(data);
+	picolcd_exit_keys(data);
+
+	mutex_destroy(&data->mutex);
+	/* Finally, clean up the picolcd data itself */
+	kfree(data);
+}
+
+static const struct hid_device_id picolcd_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, picolcd_devices);
+
+static struct hid_driver picolcd_driver = {
+	.name =          "hid-picolcd",
+	.id_table =      picolcd_devices,
+	.probe =         picolcd_probe,
+	.remove =        picolcd_remove,
+	.raw_event =     picolcd_raw_event,
+#ifdef CONFIG_PM
+	.suspend =       picolcd_suspend,
+	.resume =        picolcd_resume,
+	.reset_resume =  picolcd_reset_resume,
+#endif
+};
+
+static int __init picolcd_init(void)
+{
+	return hid_register_driver(&picolcd_driver);
+}
+
+static void __exit picolcd_exit(void)
+{
+	hid_unregister_driver(&picolcd_driver);
+	picolcd_fb_unload();
+}
+
+module_init(picolcd_init);
+module_exit(picolcd_exit);
+MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
new file mode 100644
index 0000000..ff74645
--- /dev/null
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -0,0 +1,898 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+
+static int picolcd_debug_reset_show(struct seq_file *f, void *p)
+{
+	if (picolcd_fbinfo((struct picolcd_data *)f->private))
+		seq_printf(f, "all fb\n");
+	else
+		seq_printf(f, "all\n");
+	return 0;
+}
+
+static int picolcd_debug_reset_open(struct inode *inode, struct file *f)
+{
+	return single_open(f, picolcd_debug_reset_show, inode->i_private);
+}
+
+static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf,
+		size_t count, loff_t *ppos)
+{
+	struct picolcd_data *data = ((struct seq_file *)f->private_data)->private;
+	char buf[32];
+	size_t cnt = min(count, sizeof(buf)-1);
+	if (copy_from_user(buf, user_buf, cnt))
+		return -EFAULT;
+
+	while (cnt > 0 && (buf[cnt-1] = ' ' || buf[cnt-1] = '\n'))
+		cnt--;
+	buf[cnt] = '\0';
+	if (strcmp(buf, "all") = 0) {
+		picolcd_reset(data->hdev);
+		picolcd_fb_reset(data, 1);
+	} else if (strcmp(buf, "fb") = 0) {
+		picolcd_fb_reset(data, 1);
+	} else {
+		return -EINVAL;
+	}
+	return count;
+}
+
+static const struct file_operations picolcd_debug_reset_fops = {
+	.owner    = THIS_MODULE,
+	.open     = picolcd_debug_reset_open,
+	.read     = seq_read,
+	.llseek   = seq_lseek,
+	.write    = picolcd_debug_reset_write,
+	.release  = single_release,
+};
+
+/*
+ * The "eeprom" file
+ */
+static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+	struct picolcd_pending *resp;
+	u8 raw_data[3];
+	ssize_t ret = -EIO;
+
+	if (s = 0)
+		return -EINVAL;
+	if (*off > 0x0ff)
+		return 0;
+
+	/* prepare buffer with info about what we want to read (addr & len) */
+	raw_data[0] = *off & 0xff;
+	raw_data[1] = (*off >> 8) & 0xff;
+	raw_data[2] = s < 20 ? s : 20;
+	if (*off + raw_data[2] > 0xff)
+		raw_data[2] = 0x100 - *off;
+	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data,
+			sizeof(raw_data));
+	if (!resp)
+		return -EIO;
+
+	if (resp->in_report && resp->in_report->id = REPORT_EE_DATA) {
+		/* successful read :) */
+		ret = resp->raw_data[2];
+		if (ret > s)
+			ret = s;
+		if (copy_to_user(u, resp->raw_data+3, ret))
+			ret = -EFAULT;
+		else
+			*off += ret;
+	} /* anything else is some kind of IO error */
+
+	kfree(resp);
+	return ret;
+}
+
+static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+	struct picolcd_pending *resp;
+	ssize_t ret = -EIO;
+	u8 raw_data[23];
+
+	if (s = 0)
+		return -EINVAL;
+	if (*off > 0x0ff)
+		return -ENOSPC;
+
+	memset(raw_data, 0, sizeof(raw_data));
+	raw_data[0] = *off & 0xff;
+	raw_data[1] = (*off >> 8) & 0xff;
+	raw_data[2] = min((size_t)20, s);
+	if (*off + raw_data[2] > 0xff)
+		raw_data[2] = 0x100 - *off;
+
+	if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
+		return -EFAULT;
+	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data,
+			sizeof(raw_data));
+
+	if (!resp)
+		return -EIO;
+
+	if (resp->in_report && resp->in_report->id = REPORT_EE_DATA) {
+		/* check if written data matches */
+		if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) = 0) {
+			*off += raw_data[2];
+			ret = raw_data[2];
+		}
+	}
+	kfree(resp);
+	return ret;
+}
+
+/*
+ * Notes:
+ * - read/write happens in chunks of at most 20 bytes, it's up to userspace
+ *   to loop in order to get more data.
+ * - on write errors on otherwise correct write request the bytes
+ *   that should have been written are in undefined state.
+ */
+static const struct file_operations picolcd_debug_eeprom_fops = {
+	.owner    = THIS_MODULE,
+	.open     = simple_open,
+	.read     = picolcd_debug_eeprom_read,
+	.write    = picolcd_debug_eeprom_write,
+	.llseek   = generic_file_llseek,
+};
+
+/*
+ * The "flash" file
+ */
+/* record a flash address to buf (bounds check to be done by caller) */
+static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off)
+{
+	buf[0] = off & 0xff;
+	buf[1] = (off >> 8) & 0xff;
+	if (data->addr_sz = 3)
+		buf[2] = (off >> 16) & 0xff;
+	return data->addr_sz = 2 ? 2 : 3;
+}
+
+/* read a given size of data (bounds check to be done by caller) */
+static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id,
+		char __user *u, size_t s, loff_t *off)
+{
+	struct picolcd_pending *resp;
+	u8 raw_data[4];
+	ssize_t ret = 0;
+	int len_off, err = -EIO;
+
+	while (s > 0) {
+		err = -EIO;
+		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
+		raw_data[len_off] = s > 32 ? 32 : s;
+		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1);
+		if (!resp || !resp->in_report)
+			goto skip;
+		if (resp->in_report->id = REPORT_MEMORY ||
+			resp->in_report->id = REPORT_BL_READ_MEMORY) {
+			if (memcmp(raw_data, resp->raw_data, len_off+1) != 0)
+				goto skip;
+			if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) {
+				err = -EFAULT;
+				goto skip;
+			}
+			*off += raw_data[len_off];
+			s    -= raw_data[len_off];
+			ret  += raw_data[len_off];
+			err   = 0;
+		}
+skip:
+		kfree(resp);
+		if (err)
+			return ret > 0 ? ret : err;
+	}
+	return ret;
+}
+
+static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+
+	if (s = 0)
+		return -EINVAL;
+	if (*off > 0x05fff)
+		return 0;
+	if (*off + s > 0x05fff)
+		s = 0x06000 - *off;
+
+	if (data->status & PICOLCD_BOOTLOADER)
+		return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off);
+	else
+		return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off);
+}
+
+/* erase block aligned to 64bytes boundary */
+static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id,
+		loff_t *off)
+{
+	struct picolcd_pending *resp;
+	u8 raw_data[3];
+	int len_off;
+	ssize_t ret = -EIO;
+
+	if (*off & 0x3f)
+		return -EINVAL;
+
+	len_off = _picolcd_flash_setaddr(data, raw_data, *off);
+	resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off);
+	if (!resp || !resp->in_report)
+		goto skip;
+	if (resp->in_report->id = REPORT_MEMORY ||
+		resp->in_report->id = REPORT_BL_ERASE_MEMORY) {
+		if (memcmp(raw_data, resp->raw_data, len_off) != 0)
+			goto skip;
+		ret = 0;
+	}
+skip:
+	kfree(resp);
+	return ret;
+}
+
+/* write a given size of data (bounds check to be done by caller) */
+static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id,
+		const char __user *u, size_t s, loff_t *off)
+{
+	struct picolcd_pending *resp;
+	u8 raw_data[36];
+	ssize_t ret = 0;
+	int len_off, err = -EIO;
+
+	while (s > 0) {
+		err = -EIO;
+		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
+		raw_data[len_off] = s > 32 ? 32 : s;
+		if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) {
+			err = -EFAULT;
+			break;
+		}
+		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data,
+				len_off+1+raw_data[len_off]);
+		if (!resp || !resp->in_report)
+			goto skip;
+		if (resp->in_report->id = REPORT_MEMORY ||
+			resp->in_report->id = REPORT_BL_WRITE_MEMORY) {
+			if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0)
+				goto skip;
+			*off += raw_data[len_off];
+			s    -= raw_data[len_off];
+			ret  += raw_data[len_off];
+			err   = 0;
+		}
+skip:
+		kfree(resp);
+		if (err)
+			break;
+	}
+	return ret > 0 ? ret : err;
+}
+
+static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+	ssize_t err, ret = 0;
+	int report_erase, report_write;
+
+	if (s = 0)
+		return -EINVAL;
+	if (*off > 0x5fff)
+		return -ENOSPC;
+	if (s & 0x3f)
+		return -EINVAL;
+	if (*off & 0x3f)
+		return -EINVAL;
+
+	if (data->status & PICOLCD_BOOTLOADER) {
+		report_erase = REPORT_BL_ERASE_MEMORY;
+		report_write = REPORT_BL_WRITE_MEMORY;
+	} else {
+		report_erase = REPORT_ERASE_MEMORY;
+		report_write = REPORT_WRITE_MEMORY;
+	}
+	mutex_lock(&data->mutex_flash);
+	while (s > 0) {
+		err = _picolcd_flash_erase64(data, report_erase, off);
+		if (err)
+			break;
+		err = _picolcd_flash_write(data, report_write, u, 64, off);
+		if (err < 0)
+			break;
+		ret += err;
+		*off += err;
+		s -= err;
+		if (err != 64)
+			break;
+	}
+	mutex_unlock(&data->mutex_flash);
+	return ret > 0 ? ret : err;
+}
+
+/*
+ * Notes:
+ * - concurrent writing is prevented by mutex and all writes must be
+ *   n*64 bytes and 64-byte aligned, each write being preceded by an
+ *   ERASE which erases a 64byte block.
+ *   If less than requested was written or an error is returned for an
+ *   otherwise correct write request the next 64-byte block which should
+ *   have been written is in undefined state (mostly: original, erased,
+ *   (half-)written with write error)
+ * - reading can happen without special restriction
+ */
+static const struct file_operations picolcd_debug_flash_fops = {
+	.owner    = THIS_MODULE,
+	.open     = simple_open,
+	.read     = picolcd_debug_flash_read,
+	.write    = picolcd_debug_flash_write,
+	.llseek   = generic_file_llseek,
+};
+
+
+/*
+ * Helper code for HID report level dumping/debugging
+ */
+static const char *error_codes[] = {
+	"success", "parameter missing", "data_missing", "block readonly",
+	"block not erasable", "block too big", "section overflow",
+	"invalid command length", "invalid data length",
+};
+
+static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
+		const size_t data_len)
+{
+	int i, j;
+	for (i = j = 0; i < data_len && j + 3 < dst_sz; i++) {
+		dst[j++] = hex_asc[(data[i] >> 4) & 0x0f];
+		dst[j++] = hex_asc[data[i] & 0x0f];
+		dst[j++] = ' ';
+	}
+	if (j < dst_sz) {
+		dst[j--] = '\0';
+		dst[j] = '\n';
+	} else
+		dst[j] = '\0';
+}
+
+void picolcd_debug_out_report(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report)
+{
+	u8 raw_data[70];
+	int raw_size = (report->size >> 3) + 1;
+	char *buff;
+#define BUFF_SZ 256
+
+	/* Avoid unnecessary overhead if debugfs is disabled */
+	if (!hdev->debug_events)
+		return;
+
+	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
+	if (!buff)
+		return;
+
+	snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
+			report->id, raw_size);
+	hid_debug_event(hdev, buff);
+	if (raw_size + 5 > sizeof(raw_data)) {
+		kfree(buff);
+		hid_debug_event(hdev, " TOO BIG\n");
+		return;
+	} else {
+		raw_data[0] = report->id;
+		hid_output_report(report, raw_data);
+		dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
+		hid_debug_event(hdev, buff);
+	}
+
+	switch (report->id) {
+	case REPORT_LED_STATE:
+		/* 1 data byte with GPO state */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LED_STATE", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_BRIGHTNESS:
+		/* 1 data byte with brightness */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_BRIGHTNESS", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_CONTRAST:
+		/* 1 data byte with contrast */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_CONTRAST", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_RESET:
+		/* 2 data bytes with reset duration in ms */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_RESET", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n",
+				raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_LCD_CMD:
+		/* 63 data bytes with LCD commands */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LCD_CMD", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO: format decoding */
+		break;
+	case REPORT_LCD_DATA:
+		/* 63 data bytes with LCD data */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LCD_CMD", report->id, raw_size-1);
+		/* TODO: format decoding */
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_LCD_CMD_DATA:
+		/* 63 data bytes with LCD commands and data */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LCD_CMD", report->id, raw_size-1);
+		/* TODO: format decoding */
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_EE_READ:
+		/* 3 data bytes with read area description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_EE_READ", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_EE_WRITE:
+		/* 3+1..20 data bytes with write area description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_EE_WRITE", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+		hid_debug_event(hdev, buff);
+		if (raw_data[3] = 0) {
+			snprintf(buff, BUFF_SZ, "\tNo data\n");
+		} else if (raw_data[3] + 4 <= raw_size) {
+			snprintf(buff, BUFF_SZ, "\tData: ");
+			hid_debug_event(hdev, buff);
+			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+		} else {
+			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_ERASE_MEMORY:
+	case REPORT_BL_ERASE_MEMORY:
+		/* 3 data bytes with pointer inside erase block */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_ERASE_MEMORY", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_READ_MEMORY:
+	case REPORT_BL_READ_MEMORY:
+		/* 4 data bytes with read area description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_READ_MEMORY", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_WRITE_MEMORY:
+	case REPORT_BL_WRITE_MEMORY:
+		/* 4+1..32 data bytes with write adrea description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_WRITE_MEMORY", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[3] = 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[3] + 4 <= raw_size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[4] = 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[4] + 5 <= raw_size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_SPLASH_RESTART:
+		/* TODO */
+		break;
+	case REPORT_EXIT_KEYBOARD:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_EXIT_KEYBOARD", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
+				raw_data[1] | (raw_data[2] << 8),
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_VERSION:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_VERSION", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_DEVID:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_DEVID", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_SPLASH_SIZE:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_SPLASH_SIZE", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_HOOK_VERSION:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_HOOK_VERSION", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_EXIT_FLASHER:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_VERSION", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
+				raw_data[1] | (raw_data[2] << 8),
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	default:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"<unknown>", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	}
+	wake_up_interruptible(&hdev->debug_wait);
+	kfree(buff);
+}
+
+void picolcd_debug_raw_event(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size)
+{
+	char *buff;
+
+#define BUFF_SZ 256
+	/* Avoid unnecessary overhead if debugfs is disabled */
+	if (!hdev->debug_events)
+		return;
+
+	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
+	if (!buff)
+		return;
+
+	switch (report->id) {
+	case REPORT_ERROR_CODE:
+		/* 2 data bytes with affected report and error code */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_ERROR_CODE", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		if (raw_data[2] < ARRAY_SIZE(error_codes))
+			snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n",
+					raw_data[2], error_codes[raw_data[2]], raw_data[1]);
+		else
+			snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n",
+					raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_KEY_STATE:
+		/* 2 data bytes with key state */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_KEY_STATE", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		if (raw_data[1] = 0)
+			snprintf(buff, BUFF_SZ, "\tNo key pressed\n");
+		else if (raw_data[2] = 0)
+			snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n",
+					raw_data[1], raw_data[1]);
+		else
+			snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n",
+					raw_data[1], raw_data[1], raw_data[2], raw_data[2]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_IR_DATA:
+		/* Up to 20 byes of IR scancode data */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_IR_DATA", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		if (raw_data[1] = 0) {
+			snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n");
+			hid_debug_event(hdev, buff);
+		} else if (raw_data[1] + 1 <= size) {
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ",
+					raw_data[1]-1);
+			hid_debug_event(hdev, buff);
+			dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]-1);
+			hid_debug_event(hdev, buff);
+		} else {
+			snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n",
+					raw_data[1]-1);
+			hid_debug_event(hdev, buff);
+		}
+		break;
+	case REPORT_EE_DATA:
+		/* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_EE_DATA", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+		hid_debug_event(hdev, buff);
+		if (raw_data[3] = 0) {
+			snprintf(buff, BUFF_SZ, "\tNo data\n");
+			hid_debug_event(hdev, buff);
+		} else if (raw_data[3] + 4 <= size) {
+			snprintf(buff, BUFF_SZ, "\tData: ");
+			hid_debug_event(hdev, buff);
+			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+			hid_debug_event(hdev, buff);
+		} else {
+			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			hid_debug_event(hdev, buff);
+		}
+		break;
+	case REPORT_MEMORY:
+		/* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRTIE_MEMORY */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[3] = 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[3] + 4 <= size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[4] = 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[4] + 5 <= size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_VERSION:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_VERSION", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_BL_ERASE_MEMORY:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_BL_ERASE_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO */
+		break;
+	case REPORT_BL_READ_MEMORY:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_BL_READ_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO */
+		break;
+	case REPORT_BL_WRITE_MEMORY:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_BL_WRITE_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO */
+		break;
+	case REPORT_DEVID:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_DEVID", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n",
+				raw_data[1], raw_data[2], raw_data[3], raw_data[4]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n",
+				raw_data[5]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_SPLASH_SIZE:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_SPLASH_SIZE", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n",
+				(raw_data[2] << 8) | raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n",
+				(raw_data[4] << 8) | raw_data[3]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_HOOK_VERSION:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_HOOK_VERSION", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
+				raw_data[1], raw_data[2]);
+		hid_debug_event(hdev, buff);
+		break;
+	default:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"<unknown>", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	}
+	wake_up_interruptible(&hdev->debug_wait);
+	kfree(buff);
+}
+
+void picolcd_init_devfs(struct picolcd_data *data,
+		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
+		struct hid_report *flash_r, struct hid_report *flash_w,
+		struct hid_report *reset)
+{
+	struct hid_device *hdev = data->hdev;
+
+	mutex_init(&data->mutex_flash);
+
+	/* reset */
+	if (reset)
+		data->debug_reset = debugfs_create_file("reset", 0600,
+				hdev->debug_dir, data, &picolcd_debug_reset_fops);
+
+	/* eeprom */
+	if (eeprom_r || eeprom_w)
+		data->debug_eeprom = debugfs_create_file("eeprom",
+			(eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0),
+			hdev->debug_dir, data, &picolcd_debug_eeprom_fops);
+
+	/* flash */
+	if (flash_r && flash_r->maxfield = 1 && flash_r->field[0]->report_size = 8)
+		data->addr_sz = flash_r->field[0]->report_count - 1;
+	else
+		data->addr_sz = -1;
+	if (data->addr_sz = 2 || data->addr_sz = 3) {
+		data->debug_flash = debugfs_create_file("flash",
+			(flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
+			hdev->debug_dir, data, &picolcd_debug_flash_fops);
+	} else if (flash_r || flash_w)
+		hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
+}
+
+void picolcd_exit_devfs(struct picolcd_data *data)
+{
+	struct dentry *dent;
+
+	dent = data->debug_reset;
+	data->debug_reset = NULL;
+	if (dent)
+		debugfs_remove(dent);
+	dent = data->debug_eeprom;
+	data->debug_eeprom = NULL;
+	if (dent)
+		debugfs_remove(dent);
+	dent = data->debug_flash;
+	data->debug_flash = NULL;
+	if (dent)
+		debugfs_remove(dent);
+	mutex_destroy(&data->mutex_flash);
+}
+
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
new file mode 100644
index 0000000..b2124f5
--- /dev/null
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -0,0 +1,673 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+/* Framebuffer
+ *
+ * The PicoLCD use a Topway LCD module of 256x64 pixel
+ * This display area is tiled over 4 controllers with 8 tiles
+ * each. Each tile has 8x64 pixel, each data byte representing
+ * a 1-bit wide vertical line of the tile.
+ *
+ * The display can be updated at a tile granularity.
+ *
+ *       Chip 1           Chip 2           Chip 3           Chip 4
+ * +----------------+----------------+----------------+----------------+
+ * |     Tile 1     |     Tile 1     |     Tile 1     |     Tile 1     |
+ * +----------------+----------------+----------------+----------------+
+ * |     Tile 2     |     Tile 2     |     Tile 2     |     Tile 2     |
+ * +----------------+----------------+----------------+----------------+
+ *                                  ...
+ * +----------------+----------------+----------------+----------------+
+ * |     Tile 8     |     Tile 8     |     Tile 8     |     Tile 8     |
+ * +----------------+----------------+----------------+----------------+
+ */
+#define PICOLCDFB_NAME "picolcdfb"
+#define PICOLCDFB_WIDTH (256)
+#define PICOLCDFB_HEIGHT (64)
+#define PICOLCDFB_SIZE (PICOLCDFB_WIDTH * PICOLCDFB_HEIGHT / 8)
+
+#define PICOLCDFB_UPDATE_RATE_LIMIT   10
+#define PICOLCDFB_UPDATE_RATE_DEFAULT  2
+
+/* Framebuffer visual structures */
+static const struct fb_fix_screeninfo picolcdfb_fix = {
+	.id          = PICOLCDFB_NAME,
+	.type        = FB_TYPE_PACKED_PIXELS,
+	.visual      = FB_VISUAL_MONO01,
+	.xpanstep    = 0,
+	.ypanstep    = 0,
+	.ywrapstep   = 0,
+	.line_length = PICOLCDFB_WIDTH / 8,
+	.accel       = FB_ACCEL_NONE,
+};
+
+static const struct fb_var_screeninfo picolcdfb_var = {
+	.xres           = PICOLCDFB_WIDTH,
+	.yres           = PICOLCDFB_HEIGHT,
+	.xres_virtual   = PICOLCDFB_WIDTH,
+	.yres_virtual   = PICOLCDFB_HEIGHT,
+	.width          = 103,
+	.height         = 26,
+	.bits_per_pixel = 1,
+	.grayscale      = 1,
+	.red            = {
+		.offset = 0,
+		.length = 1,
+		.msb_right = 0,
+	},
+	.green          = {
+		.offset = 0,
+		.length = 1,
+		.msb_right = 0,
+	},
+	.blue           = {
+		.offset = 0,
+		.length = 1,
+		.msb_right = 0,
+	},
+	.transp         = {
+		.offset = 0,
+		.length = 0,
+		.msb_right = 0,
+	},
+};
+
+/* Send a given tile to PicoLCD */
+static int picolcd_fb_send_tile(struct hid_device *hdev, int chip, int tile)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	struct hid_report *report1 = picolcd_out_report(REPORT_LCD_CMD_DATA, hdev);
+	struct hid_report *report2 = picolcd_out_report(REPORT_LCD_DATA, hdev);
+	unsigned long flags;
+	u8 *tdata;
+	int i;
+
+	if (!report1 || report1->maxfield != 1 || !report2 || report2->maxfield != 1)
+		return -ENODEV;
+
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report1->field[0],  0, chip << 2);
+	hid_set_field(report1->field[0],  1, 0x02);
+	hid_set_field(report1->field[0],  2, 0x00);
+	hid_set_field(report1->field[0],  3, 0x00);
+	hid_set_field(report1->field[0],  4, 0xb8 | tile);
+	hid_set_field(report1->field[0],  5, 0x00);
+	hid_set_field(report1->field[0],  6, 0x00);
+	hid_set_field(report1->field[0],  7, 0x40);
+	hid_set_field(report1->field[0],  8, 0x00);
+	hid_set_field(report1->field[0],  9, 0x00);
+	hid_set_field(report1->field[0], 10,   32);
+
+	hid_set_field(report2->field[0],  0, (chip << 2) | 0x01);
+	hid_set_field(report2->field[0],  1, 0x00);
+	hid_set_field(report2->field[0],  2, 0x00);
+	hid_set_field(report2->field[0],  3,   32);
+
+	tdata = data->fb_vbitmap + (tile * 4 + chip) * 64;
+	for (i = 0; i < 64; i++)
+		if (i < 32)
+			hid_set_field(report1->field[0], 11 + i, tdata[i]);
+		else
+			hid_set_field(report2->field[0], 4 + i - 32, tdata[i]);
+
+	usbhid_submit_report(data->hdev, report1, USB_DIR_OUT);
+	usbhid_submit_report(data->hdev, report2, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+/* Translate a single tile*/
+static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp,
+		int chip, int tile)
+{
+	int i, b, changed = 0;
+	u8 tdata[64];
+	u8 *vdata = vbitmap + (tile * 4 + chip) * 64;
+
+	if (bpp = 1) {
+		for (b = 7; b >= 0; b--) {
+			const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32;
+			for (i = 0; i < 64; i++) {
+				tdata[i] <<= 1;
+				tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01;
+			}
+		}
+	} else if (bpp = 8) {
+		for (b = 7; b >= 0; b--) {
+			const u8 *bdata = bitmap + (tile * 256 + chip * 8 + b * 32) * 8;
+			for (i = 0; i < 64; i++) {
+				tdata[i] <<= 1;
+				tdata[i] |= (bdata[i] & 0x80) ? 0x01 : 0x00;
+			}
+		}
+	} else {
+		/* Oops, we should never get here! */
+		WARN_ON(1);
+		return 0;
+	}
+
+	for (i = 0; i < 64; i++)
+		if (tdata[i] != vdata[i]) {
+			changed = 1;
+			vdata[i] = tdata[i];
+		}
+	return changed;
+}
+
+void picolcd_fb_refresh(struct picolcd_data *data)
+{
+	if (data->fb_info)
+		schedule_delayed_work(&data->fb_info->deferred_work, 0);
+}
+
+/* Reconfigure LCD display */
+int picolcd_fb_reset(struct picolcd_data *data, int clear)
+{
+	struct hid_report *report = picolcd_out_report(REPORT_LCD_CMD, data->hdev);
+	int i, j;
+	unsigned long flags;
+	static const u8 mapcmd[8] = { 0x00, 0x02, 0x00, 0x64, 0x3f, 0x00, 0x64, 0xc0 };
+
+	if (!report || report->maxfield != 1)
+		return -ENODEV;
+
+	spin_lock_irqsave(&data->lock, flags);
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < report->field[0]->maxusage; j++)
+			if (j = 0)
+				hid_set_field(report->field[0], j, i << 2);
+			else if (j < sizeof(mapcmd))
+				hid_set_field(report->field[0], j, mapcmd[j]);
+			else
+				hid_set_field(report->field[0], j, 0);
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	}
+
+	data->status |= PICOLCD_READY_FB;
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	if (data->fb_bitmap) {
+		if (clear) {
+			memset(data->fb_vbitmap, 0, PICOLCDFB_SIZE);
+			memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp);
+		}
+		data->fb_force = 1;
+	}
+
+	/* schedule first output of framebuffer */
+	picolcd_fb_refresh(data);
+
+	return 0;
+}
+
+/* Update fb_vbitmap from the screen_base and send changed tiles to device */
+static void picolcd_fb_update(struct picolcd_data *data)
+{
+	int chip, tile, n;
+	unsigned long flags;
+
+	if (!data)
+		return;
+
+	spin_lock_irqsave(&data->lock, flags);
+	if (!(data->status & PICOLCD_READY_FB)) {
+		spin_unlock_irqrestore(&data->lock, flags);
+		picolcd_fb_reset(data, 0);
+	} else {
+		spin_unlock_irqrestore(&data->lock, flags);
+	}
+
+	/*
+	 * Translate the framebuffer into the format needed by the PicoLCD.
+	 * See display layout above.
+	 * Do this one tile after the other and push those tiles that changed.
+	 *
+	 * Wait for our IO to complete as otherwise we might flood the queue!
+	 */
+	n = 0;
+	for (chip = 0; chip < 4; chip++)
+		for (tile = 0; tile < 8; tile++)
+			if (picolcd_fb_update_tile(data->fb_vbitmap,
+					data->fb_bitmap, data->fb_bpp, chip, tile) ||
+				data->fb_force) {
+				n += 2;
+				if (!data->fb_info->par)
+					return; /* device lost! */
+				if (n >= HID_OUTPUT_FIFO_SIZE / 2) {
+					usbhid_wait_io(data->hdev);
+					n = 0;
+				}
+				picolcd_fb_send_tile(data->hdev, chip, tile);
+			}
+	data->fb_force = false;
+	if (n)
+		usbhid_wait_io(data->hdev);
+}
+
+/* Stub to call the system default and update the image on the picoLCD */
+static void picolcd_fb_fillrect(struct fb_info *info,
+		const struct fb_fillrect *rect)
+{
+	if (!info->par)
+		return;
+	sys_fillrect(info, rect);
+
+	schedule_delayed_work(&info->deferred_work, 0);
+}
+
+/* Stub to call the system default and update the image on the picoLCD */
+static void picolcd_fb_copyarea(struct fb_info *info,
+		const struct fb_copyarea *area)
+{
+	if (!info->par)
+		return;
+	sys_copyarea(info, area);
+
+	schedule_delayed_work(&info->deferred_work, 0);
+}
+
+/* Stub to call the system default and update the image on the picoLCD */
+static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if (!info->par)
+		return;
+	sys_imageblit(info, image);
+
+	schedule_delayed_work(&info->deferred_work, 0);
+}
+
+/*
+ * this is the slow path from userspace. they can seek and write to
+ * the fb. it's inefficient to do anything less than a full screen draw
+ */
+static ssize_t picolcd_fb_write(struct fb_info *info, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	ssize_t ret;
+	if (!info->par)
+		return -ENODEV;
+	ret = fb_sys_write(info, buf, count, ppos);
+	if (ret >= 0)
+		schedule_delayed_work(&info->deferred_work, 0);
+	return ret;
+}
+
+static int picolcd_fb_blank(int blank, struct fb_info *info)
+{
+	if (!info->par)
+		return -ENODEV;
+	/* We let fb notification do this for us via lcd/backlight device */
+	return 0;
+}
+
+static void picolcd_fb_destroy(struct fb_info *info)
+{
+	struct picolcd_data *data = info->par;
+	u32 *ref_cnt = info->pseudo_palette;
+	int may_release;
+
+	info->par = NULL;
+	if (data)
+		data->fb_info = NULL;
+	fb_deferred_io_cleanup(info);
+
+	ref_cnt--;
+	mutex_lock(&info->lock);
+	(*ref_cnt)--;
+	may_release = !*ref_cnt;
+	mutex_unlock(&info->lock);
+	if (may_release) {
+		vfree((u8 *)info->fix.smem_start);
+		framebuffer_release(info);
+	}
+}
+
+static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	__u32 bpp      = var->bits_per_pixel;
+	__u32 activate = var->activate;
+
+	/* only allow 1/8 bit depth (8-bit is grayscale) */
+	*var = picolcdfb_var;
+	var->activate = activate;
+	if (bpp >= 8) {
+		var->bits_per_pixel = 8;
+		var->red.length     = 8;
+		var->green.length   = 8;
+		var->blue.length    = 8;
+	} else {
+		var->bits_per_pixel = 1;
+		var->red.length     = 1;
+		var->green.length   = 1;
+		var->blue.length    = 1;
+	}
+	return 0;
+}
+
+static int picolcd_set_par(struct fb_info *info)
+{
+	struct picolcd_data *data = info->par;
+	u8 *tmp_fb, *o_fb;
+	if (!data)
+		return -ENODEV;
+	if (info->var.bits_per_pixel = data->fb_bpp)
+		return 0;
+	/* switch between 1/8 bit depths */
+	if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8)
+		return -EINVAL;
+
+	o_fb   = data->fb_bitmap;
+	tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL);
+	if (!tmp_fb)
+		return -ENOMEM;
+
+	/* translate FB content to new bits-per-pixel */
+	if (info->var.bits_per_pixel = 1) {
+		int i, b;
+		for (i = 0; i < PICOLCDFB_SIZE; i++) {
+			u8 p = 0;
+			for (b = 0; b < 8; b++) {
+				p <<= 1;
+				p |= o_fb[i*8+b] ? 0x01 : 0x00;
+			}
+			tmp_fb[i] = p;
+		}
+		memcpy(o_fb, tmp_fb, PICOLCDFB_SIZE);
+		info->fix.visual = FB_VISUAL_MONO01;
+		info->fix.line_length = PICOLCDFB_WIDTH / 8;
+	} else {
+		int i;
+		memcpy(tmp_fb, o_fb, PICOLCDFB_SIZE);
+		for (i = 0; i < PICOLCDFB_SIZE * 8; i++)
+			o_fb[i] = tmp_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00;
+		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+		info->fix.line_length = PICOLCDFB_WIDTH;
+	}
+
+	kfree(tmp_fb);
+	data->fb_bpp      = info->var.bits_per_pixel;
+	return 0;
+}
+
+/* Do refcounting on our FB and cleanup per worker if FB is
+ * closed after unplug of our device
+ * (fb_release holds info->lock and still touches info after
+ *  we return so we can't release it immediately.
+ */
+struct picolcd_fb_cleanup_item {
+	struct fb_info *info;
+	struct picolcd_fb_cleanup_item *next;
+};
+static struct picolcd_fb_cleanup_item *fb_pending;
+static DEFINE_SPINLOCK(fb_pending_lock);
+
+static void picolcd_fb_do_cleanup(struct work_struct *data)
+{
+	struct picolcd_fb_cleanup_item *item;
+	unsigned long flags;
+
+	do {
+		spin_lock_irqsave(&fb_pending_lock, flags);
+		item = fb_pending;
+		fb_pending = item ? item->next : NULL;
+		spin_unlock_irqrestore(&fb_pending_lock, flags);
+
+		if (item) {
+			u8 *fb = (u8 *)item->info->fix.smem_start;
+			/* make sure we do not race against fb core when
+			 * releasing */
+			mutex_lock(&item->info->lock);
+			mutex_unlock(&item->info->lock);
+			framebuffer_release(item->info);
+			vfree(fb);
+		}
+	} while (item);
+}
+
+static DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup);
+
+static int picolcd_fb_open(struct fb_info *info, int u)
+{
+	u32 *ref_cnt = info->pseudo_palette;
+	ref_cnt--;
+
+	(*ref_cnt)++;
+	return 0;
+}
+
+static int picolcd_fb_release(struct fb_info *info, int u)
+{
+	u32 *ref_cnt = info->pseudo_palette;
+	ref_cnt--;
+
+	(*ref_cnt)++;
+	if (!*ref_cnt) {
+		unsigned long flags;
+		struct picolcd_fb_cleanup_item *item = (struct picolcd_fb_cleanup_item *)ref_cnt;
+		item--;
+		spin_lock_irqsave(&fb_pending_lock, flags);
+		item->next = fb_pending;
+		fb_pending = item;
+		spin_unlock_irqrestore(&fb_pending_lock, flags);
+		schedule_work(&picolcd_fb_cleanup);
+	}
+	return 0;
+}
+
+/* Note this can't be const because of struct fb_info definition */
+static struct fb_ops picolcdfb_ops = {
+	.owner        = THIS_MODULE,
+	.fb_destroy   = picolcd_fb_destroy,
+	.fb_open      = picolcd_fb_open,
+	.fb_release   = picolcd_fb_release,
+	.fb_read      = fb_sys_read,
+	.fb_write     = picolcd_fb_write,
+	.fb_blank     = picolcd_fb_blank,
+	.fb_fillrect  = picolcd_fb_fillrect,
+	.fb_copyarea  = picolcd_fb_copyarea,
+	.fb_imageblit = picolcd_fb_imageblit,
+	.fb_check_var = picolcd_fb_check_var,
+	.fb_set_par   = picolcd_set_par,
+};
+
+
+/* Callback from deferred IO workqueue */
+static void picolcd_fb_deferred_io(struct fb_info *info, struct list_head *pagelist)
+{
+	picolcd_fb_update(info->par);
+}
+
+static const struct fb_deferred_io picolcd_fb_defio = {
+	.delay = HZ / PICOLCDFB_UPDATE_RATE_DEFAULT,
+	.deferred_io = picolcd_fb_deferred_io,
+};
+
+
+/*
+ * The "fb_update_rate" sysfs attribute
+ */
+static ssize_t picolcd_fb_update_rate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	unsigned i, fb_update_rate = data->fb_update_rate;
+	size_t ret = 0;
+
+	for (i = 1; i <= PICOLCDFB_UPDATE_RATE_LIMIT; i++)
+		if (ret >= PAGE_SIZE)
+			break;
+		else if (i = fb_update_rate)
+			ret += snprintf(buf+ret, PAGE_SIZE-ret, "[%u] ", i);
+		else
+			ret += snprintf(buf+ret, PAGE_SIZE-ret, "%u ", i);
+	if (ret > 0)
+		buf[min(ret, (size_t)PAGE_SIZE)-1] = '\n';
+	return ret;
+}
+
+static ssize_t picolcd_fb_update_rate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	int i;
+	unsigned u;
+
+	if (count < 1 || count > 10)
+		return -EINVAL;
+
+	i = sscanf(buf, "%u", &u);
+	if (i != 1)
+		return -EINVAL;
+
+	if (u > PICOLCDFB_UPDATE_RATE_LIMIT)
+		return -ERANGE;
+	else if (u = 0)
+		u = PICOLCDFB_UPDATE_RATE_DEFAULT;
+
+	data->fb_update_rate = u;
+	data->fb_defio.delay = HZ / data->fb_update_rate;
+	return count;
+}
+
+static DEVICE_ATTR(fb_update_rate, 0666, picolcd_fb_update_rate_show,
+		picolcd_fb_update_rate_store);
+
+/* initialize Framebuffer device */
+int picolcd_init_framebuffer(struct picolcd_data *data)
+{
+	struct device *dev = &data->hdev->dev;
+	struct fb_info *info = NULL;
+	int i, error = -ENOMEM;
+	u8 *fb_vbitmap = NULL;
+	u8 *fb_bitmap  = NULL;
+	u32 *palette;
+
+	fb_bitmap = vmalloc(PICOLCDFB_SIZE*8);
+	if (fb_bitmap = NULL) {
+		dev_err(dev, "can't get a free page for framebuffer\n");
+		goto err_nomem;
+	}
+
+	fb_vbitmap = kmalloc(PICOLCDFB_SIZE, GFP_KERNEL);
+	if (fb_vbitmap = NULL) {
+		dev_err(dev, "can't alloc vbitmap image buffer\n");
+		goto err_nomem;
+	}
+
+	data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT;
+	data->fb_defio = picolcd_fb_defio;
+	/* The extra memory is:
+	 * - struct picolcd_fb_cleanup_item
+	 * - u32 for ref_count
+	 * - 256*u32 for pseudo_palette
+	 */
+	info = framebuffer_alloc(257 * sizeof(u32) + sizeof(struct picolcd_fb_cleanup_item), dev);
+	if (info = NULL) {
+		dev_err(dev, "failed to allocate a framebuffer\n");
+		goto err_nomem;
+	}
+
+	palette  = info->par + sizeof(struct picolcd_fb_cleanup_item);
+	*palette = 1;
+	palette++;
+	for (i = 0; i < 256; i++)
+		palette[i] = i > 0 && i < 16 ? 0xff : 0;
+	info->pseudo_palette = palette;
+	info->fbdefio = &data->fb_defio;
+	info->screen_base = (char __force __iomem *)fb_bitmap;
+	info->fbops = &picolcdfb_ops;
+	info->var = picolcdfb_var;
+	info->fix = picolcdfb_fix;
+	info->fix.smem_len   = PICOLCDFB_SIZE*8;
+	info->fix.smem_start = (unsigned long)fb_bitmap;
+	info->par = data;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	data->fb_vbitmap = fb_vbitmap;
+	data->fb_bitmap  = fb_bitmap;
+	data->fb_bpp     = picolcdfb_var.bits_per_pixel;
+	error = picolcd_fb_reset(data, 1);
+	if (error) {
+		dev_err(dev, "failed to configure display\n");
+		goto err_cleanup;
+	}
+	error = device_create_file(dev, &dev_attr_fb_update_rate);
+	if (error) {
+		dev_err(dev, "failed to create sysfs attributes\n");
+		goto err_cleanup;
+	}
+	fb_deferred_io_init(info);
+	data->fb_info    = info;
+	error = register_framebuffer(info);
+	if (error) {
+		dev_err(dev, "failed to register framebuffer\n");
+		goto err_sysfs;
+	}
+	/* schedule first output of framebuffer */
+	data->fb_force = 1;
+	schedule_delayed_work(&info->deferred_work, 0);
+	return 0;
+
+err_sysfs:
+	fb_deferred_io_cleanup(info);
+	device_remove_file(dev, &dev_attr_fb_update_rate);
+err_cleanup:
+	data->fb_vbitmap = NULL;
+	data->fb_bitmap  = NULL;
+	data->fb_bpp     = 0;
+	data->fb_info    = NULL;
+
+err_nomem:
+	framebuffer_release(info);
+	vfree(fb_bitmap);
+	kfree(fb_vbitmap);
+	return error;
+}
+
+void picolcd_exit_framebuffer(struct picolcd_data *data)
+{
+	struct fb_info *info = data->fb_info;
+	u8 *fb_vbitmap = data->fb_vbitmap;
+
+	if (!info)
+		return;
+
+	device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
+	unregister_framebuffer(info);
+	data->fb_vbitmap = NULL;
+	data->fb_bitmap  = NULL;
+	data->fb_bpp     = 0;
+	data->fb_info    = NULL;
+	kfree(fb_vbitmap);
+}
+
+void picolcd_fb_unload()
+{
+	flush_work_sync(&picolcd_fb_cleanup);
+	WARN_ON(fb_pending);
+}
diff --git a/drivers/hid/hid-picolcd_lcd.c b/drivers/hid/hid-picolcd_lcd.c
new file mode 100644
index 0000000..64a067f
--- /dev/null
+++ b/drivers/hid/hid-picolcd_lcd.c
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/lcd.h>
+
+#include "hid-picolcd.h"
+
+/*
+ * lcd class device
+ */
+static int picolcd_get_contrast(struct lcd_device *ldev)
+{
+	struct picolcd_data *data = lcd_get_data(ldev);
+	return data->lcd_contrast;
+}
+
+static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
+{
+	struct picolcd_data *data = lcd_get_data(ldev);
+	struct hid_report *report = picolcd_out_report(REPORT_CONTRAST, data->hdev);
+	unsigned long flags;
+
+	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
+		return -ENODEV;
+
+	data->lcd_contrast = contrast & 0x0ff;
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, data->lcd_contrast);
+	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+static int picolcd_check_lcd_fb(struct lcd_device *ldev, struct fb_info *fb)
+{
+	return fb && fb = picolcd_fbinfo((struct picolcd_data *)lcd_get_data(ldev));
+}
+
+static struct lcd_ops picolcd_lcdops = {
+	.get_contrast   = picolcd_get_contrast,
+	.set_contrast   = picolcd_set_contrast,
+	.check_fb       = picolcd_check_lcd_fb,
+};
+
+int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report)
+{
+	struct device *dev = &data->hdev->dev;
+	struct lcd_device *ldev;
+
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
+			report->field[0]->report_size != 8) {
+		dev_err(dev, "unsupported CONTRAST report");
+		return -EINVAL;
+	}
+
+	ldev = lcd_device_register(dev_name(dev), dev, data, &picolcd_lcdops);
+	if (IS_ERR(ldev)) {
+		dev_err(dev, "failed to register LCD\n");
+		return PTR_ERR(ldev);
+	}
+	ldev->props.max_contrast = 0x0ff;
+	data->lcd_contrast = 0xe5;
+	data->lcd = ldev;
+	picolcd_set_contrast(ldev, 0xe5);
+	return 0;
+}
+
+void picolcd_exit_lcd(struct picolcd_data *data)
+{
+	struct lcd_device *ldev = data->lcd;
+
+	data->lcd = NULL;
+	if (ldev)
+		lcd_device_unregister(ldev);
+}
+
+int picolcd_resume_lcd(struct picolcd_data *data)
+{
+	if (!data->lcd)
+		return 0;
+	return picolcd_set_contrast(data->lcd, data->lcd_contrast);
+}
+
diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c
new file mode 100644
index 0000000..9249c06
--- /dev/null
+++ b/drivers/hid/hid-picolcd_leds.c
@@ -0,0 +1,172 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   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, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include <linux/input.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <linux/leds.h>
+
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+
+void picolcd_leds_set(struct picolcd_data *data)
+{
+	struct hid_report *report;
+	unsigned long flags;
+
+	if (!data->led[0])
+		return;
+	report = picolcd_out_report(REPORT_LED_STATE, data->hdev);
+	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
+		return;
+
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, data->led_state);
+	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static void picolcd_led_set_brightness(struct led_classdev *led_cdev,
+			enum led_brightness value)
+{
+	struct device *dev;
+	struct hid_device *hdev;
+	struct picolcd_data *data;
+	int i, state = 0;
+
+	dev  = led_cdev->dev->parent;
+	hdev = container_of(dev, struct hid_device, dev);
+	data = hid_get_drvdata(hdev);
+	for (i = 0; i < 8; i++) {
+		if (led_cdev != data->led[i])
+			continue;
+		state = (data->led_state >> i) & 1;
+		if (value = LED_OFF && state) {
+			data->led_state &= ~(1 << i);
+			picolcd_leds_set(data);
+		} else if (value != LED_OFF && !state) {
+			data->led_state |= 1 << i;
+			picolcd_leds_set(data);
+		}
+		break;
+	}
+}
+
+static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev)
+{
+	struct device *dev;
+	struct hid_device *hdev;
+	struct picolcd_data *data;
+	int i, value = 0;
+
+	dev  = led_cdev->dev->parent;
+	hdev = container_of(dev, struct hid_device, dev);
+	data = hid_get_drvdata(hdev);
+	for (i = 0; i < 8; i++)
+		if (led_cdev = data->led[i]) {
+			value = (data->led_state >> i) & 1;
+			break;
+		}
+	return value ? LED_FULL : LED_OFF;
+}
+
+int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report)
+{
+	struct device *dev = &data->hdev->dev;
+	struct led_classdev *led;
+	size_t name_sz = strlen(dev_name(dev)) + 8;
+	char *name;
+	int i, ret = 0;
+
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
+			report->field[0]->report_size != 8) {
+		dev_err(dev, "unsupported LED_STATE report");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 8; i++) {
+		led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
+		if (!led) {
+			dev_err(dev, "can't allocate memory for LED %d\n", i);
+			ret = -ENOMEM;
+			goto err;
+		}
+		name = (void *)(&led[1]);
+		snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i);
+		led->name = name;
+		led->brightness = 0;
+		led->max_brightness = 1;
+		led->brightness_get = picolcd_led_get_brightness;
+		led->brightness_set = picolcd_led_set_brightness;
+
+		data->led[i] = led;
+		ret = led_classdev_register(dev, data->led[i]);
+		if (ret) {
+			data->led[i] = NULL;
+			kfree(led);
+			dev_err(dev, "can't register LED %d\n", i);
+			goto err;
+		}
+	}
+	return 0;
+err:
+	for (i = 0; i < 8; i++)
+		if (data->led[i]) {
+			led = data->led[i];
+			data->led[i] = NULL;
+			led_classdev_unregister(led);
+			kfree(led);
+		}
+	return ret;
+}
+
+void picolcd_exit_leds(struct picolcd_data *data)
+{
+	struct led_classdev *led;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		led = data->led[i];
+		data->led[i] = NULL;
+		if (!led)
+			continue;
+		led_classdev_unregister(led);
+		kfree(led);
+	}
+}
+
+
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 7/7] HID: picoLCD: add myself to MAINTAINERS
From: Bruno Prémont @ 2012-07-30 19:39 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: Jaya Kumar, linux-fbdev
In-Reply-To: <20120730213656.0a9f6d30@neptune.home>


Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
 MAINTAINERS |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index fe643e7..0042553 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5283,6 +5283,12 @@ L:	linux-mtd@lists.infradead.org
 S:	Maintained
 F:	drivers/mtd/devices/phram.c
 
+PICOLCD HID DRIVER
+M:	Bruno Prémont <bonbons@linux-vserver.org>
+L:	linux-input@vger.kernel.org
+S:	Maintained
+F:	drivers/hid/hid-picolcd*
+
 PICOXCELL SUPPORT
 M:	Jamie Iles <jamie@jamieiles.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 6/7] HID: picoLCD: disable version check during probe
From: Bruno Prémont @ 2012-07-30 19:38 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: Jaya Kumar, linux-fbdev
In-Reply-To: <20120730213656.0a9f6d30@neptune.home>

Commit 4ea5454203d991ec85264f64f89ca8855fce69b0
[HID: Fix race condition between driver core and ll-driver] introduced
new locking around proce/remove functions that prevent any report/reply
from hardware to reach driver until it returned from probe.

As such, the ask-reply way to checking picoLCD firmware version during
probe is bound to timeout and let probe fail.

Disabling the check lets driver sucessfully probe again.

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
 drivers/hid/hid-picolcd_core.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
index 2d7ef68..42d0791 100644
--- a/drivers/hid/hid-picolcd_core.c
+++ b/drivers/hid/hid-picolcd_core.c
@@ -478,13 +478,13 @@ static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data)
 {
 	int error;
 
-	error = picolcd_check_version(hdev);
+/*	error = picolcd_check_version(hdev);
 	if (error)
 		return error;
 
 	if (data->version[0] != 0 && data->version[1] != 3)
 		hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
-			 dev_name(&hdev->dev));
+			 dev_name(&hdev->dev)); */
 
 	/* Setup keypad input device */
 	error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev));
@@ -534,7 +534,7 @@ err:
 
 static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data)
 {
-	int error;
+/*	int error;
 
 	error = picolcd_check_version(hdev);
 	if (error)
@@ -542,7 +542,7 @@ static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data
 
 	if (data->version[0] != 1 && data->version[1] != 0)
 		hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
-			 dev_name(&hdev->dev));
+			 dev_name(&hdev->dev)); */
 
 	picolcd_init_devfs(data, NULL, NULL,
 			picolcd_out_report(REPORT_BL_READ_MEMORY, hdev),
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 5/7] HID: picoLCD: Improve unplug handling
From: Bruno Prémont @ 2012-07-30 19:38 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: Jaya Kumar, linux-fbdev
In-Reply-To: <20120730213656.0a9f6d30@neptune.home>

Stop earlier attempting to submit new reports/URBs (though locking and
usbhid still prevents to bail out early enough to not produce multiple
  hid-picolcd 0003:04D8:C002.0003: usb_submit_urb(out) failed: -19
messages in kernel log.

Strengthen framebuffer removal to be less racy, though quick
bind/unbind sequences triggered via sysfs still trigger weird behavior:
- either SLAB corruptions
  Seems related to fbdefio
- immediate system reboot
  Unexplained as there is no explaining output on any console, not even
  serial console.
(note: picoLCD is hosting fbcon in both cases, but manual plug/unplug
seems too slow to trigger madness)

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
 drivers/hid/hid-picolcd_backlight.c |    3 +-
 drivers/hid/hid-picolcd_core.c      |   21 ++++++++++++-----
 drivers/hid/hid-picolcd_fb.c        |   41 +++++++++++++++++++++-------------
 drivers/hid/hid-picolcd_lcd.c       |    3 +-
 drivers/hid/hid-picolcd_leds.c      |    3 +-
 5 files changed, 46 insertions(+), 25 deletions(-)

diff --git a/drivers/hid/hid-picolcd_backlight.c b/drivers/hid/hid-picolcd_backlight.c
index cd1ccd7..b91f309 100644
--- a/drivers/hid/hid-picolcd_backlight.c
+++ b/drivers/hid/hid-picolcd_backlight.c
@@ -45,7 +45,8 @@ static int picolcd_set_brightness(struct backlight_device *bdev)
 	data->lcd_power      = bdev->props.power;
 	spin_lock_irqsave(&data->lock, flags);
 	hid_set_field(report->field[0], 0, data->lcd_power = FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	if (!(data->status & PICOLCD_FAILED))
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
 	spin_unlock_irqrestore(&data->lock, flags);
 	return 0;
 }
diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
index 8d5d341..2d7ef68 100644
--- a/drivers/hid/hid-picolcd_core.c
+++ b/drivers/hid/hid-picolcd_core.c
@@ -105,12 +105,17 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
 			hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0);
 			k++;
 		}
-	data->pending = work;
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-	wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
-	spin_lock_irqsave(&data->lock, flags);
-	data->pending = NULL;
+	if (data->status & PICOLCD_FAILED) {
+		kfree(work);
+		work = NULL;
+	} else {
+		data->pending = work;
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+		spin_unlock_irqrestore(&data->lock, flags);
+		wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
+		spin_lock_irqsave(&data->lock, flags);
+		data->pending = NULL;
+	}
 	spin_unlock_irqrestore(&data->lock, flags);
 	mutex_unlock(&data->mutex);
 	return work;
@@ -235,6 +240,10 @@ int picolcd_reset(struct hid_device *hdev)
 
 	/* perform the reset */
 	hid_set_field(report->field[0], 0, 1);
+	if (data->status & PICOLCD_FAILED) {
+		spin_unlock_irqrestore(&data->lock, flags);
+		return -ENODEV;
+	}
 	usbhid_submit_report(hdev, report, USB_DIR_OUT);
 	spin_unlock_irqrestore(&data->lock, flags);
 
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index 602786c..4d8e22c 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -226,13 +226,16 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear)
 }
 
 /* Update fb_vbitmap from the screen_base and send changed tiles to device */
-static void picolcd_fb_update(struct picolcd_data *data)
+static void picolcd_fb_update(struct fb_info *info)
 {
 	int chip, tile, n;
 	unsigned long flags;
+	struct picolcd_data *data;
 
+	mutex_lock(&info->lock);
+	data = info->par;
 	if (!data)
-		return;
+		goto out;
 
 	spin_lock_irqsave(&data->lock, flags);
 	if (!(data->status & PICOLCD_READY_FB)) {
@@ -256,17 +259,31 @@ static void picolcd_fb_update(struct picolcd_data *data)
 					data->fb_bitmap, data->fb_bpp, chip, tile) ||
 				data->fb_force) {
 				n += 2;
-				if (data->status & PICOLCD_FAILED)
-					return; /* device lost! */
 				if (n >= HID_OUTPUT_FIFO_SIZE / 2) {
+					mutex_unlock(&info->lock);
 					usbhid_wait_io(data->hdev);
+					mutex_lock(&info->lock);
+					data = info->par;
+					if (!data)
+						goto out;
+					spin_lock_irqsave(&data->lock, flags);
+					if (data->status & PICOLCD_FAILED) {
+						spin_unlock_irqrestore(&data->lock, flags);
+						goto out;
+					}
+					spin_unlock_irqrestore(&data->lock, flags);
 					n = 0;
 				}
 				picolcd_fb_send_tile(data->hdev, chip, tile);
 			}
 	data->fb_force = false;
-	if (n)
+	if (n) {
+		mutex_unlock(&info->lock);
 		usbhid_wait_io(data->hdev);
+		return;
+	}
+out:
+	mutex_unlock(&info->lock);
 }
 
 /* Stub to call the system default and update the image on the picoLCD */
@@ -327,17 +344,12 @@ static int picolcd_fb_blank(int blank, struct fb_info *info)
 
 static void picolcd_fb_destroy(struct fb_info *info)
 {
-	struct picolcd_data *data;
-
 	/* make sure no work is deferred */
-	cancel_delayed_work_sync(&info->deferred_work);
-	data = info->par;
-	info->par = NULL;
-	if (data)
-		data->fb_info = NULL;
+	fb_deferred_io_cleanup(info);
 
 	vfree((u8 *)info->fix.smem_start);
 	framebuffer_release(info);
+	printk(KERN_DEBUG "picolcd_fb_destroy(%p)\n", info);
 }
 
 static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
@@ -425,7 +437,7 @@ static struct fb_ops picolcdfb_ops = {
 /* Callback from deferred IO workqueue */
 static void picolcd_fb_deferred_io(struct fb_info *info, struct list_head *pagelist)
 {
-	picolcd_fb_update(info->par);
+	picolcd_fb_update(info);
 }
 
 static const struct fb_deferred_io picolcd_fb_defio = {
@@ -582,10 +594,7 @@ void picolcd_exit_framebuffer(struct picolcd_data *data)
 		return;
 
 	device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
-	mutex_lock(&info->lock);
-	fb_deferred_io_cleanup(info);
 	info->par = NULL;
-	mutex_unlock(&info->lock);
 	unregister_framebuffer(info);
 	data->fb_vbitmap = NULL;
 	data->fb_bitmap  = NULL;
diff --git a/drivers/hid/hid-picolcd_lcd.c b/drivers/hid/hid-picolcd_lcd.c
index 64a067f..2d0ddc5 100644
--- a/drivers/hid/hid-picolcd_lcd.c
+++ b/drivers/hid/hid-picolcd_lcd.c
@@ -47,7 +47,8 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
 	data->lcd_contrast = contrast & 0x0ff;
 	spin_lock_irqsave(&data->lock, flags);
 	hid_set_field(report->field[0], 0, data->lcd_contrast);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	if (!(data->status & PICOLCD_FAILED))
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
 	spin_unlock_irqrestore(&data->lock, flags);
 	return 0;
 }
diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c
index 5573cd8..28cb6a4 100644
--- a/drivers/hid/hid-picolcd_leds.c
+++ b/drivers/hid/hid-picolcd_leds.c
@@ -54,7 +54,8 @@ void picolcd_leds_set(struct picolcd_data *data)
 
 	spin_lock_irqsave(&data->lock, flags);
 	hid_set_field(report->field[0], 0, data->led_state);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	if (!(data->status & PICOLCD_FAILED))
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
 	spin_unlock_irqrestore(&data->lock, flags);
 }
 
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 4/7] HID: picoLCD: satify some checkpatch warnings
From: Bruno Prémont @ 2012-07-30 19:38 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: Jaya Kumar, linux-fbdev
In-Reply-To: <20120730213656.0a9f6d30@neptune.home>

WARNING: static const char * array should probably be static const char * const
+static const char *error_codes[] = {

WARNING: min() should probably be min_t(size_t, 20, s)
+       raw_data[2] = min((size_t)20, s);

Note: the second min_t suggestion cannot be followed because GCC is not
smart enough to track constants through it and make
copy_from_user_overflow() check happy.

WARNING: min() should probably be min_t(u8, 20, raw_data[2])
+       if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
                return -EFAULT;

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
 drivers/hid/hid-picolcd_debugfs.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
index ff74645..f2491fa 100644
--- a/drivers/hid/hid-picolcd_debugfs.c
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -135,7 +135,7 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
 	memset(raw_data, 0, sizeof(raw_data));
 	raw_data[0] = *off & 0xff;
 	raw_data[1] = (*off >> 8) & 0xff;
-	raw_data[2] = min((size_t)20, s);
+	raw_data[2] = min_t(size_t, 20, s);
 	if (*off + raw_data[2] > 0xff)
 		raw_data[2] = 0x100 - *off;
 
@@ -370,7 +370,7 @@ static const struct file_operations picolcd_debug_flash_fops = {
 /*
  * Helper code for HID report level dumping/debugging
  */
-static const char *error_codes[] = {
+static const char * const error_codes[] = {
 	"success", "parameter missing", "data_missing", "block readonly",
 	"block not erasable", "block too big", "section overflow",
 	"invalid command length", "invalid data length",
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 3/7] HID: picoLCD: prevent NULL pointer dereference on unplug
From: Bruno Prémont @ 2012-07-30 19:38 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: Jaya Kumar, linux-fbdev
In-Reply-To: <20120730213656.0a9f6d30@neptune.home>

[  679.807480] BUG: unable to handle kernel NULL pointer dereference at 00000074
[  679.814457] IP: [<de93b5bf>] picolcd_led_set_brightness+0x1f/0xb0 [hid_picolcd]
[  679.814457] *pde = 00000000
[  679.814457] Oops: 0000 [#1]
[  679.814457] Modules linked in: hid_picolcd fb_sys_fops sysimgblt sysfillrect syscopyarea drm_kms_helper nfs lockd nfs_acl sunrpc [last unloaded: hid_picolcd]
[  679.814457]
[  679.814457] Pid: 272, comm: khubd Not tainted 3.5.0-jupiter-00006-g463a4c0 #1 NVIDIA Corporation. nFORCE-MCP/MS-6373
[  679.814457] EIP: 0060:[<de93b5bf>] EFLAGS: 00010246 CPU: 0
[  679.814457] EIP is at picolcd_led_set_brightness+0x1f/0xb0 [hid_picolcd]
[  679.814457] EAX: 00000000 EBX: d9f0c4e0 ECX: 00000000 EDX: 00000000
[  679.814457] ESI: 00000000 EDI: dd6b79c0 EBP: dd4f7d90 ESP: dd4f7d80
[  679.814457]  DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068
[  679.814457] CR0: 8005003b CR2: 00000074 CR3: 1d74e000 CR4: 000007d0
[  679.814457] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[  679.814457] DR6: ffff0ff0 DR7: 00000400
[  679.814457] Process khubd (pid: 272, tiÝ4f6000 taskÝ442470 task.tiÝ4f6000)
[  679.814457] Stack:
[  679.814457]  1d6c3300 d9f0c4e0 d9f0c4e0 dd6b79c0 dd4f7da0 c132912a 00000000 d9f0c4e0
[  679.814457]  dd4f7dac c132935d 00000000 dd4f7dc0 de93b847 dd6b79c0 00000282 c700ecc8
[  679.814457]  dd4f7ddc de93924f 00000004 c700ecc8 c700e060 c700ecbc c15ee300 dd4f7dec
[  679.814457] Call Trace:
[  679.814457]  [<c132912a>] led_brightness_set+0x2a/0x30
[  679.814457]  [<c132935d>] led_classdev_unregister+0xd/0x50
[  679.814457]  [<de93b847>] picolcd_exit_leds+0x27/0x40 [hid_picolcd]
[  679.814457]  [<de93924f>] picolcd_remove+0xbf/0x110 [hid_picolcd]
[  679.814457]  [<c132c5dd>] hid_device_remove+0x3d/0x80
[  679.814457]  [<c1294126>] __device_release_driver+0x56/0xa0
[  679.814457]  [<c1294190>] device_release_driver+0x20/0x30
[  679.814457]  [<c1293bbf>] bus_remove_device+0x9f/0xc0
[  679.814457]  [<c1291a1d>] device_del+0xdd/0x150
[  679.814457]  [<c132c205>] hid_destroy_device+0x25/0x60
[  679.814457]  [<c13368cb>] usbhid_disconnect+0x1b/0x40
[  679.814457]  [<c12f4976>] usb_unbind_interface+0x46/0x170
[  679.814457]  [<c1294126>] __device_release_driver+0x56/0xa0
[  679.814457]  [<c1294190>] device_release_driver+0x20/0x30
[  679.814457]  [<c1293bbf>] bus_remove_device+0x9f/0xc0
[  679.814457]  [<c1291a1d>] device_del+0xdd/0x150
[  679.814457]  [<c12f2975>] usb_disable_device+0x85/0x1a0
[  679.814457]  [<c1053146>] ? __cond_resched+0x16/0x30
[  679.814457]  [<c12ebdb0>] usb_disconnect+0x80/0xf0
[  679.814457]  [<c12ed61f>] hub_thread+0x3df/0x1030
[  679.814457]  [<c10484a0>] ? wake_up_bit+0x30/0x30
[  679.814457]  [<c12ed240>] ? usb_remote_wakeup+0x40/0x40
[  679.814457]  [<c1047f94>] kthread+0x74/0x80
[  679.814457]  [<c1047f20>] ? flush_kthread_worker+0x90/0x90
[  679.814457]  [<c140e33e>] kernel_thread_helper+0x6/0xd
[  679.814457] Code: e0 25 00 e0 ff ff ff 48 14 eb 99 90 55 89 e5 83 ec 10 89 5d f4 89 75 f8 89 c3 89 7d fc 8b 40 1c 89 d6 8b 00 e8 13 89 95 e2 31 c9 <39> 5c 88 74 74 13 41 83 f9 08 75 f4 8b 5d f4 8b 75 f8 8b 7d fc
[  679.814457] EIP: [<de93b5bf>] picolcd_led_set_brightness+0x1f/0xb0 [hid_picolcd] SS:ESP 0068:dd4f7d80
[  679.814457] CR2: 0000000000000074
[  680.116438] ---[ end trace 6f0d9d63bff280ff ]---

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
 drivers/hid/hid-picolcd_leds.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c
index 9249c06..5573cd8 100644
--- a/drivers/hid/hid-picolcd_leds.c
+++ b/drivers/hid/hid-picolcd_leds.c
@@ -69,6 +69,8 @@ static void picolcd_led_set_brightness(struct led_classdev *led_cdev,
 	dev  = led_cdev->dev->parent;
 	hdev = container_of(dev, struct hid_device, dev);
 	data = hid_get_drvdata(hdev);
+	if (!data)
+		return;
 	for (i = 0; i < 8; i++) {
 		if (led_cdev != data->led[i])
 			continue;
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 2/7] HID: picoLCD: Replace own refcounting with fbdev's
From: Bruno Prémont @ 2012-07-30 19:38 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: Jaya Kumar, linux-fbdev
In-Reply-To: <20120730213656.0a9f6d30@neptune.home>


Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
 drivers/hid/hid-picolcd.h      |    6 --
 drivers/hid/hid-picolcd_core.c |    1 -
 drivers/hid/hid-picolcd_fb.c   |  114 ++++++---------------------------------
 3 files changed, 18 insertions(+), 103 deletions(-)

diff --git a/drivers/hid/hid-picolcd.h b/drivers/hid/hid-picolcd.h
index 4ddb318..9200be1 100644
--- a/drivers/hid/hid-picolcd.h
+++ b/drivers/hid/hid-picolcd.h
@@ -96,7 +96,6 @@ struct picolcd_data {
 	u8 *fb_vbitmap;		/* local copy of what was sent to PicoLCD */
 	u8 *fb_bitmap;		/* framebuffer */
 	struct fb_info *fb_info;
-	struct fb_deferred_io fb_defio;
 #endif /* CONFIG_HID_PICOLCD_FB */
 #ifdef CONFIG_HID_PICOLCD_LCD
 	struct lcd_device *lcd;
@@ -179,8 +178,6 @@ int picolcd_init_framebuffer(struct picolcd_data *data);
 
 void picolcd_exit_framebuffer(struct picolcd_data *data);
 
-void picolcd_fb_unload(void);
-
 void picolcd_fb_refresh(struct picolcd_data *data);
 #define picolcd_fbinfo(d) ((d)->fb_info)
 #else
@@ -195,9 +192,6 @@ static inline int picolcd_init_framebuffer(struct picolcd_data *data)
 static inline void picolcd_exit_framebuffer(struct picolcd_data *data)
 {
 }
-static inline void picolcd_fb_unload(void)
-{
-}
 static inline void picolcd_fb_refresh(struct picolcd_data *data)
 {
 }
diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
index 36e7548..8d5d341 100644
--- a/drivers/hid/hid-picolcd_core.c
+++ b/drivers/hid/hid-picolcd_core.c
@@ -695,7 +695,6 @@ static int __init picolcd_init(void)
 static void __exit picolcd_exit(void)
 {
 	hid_unregister_driver(&picolcd_driver);
-	picolcd_fb_unload();
 }
 
 module_init(picolcd_init);
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index b2124f5..602786c 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -256,7 +256,7 @@ static void picolcd_fb_update(struct picolcd_data *data)
 					data->fb_bitmap, data->fb_bpp, chip, tile) ||
 				data->fb_force) {
 				n += 2;
-				if (!data->fb_info->par)
+				if (data->status & PICOLCD_FAILED)
 					return; /* device lost! */
 				if (n >= HID_OUTPUT_FIFO_SIZE / 2) {
 					usbhid_wait_io(data->hdev);
@@ -327,24 +327,17 @@ static int picolcd_fb_blank(int blank, struct fb_info *info)
 
 static void picolcd_fb_destroy(struct fb_info *info)
 {
-	struct picolcd_data *data = info->par;
-	u32 *ref_cnt = info->pseudo_palette;
-	int may_release;
+	struct picolcd_data *data;
 
+	/* make sure no work is deferred */
+	cancel_delayed_work_sync(&info->deferred_work);
+	data = info->par;
 	info->par = NULL;
 	if (data)
 		data->fb_info = NULL;
-	fb_deferred_io_cleanup(info);
 
-	ref_cnt--;
-	mutex_lock(&info->lock);
-	(*ref_cnt)--;
-	may_release = !*ref_cnt;
-	mutex_unlock(&info->lock);
-	if (may_release) {
-		vfree((u8 *)info->fix.smem_start);
-		framebuffer_release(info);
-	}
+	vfree((u8 *)info->fix.smem_start);
+	framebuffer_release(info);
 }
 
 static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
@@ -414,77 +407,10 @@ static int picolcd_set_par(struct fb_info *info)
 	return 0;
 }
 
-/* Do refcounting on our FB and cleanup per worker if FB is
- * closed after unplug of our device
- * (fb_release holds info->lock and still touches info after
- *  we return so we can't release it immediately.
- */
-struct picolcd_fb_cleanup_item {
-	struct fb_info *info;
-	struct picolcd_fb_cleanup_item *next;
-};
-static struct picolcd_fb_cleanup_item *fb_pending;
-static DEFINE_SPINLOCK(fb_pending_lock);
-
-static void picolcd_fb_do_cleanup(struct work_struct *data)
-{
-	struct picolcd_fb_cleanup_item *item;
-	unsigned long flags;
-
-	do {
-		spin_lock_irqsave(&fb_pending_lock, flags);
-		item = fb_pending;
-		fb_pending = item ? item->next : NULL;
-		spin_unlock_irqrestore(&fb_pending_lock, flags);
-
-		if (item) {
-			u8 *fb = (u8 *)item->info->fix.smem_start;
-			/* make sure we do not race against fb core when
-			 * releasing */
-			mutex_lock(&item->info->lock);
-			mutex_unlock(&item->info->lock);
-			framebuffer_release(item->info);
-			vfree(fb);
-		}
-	} while (item);
-}
-
-static DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup);
-
-static int picolcd_fb_open(struct fb_info *info, int u)
-{
-	u32 *ref_cnt = info->pseudo_palette;
-	ref_cnt--;
-
-	(*ref_cnt)++;
-	return 0;
-}
-
-static int picolcd_fb_release(struct fb_info *info, int u)
-{
-	u32 *ref_cnt = info->pseudo_palette;
-	ref_cnt--;
-
-	(*ref_cnt)++;
-	if (!*ref_cnt) {
-		unsigned long flags;
-		struct picolcd_fb_cleanup_item *item = (struct picolcd_fb_cleanup_item *)ref_cnt;
-		item--;
-		spin_lock_irqsave(&fb_pending_lock, flags);
-		item->next = fb_pending;
-		fb_pending = item;
-		spin_unlock_irqrestore(&fb_pending_lock, flags);
-		schedule_work(&picolcd_fb_cleanup);
-	}
-	return 0;
-}
-
 /* Note this can't be const because of struct fb_info definition */
 static struct fb_ops picolcdfb_ops = {
 	.owner        = THIS_MODULE,
 	.fb_destroy   = picolcd_fb_destroy,
-	.fb_open      = picolcd_fb_open,
-	.fb_release   = picolcd_fb_release,
 	.fb_read      = fb_sys_read,
 	.fb_write     = picolcd_fb_write,
 	.fb_blank     = picolcd_fb_blank,
@@ -550,7 +476,7 @@ static ssize_t picolcd_fb_update_rate_store(struct device *dev,
 		u = PICOLCDFB_UPDATE_RATE_DEFAULT;
 
 	data->fb_update_rate = u;
-	data->fb_defio.delay = HZ / data->fb_update_rate;
+	data->fb_info->fbdefio->delay = HZ / data->fb_update_rate;
 	return count;
 }
 
@@ -580,25 +506,23 @@ int picolcd_init_framebuffer(struct picolcd_data *data)
 	}
 
 	data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT;
-	data->fb_defio = picolcd_fb_defio;
 	/* The extra memory is:
-	 * - struct picolcd_fb_cleanup_item
-	 * - u32 for ref_count
 	 * - 256*u32 for pseudo_palette
+	 * - struct fb_deferred_io
 	 */
-	info = framebuffer_alloc(257 * sizeof(u32) + sizeof(struct picolcd_fb_cleanup_item), dev);
+	info = framebuffer_alloc(256 * sizeof(u32) +
+			sizeof(struct fb_deferred_io), dev);
 	if (info = NULL) {
 		dev_err(dev, "failed to allocate a framebuffer\n");
 		goto err_nomem;
 	}
 
-	palette  = info->par + sizeof(struct picolcd_fb_cleanup_item);
-	*palette = 1;
-	palette++;
+	info->fbdefio = info->par;
+	*info->fbdefio = picolcd_fb_defio;
+	palette  = info->par + sizeof(struct fb_deferred_io);
 	for (i = 0; i < 256; i++)
 		palette[i] = i > 0 && i < 16 ? 0xff : 0;
 	info->pseudo_palette = palette;
-	info->fbdefio = &data->fb_defio;
 	info->screen_base = (char __force __iomem *)fb_bitmap;
 	info->fbops = &picolcdfb_ops;
 	info->var = picolcdfb_var;
@@ -658,6 +582,10 @@ void picolcd_exit_framebuffer(struct picolcd_data *data)
 		return;
 
 	device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
+	mutex_lock(&info->lock);
+	fb_deferred_io_cleanup(info);
+	info->par = NULL;
+	mutex_unlock(&info->lock);
 	unregister_framebuffer(info);
 	data->fb_vbitmap = NULL;
 	data->fb_bitmap  = NULL;
@@ -665,9 +593,3 @@ void picolcd_exit_framebuffer(struct picolcd_data *data)
 	data->fb_info    = NULL;
 	kfree(fb_vbitmap);
 }
-
-void picolcd_fb_unload()
-{
-	flush_work_sync(&picolcd_fb_cleanup);
-	WARN_ON(fb_pending);
-}
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 0/7] HID: picoLCD updates
From: Bruno Prémont @ 2012-07-30 19:36 UTC (permalink / raw)
  To: linux-input, linux-kernel, Jiri Kosina; +Cc: Jaya Kumar, linux-fbdev

Hi,

This series updates picoLCD driver:
- split the driver functions into separate files which get included
  depending on Kconfig selection
  (implementation for CIR using RC_CORE will follow later)
- drop private framebuffer refcounting in favor of refcounting added
  to fb_info some time ago
- fix various bugs issues
- disabled firmware version checking in probe() as it does not work
  anymore since commit 4ea5454203d991ec85264f64f89ca8855fce69b0
  [HID: Fix race condition between driver core and ll-driver]

Note: I still get weird behavior on quick unbind/bind sequences
issued via sysfs (CONFIG_SMP=n system) that are triggered by framebuffer
support and apparently more specifically fb_defio part of it.

Unfortunately I'm out of ideas as to how to track down the problem which
shows either as SLAB corruption (detected with SLUB debugging, e.g.

[ 6383.521833] ======================================[ 6383.530020] BUG kmalloc-64 (Not tainted): Object already free
[ 6383.530020] -----------------------------------------------------------------------------
[ 6383.530020] 
[ 6383.530020] INFO: Slab 0xdde0ea20 objectsQ used@ fp=0xcef516e0 flags=0x40000080
[ 6383.530020] INFO: Object 0xcef51190 @offset@0 fp=0xcef51f50
[ 6383.530020] 
[ 6383.530020] Bytes b4 cef51180: cc cc cc cc d0 12 f5 ce 5a 5a 5a 5a 5a 5a 5a 5a  ........ZZZZZZZZ
[ 6383.530020] Object cef51190: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[ 6383.530020] Object cef511a0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[ 6383.530020] Object cef511b0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[ 6383.530020] Object cef511c0: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5  kkkkkkkkkkkkkkk.
[ 6383.530020] Redzone cef511d0: bb bb bb bb                                      ....
[ 6383.530020] Padding cef511d8: 5a 5a 5a 5a 5a 5a 5a 5a                          ZZZZZZZZ
[ 6383.530020] Pid: 1922, comm: bash Not tainted 3.5.0-jupiter-00003-g8d858b1-dirty #2
[ 6383.530020] Call Trace:
[ 6383.530020]  [<c10bd3cc>] print_trailer+0x11c/0x130
[ 6383.530020]  [<c10bd415>] object_err+0x35/0x40
[ 6383.530020]  [<c10be809>] free_debug_processing+0x99/0x200
[ 6383.530020]  [<c10bf77e>] __slab_free+0x2e/0x280
[ 6383.530020]  [<c1322284>] ? hid_submit_out+0xa4/0x120
[ 6383.530020]  [<c1322870>] ? __usbhid_submit_report+0xc0/0x3c0
[ 6383.530020]  [<c10bfbda>] ? kfree+0xfa/0x110
[ 6383.530020]  [<de932aa4>] ? picolcd_debug_out_report+0x8c4/0x8e0 [hid_picolcd]
[ 6383.530020]  [<c10bfbda>] kfree+0xfa/0x110
[ 6383.530020]  [<c1322284>] ? hid_submit_out+0xa4/0x120
[ 6383.530020]  [<c1322284>] ? hid_submit_out+0xa4/0x120
[ 6383.530020]  [<c1322284>] ? hid_submit_out+0xa4/0x120
[ 6383.530020]  [<c1322284>] hid_submit_out+0xa4/0x120
[ 6383.530020]  [<c1322908>] __usbhid_submit_report+0x158/0x3c0
[ 6383.530020]  [<c1322c2b>] usbhid_submit_report+0x1b/0x30
[ 6383.530020]  [<de930789>] picolcd_fb_reset+0xb9/0x180 [hid_picolcd]
[ 6383.530020]  [<de930f1d>] picolcd_init_framebuffer+0x20d/0x2e0 [hid_picolcd]
[ 6383.530020]  [<de92fb9c>] picolcd_probe+0x3cc/0x580 [hid_picolcd]
[ 6383.530020]  [<c1319147>] hid_device_probe+0x67/0xf0
[ 6383.530020]  [<c1282f97>] ? driver_sysfs_add+0x57/0x80
[ 6383.530020]  [<c128329d>] driver_probe_device+0xbd/0x1c0
[ 6383.530020]  [<c1318a1b>] ? hid_match_device+0x7b/0x90
[ 6383.530020]  [<c12821e5>] driver_bind+0x75/0xd0
[ 6383.530020]  [<c1282170>] ? driver_unbind+0x90/0x90
[ 6383.530020]  [<c12818b7>] drv_attr_store+0x27/0x30
[ 6383.530020]  [<c1114aec>] sysfs_write_file+0xac/0xf0
[ 6383.530020]  [<c10c794c>] vfs_write+0x9c/0x130
[ 6383.530020]  [<c10d4a1f>] ? sys_dup3+0x11f/0x160
[ 6383.530020]  [<c1114a40>] ? sysfs_poll+0x90/0x90
[ 6383.530020]  [<c10c7bbd>] sys_write+0x3d/0x70
[ 6383.530020]  [<c13f2557>] sysenter_do_call+0x12/0x26
[ 6383.530020] FIX kmalloc-64: Object at 0xcef51190 not freed

or worse spontaneous reboot of the system without any trace on netconsole or
serial console.

echo $devid > bind; echo $devid > unbind
or
echo $devid > bind; echo $devid > unbind; sleep 0.2; echo $devid > bind; echo $devid > unbind

is sufficient to trigger the above issue while waiting a few seconds between bind and unbind
shows no sign of trouble.

Suggestions as to how to debug this and fix it are welcome!

Thanks,
Bruno

^ permalink raw reply

* Re: [PATCH] video/smscufx: fix line counting in fb_write
From: Alexander Holler @ 2012-07-30 19:28 UTC (permalink / raw)
  To: Florian Tobias Schandinat; +Cc: linux-kernel, linux-fbdev
In-Reply-To: <50117DD9.6070200@gmx.de>

Hello,

Am 26.07.2012 19:26, schrieb Florian Tobias Schandinat:

> Well, as this patch fixes a bug I applied it as is.

Thanks a lot, actually I was more interested to get that one-line-patch 
for udlfb, because I've discovered that bug using one of those Mimo-LCDs. ;)

Are you responsible for that too?

Regards,

Alexander

^ permalink raw reply

* [PATCH] fbcon: Fix bit_putcs() call to kmalloc(s, GFP_KERNEL)
From: Bruno Prémont @ 2012-07-30 19:09 UTC (permalink / raw)
  To: linux-fbdev, FlorianSchandinat; +Cc: linux-kernel

Switch to kmalloc(,GFP_ATOMIC) in bit_putcs to fix below trace:

[    9.771812] BUG: sleeping function called from invalid context at /usr/src/linux-git/mm/slub.c:943
[    9.771814] in_atomic(): 1, irqs_disabled(): 1, pid: 1063, name: mount
[    9.771818] Pid: 1063, comm: mount Not tainted 3.5.0-jupiter-00003-g8d858b1-dirty #2
[    9.771819] Call Trace:
[    9.771838]  [<c104f79b>] __might_sleep+0xcb/0xe0
[    9.771844]  [<c10c00d4>] __kmalloc+0xb4/0x1c0
[    9.771851]  [<c1041d4a>] ? queue_work+0x1a/0x30
[    9.771854]  [<c1041dcf>] ? queue_delayed_work+0xf/0x30
[    9.771862]  [<c1205832>] ? bit_putcs+0xf2/0x3e0
[    9.771865]  [<c1041e01>] ? schedule_delayed_work+0x11/0x20
[    9.771868]  [<c1205832>] bit_putcs+0xf2/0x3e0
[    9.771875]  [<c12002b8>] ? get_color.clone.14+0x28/0x100
[    9.771878]  [<c1200d2f>] fbcon_putcs+0x11f/0x130
[    9.771882]  [<c1205740>] ? bit_clear+0xe0/0xe0
[    9.771885]  [<c1200f6d>] fbcon_redraw.clone.21+0x11d/0x160
[    9.771889]  [<c120383d>] fbcon_scroll+0x79d/0xe10
[    9.771892]  [<c12002b8>] ? get_color.clone.14+0x28/0x100
[    9.771897]  [<c124c0b4>] scrup+0x64/0xd0
[    9.771900]  [<c124c22b>] lf+0x2b/0x60
[    9.771903]  [<c124cc95>] vt_console_print+0x1d5/0x2f0
[    9.771907]  [<c124cac0>] ? register_vt_notifier+0x20/0x20
[    9.771913]  [<c102b335>] call_console_drivers.clone.5+0xa5/0xc0
[    9.771916]  [<c102c58e>] console_unlock+0x2fe/0x3c0
[    9.771920]  [<c102ca16>] vprintk_emit+0x2e6/0x300
[    9.771924]  [<c13f01ae>] printk+0x38/0x3a
[    9.771931]  [<c112e8fe>] reiserfs_remount+0x2ae/0x3e0
[    9.771934]  [<c112e650>] ? reiserfs_fill_super+0xb00/0xb00
[    9.771939]  [<c10ca0ab>] do_remount_sb+0xab/0x150
[    9.771943]  [<c1034476>] ? ns_capable+0x46/0x70
[    9.771948]  [<c10e059c>] do_mount+0x20c/0x6b0
[    9.771955]  [<c10a7044>] ? strndup_user+0x34/0x50
[    9.771958]  [<c10e0acc>] sys_mount+0x6c/0xa0
[    9.771964]  [<c13f2557>] sysenter_do_call+0x12/0x26

According to comment in bit_putcs() that kammloc() call only happens
when fbcon is drawing to a monochrome framebuffer (which is my case with
hid-picolcd).

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
 drivers/video/console/bitblit.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 28b1a83..61b182b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -162,7 +162,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
 	image.depth = 1;
 
 	if (attribute) {
-		buf = kmalloc(cellsize, GFP_KERNEL);
+		buf = kmalloc(cellsize, GFP_ATOMIC);
 		if (!buf)
 			return;
 	}
-- 
1.7.8.6


^ permalink raw reply related

* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Mark Brown @ 2012-07-30 15:47 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Stephen Warren,
	Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Alexandre Courbot, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <5016ABDD.5010809-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Mon, Jul 30, 2012 at 10:44:29AM -0500, Rob Herring wrote:
> On 07/27/2012 07:05 AM, Alexandre Courbot wrote:

> > +		power-on-sequence {
> > +			regulator@0 {
> > +				id = "power";
> > +				enable;

> What do this mean? Isn't this implied for a regulator?

I assume you might have some sequences which need some things to be
turned off for some reason; it at least seems to be something you'd want
to design for.

> This looks like you designed the platform_data structs first and then
> came up with device nodes to mirror the struct.

Judging by most of the DT I review this seems idiomatic :)

^ permalink raw reply

* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Rob Herring @ 2012-07-30 15:44 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: Stephen Warren, Thierry Reding, Simon Glass, Grant Likely,
	Greg Kroah-Hartman, Mark Brown, Arnd Bergmann,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1343390750-3642-2-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

On 07/27/2012 07:05 AM, Alexandre Courbot wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
> 
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.
> 

Why not? We'll always have some amount of board code. The key is to
limit parts that are just data. I'm not sure this is something that
should be in devicetree.

Perhaps what is needed is a better way to hook into the driver like
notifiers?

> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  Documentation/power/power_seq.txt | 120 +++++++++++++++
>  drivers/base/Kconfig              |   4 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>  include/linux/power_seq.h         | 139 ++++++++++++++++++
>  5 files changed, 564 insertions(+)
>  create mode 100644 Documentation/power/power_seq.txt
>  create mode 100644 drivers/base/power_seq.c
>  create mode 100644 include/linux/power_seq.h
> 
> diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
> new file mode 100644
> index 0000000..aa2ceb5
> --- /dev/null
> +++ b/Documentation/power/power_seq.txt
> @@ -0,0 +1,120 @@
> +Runtime Interpreted Power Sequences
> +-----------------------------------
> +
> +Problem
> +-------
> +One very common board-dependent code is the out-of-driver code that is used to
> +turn a device on or off. For instance, SoC boards very commonly use a GPIO
> +(abstracted to a regulator or not) to control the power supply of a backlight,
> +disabling it when the backlight is not used in order to save power. The GPIO
> +that should be used, however, as well as the exact power sequence that may
> +involve different resources, is board-dependent and thus unknown of the driver.
> +
> +This has been addressed so far by using hooks in the device's platform data that
> +are called whenever the state of the device might reflect a power change. This
> +approach, however, introduces board-dependant code into the kernel and is not
> +compatible with the device tree.
> +
> +The Runtime Interpreted Power Sequences (or power sequences for short) aim at
> +turning this code into platform data or device tree nodes. Power sequences are
> +described using a simple format and run by a simple interpreter whenever needed.
> +This allows to remove the callback mechanism and makes the kernel less
> +board-dependant.
> +
> +Sequences Format
> +----------------
> +Power sequences are a series of sequential steps during which an action is
> +performed on a resource. The supported resources so far are:
> +- GPIOs
> +- Regulators
> +- PWMs
> +
> +Each step designates a resource and the following parameters:
> +- Whether the step should enable or disable the resource,
> +- Delay to wait before performing the action,
> +- Delay to wait after performing the action.
> +
> +Both new resources and parameters can be introduced, but the goal is of course
> +to keep things as simple and compact as possible.
> +
> +The platform data is a simple array of platform_power_seq_step instances, each
> +instance describing a step. The type as well as one of id or gpio members
> +(depending on the type) must be specified. The last step must be of type
> +POWER_SEQ_STOP. Regulator and PWM resources are identified by name. GPIO are
> +identified by number. For example, the following sequence will turn on the
> +"power" regulator of the device, wait 10ms, and set GPIO number 110 to 1:
> +
> +struct platform_power_seq_step power_on_seq[] = {
> +	{
> +		.type = POWER_SEQ_REGULATOR,
> +		.id = "power",
> +		.params = {
> +			.enable = 1,
> +			.post_delay = 10,
> +		},
> +	},
> +	{
> +		.type = POWER_SEQ_GPIO,
> +		.gpio = 110,
> +		.params = {
> +			.enable = 1,
> +		},
> +	},
> +	{
> +		.type = POWER_SEQ_STOP,
> +	},
> +};
> +
> +Usage by Drivers and Resources Management
> +-----------------------------------------
> +Power sequences make use of resources that must be properly allocated and
> +managed. The power_seq_build() function takes care of resolving the resources as
> +they are met in the sequence and to allocate them if needed:
> +
> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> +			   platform_power_seq *pseq);
> +
> +You will need an instance of power_seq_resources to keep track of the resources
> +that are already allocated. On success, the function returns a devm allocated
> +resolved sequence that is ready to be passed to power_seq_run(). In case of
> +failure, and error code is returned.
> +
> +A resolved power sequence returned by power_seq_build can be run by
> +power_run_run():
> +
> +int power_seq_run(struct device *dev, power_seq *seq);
> +
> +It returns 0 if the sequence has successfully been run, or an error code if a
> +problem occured.
> +
> +Finally, some resources that cannot be allocated through devm need to be freed
> +manually. Therefore, be sure to call power_seq_free_resources() in your device
> +remove function:
> +
> +void power_seq_free_resources(power_seq_resources *ress);
> +
> +Device tree

Bindings need to documented in Documentation/devicetree

> +-----------
> +All the same, power sequences can be encoded as device tree nodes. The following
> +properties and nodes are equivalent to the platform data defined previously:
> +
> +		power-supply = <&mydevice_reg>;
> +		enable-gpio = <&gpio 6 0>;
> +
> +		power-on-sequence {
> +			regulator@0 {
> +				id = "power";
> +				enable;

What do this mean? Isn't this implied for a regulator?

> +				post-delay = <10>;
> +			};
> +			gpio@1 {
> +				id = "enable-gpio";
> +				enable;
> +			};
> +		};

This looks like you designed the platform_data structs first and then
came up with device nodes to mirror the struct.

Rob

^ permalink raw reply

* Re: [PATCH 1/3] Move FIMD register headers to include/video/
From: Tomasz Figa @ 2012-07-30 14:32 UTC (permalink / raw)
  To: Leela Krishna Amudala
  Cc: Jingoo Han, linux-arm-kernel, linux-samsung-soc, dri-devel,
	linux-fbdev, ben-linux, inki.dae, kgene.kim, joshi,
	Marek Szyprowski
In-Reply-To: <CAL1wa8e7Joghf9S=SgbQLJFWcYOrP5uK6qYXsV_N6rX1MVEALg@mail.gmail.com>

Hi,

On Monday 30 of July 2012 at 16:46:03, Leela Krishna Amudala wrote:
> Hello Jingoo Han,
> 
> On Mon, Jul 30, 2012 at 2:23 PM, Jingoo Han <jg1.han@samsung.com> wrote:
> > On Monday, July 30, 2012 5:45 PM, Leela Krishna Amudala wrote:
> >> Moved the contents of regs-fb-v4.h and regs-fb.h from arch side
> >> to include/video/samsung_fimd.h
> >> 
> >> Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
> >> ---
> >> 
> >>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 -------
> >>  arch/arm/plat-samsung/include/plat/regs-fb.h    |  403 -----------------
> >>  include/video/samsung_fimd.h                    |  533
> >>  +++++++++++++++++++++++ 3 files changed, 533 insertions(+), 562
> >>  deletions(-)
> >>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
> >>  create mode 100644 include/video/samsung_fimd.h
> >> 
> >> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >> b/arch/arm/plat-samsung/include/plat/regs- fb-v4.h
> >> deleted file mode 100644
> >> index 4c3647f..0000000
> >> --- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >> +++ /dev/null
> >> @@ -1,159 +0,0 @@
> >> -/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >> - *
> >> - * Copyright 2008 Openmoko, Inc.
> >> - * Copyright 2008 Simtec Electronics
> >> - *      http://armlinux.simtec.co.uk/
> >> - *      Ben Dooks <ben@simtec.co.uk>
> >> - *
> >> - * S3C64XX - new-style framebuffer register definitions
> >> - *
> >> - * This is the register set for the new style framebuffer interface
> >> - * found from the S3C2443 onwards and specifically the S3C64XX series
> >> - * S3C6400 and S3C6410.
> >> - *
> >> - * The file contains the cpu specific items which change between
> >> whichever
> >> - * architecture is selected. See <plat/regs-fb.h> for the core
> >> definitions
> >> - * that are the same.
> >> - *
> >> - * This program is free software; you can redistribute it and/or modify
> >> - * it under the terms of the GNU General Public License version 2 as
> >> - * published by the Free Software Foundation.
> >> -*/
> >> -
> >> -/* include the core definitions here, in case we really do need to
> >> - * override them at a later date.
> >> -*/
> >> -
> >> -#include <plat/regs-fb.h>
> >> -
> >> -#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
> >> -#define VIDCON1_FSTATUS_EVEN (1 << 15)
> >> -
> >> -/* Video timing controls */
> >> -#define VIDTCON0                             (0x10)
> >> -#define VIDTCON1                             (0x14)
> >> -#define VIDTCON2                             (0x18)
> >> -
> >> -/* Window position controls */
> >> -
> >> -#define WINCON(_win)                         (0x20 + ((_win) * 4))
> >> -
> >> -/* OSD1 and OSD4 do not have register D */
> >> -
> >> -#define VIDOSD_BASE                          (0x40)
> >> -
> >> -#define VIDINTCON0                           (0x130)
> >> -
> >> -/* WINCONx */
> >> -
> >> -#define WINCONx_CSCWIDTH_MASK                        (0x3 << 26)
> >> -#define WINCONx_CSCWIDTH_SHIFT                       (26)
> >> -#define WINCONx_CSCWIDTH_WIDE                        (0x0 << 26)
> >> -#define WINCONx_CSCWIDTH_NARROW                      (0x3 << 26)
> >> -
> >> -#define WINCONx_ENLOCAL                              (1 << 22)
> >> -#define WINCONx_BUFSTATUS                    (1 << 21)
> >> -#define WINCONx_BUFSEL                               (1 << 20)
> >> -#define WINCONx_BUFAUTOEN                    (1 << 19)
> >> -#define WINCONx_YCbCr                                (1 << 13)
> >> -
> >> -#define WINCON1_LOCALSEL_CAMIF                       (1 << 23)
> >> -
> >> -#define WINCON2_LOCALSEL_CAMIF                       (1 << 23)
> >> -#define WINCON2_BLD_PIX                              (1 << 6)
> >> -
> >> -#define WINCON2_ALPHA_SEL                    (1 << 1)
> >> -#define WINCON2_BPPMODE_MASK                 (0xf << 2)
> >> -#define WINCON2_BPPMODE_SHIFT                        (2)
> >> -#define WINCON2_BPPMODE_1BPP                 (0x0 << 2)
> >> -#define WINCON2_BPPMODE_2BPP                 (0x1 << 2)
> >> -#define WINCON2_BPPMODE_4BPP                 (0x2 << 2)
> >> -#define WINCON2_BPPMODE_8BPP_1232            (0x4 << 2)
> >> -#define WINCON2_BPPMODE_16BPP_565            (0x5 << 2)
> >> -#define WINCON2_BPPMODE_16BPP_A1555          (0x6 << 2)
> >> -#define WINCON2_BPPMODE_16BPP_I1555          (0x7 << 2)
> >> -#define WINCON2_BPPMODE_18BPP_666            (0x8 << 2)
> >> -#define WINCON2_BPPMODE_18BPP_A1665          (0x9 << 2)
> >> -#define WINCON2_BPPMODE_19BPP_A1666          (0xa << 2)
> >> -#define WINCON2_BPPMODE_24BPP_888            (0xb << 2)
> >> -#define WINCON2_BPPMODE_24BPP_A1887          (0xc << 2)
> >> -#define WINCON2_BPPMODE_25BPP_A1888          (0xd << 2)
> >> -#define WINCON2_BPPMODE_28BPP_A4888          (0xd << 2)
> >> -
> >> -#define WINCON3_BLD_PIX                              (1 << 6)
> >> -
> >> -#define WINCON3_ALPHA_SEL                    (1 << 1)
> >> -#define WINCON3_BPPMODE_MASK                 (0xf << 2)
> >> -#define WINCON3_BPPMODE_SHIFT                        (2)
> >> -#define WINCON3_BPPMODE_1BPP                 (0x0 << 2)
> >> -#define WINCON3_BPPMODE_2BPP                 (0x1 << 2)
> >> -#define WINCON3_BPPMODE_4BPP                 (0x2 << 2)
> >> -#define WINCON3_BPPMODE_16BPP_565            (0x5 << 2)
> >> -#define WINCON3_BPPMODE_16BPP_A1555          (0x6 << 2)
> >> -#define WINCON3_BPPMODE_16BPP_I1555          (0x7 << 2)
> >> -#define WINCON3_BPPMODE_18BPP_666            (0x8 << 2)
> >> -#define WINCON3_BPPMODE_18BPP_A1665          (0x9 << 2)
> >> -#define WINCON3_BPPMODE_19BPP_A1666          (0xa << 2)
> >> -#define WINCON3_BPPMODE_24BPP_888            (0xb << 2)
> >> -#define WINCON3_BPPMODE_24BPP_A1887          (0xc << 2)
> >> -#define WINCON3_BPPMODE_25BPP_A1888          (0xd << 2)
> >> -#define WINCON3_BPPMODE_28BPP_A4888          (0xd << 2)
> >> -
> >> -#define VIDINTCON0_FIFIOSEL_WINDOW2          (0x10 << 5)
> >> -#define VIDINTCON0_FIFIOSEL_WINDOW3          (0x20 << 5)
> >> -#define VIDINTCON0_FIFIOSEL_WINDOW4          (0x40 << 5)
> >> -
> >> -#define DITHMODE                             (0x170)
> >> -#define WINxMAP(_win)                                (0x180 + ((_win) *
> >> 4)) -
> >> -
> >> -#define DITHMODE_R_POS_MASK                  (0x3 << 5)
> >> -#define DITHMODE_R_POS_SHIFT                 (5)
> >> -#define DITHMODE_R_POS_8BIT                  (0x0 << 5)
> >> -#define DITHMODE_R_POS_6BIT                  (0x1 << 5)
> >> -#define DITHMODE_R_POS_5BIT                  (0x2 << 5)
> >> -
> >> -#define DITHMODE_G_POS_MASK                  (0x3 << 3)
> >> -#define DITHMODE_G_POS_SHIFT                 (3)
> >> -#define DITHMODE_G_POS_8BIT                  (0x0 << 3)
> >> -#define DITHMODE_G_POS_6BIT                  (0x1 << 3)
> >> -#define DITHMODE_G_POS_5BIT                  (0x2 << 3)
> >> -
> >> -#define DITHMODE_B_POS_MASK                  (0x3 << 1)
> >> -#define DITHMODE_B_POS_SHIFT                 (1)
> >> -#define DITHMODE_B_POS_8BIT                  (0x0 << 1)
> >> -#define DITHMODE_B_POS_6BIT                  (0x1 << 1)
> >> -#define DITHMODE_B_POS_5BIT                  (0x2 << 1)
> >> -
> >> -#define DITHMODE_DITH_EN                     (1 << 0)
> >> -
> >> -#define WPALCON                                      (0x1A0)
> >> -
> >> -/* Palette control */
> >> -/* Note for S5PC100: you can still use those macros on WPALCON (aka
> >> WPALCON_L), - * but make sure that WPALCON_H W2PAL-W4PAL entries are
> >> zeroed out */ -#define WPALCON_W4PAL_16BPP_A555             (1 << 8)
> >> -#define WPALCON_W3PAL_16BPP_A555             (1 << 7)
> >> -#define WPALCON_W2PAL_16BPP_A555             (1 << 6)
> >> -
> >> -
> >> -/* Notes on per-window bpp settings
> >> - *
> >> - * Value     Win0     Win1     Win2     Win3     Win 4
> >> - * 0000              1(P)     1(P)     1(P)     1(P)     1(P)
> >> - * 0001              2(P)     2(P)     2(P)     2(P)     2(P)
> >> - * 0010              4(P)     4(P)     4(P)     4(P)     -none-
> >> - * 0011              8(P)     8(P)     -none-   -none-   -none-
> >> - * 0100              -none-   8(A232)  8(A232)  -none-   -none-
> >> - * 0101              16(565)  16(565)  16(565)  16(565)   16(565)
> >> - * 0110              -none-   16(A555) 16(A555) 16(A555)  16(A555)
> >> - * 0111              16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
> >> - * 1000              18(666)  18(666)  18(666)  18(666)   18(666)
> >> - * 1001              -none-   18(A665) 18(A665) 18(A665)  16(A665)
> >> - * 1010              -none-   19(A666) 19(A666) 19(A666)  19(A666)
> >> - * 1011              24(888)  24(888)  24(888)  24(888)   24(888)
> >> - * 1100              -none-   24(A887) 24(A887) 24(A887)  24(A887)
> >> - * 1101              -none-   25(A888) 25(A888) 25(A888)  25(A888)
> >> - * 1110              -none-   -none-   -none-   -none-    -none-
> >> - * 1111              -none-   -none-   -none-   -none-    -none-
> >> -*/
> >> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h
> >> b/arch/arm/plat-samsung/include/plat/regs-fb.h deleted file mode 100644
> >> index 9a78012..0000000
> >> --- a/arch/arm/plat-samsung/include/plat/regs-fb.h
> >> +++ /dev/null
> >> @@ -1,403 +0,0 @@
> >> -/* arch/arm/plat-samsung/include/plat/regs-fb.h
> >> - *
> >> - * Copyright 2008 Openmoko, Inc.
> >> - * Copyright 2008 Simtec Electronics
> >> - *      http://armlinux.simtec.co.uk/
> >> - *      Ben Dooks <ben@simtec.co.uk>
> >> - *
> >> - * S3C Platform - new-style framebuffer register definitions
> >> - *
> >> - * This is the register set for the new style framebuffer interface
> >> - * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
> >> - * S3C64XX series such as the S3C6400 and S3C6410.
> >> - *
> >> - * The file does not contain the cpu specific items which are based on
> >> - * whichever architecture is selected, it only contains the core of the
> >> - * register set. See <mach/regs-fb.h> to get the specifics.
> >> - *
> >> - * Note, we changed to using regs-fb.h as it avoids any clashes with
> >> - * the original regs-lcd.h so out of the way of regs-lcd.h as well as
> >> - * indicating the newer block is much more than just an LCD interface.
> >> - *
> >> - * This program is free software; you can redistribute it and/or modify
> >> - * it under the terms of the GNU General Public License version 2 as
> >> - * published by the Free Software Foundation.
> >> -*/
> >> -
> >> -/* Please do not include this file directly, use <mach/regs-fb.h> to
> >> - * ensure all the localised SoC support is included as necessary.
> >> -*/
> >> -
> >> -/* VIDCON0 */
> >> -
> >> -#define VIDCON0                                      (0x00)
> >> -#define VIDCON0_INTERLACE                    (1 << 29)
> >> -#define VIDCON0_VIDOUT_MASK                  (0x3 << 26)
> >> -#define VIDCON0_VIDOUT_SHIFT                 (26)
> >> -#define VIDCON0_VIDOUT_RGB                   (0x0 << 26)
> >> -#define VIDCON0_VIDOUT_TV                    (0x1 << 26)
> >> -#define VIDCON0_VIDOUT_I80_LDI0                      (0x2 << 26)
> >> -#define VIDCON0_VIDOUT_I80_LDI1                      (0x3 << 26)
> >> -
> >> -#define VIDCON0_L1_DATA_MASK                 (0x7 << 23)
> >> -#define VIDCON0_L1_DATA_SHIFT                        (23)
> >> -#define VIDCON0_L1_DATA_16BPP                        (0x0 << 23)
> >> -#define VIDCON0_L1_DATA_18BPP16                      (0x1 << 23)
> >> -#define VIDCON0_L1_DATA_18BPP9                       (0x2 << 23)
> >> -#define VIDCON0_L1_DATA_24BPP                        (0x3 << 23)
> >> -#define VIDCON0_L1_DATA_18BPP                        (0x4 << 23)
> >> -#define VIDCON0_L1_DATA_16BPP8                       (0x5 << 23)
> >> -
> >> -#define VIDCON0_L0_DATA_MASK                 (0x7 << 20)
> >> -#define VIDCON0_L0_DATA_SHIFT                        (20)
> >> -#define VIDCON0_L0_DATA_16BPP                        (0x0 << 20)
> >> -#define VIDCON0_L0_DATA_18BPP16                      (0x1 << 20)
> >> -#define VIDCON0_L0_DATA_18BPP9                       (0x2 << 20)
> >> -#define VIDCON0_L0_DATA_24BPP                        (0x3 << 20)
> >> -#define VIDCON0_L0_DATA_18BPP                        (0x4 << 20)
> >> -#define VIDCON0_L0_DATA_16BPP8                       (0x5 << 20)
> >> -
> >> -#define VIDCON0_PNRMODE_MASK                 (0x3 << 17)
> >> -#define VIDCON0_PNRMODE_SHIFT                        (17)
> >> -#define VIDCON0_PNRMODE_RGB                  (0x0 << 17)
> >> -#define VIDCON0_PNRMODE_BGR                  (0x1 << 17)
> >> -#define VIDCON0_PNRMODE_SERIAL_RGB           (0x2 << 17)
> >> -#define VIDCON0_PNRMODE_SERIAL_BGR           (0x3 << 17)
> >> -
> >> -#define VIDCON0_CLKVALUP                     (1 << 16)
> >> -#define VIDCON0_CLKVAL_F_MASK                        (0xff << 6)
> >> -#define VIDCON0_CLKVAL_F_SHIFT                       (6)
> >> -#define VIDCON0_CLKVAL_F_LIMIT                       (0xff)
> >> -#define VIDCON0_CLKVAL_F(_x)                 ((_x) << 6)
> >> -#define VIDCON0_VLCKFREE                     (1 << 5)
> >> -#define VIDCON0_CLKDIR                               (1 << 4)
> >> -
> >> -#define VIDCON0_CLKSEL_MASK                  (0x3 << 2)
> >> -#define VIDCON0_CLKSEL_SHIFT                 (2)
> >> -#define VIDCON0_CLKSEL_HCLK                  (0x0 << 2)
> >> -#define VIDCON0_CLKSEL_LCD                   (0x1 << 2)
> >> -#define VIDCON0_CLKSEL_27M                   (0x3 << 2)
> >> -
> >> -#define VIDCON0_ENVID                                (1 << 1)
> >> -#define VIDCON0_ENVID_F                              (1 << 0)
> >> -
> >> -#define VIDCON1                                      (0x04)
> >> -#define VIDCON1_LINECNT_MASK                 (0x7ff << 16)
> >> -#define VIDCON1_LINECNT_SHIFT                        (16)
> >> -#define VIDCON1_LINECNT_GET(_v)                      (((_v) >> 16) &
> >> 0x7ff) -#define VIDCON1_VSTATUS_MASK                 (0x3 << 13)
> >> -#define VIDCON1_VSTATUS_SHIFT                        (13)
> >> -#define VIDCON1_VSTATUS_VSYNC                        (0x0 << 13)
> >> -#define VIDCON1_VSTATUS_BACKPORCH            (0x1 << 13)
> >> -#define VIDCON1_VSTATUS_ACTIVE                       (0x2 << 13)
> >> -#define VIDCON1_VSTATUS_FRONTPORCH           (0x0 << 13)
> >> -#define VIDCON1_VCLK_MASK                    (0x3 << 9)
> >> -#define VIDCON1_VCLK_HOLD                    (0x0 << 9)
> >> -#define VIDCON1_VCLK_RUN                     (0x1 << 9)
> >> -
> >> -#define VIDCON1_INV_VCLK                     (1 << 7)
> >> -#define VIDCON1_INV_HSYNC                    (1 << 6)
> >> -#define VIDCON1_INV_VSYNC                    (1 << 5)
> >> -#define VIDCON1_INV_VDEN                     (1 << 4)
> >> -
> >> -/* VIDCON2 */
> >> -
> >> -#define VIDCON2                                      (0x08)
> >> -#define VIDCON2_EN601                                (1 << 23)
> >> -#define VIDCON2_TVFMTSEL_SW                  (1 << 14)
> >> -
> >> -#define VIDCON2_TVFMTSEL1_MASK                       (0x3 << 12)
> >> -#define VIDCON2_TVFMTSEL1_SHIFT                      (12)
> >> -#define VIDCON2_TVFMTSEL1_RGB                        (0x0 << 12)
> >> -#define VIDCON2_TVFMTSEL1_YUV422             (0x1 << 12)
> >> -#define VIDCON2_TVFMTSEL1_YUV444             (0x2 << 12)
> >> -
> >> -#define VIDCON2_ORGYCbCr                     (1 << 8)
> >> -#define VIDCON2_YUVORDCrCb                   (1 << 7)
> >> -
> >> -/* PRTCON (S3C6410, S5PC100)
> >> - * Might not be present in the S3C6410 documentation,
> >> - * but tests prove it's there almost for sure; shouldn't hurt in any
> >> case.
> >> - */
> >> -#define PRTCON                                       (0x0c)
> >> -#define PRTCON_PROTECT                               (1 << 11)
> >> -
> >> -/* VIDTCON0 */
> >> -
> >> -#define VIDTCON0_VBPDE_MASK                  (0xff << 24)
> >> -#define VIDTCON0_VBPDE_SHIFT                 (24)
> >> -#define VIDTCON0_VBPDE_LIMIT                 (0xff)
> >> -#define VIDTCON0_VBPDE(_x)                   ((_x) << 24)
> >> -
> >> -#define VIDTCON0_VBPD_MASK                   (0xff << 16)
> >> -#define VIDTCON0_VBPD_SHIFT                  (16)
> >> -#define VIDTCON0_VBPD_LIMIT                  (0xff)
> >> -#define VIDTCON0_VBPD(_x)                    ((_x) << 16)
> >> -
> >> -#define VIDTCON0_VFPD_MASK                   (0xff << 8)
> >> -#define VIDTCON0_VFPD_SHIFT                  (8)
> >> -#define VIDTCON0_VFPD_LIMIT                  (0xff)
> >> -#define VIDTCON0_VFPD(_x)                    ((_x) << 8)
> >> -
> >> -#define VIDTCON0_VSPW_MASK                   (0xff << 0)
> >> -#define VIDTCON0_VSPW_SHIFT                  (0)
> >> -#define VIDTCON0_VSPW_LIMIT                  (0xff)
> >> -#define VIDTCON0_VSPW(_x)                    ((_x) << 0)
> >> -
> >> -/* VIDTCON1 */
> >> -
> >> -#define VIDTCON1_VFPDE_MASK                  (0xff << 24)
> >> -#define VIDTCON1_VFPDE_SHIFT                 (24)
> >> -#define VIDTCON1_VFPDE_LIMIT                 (0xff)
> >> -#define VIDTCON1_VFPDE(_x)                   ((_x) << 24)
> >> -
> >> -#define VIDTCON1_HBPD_MASK                   (0xff << 16)
> >> -#define VIDTCON1_HBPD_SHIFT                  (16)
> >> -#define VIDTCON1_HBPD_LIMIT                  (0xff)
> >> -#define VIDTCON1_HBPD(_x)                    ((_x) << 16)
> >> -
> >> -#define VIDTCON1_HFPD_MASK                   (0xff << 8)
> >> -#define VIDTCON1_HFPD_SHIFT                  (8)
> >> -#define VIDTCON1_HFPD_LIMIT                  (0xff)
> >> -#define VIDTCON1_HFPD(_x)                    ((_x) << 8)
> >> -
> >> -#define VIDTCON1_HSPW_MASK                   (0xff << 0)
> >> -#define VIDTCON1_HSPW_SHIFT                  (0)
> >> -#define VIDTCON1_HSPW_LIMIT                  (0xff)
> >> -#define VIDTCON1_HSPW(_x)                    ((_x) << 0)
> >> -
> >> -#define VIDTCON2                             (0x18)
> >> -#define VIDTCON2_LINEVAL_E(_x)                       ((((_x) & 0x800) >>
> >> 11) << 23) -#define VIDTCON2_LINEVAL_MASK                        (0x7ff
> >> << 11) -#define VIDTCON2_LINEVAL_SHIFT                       (11)
> >> -#define VIDTCON2_LINEVAL_LIMIT                       (0x7ff)
> >> -#define VIDTCON2_LINEVAL(_x)                 (((_x) & 0x7ff) << 11)
> >> -
> >> -#define VIDTCON2_HOZVAL_E(_x)                        ((((_x) & 0x800) >>
> >> 11) << 22) -#define VIDTCON2_HOZVAL_MASK                 (0x7ff << 0)
> >> -#define VIDTCON2_HOZVAL_SHIFT                        (0)
> >> -#define VIDTCON2_HOZVAL_LIMIT                        (0x7ff)
> >> -#define VIDTCON2_HOZVAL(_x)                  (((_x) & 0x7ff) << 0)
> >> -
> >> -/* WINCONx */
> >> -
> >> -
> >> -#define WINCONx_BITSWP                               (1 << 18)
> >> -#define WINCONx_BYTSWP                               (1 << 17)
> >> -#define WINCONx_HAWSWP                               (1 << 16)
> >> -#define WINCONx_WSWP                         (1 << 15)
> >> -#define WINCONx_BURSTLEN_MASK                        (0x3 << 9)
> >> -#define WINCONx_BURSTLEN_SHIFT                       (9)
> >> -#define WINCONx_BURSTLEN_16WORD                      (0x0 << 9)
> >> -#define WINCONx_BURSTLEN_8WORD                       (0x1 << 9)
> >> -#define WINCONx_BURSTLEN_4WORD                       (0x2 << 9)
> >> -
> >> -#define WINCONx_ENWIN                                (1 << 0)
> >> -#define WINCON0_BPPMODE_MASK                 (0xf << 2)
> >> -#define WINCON0_BPPMODE_SHIFT                        (2)
> >> -#define WINCON0_BPPMODE_1BPP                 (0x0 << 2)
> >> -#define WINCON0_BPPMODE_2BPP                 (0x1 << 2)
> >> -#define WINCON0_BPPMODE_4BPP                 (0x2 << 2)
> >> -#define WINCON0_BPPMODE_8BPP_PALETTE         (0x3 << 2)
> >> -#define WINCON0_BPPMODE_16BPP_565            (0x5 << 2)
> >> -#define WINCON0_BPPMODE_16BPP_1555           (0x7 << 2)
> >> -#define WINCON0_BPPMODE_18BPP_666            (0x8 << 2)
> >> -#define WINCON0_BPPMODE_24BPP_888            (0xb << 2)
> >> -
> >> -#define WINCON1_BLD_PIX                              (1 << 6)
> >> -
> >> -#define WINCON1_ALPHA_SEL                    (1 << 1)
> >> -#define WINCON1_BPPMODE_MASK                 (0xf << 2)
> >> -#define WINCON1_BPPMODE_SHIFT                        (2)
> >> -#define WINCON1_BPPMODE_1BPP                 (0x0 << 2)
> >> -#define WINCON1_BPPMODE_2BPP                 (0x1 << 2)
> >> -#define WINCON1_BPPMODE_4BPP                 (0x2 << 2)
> >> -#define WINCON1_BPPMODE_8BPP_PALETTE         (0x3 << 2)
> >> -#define WINCON1_BPPMODE_8BPP_1232            (0x4 << 2)
> >> -#define WINCON1_BPPMODE_16BPP_565            (0x5 << 2)
> >> -#define WINCON1_BPPMODE_16BPP_A1555          (0x6 << 2)
> >> -#define WINCON1_BPPMODE_16BPP_I1555          (0x7 << 2)
> >> -#define WINCON1_BPPMODE_18BPP_666            (0x8 << 2)
> >> -#define WINCON1_BPPMODE_18BPP_A1665          (0x9 << 2)
> >> -#define WINCON1_BPPMODE_19BPP_A1666          (0xa << 2)
> >> -#define WINCON1_BPPMODE_24BPP_888            (0xb << 2)
> >> -#define WINCON1_BPPMODE_24BPP_A1887          (0xc << 2)
> >> -#define WINCON1_BPPMODE_25BPP_A1888          (0xd << 2)
> >> -#define WINCON1_BPPMODE_28BPP_A4888          (0xd << 2)
> >> -
> >> -/* S5PV210 */
> >> -#define SHADOWCON                            (0x34)
> >> -#define SHADOWCON_WINx_PROTECT(_win)         (1 << (10 + (_win)))
> >> -/* DMA channels (all windows) */
> >> -#define SHADOWCON_CHx_ENABLE(_win)           (1 << (_win))
> >> -/* Local input channels (windows 0-2) */
> >> -#define SHADOWCON_CHx_LOCAL_ENABLE(_win)     (1 << (5 + (_win)))
> >> -
> >> -#define VIDOSDxA_TOPLEFT_X_E(_x)             ((((_x) & 0x800) >> 11) <<
> >> 23) -#define VIDOSDxA_TOPLEFT_X_MASK                      (0x7ff << 11)
> >> -#define VIDOSDxA_TOPLEFT_X_SHIFT             (11)
> >> -#define VIDOSDxA_TOPLEFT_X_LIMIT             (0x7ff)
> >> -#define VIDOSDxA_TOPLEFT_X(_x)                       (((_x) & 0x7ff) <<
> >> 11) -
> >> -#define VIDOSDxA_TOPLEFT_Y_E(_x)             ((((_x) & 0x800) >> 11) <<
> >> 22) -#define VIDOSDxA_TOPLEFT_Y_MASK                      (0x7ff << 0)
> >> -#define VIDOSDxA_TOPLEFT_Y_SHIFT             (0)
> >> -#define VIDOSDxA_TOPLEFT_Y_LIMIT             (0x7ff)
> >> -#define VIDOSDxA_TOPLEFT_Y(_x)                       (((_x) & 0x7ff) <<
> >> 0)
> >> -
> >> -#define VIDOSDxB_BOTRIGHT_X_E(_x)            ((((_x) & 0x800) >> 11) <<
> >> 23) -#define VIDOSDxB_BOTRIGHT_X_MASK             (0x7ff << 11)
> >> -#define VIDOSDxB_BOTRIGHT_X_SHIFT            (11)
> >> -#define VIDOSDxB_BOTRIGHT_X_LIMIT            (0x7ff)
> >> -#define VIDOSDxB_BOTRIGHT_X(_x)                      (((_x) & 0x7ff) <<
> >> 11) -
> >> -#define VIDOSDxB_BOTRIGHT_Y_E(_x)            ((((_x) & 0x800) >> 11) <<
> >> 22) -#define VIDOSDxB_BOTRIGHT_Y_MASK             (0x7ff << 0)
> >> -#define VIDOSDxB_BOTRIGHT_Y_SHIFT            (0)
> >> -#define VIDOSDxB_BOTRIGHT_Y_LIMIT            (0x7ff)
> >> -#define VIDOSDxB_BOTRIGHT_Y(_x)                      (((_x) & 0x7ff) <<
> >> 0)
> >> -
> >> -/* For VIDOSD[1..4]C */
> >> -#define VIDISD14C_ALPHA0_R(_x)                       ((_x) << 20)
> >> -#define VIDISD14C_ALPHA0_G_MASK                      (0xf << 16)
> >> -#define VIDISD14C_ALPHA0_G_SHIFT             (16)
> >> -#define VIDISD14C_ALPHA0_G_LIMIT             (0xf)
> >> -#define VIDISD14C_ALPHA0_G(_x)                       ((_x) << 16)
> >> -#define VIDISD14C_ALPHA0_B_MASK                      (0xf << 12)
> >> -#define VIDISD14C_ALPHA0_B_SHIFT             (12)
> >> -#define VIDISD14C_ALPHA0_B_LIMIT             (0xf)
> >> -#define VIDISD14C_ALPHA0_B(_x)                       ((_x) << 12)
> >> -#define VIDISD14C_ALPHA1_R_MASK                      (0xf << 8)
> >> -#define VIDISD14C_ALPHA1_R_SHIFT             (8)
> >> -#define VIDISD14C_ALPHA1_R_LIMIT             (0xf)
> >> -#define VIDISD14C_ALPHA1_R(_x)                       ((_x) << 8)
> >> -#define VIDISD14C_ALPHA1_G_MASK                      (0xf << 4)
> >> -#define VIDISD14C_ALPHA1_G_SHIFT             (4)
> >> -#define VIDISD14C_ALPHA1_G_LIMIT             (0xf)
> >> -#define VIDISD14C_ALPHA1_G(_x)                       ((_x) << 4)
> >> -#define VIDISD14C_ALPHA1_B_MASK                      (0xf << 0)
> >> -#define VIDISD14C_ALPHA1_B_SHIFT             (0)
> >> -#define VIDISD14C_ALPHA1_B_LIMIT             (0xf)
> >> -#define VIDISD14C_ALPHA1_B(_x)                       ((_x) << 0)
> >> -
> >> -/* Video buffer addresses */
> >> -#define VIDW_BUF_START(_buff)                        (0xA0 + ((_buff) *
> >> 8)) -#define VIDW_BUF_START1(_buff)                       (0xA4 +
> >> ((_buff) * 8)) -#define VIDW_BUF_END(_buff)                  (0xD0 +
> >> ((_buff) * 8)) -#define VIDW_BUF_END1(_buff)                 (0xD4 +
> >> ((_buff) * 8)) -#define VIDW_BUF_SIZE(_buff)                 (0x100 +
> >> ((_buff) * 4)) -
> >> -#define VIDW_BUF_SIZE_OFFSET_E(_x)           ((((_x) & 0x2000) >> 13) <<
> >> 27) -#define VIDW_BUF_SIZE_OFFSET_MASK            (0x1fff << 13)
> >> -#define VIDW_BUF_SIZE_OFFSET_SHIFT           (13)
> >> -#define VIDW_BUF_SIZE_OFFSET_LIMIT           (0x1fff)
> >> -#define VIDW_BUF_SIZE_OFFSET(_x)             (((_x) & 0x1fff) << 13)
> >> -
> >> -#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)                ((((_x) & 0x2000)
> >> >> 13) << 26) -#define VIDW_BUF_SIZE_PAGEWIDTH_MASK         (0x1fff <<
> >> 0)
> >> -#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT                (0)
> >> -#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT                (0x1fff)
> >> -#define VIDW_BUF_SIZE_PAGEWIDTH(_x)          (((_x) & 0x1fff) << 0)
> >> -
> >> -/* Interrupt controls and status */
> >> -
> >> -#define VIDINTCON0_FIFOINTERVAL_MASK         (0x3f << 20)
> >> -#define VIDINTCON0_FIFOINTERVAL_SHIFT                (20)
> >> -#define VIDINTCON0_FIFOINTERVAL_LIMIT                (0x3f)
> >> -#define VIDINTCON0_FIFOINTERVAL(_x)          ((_x) << 20)
> >> -
> >> -#define VIDINTCON0_INT_SYSMAINCON            (1 << 19)
> >> -#define VIDINTCON0_INT_SYSSUBCON             (1 << 18)
> >> -#define VIDINTCON0_INT_I80IFDONE             (1 << 17)
> >> -
> >> -#define VIDINTCON0_FRAMESEL0_MASK            (0x3 << 15)
> >> -#define VIDINTCON0_FRAMESEL0_SHIFT           (15)
> >> -#define VIDINTCON0_FRAMESEL0_BACKPORCH               (0x0 << 15)
> >> -#define VIDINTCON0_FRAMESEL0_VSYNC           (0x1 << 15)
> >> -#define VIDINTCON0_FRAMESEL0_ACTIVE          (0x2 << 15)
> >> -#define VIDINTCON0_FRAMESEL0_FRONTPORCH              (0x3 << 15)
> >> -
> >> -#define VIDINTCON0_FRAMESEL1                 (1 << 13)
> >> -#define VIDINTCON0_FRAMESEL1_MASK            (0x3 << 13)
> >> -#define VIDINTCON0_FRAMESEL1_NONE            (0x0 << 13)
> >> -#define VIDINTCON0_FRAMESEL1_BACKPORCH               (0x1 << 13)
> >> -#define VIDINTCON0_FRAMESEL1_VSYNC           (0x2 << 13)
> >> -#define VIDINTCON0_FRAMESEL1_FRONTPORCH              (0x3 << 13)
> >> -
> >> -#define VIDINTCON0_INT_FRAME                 (1 << 12)
> >> -#define VIDINTCON0_FIFIOSEL_MASK             (0x7f << 5)
> >> -#define VIDINTCON0_FIFIOSEL_SHIFT            (5)
> >> -#define VIDINTCON0_FIFIOSEL_WINDOW0          (0x1 << 5)
> >> -#define VIDINTCON0_FIFIOSEL_WINDOW1          (0x2 << 5)
> >> -
> >> -#define VIDINTCON0_FIFOLEVEL_MASK            (0x7 << 2)
> >> -#define VIDINTCON0_FIFOLEVEL_SHIFT           (2)
> >> -#define VIDINTCON0_FIFOLEVEL_TO25PC          (0x0 << 2)
> >> -#define VIDINTCON0_FIFOLEVEL_TO50PC          (0x1 << 2)
> >> -#define VIDINTCON0_FIFOLEVEL_TO75PC          (0x2 << 2)
> >> -#define VIDINTCON0_FIFOLEVEL_EMPTY           (0x3 << 2)
> >> -#define VIDINTCON0_FIFOLEVEL_FULL            (0x4 << 2)
> >> -
> >> -#define VIDINTCON0_INT_FIFO_MASK             (0x3 << 0)
> >> -#define VIDINTCON0_INT_FIFO_SHIFT            (0)
> >> -#define VIDINTCON0_INT_ENABLE                        (1 << 0)
> >> -
> >> -#define VIDINTCON1                           (0x134)
> >> -#define VIDINTCON1_INT_I180                  (1 << 2)
> >> -#define VIDINTCON1_INT_FRAME                 (1 << 1)
> >> -#define VIDINTCON1_INT_FIFO                  (1 << 0)
> >> -
> >> -/* Window colour-key control registers */
> >> -#define WKEYCON                                      (0x140) /*
> >> 6410,V210 */ -
> >> -#define WKEYCON0                             (0x00)
> >> -#define WKEYCON1                             (0x04)
> >> -
> >> -#define WxKEYCON0_KEYBL_EN                   (1 << 26)
> >> -#define WxKEYCON0_KEYEN_F                    (1 << 25)
> >> -#define WxKEYCON0_DIRCON                     (1 << 24)
> >> -#define WxKEYCON0_COMPKEY_MASK                       (0xffffff << 0)
> >> -#define WxKEYCON0_COMPKEY_SHIFT                      (0)
> >> -#define WxKEYCON0_COMPKEY_LIMIT                      (0xffffff)
> >> -#define WxKEYCON0_COMPKEY(_x)                        ((_x) << 0)
> >> -#define WxKEYCON1_COLVAL_MASK                        (0xffffff << 0)
> >> -#define WxKEYCON1_COLVAL_SHIFT                       (0)
> >> -#define WxKEYCON1_COLVAL_LIMIT                       (0xffffff)
> >> -#define WxKEYCON1_COLVAL(_x)                 ((_x) << 0)
> >> -
> >> -
> >> -/* Window blanking (MAP) */
> >> -
> >> -#define WINxMAP_MAP                          (1 << 24)
> >> -#define WINxMAP_MAP_COLOUR_MASK                      (0xffffff << 0)
> >> -#define WINxMAP_MAP_COLOUR_SHIFT             (0)
> >> -#define WINxMAP_MAP_COLOUR_LIMIT             (0xffffff)
> >> -#define WINxMAP_MAP_COLOUR(_x)                       ((_x) << 0)
> >> -
> >> -#define WPALCON_PAL_UPDATE                   (1 << 9)
> >> -#define WPALCON_W1PAL_MASK                   (0x7 << 3)
> >> -#define WPALCON_W1PAL_SHIFT                  (3)
> >> -#define WPALCON_W1PAL_25BPP_A888             (0x0 << 3)
> >> -#define WPALCON_W1PAL_24BPP                  (0x1 << 3)
> >> -#define WPALCON_W1PAL_19BPP_A666             (0x2 << 3)
> >> -#define WPALCON_W1PAL_18BPP_A665             (0x3 << 3)
> >> -#define WPALCON_W1PAL_18BPP                  (0x4 << 3)
> >> -#define WPALCON_W1PAL_16BPP_A555             (0x5 << 3)
> >> -#define WPALCON_W1PAL_16BPP_565                      (0x6 << 3)
> >> -
> >> -#define WPALCON_W0PAL_MASK                   (0x7 << 0)
> >> -#define WPALCON_W0PAL_SHIFT                  (0)
> >> -#define WPALCON_W0PAL_25BPP_A888             (0x0 << 0)
> >> -#define WPALCON_W0PAL_24BPP                  (0x1 << 0)
> >> -#define WPALCON_W0PAL_19BPP_A666             (0x2 << 0)
> >> -#define WPALCON_W0PAL_18BPP_A665             (0x3 << 0)
> >> -#define WPALCON_W0PAL_18BPP                  (0x4 << 0)
> >> -#define WPALCON_W0PAL_16BPP_A555             (0x5 << 0)
> >> -#define WPALCON_W0PAL_16BPP_565                      (0x6 << 0)
> >> -
> >> -/* Blending equation control */
> >> -#define BLENDCON                             (0x260)
> >> -#define BLENDCON_NEW_MASK                    (1 << 0)
> >> -#define BLENDCON_NEW_8BIT_ALPHA_VALUE                (1 << 0)
> >> -#define BLENDCON_NEW_4BIT_ALPHA_VALUE                (0 << 0)
> >> -
> >> diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
> >> new file mode 100644
> >> index 0000000..1b5ff4c
> >> --- /dev/null
> >> +++ b/include/video/samsung_fimd.h
> >> @@ -0,0 +1,533 @@
> >> +/* include/video/samsung_fimd.h
> >> + *
> >> + * Copyright 2008 Openmoko, Inc.
> >> + * Copyright 2008 Simtec Electronics
> >> + *      http://armlinux.simtec.co.uk/
> >> + *      Ben Dooks <ben@simtec.co.uk>
> >> + *
> >> + * S3C Platform - new-style fimd and framebuffer register definitions
> >> + *
> >> + * This is the register set for the fimd and new style framebuffer
> >> interface + * found from the S3C2443 onwards into the S3C2416, S3C2450
> >> and the + * S3C64XX series such as the S3C6400 and S3C6410.
> >> + *
> >> + * The file does not contain the cpu specific items which are based on
> >> + * whichever architecture is selected, it only contains the core of the
> >> + * register set. See <mach/regs-fb.h> to get the specifics.
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License version 2 as
> >> + * published by the Free Software Foundation.
> >> +*/
> >> +
> >> +/* VIDCON0 */
> >> +
> >> +#define VIDCON0                                      (0x00)
> >> +#define VIDCON0_INTERLACE                    (1 << 29)
> >> +#define VIDCON0_VIDOUT_MASK                  (0x3 << 26)
> >> +#define VIDCON0_VIDOUT_SHIFT                 (26)
> >> +#define VIDCON0_VIDOUT_RGB                   (0x0 << 26)
> >> +#define VIDCON0_VIDOUT_TV                    (0x1 << 26)
> >> +#define VIDCON0_VIDOUT_I80_LDI0                      (0x2 << 26)
> >> +#define VIDCON0_VIDOUT_I80_LDI1                      (0x3 << 26)
> >> +
> >> +#define VIDCON0_L1_DATA_MASK                 (0x7 << 23)
> >> +#define VIDCON0_L1_DATA_SHIFT                        (23)
> >> +#define VIDCON0_L1_DATA_16BPP                        (0x0 << 23)
> >> +#define VIDCON0_L1_DATA_18BPP16                      (0x1 << 23)
> >> +#define VIDCON0_L1_DATA_18BPP9                       (0x2 << 23)
> >> +#define VIDCON0_L1_DATA_24BPP                        (0x3 << 23)
> >> +#define VIDCON0_L1_DATA_18BPP                        (0x4 << 23)
> >> +#define VIDCON0_L1_DATA_16BPP8                       (0x5 << 23)
> >> +
> >> +#define VIDCON0_L0_DATA_MASK                 (0x7 << 20)
> >> +#define VIDCON0_L0_DATA_SHIFT                        (20)
> >> +#define VIDCON0_L0_DATA_16BPP                        (0x0 << 20)
> >> +#define VIDCON0_L0_DATA_18BPP16                      (0x1 << 20)
> >> +#define VIDCON0_L0_DATA_18BPP9                       (0x2 << 20)
> >> +#define VIDCON0_L0_DATA_24BPP                        (0x3 << 20)
> >> +#define VIDCON0_L0_DATA_18BPP                        (0x4 << 20)
> >> +#define VIDCON0_L0_DATA_16BPP8                       (0x5 << 20)
> >> +
> >> +#define VIDCON0_PNRMODE_MASK                 (0x3 << 17)
> >> +#define VIDCON0_PNRMODE_SHIFT                        (17)
> >> +#define VIDCON0_PNRMODE_RGB                  (0x0 << 17)
> >> +#define VIDCON0_PNRMODE_BGR                  (0x1 << 17)
> >> +#define VIDCON0_PNRMODE_SERIAL_RGB           (0x2 << 17)
> >> +#define VIDCON0_PNRMODE_SERIAL_BGR           (0x3 << 17)
> >> +
> >> +#define VIDCON0_CLKVALUP                     (1 << 16)
> >> +#define VIDCON0_CLKVAL_F_MASK                        (0xff << 6)
> >> +#define VIDCON0_CLKVAL_F_SHIFT                       (6)
> >> +#define VIDCON0_CLKVAL_F_LIMIT                       (0xff)
> >> +#define VIDCON0_CLKVAL_F(_x)                 ((_x) << 6)
> >> +#define VIDCON0_VLCKFREE                     (1 << 5)
> >> +#define VIDCON0_CLKDIR                               (1 << 4)
> >> +
> >> +#define VIDCON0_CLKSEL_MASK                  (0x3 << 2)
> >> +#define VIDCON0_CLKSEL_SHIFT                 (2)
> >> +#define VIDCON0_CLKSEL_HCLK                  (0x0 << 2)
> >> +#define VIDCON0_CLKSEL_LCD                   (0x1 << 2)
> >> +#define VIDCON0_CLKSEL_27M                   (0x3 << 2)
> >> +
> >> +#define VIDCON0_ENVID                                (1 << 1)
> >> +#define VIDCON0_ENVID_F                              (1 << 0)
> >> +
> >> +#define VIDCON1                                      (0x04)
> >> +#define VIDCON1_LINECNT_MASK                 (0x7ff << 16)
> >> +#define VIDCON1_LINECNT_SHIFT                        (16)
> >> +#define VIDCON1_LINECNT_GET(_v)                      (((_v) >> 16) &
> >> 0x7ff) +#define VIDCON1_VSTATUS_MASK                 (0x3 << 13)
> >> +#define VIDCON1_VSTATUS_SHIFT                        (13)
> >> +#define VIDCON1_VSTATUS_VSYNC                        (0x0 << 13)
> >> +#define VIDCON1_VSTATUS_BACKPORCH            (0x1 << 13)
> >> +#define VIDCON1_VSTATUS_ACTIVE                       (0x2 << 13)
> >> +#define VIDCON1_VSTATUS_FRONTPORCH           (0x0 << 13)
> >> +#define VIDCON1_VCLK_MASK                    (0x3 << 9)
> >> +#define VIDCON1_VCLK_HOLD                    (0x0 << 9)
> >> +#define VIDCON1_VCLK_RUN                     (0x1 << 9)
> >> +
> >> +#define VIDCON1_INV_VCLK                     (1 << 7)
> >> +#define VIDCON1_INV_HSYNC                    (1 << 6)
> >> +#define VIDCON1_INV_VSYNC                    (1 << 5)
> >> +#define VIDCON1_INV_VDEN                     (1 << 4)
> >> +
> >> +/* VIDCON2 */
> >> +
> >> +#define VIDCON2                                      (0x08)
> >> +#define VIDCON2_EN601                                (1 << 23)
> >> +#define VIDCON2_TVFMTSEL_SW                  (1 << 14)
> >> +
> >> +#define VIDCON2_TVFMTSEL1_MASK                       (0x3 << 12)
> >> +#define VIDCON2_TVFMTSEL1_SHIFT                      (12)
> >> +#define VIDCON2_TVFMTSEL1_RGB                        (0x0 << 12)
> >> +#define VIDCON2_TVFMTSEL1_YUV422             (0x1 << 12)
> >> +#define VIDCON2_TVFMTSEL1_YUV444             (0x2 << 12)
> >> +
> >> +#define VIDCON2_ORGYCbCr                     (1 << 8)
> >> +#define VIDCON2_YUVORDCrCb                   (1 << 7)
> >> +
> >> +/* PRTCON (S3C6410, S5PC100)
> >> + * Might not be present in the S3C6410 documentation,
> >> + * but tests prove it's there almost for sure; shouldn't hurt in any
> >> case.
> >> + */
> >> +#define PRTCON                                       (0x0c)
> >> +#define PRTCON_PROTECT                               (1 << 11)
> >> +
> >> +/* VIDTCON0 */
> >> +
> >> +#define VIDTCON0_VBPDE_MASK                  (0xff << 24)
> >> +#define VIDTCON0_VBPDE_SHIFT                 (24)
> >> +#define VIDTCON0_VBPDE_LIMIT                 (0xff)
> >> +#define VIDTCON0_VBPDE(_x)                   ((_x) << 24)
> >> +
> >> +#define VIDTCON0_VBPD_MASK                   (0xff << 16)
> >> +#define VIDTCON0_VBPD_SHIFT                  (16)
> >> +#define VIDTCON0_VBPD_LIMIT                  (0xff)
> >> +#define VIDTCON0_VBPD(_x)                    ((_x) << 16)
> >> +
> >> +#define VIDTCON0_VFPD_MASK                   (0xff << 8)
> >> +#define VIDTCON0_VFPD_SHIFT                  (8)
> >> +#define VIDTCON0_VFPD_LIMIT                  (0xff)
> >> +#define VIDTCON0_VFPD(_x)                    ((_x) << 8)
> >> +
> >> +#define VIDTCON0_VSPW_MASK                   (0xff << 0)
> >> +#define VIDTCON0_VSPW_SHIFT                  (0)
> >> +#define VIDTCON0_VSPW_LIMIT                  (0xff)
> >> +#define VIDTCON0_VSPW(_x)                    ((_x) << 0)
> >> +
> >> +/* VIDTCON1 */
> >> +
> >> +#define VIDTCON1_VFPDE_MASK                  (0xff << 24)
> >> +#define VIDTCON1_VFPDE_SHIFT                 (24)
> >> +#define VIDTCON1_VFPDE_LIMIT                 (0xff)
> >> +#define VIDTCON1_VFPDE(_x)                   ((_x) << 24)
> >> +
> >> +#define VIDTCON1_HBPD_MASK                   (0xff << 16)
> >> +#define VIDTCON1_HBPD_SHIFT                  (16)
> >> +#define VIDTCON1_HBPD_LIMIT                  (0xff)
> >> +#define VIDTCON1_HBPD(_x)                    ((_x) << 16)
> >> +
> >> +#define VIDTCON1_HFPD_MASK                   (0xff << 8)
> >> +#define VIDTCON1_HFPD_SHIFT                  (8)
> >> +#define VIDTCON1_HFPD_LIMIT                  (0xff)
> >> +#define VIDTCON1_HFPD(_x)                    ((_x) << 8)
> >> +
> >> +#define VIDTCON1_HSPW_MASK                   (0xff << 0)
> >> +#define VIDTCON1_HSPW_SHIFT                  (0)
> >> +#define VIDTCON1_HSPW_LIMIT                  (0xff)
> >> +#define VIDTCON1_HSPW(_x)                    ((_x) << 0)
> >> +
> >> +#define VIDTCON2                             (0x18)
> >> +#define VIDTCON2_LINEVAL_E(_x)                       ((((_x) & 0x800) >>
> >> 11) << 23) +#define VIDTCON2_LINEVAL_MASK                        (0x7ff
> >> << 11) +#define VIDTCON2_LINEVAL_SHIFT                       (11)
> >> +#define VIDTCON2_LINEVAL_LIMIT                       (0x7ff)
> >> +#define VIDTCON2_LINEVAL(_x)                 (((_x) & 0x7ff) << 11)
> >> +
> >> +#define VIDTCON2_HOZVAL_E(_x)                        ((((_x) & 0x800) >>
> >> 11) << 22) +#define VIDTCON2_HOZVAL_MASK                 (0x7ff << 0)
> >> +#define VIDTCON2_HOZVAL_SHIFT                        (0)
> >> +#define VIDTCON2_HOZVAL_LIMIT                        (0x7ff)
> >> +#define VIDTCON2_HOZVAL(_x)                  (((_x) & 0x7ff) << 0)
> >> +
> >> +/* WINCONx */
> >> +
> >> +
> >> +#define WINCONx_BITSWP                               (1 << 18)
> >> +#define WINCONx_BYTSWP                               (1 << 17)
> >> +#define WINCONx_HAWSWP                               (1 << 16)
> >> +#define WINCONx_WSWP                         (1 << 15)
> >> +#define WINCONx_BURSTLEN_MASK                        (0x3 << 9)
> >> +#define WINCONx_BURSTLEN_SHIFT                       (9)
> >> +#define WINCONx_BURSTLEN_16WORD                      (0x0 << 9)
> >> +#define WINCONx_BURSTLEN_8WORD                       (0x1 << 9)
> >> +#define WINCONx_BURSTLEN_4WORD                       (0x2 << 9)
> >> +
> >> +#define WINCONx_ENWIN                                (1 << 0)
> >> +#define WINCON0_BPPMODE_MASK                 (0xf << 2)
> >> +#define WINCON0_BPPMODE_SHIFT                        (2)
> >> +#define WINCON0_BPPMODE_1BPP                 (0x0 << 2)
> >> +#define WINCON0_BPPMODE_2BPP                 (0x1 << 2)
> >> +#define WINCON0_BPPMODE_4BPP                 (0x2 << 2)
> >> +#define WINCON0_BPPMODE_8BPP_PALETTE         (0x3 << 2)
> >> +#define WINCON0_BPPMODE_16BPP_565            (0x5 << 2)
> >> +#define WINCON0_BPPMODE_16BPP_1555           (0x7 << 2)
> >> +#define WINCON0_BPPMODE_18BPP_666            (0x8 << 2)
> >> +#define WINCON0_BPPMODE_24BPP_888            (0xb << 2)
> >> +
> >> +#define WINCON1_BLD_PIX                              (1 << 6)
> >> +
> >> +#define WINCON1_ALPHA_SEL                    (1 << 1)
> >> +#define WINCON1_BPPMODE_MASK                 (0xf << 2)
> >> +#define WINCON1_BPPMODE_SHIFT                        (2)
> >> +#define WINCON1_BPPMODE_1BPP                 (0x0 << 2)
> >> +#define WINCON1_BPPMODE_2BPP                 (0x1 << 2)
> >> +#define WINCON1_BPPMODE_4BPP                 (0x2 << 2)
> >> +#define WINCON1_BPPMODE_8BPP_PALETTE         (0x3 << 2)
> >> +#define WINCON1_BPPMODE_8BPP_1232            (0x4 << 2)
> >> +#define WINCON1_BPPMODE_16BPP_565            (0x5 << 2)
> >> +#define WINCON1_BPPMODE_16BPP_A1555          (0x6 << 2)
> >> +#define WINCON1_BPPMODE_16BPP_I1555          (0x7 << 2)
> >> +#define WINCON1_BPPMODE_18BPP_666            (0x8 << 2)
> >> +#define WINCON1_BPPMODE_18BPP_A1665          (0x9 << 2)
> >> +#define WINCON1_BPPMODE_19BPP_A1666          (0xa << 2)
> >> +#define WINCON1_BPPMODE_24BPP_888            (0xb << 2)
> >> +#define WINCON1_BPPMODE_24BPP_A1887          (0xc << 2)
> >> +#define WINCON1_BPPMODE_25BPP_A1888          (0xd << 2)
> >> +#define WINCON1_BPPMODE_28BPP_A4888          (0xd << 2)
> >> +
> >> +/* S5PV210 */
> >> +#define SHADOWCON                            (0x34)
> >> +#define SHADOWCON_WINx_PROTECT(_win)         (1 << (10 + (_win)))
> >> +/* DMA channels (all windows) */
> >> +#define SHADOWCON_CHx_ENABLE(_win)           (1 << (_win))
> >> +/* Local input channels (windows 0-2) */
> >> +#define SHADOWCON_CHx_LOCAL_ENABLE(_win)     (1 << (5 + (_win)))
> >> +
> >> +#define VIDOSDxA_TOPLEFT_X_E(_x)             ((((_x) & 0x800) >> 11) <<
> >> 23) +#define VIDOSDxA_TOPLEFT_X_MASK                      (0x7ff << 11)
> >> +#define VIDOSDxA_TOPLEFT_X_SHIFT             (11)
> >> +#define VIDOSDxA_TOPLEFT_X_LIMIT             (0x7ff)
> >> +#define VIDOSDxA_TOPLEFT_X(_x)                       (((_x) & 0x7ff) <<
> >> 11) +
> >> +#define VIDOSDxA_TOPLEFT_Y_E(_x)             ((((_x) & 0x800) >> 11) <<
> >> 22) +#define VIDOSDxA_TOPLEFT_Y_MASK                      (0x7ff << 0)
> >> +#define VIDOSDxA_TOPLEFT_Y_SHIFT             (0)
> >> +#define VIDOSDxA_TOPLEFT_Y_LIMIT             (0x7ff)
> >> +#define VIDOSDxA_TOPLEFT_Y(_x)                       (((_x) & 0x7ff) <<
> >> 0)
> >> +
> >> +#define VIDOSDxB_BOTRIGHT_X_E(_x)            ((((_x) & 0x800) >> 11) <<
> >> 23) +#define VIDOSDxB_BOTRIGHT_X_MASK             (0x7ff << 11)
> >> +#define VIDOSDxB_BOTRIGHT_X_SHIFT            (11)
> >> +#define VIDOSDxB_BOTRIGHT_X_LIMIT            (0x7ff)
> >> +#define VIDOSDxB_BOTRIGHT_X(_x)                      (((_x) & 0x7ff) <<
> >> 11) +
> >> +#define VIDOSDxB_BOTRIGHT_Y_E(_x)            ((((_x) & 0x800) >> 11) <<
> >> 22) +#define VIDOSDxB_BOTRIGHT_Y_MASK             (0x7ff << 0)
> >> +#define VIDOSDxB_BOTRIGHT_Y_SHIFT            (0)
> >> +#define VIDOSDxB_BOTRIGHT_Y_LIMIT            (0x7ff)
> >> +#define VIDOSDxB_BOTRIGHT_Y(_x)                      (((_x) & 0x7ff) <<
> >> 0)
> >> +
> >> +/* For VIDOSD[1..4]C */
> >> +#define VIDISD14C_ALPHA0_R(_x)                       ((_x) << 20)
> >> +#define VIDISD14C_ALPHA0_G_MASK                      (0xf << 16)
> >> +#define VIDISD14C_ALPHA0_G_SHIFT             (16)
> >> +#define VIDISD14C_ALPHA0_G_LIMIT             (0xf)
> >> +#define VIDISD14C_ALPHA0_G(_x)                       ((_x) << 16)
> >> +#define VIDISD14C_ALPHA0_B_MASK                      (0xf << 12)
> >> +#define VIDISD14C_ALPHA0_B_SHIFT             (12)
> >> +#define VIDISD14C_ALPHA0_B_LIMIT             (0xf)
> >> +#define VIDISD14C_ALPHA0_B(_x)                       ((_x) << 12)
> >> +#define VIDISD14C_ALPHA1_R_MASK                      (0xf << 8)
> >> +#define VIDISD14C_ALPHA1_R_SHIFT             (8)
> >> +#define VIDISD14C_ALPHA1_R_LIMIT             (0xf)
> >> +#define VIDISD14C_ALPHA1_R(_x)                       ((_x) << 8)
> >> +#define VIDISD14C_ALPHA1_G_MASK                      (0xf << 4)
> >> +#define VIDISD14C_ALPHA1_G_SHIFT             (4)
> >> +#define VIDISD14C_ALPHA1_G_LIMIT             (0xf)
> >> +#define VIDISD14C_ALPHA1_G(_x)                       ((_x) << 4)
> >> +#define VIDISD14C_ALPHA1_B_MASK                      (0xf << 0)
> >> +#define VIDISD14C_ALPHA1_B_SHIFT             (0)
> >> +#define VIDISD14C_ALPHA1_B_LIMIT             (0xf)
> >> +#define VIDISD14C_ALPHA1_B(_x)                       ((_x) << 0)
> >> +
> >> +/* Video buffer addresses */
> >> +#define VIDW_BUF_START(_buff)                        (0xA0 + ((_buff) *
> >> 8)) +#define VIDW_BUF_START1(_buff)                       (0xA4 +
> >> ((_buff) * 8)) +#define VIDW_BUF_END(_buff)                  (0xD0 +
> >> ((_buff) * 8)) +#define VIDW_BUF_END1(_buff)                 (0xD4 +
> >> ((_buff) * 8)) +#define VIDW_BUF_SIZE(_buff)                 (0x100 +
> >> ((_buff) * 4)) +
> >> +#define VIDW_BUF_SIZE_OFFSET_E(_x)           ((((_x) & 0x2000) >> 13) <<
> >> 27) +#define VIDW_BUF_SIZE_OFFSET_MASK            (0x1fff << 13)
> >> +#define VIDW_BUF_SIZE_OFFSET_SHIFT           (13)
> >> +#define VIDW_BUF_SIZE_OFFSET_LIMIT           (0x1fff)
> >> +#define VIDW_BUF_SIZE_OFFSET(_x)             (((_x) & 0x1fff) << 13)
> >> +
> >> +#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)                ((((_x) & 0x2000)
> >> >> 13) << 26) +#define VIDW_BUF_SIZE_PAGEWIDTH_MASK         (0x1fff <<
> >> 0)
> >> +#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT                (0)
> >> +#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT                (0x1fff)
> >> +#define VIDW_BUF_SIZE_PAGEWIDTH(_x)          (((_x) & 0x1fff) << 0)
> >> +
> >> +/* Interrupt controls and status */
> >> +
> >> +#define VIDINTCON0_FIFOINTERVAL_MASK         (0x3f << 20)
> >> +#define VIDINTCON0_FIFOINTERVAL_SHIFT                (20)
> >> +#define VIDINTCON0_FIFOINTERVAL_LIMIT                (0x3f)
> >> +#define VIDINTCON0_FIFOINTERVAL(_x)          ((_x) << 20)
> >> +
> >> +#define VIDINTCON0_INT_SYSMAINCON            (1 << 19)
> >> +#define VIDINTCON0_INT_SYSSUBCON             (1 << 18)
> >> +#define VIDINTCON0_INT_I80IFDONE             (1 << 17)
> >> +
> >> +#define VIDINTCON0_FRAMESEL0_MASK            (0x3 << 15)
> >> +#define VIDINTCON0_FRAMESEL0_SHIFT           (15)
> >> +#define VIDINTCON0_FRAMESEL0_BACKPORCH               (0x0 << 15)
> >> +#define VIDINTCON0_FRAMESEL0_VSYNC           (0x1 << 15)
> >> +#define VIDINTCON0_FRAMESEL0_ACTIVE          (0x2 << 15)
> >> +#define VIDINTCON0_FRAMESEL0_FRONTPORCH              (0x3 << 15)
> >> +
> >> +#define VIDINTCON0_FRAMESEL1                 (1 << 13)
> >> +#define VIDINTCON0_FRAMESEL1_MASK            (0x3 << 13)
> >> +#define VIDINTCON0_FRAMESEL1_NONE            (0x0 << 13)
> >> +#define VIDINTCON0_FRAMESEL1_BACKPORCH               (0x1 << 13)
> >> +#define VIDINTCON0_FRAMESEL1_VSYNC           (0x2 << 13)
> >> +#define VIDINTCON0_FRAMESEL1_FRONTPORCH              (0x3 << 13)
> >> +
> >> +#define VIDINTCON0_INT_FRAME                 (1 << 12)
> >> +#define VIDINTCON0_FIFIOSEL_MASK             (0x7f << 5)
> >> +#define VIDINTCON0_FIFIOSEL_SHIFT            (5)
> >> +#define VIDINTCON0_FIFIOSEL_WINDOW0          (0x1 << 5)
> >> +#define VIDINTCON0_FIFIOSEL_WINDOW1          (0x2 << 5)
> >> +
> >> +#define VIDINTCON0_FIFOLEVEL_MASK            (0x7 << 2)
> >> +#define VIDINTCON0_FIFOLEVEL_SHIFT           (2)
> >> +#define VIDINTCON0_FIFOLEVEL_TO25PC          (0x0 << 2)
> >> +#define VIDINTCON0_FIFOLEVEL_TO50PC          (0x1 << 2)
> >> +#define VIDINTCON0_FIFOLEVEL_TO75PC          (0x2 << 2)
> >> +#define VIDINTCON0_FIFOLEVEL_EMPTY           (0x3 << 2)
> >> +#define VIDINTCON0_FIFOLEVEL_FULL            (0x4 << 2)
> >> +
> >> +#define VIDINTCON0_INT_FIFO_MASK             (0x3 << 0)
> >> +#define VIDINTCON0_INT_FIFO_SHIFT            (0)
> >> +#define VIDINTCON0_INT_ENABLE                        (1 << 0)
> >> +
> >> +#define VIDINTCON1                           (0x134)
> >> +#define VIDINTCON1_INT_I180                  (1 << 2)
> >> +#define VIDINTCON1_INT_FRAME                 (1 << 1)
> >> +#define VIDINTCON1_INT_FIFO                  (1 << 0)
> >> +
> >> +/* Window colour-key control registers */
> >> +#define WKEYCON                                      (0x140) /*
> >> 6410,V210 */ +
> >> +#define WKEYCON0                             (0x00)
> >> +#define WKEYCON1                             (0x04)
> >> +
> >> +#define WxKEYCON0_KEYBL_EN                   (1 << 26)
> >> +#define WxKEYCON0_KEYEN_F                    (1 << 25)
> >> +#define WxKEYCON0_DIRCON                     (1 << 24)
> >> +#define WxKEYCON0_COMPKEY_MASK                       (0xffffff << 0)
> >> +#define WxKEYCON0_COMPKEY_SHIFT                      (0)
> >> +#define WxKEYCON0_COMPKEY_LIMIT                      (0xffffff)
> >> +#define WxKEYCON0_COMPKEY(_x)                        ((_x) << 0)
> >> +#define WxKEYCON1_COLVAL_MASK                        (0xffffff << 0)
> >> +#define WxKEYCON1_COLVAL_SHIFT                       (0)
> >> +#define WxKEYCON1_COLVAL_LIMIT                       (0xffffff)
> >> +#define WxKEYCON1_COLVAL(_x)                 ((_x) << 0)
> >> +
> >> +
> >> +/* Window blanking (MAP) */
> >> +
> >> +#define WINxMAP_MAP                          (1 << 24)
> >> +#define WINxMAP_MAP_COLOUR_MASK                      (0xffffff << 0)
> >> +#define WINxMAP_MAP_COLOUR_SHIFT             (0)
> >> +#define WINxMAP_MAP_COLOUR_LIMIT             (0xffffff)
> >> +#define WINxMAP_MAP_COLOUR(_x)                       ((_x) << 0)
> >> +
> >> +#define WPALCON_PAL_UPDATE                   (1 << 9)
> >> +#define WPALCON_W1PAL_MASK                   (0x7 << 3)
> >> +#define WPALCON_W1PAL_SHIFT                  (3)
> >> +#define WPALCON_W1PAL_25BPP_A888             (0x0 << 3)
> >> +#define WPALCON_W1PAL_24BPP                  (0x1 << 3)
> >> +#define WPALCON_W1PAL_19BPP_A666             (0x2 << 3)
> >> +#define WPALCON_W1PAL_18BPP_A665             (0x3 << 3)
> >> +#define WPALCON_W1PAL_18BPP                  (0x4 << 3)
> >> +#define WPALCON_W1PAL_16BPP_A555             (0x5 << 3)
> >> +#define WPALCON_W1PAL_16BPP_565                      (0x6 << 3)
> >> +
> >> +#define WPALCON_W0PAL_MASK                   (0x7 << 0)
> >> +#define WPALCON_W0PAL_SHIFT                  (0)
> >> +#define WPALCON_W0PAL_25BPP_A888             (0x0 << 0)
> >> +#define WPALCON_W0PAL_24BPP                  (0x1 << 0)
> >> +#define WPALCON_W0PAL_19BPP_A666             (0x2 << 0)
> >> +#define WPALCON_W0PAL_18BPP_A665             (0x3 << 0)
> >> +#define WPALCON_W0PAL_18BPP                  (0x4 << 0)
> >> +#define WPALCON_W0PAL_16BPP_A555             (0x5 << 0)
> >> +#define WPALCON_W0PAL_16BPP_565                      (0x6 << 0)
> >> +
> >> +/* Blending equation control */
> >> +#define BLENDCON                             (0x260)
> >> +#define BLENDCON_NEW_MASK                    (1 << 0)
> >> +#define BLENDCON_NEW_8BIT_ALPHA_VALUE                (1 << 0)
> >> +#define BLENDCON_NEW_4BIT_ALPHA_VALUE                (0 << 0)
> >> +
> >> +#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
> >> +#define VIDCON1_FSTATUS_EVEN (1 << 15)
> >> +
> >> +/* Video timing controls */
> >> +#define VIDTCON0                             (0x10)
> >> +#define VIDTCON1                             (0x14)
> >> +#define VIDTCON2                             (0x18)
> >> +
> >> +/* Window position controls */
> >> +
> >> +#define WINCON(_win)                         (0x20 + ((_win) * 4))
> >> +
> >> +/* OSD1 and OSD4 do not have register D */
> >> +
> >> +#define VIDOSD_BASE                          (0x40)
> >> +
> >> +#define VIDINTCON0                           (0x130)
> >> +
> >> +/* WINCONx */
> >> +
> >> +#define WINCONx_CSCWIDTH_MASK                        (0x3 << 26)
> >> +#define WINCONx_CSCWIDTH_SHIFT                       (26)
> >> +#define WINCONx_CSCWIDTH_WIDE                        (0x0 << 26)
> >> +#define WINCONx_CSCWIDTH_NARROW                      (0x3 << 26)
> >> +
> >> +#define WINCONx_ENLOCAL                              (1 << 22)
> >> +#define WINCONx_BUFSTATUS                    (1 << 21)
> >> +#define WINCONx_BUFSEL                               (1 << 20)
> >> +#define WINCONx_BUFAUTOEN                    (1 << 19)
> >> +#define WINCONx_YCbCr                                (1 << 13)
> >> +
> >> +#define WINCON1_LOCALSEL_CAMIF                       (1 << 23)
> >> +
> >> +#define WINCON2_LOCALSEL_CAMIF                       (1 << 23)
> >> +#define WINCON2_BLD_PIX                              (1 << 6)
> >> +
> >> +#define WINCON2_ALPHA_SEL                    (1 << 1)
> >> +#define WINCON2_BPPMODE_MASK                 (0xf << 2)
> >> +#define WINCON2_BPPMODE_SHIFT                        (2)
> >> +#define WINCON2_BPPMODE_1BPP                 (0x0 << 2)
> >> +#define WINCON2_BPPMODE_2BPP                 (0x1 << 2)
> >> +#define WINCON2_BPPMODE_4BPP                 (0x2 << 2)
> >> +#define WINCON2_BPPMODE_8BPP_1232            (0x4 << 2)
> >> +#define WINCON2_BPPMODE_16BPP_565            (0x5 << 2)
> >> +#define WINCON2_BPPMODE_16BPP_A1555          (0x6 << 2)
> >> +#define WINCON2_BPPMODE_16BPP_I1555          (0x7 << 2)
> >> +#define WINCON2_BPPMODE_18BPP_666            (0x8 << 2)
> >> +#define WINCON2_BPPMODE_18BPP_A1665          (0x9 << 2)
> >> +#define WINCON2_BPPMODE_19BPP_A1666          (0xa << 2)
> >> +#define WINCON2_BPPMODE_24BPP_888            (0xb << 2)
> >> +#define WINCON2_BPPMODE_24BPP_A1887          (0xc << 2)
> >> +#define WINCON2_BPPMODE_25BPP_A1888          (0xd << 2)
> >> +#define WINCON2_BPPMODE_28BPP_A4888          (0xd << 2)
> >> +
> >> +#define WINCON3_BLD_PIX                              (1 << 6)
> >> +
> >> +#define WINCON3_ALPHA_SEL                    (1 << 1)
> >> +#define WINCON3_BPPMODE_MASK                 (0xf << 2)
> >> +#define WINCON3_BPPMODE_SHIFT                        (2)
> >> +#define WINCON3_BPPMODE_1BPP                 (0x0 << 2)
> >> +#define WINCON3_BPPMODE_2BPP                 (0x1 << 2)
> >> +#define WINCON3_BPPMODE_4BPP                 (0x2 << 2)
> >> +#define WINCON3_BPPMODE_16BPP_565            (0x5 << 2)
> >> +#define WINCON3_BPPMODE_16BPP_A1555          (0x6 << 2)
> >> +#define WINCON3_BPPMODE_16BPP_I1555          (0x7 << 2)
> >> +#define WINCON3_BPPMODE_18BPP_666            (0x8 << 2)
> >> +#define WINCON3_BPPMODE_18BPP_A1665          (0x9 << 2)
> >> +#define WINCON3_BPPMODE_19BPP_A1666          (0xa << 2)
> >> +#define WINCON3_BPPMODE_24BPP_888            (0xb << 2)
> >> +#define WINCON3_BPPMODE_24BPP_A1887          (0xc << 2)
> >> +#define WINCON3_BPPMODE_25BPP_A1888          (0xd << 2)
> >> +#define WINCON3_BPPMODE_28BPP_A4888          (0xd << 2)
> >> +
> >> +#define VIDINTCON0_FIFIOSEL_WINDOW2          (0x10 << 5)
> >> +#define VIDINTCON0_FIFIOSEL_WINDOW3          (0x20 << 5)
> >> +#define VIDINTCON0_FIFIOSEL_WINDOW4          (0x40 << 5)
> >> +
> >> +#define DITHMODE                             (0x170)
> >> +#define WINxMAP(_win)                                (0x180 + ((_win) *
> >> 4)) +
> >> +
> >> +#define DITHMODE_R_POS_MASK                  (0x3 << 5)
> >> +#define DITHMODE_R_POS_SHIFT                 (5)
> >> +#define DITHMODE_R_POS_8BIT                  (0x0 << 5)
> >> +#define DITHMODE_R_POS_6BIT                  (0x1 << 5)
> >> +#define DITHMODE_R_POS_5BIT                  (0x2 << 5)
> >> +
> >> +#define DITHMODE_G_POS_MASK                  (0x3 << 3)
> >> +#define DITHMODE_G_POS_SHIFT                 (3)
> >> +#define DITHMODE_G_POS_8BIT                  (0x0 << 3)
> >> +#define DITHMODE_G_POS_6BIT                  (0x1 << 3)
> >> +#define DITHMODE_G_POS_5BIT                  (0x2 << 3)
> >> +
> >> +#define DITHMODE_B_POS_MASK                  (0x3 << 1)
> >> +#define DITHMODE_B_POS_SHIFT                 (1)
> >> +#define DITHMODE_B_POS_8BIT                  (0x0 << 1)
> >> +#define DITHMODE_B_POS_6BIT                  (0x1 << 1)
> >> +#define DITHMODE_B_POS_5BIT                  (0x2 << 1)
> >> +
> >> +#define DITHMODE_DITH_EN                     (1 << 0)
> >> +
> >> +#define WPALCON                                      (0x1A0)
> >> +
> >> +/* Palette control */
> >> +/* Note for S5PC100: you can still use those macros on WPALCON (aka
> >> WPALCON_L), + * but make sure that WPALCON_H W2PAL-W4PAL entries are
> >> zeroed out */ +#define WPALCON_W4PAL_16BPP_A555             (1 << 8)
> >> +#define WPALCON_W3PAL_16BPP_A555             (1 << 7)
> >> +#define WPALCON_W2PAL_16BPP_A555             (1 << 6)
> >> +
> >> +
> >> +/* Notes on per-window bpp settings
> >> + *
> >> + * Value     Win0     Win1     Win2     Win3     Win 4
> >> + * 0000              1(P)     1(P)     1(P)     1(P)     1(P)
> >> + * 0001              2(P)     2(P)     2(P)     2(P)     2(P)
> >> + * 0010              4(P)     4(P)     4(P)     4(P)     -none-
> >> + * 0011              8(P)     8(P)     -none-   -none-   -none-
> >> + * 0100              -none-   8(A232)  8(A232)  -none-   -none-
> >> + * 0101              16(565)  16(565)  16(565)  16(565)   16(565)
> >> + * 0110              -none-   16(A555) 16(A555) 16(A555)  16(A555)
> >> + * 0111              16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
> >> + * 1000              18(666)  18(666)  18(666)  18(666)   18(666)
> >> + * 1001              -none-   18(A665) 18(A665) 18(A665)  16(A665)
> >> + * 1010              -none-   19(A666) 19(A666) 19(A666)  19(A666)
> >> + * 1011              24(888)  24(888)  24(888)  24(888)   24(888)
> >> + * 1100              -none-   24(A887) 24(A887) 24(A887)  24(A887)
> >> + * 1101              -none-   25(A888) 25(A888) 25(A888)  25(A888)
> >> + * 1110              -none-   -none-   -none-   -none-    -none-
> >> + * 1111              -none-   -none-   -none-   -none-    -none-
> >> +*/
> >> +
> >> +/*FIMD V8 REG OFFSET */
> >> +#define FIMD_V8_VIDTCON0     (0x20010)
> >> +#define FIMD_V8_VIDTCON1     (0x20014)
> >> +#define FIMD_V8_VIDTCON2     (0x20018)
> >> +#define FIMD_V8_VIDTCON3     (0x2001C)
> >> +#define FIMD_V8_VIDCON1              (0x20004)
> > 
> > CC'ed Marek.
> > 
> > To Leela Krishna Amudala,
> > 
> > Don't add these definitions for FIMD_V8_xxx registers, which are not
> > related to current "regs-fb-v4.h and regs-fb.h". Just "move" and "merge"
> > regs-fb-v4.h and regs-fb.h to one header file, not "add" new definitions.
> > If you want to add these definitions, please make new patch for this.
> Will do it in the suggested way,
> 
> > Also, "#define FIMD_V8_xxx" is ugly.
> > I think that there is better way.
> > Please, find other way.
> 
> I used FIMD_V8_xxx instead of  EXYNOS5_FIMD_*, because in future,
> there is a possibility that version 8 FIMD can be used in other
> application processors also.
> Thanks for reviewing the patch.

Possibly a simple "#define REGNAME_V8 ..." would be better?

Best regards,
Tomasz Figa

> 
> Best Wishes,
> Leela Krishna.
> 
> >> --
> >> 1.7.0.4
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc"
> in the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] Fix newport con crashes
From: Ralf Baechle @ 2012-07-30 13:34 UTC (permalink / raw)
  To: Thomas Bogendoerfer; +Cc: linux-mips, linux-fbdev, FlorianSchandinat
In-Reply-To: <20120730105416.DBB961D1CF@solo.franken.de>

On Mon, Jul 30, 2012 at 12:54:16PM +0200, Thomas Bogendoerfer wrote:

> Because of commit e84de0c61905030a0fe66b7210b6f1bb7c3e1eab
> [MIPS: GIO bus support for SGI IP22/28] newport con is now taking over
> console from dummy con, therefore it's necessary to resize the VC to
> the correct size to avoid crashes and garbage on console
> 
> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

I've applied your patch to master and the affected -stable branches of the
lmo git tree.

Florian, since this is a driver specific to certain MIPS platforms I'd like
to merge it through the MIPS tree with your ack, if that's ok?

Thanks folks,

  Ralf

^ permalink raw reply

* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Thierry Reding @ 2012-07-30 11:33 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Stephen Warren,
	Greg Kroah-Hartman, Mark Brown,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1343390750-3642-2-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

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

On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
> 
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.
> 
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  Documentation/power/power_seq.txt | 120 +++++++++++++++
>  drivers/base/Kconfig              |   4 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>  include/linux/power_seq.h         | 139 ++++++++++++++++++
>  5 files changed, 564 insertions(+)
>  create mode 100644 Documentation/power/power_seq.txt
>  create mode 100644 drivers/base/power_seq.c
>  create mode 100644 include/linux/power_seq.h
> 
> diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
> new file mode 100644
> index 0000000..aa2ceb5
> --- /dev/null
> +++ b/Documentation/power/power_seq.txt
> @@ -0,0 +1,120 @@
> +Runtime Interpreted Power Sequences
> +-----------------------------------
> +
> +Problem
> +-------
> +One very common board-dependent code is the out-of-driver code that is used to
> +turn a device on or off. For instance, SoC boards very commonly use a GPIO
> +(abstracted to a regulator or not) to control the power supply of a backlight,
> +disabling it when the backlight is not used in order to save power. The GPIO
> +that should be used, however, as well as the exact power sequence that may
> +involve different resources, is board-dependent and thus unknown of the driver.
> +
> +This has been addressed so far by using hooks in the device's platform data that
> +are called whenever the state of the device might reflect a power change. This
> +approach, however, introduces board-dependant code into the kernel and is not
> +compatible with the device tree.
> +
> +The Runtime Interpreted Power Sequences (or power sequences for short) aim at
> +turning this code into platform data or device tree nodes. Power sequences are
> +described using a simple format and run by a simple interpreter whenever needed.
> +This allows to remove the callback mechanism and makes the kernel less
> +board-dependant.
> +
> +Sequences Format
> +----------------
> +Power sequences are a series of sequential steps during which an action is
> +performed on a resource. The supported resources so far are:
> +- GPIOs
> +- Regulators
> +- PWMs
> +
> +Each step designates a resource and the following parameters:
> +- Whether the step should enable or disable the resource,
> +- Delay to wait before performing the action,
> +- Delay to wait after performing the action.
> +
> +Both new resources and parameters can be introduced, but the goal is of course
> +to keep things as simple and compact as possible.
> +
> +The platform data is a simple array of platform_power_seq_step instances, each
> +instance describing a step. The type as well as one of id or gpio members
> +(depending on the type) must be specified. The last step must be of type
> +POWER_SEQ_STOP. Regulator and PWM resources are identified by name. GPIO are
> +identified by number. For example, the following sequence will turn on the
> +"power" regulator of the device, wait 10ms, and set GPIO number 110 to 1:
> +
> +struct platform_power_seq_step power_on_seq[] = {
> +	{
> +		.type = POWER_SEQ_REGULATOR,
> +		.id = "power",
> +		.params = {
> +			.enable = 1,
> +			.post_delay = 10,
> +		},
> +	},
> +	{
> +		.type = POWER_SEQ_GPIO,
> +		.gpio = 110,
> +		.params = {
> +			.enable = 1,
> +		},
> +	},
> +	{
> +		.type = POWER_SEQ_STOP,
> +	},
> +};
> +
> +Usage by Drivers and Resources Management
> +-----------------------------------------
> +Power sequences make use of resources that must be properly allocated and
> +managed. The power_seq_build() function takes care of resolving the resources as
> +they are met in the sequence and to allocate them if needed:
> +
> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> +			   platform_power_seq *pseq);
> +
> +You will need an instance of power_seq_resources to keep track of the resources
> +that are already allocated. On success, the function returns a devm allocated
> +resolved sequence that is ready to be passed to power_seq_run(). In case of
> +failure, and error code is returned.

I don't quite understand why the struct power_seq_resources is needed.
Can this not be stored within power_seq?

> +
> +A resolved power sequence returned by power_seq_build can be run by
> +power_run_run():
> +
> +int power_seq_run(struct device *dev, power_seq *seq);

Why is the struct device required here? It already is passed during the
call to pwm_seq_build(), so perhaps you should keep a reference to it
within struct power_seq?

> +
> +It returns 0 if the sequence has successfully been run, or an error code if a
> +problem occured.
> +
> +Finally, some resources that cannot be allocated through devm need to be freed
> +manually. Therefore, be sure to call power_seq_free_resources() in your device
> +remove function:
> +
> +void power_seq_free_resources(power_seq_resources *ress);

Could this not also be handled by a managed version? If a power_seq is
always managed, then I would assume that it also takes care of freeing
the resources, even if the resources have no managed equivalents.

Perhaps it would also make sense to provide non-managed version of these
functions. I think that would make the managed versions easier and more
canonical to implement.

> +
> +Device tree
> +-----------
> +All the same, power sequences can be encoded as device tree nodes. The following
> +properties and nodes are equivalent to the platform data defined previously:
> +
> +		power-supply = <&mydevice_reg>;
> +		enable-gpio = <&gpio 6 0>;
> +
> +		power-on-sequence {
> +			regulator@0 {
> +				id = "power";
> +				enable;
> +				post-delay = <10>;
> +			};
> +			gpio@1 {
> +				id = "enable-gpio";
> +				enable;
> +			};
> +		};
> +
> +Note that first, the phandles of the regulator and gpio used in the sequences
> +are defined as properties. Then the sequence references them through the id
> +property of every step. The name of sub-properties defines the type of the step.
> +Valid names are "regulator", "gpio" and "pwm". Steps must be numbered
> +sequentially.

I think there has been quite some discussion regarding the naming of
subnodes and the conclusion seems to have been to name them uniformly
after what they represent. As such the power-on-sequence subnodes should
be called step@0, step@1, etc. However, that will require the addition
of a property to define the type of resource.

Also, is there some way we can make the id property for GPIOs not
require the -gpio suffix? If the resource type is already GPIO, then it
seems redundant to add -gpio to the ID.

> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index 08b4c52..65bebfe 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -282,4 +282,8 @@ config CMA_AREAS
>  
>  endif
>  
> +config POWER_SEQ
> +	bool
> +	default n
> +

"default n" is already the default, so you can drop that line.

>  endmenu
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 5aa2d70..4c498c1 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
>  ifeq ($(CONFIG_SYSFS),y)
>  obj-$(CONFIG_MODULES)	+= module.o
>  endif
> +obj-$(CONFIG_POWER_SEQ)	+= power_seq.o
>  obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
>  obj-$(CONFIG_REGMAP)	+= regmap/
>  obj-$(CONFIG_SOC_BUS) += soc.o
> diff --git a/drivers/base/power_seq.c b/drivers/base/power_seq.c
> new file mode 100644
> index 0000000..6ccefa1
> --- /dev/null
> +++ b/drivers/base/power_seq.c
> @@ -0,0 +1,300 @@
> +/*
> + * power_seq.c - A simple power sequence interpreter for platform devices
> + *               and device tree.
> + *
> + * Author: Alexandre Courbot <acourbot@nvidia.com>
> + *
> + * Copyright (c) 2012 NVIDIA Corporation.
> + *
> + * 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; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + */
> +
> +#include <linux/power_seq.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/gpio.h>
> +
> +#ifdef CONFIG_OF
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
> +#endif

I think you don't need the CONFIG_OF guard around these. Both of.h and
of_gpio.h can be included unconditionally and actually contain dummy
definitions for the public functions in the !OF case.

> +
> +static int power_seq_step_run(struct power_seq_step *step)
> +{
> +	int err = 0;
> +
> +	if (step->params.pre_delay)
> +		mdelay(step->params.pre_delay);
> +
> +	switch (step->resource->type) {
> +#ifdef CONFIG_REGULATOR
> +	case POWER_SEQ_REGULATOR:
> +		if (step->params.enable)
> +			err = regulator_enable(step->resource->regulator);
> +		else
> +			err = regulator_disable(step->resource->regulator);
> +		break;
> +#endif
> +#ifdef CONFIG_PWM
> +	case POWER_SEQ_PWM:
> +		if (step->params.enable)
> +			err = pwm_enable(step->resource->pwm);
> +		else
> +			pwm_disable(step->resource->pwm);
> +		break;
> +#endif
> +#ifdef CONFIG_GPIOLIB
> +	case POWER_SEQ_GPIO:
> +		gpio_set_value_cansleep(step->resource->gpio,
> +					step->params.enable);
> +		break;
> +#endif

This kind of #ifdef'ery is quite ugly. I don't know if adding separate
*_run() functions for each type of resource would be any better, though.
Alternatively, maybe POWER_SEQ should depend on the REGULATOR, PWM and
GPIOLIB symbols to side-step the issue completely?

> +	/*
> +	 * should never happen unless the sequence includes a step which
> +	 * type does not have support compiled in
> +	 */
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (err < 0)
> +		return err;
> +
> +	if (step->params.post_delay)
> +		mdelay(step->params.post_delay);
> +
> +	return 0;
> +}
> +
> +int power_seq_run(struct device *dev, power_seq *seq)
> +{
> +	int err;
> +
> +	if (!seq) return 0;

I don't think this is acceptable according to the coding style. Also,
perhaps returning -EINVAL would be more meaningful?

> +
> +	while (seq->resource) {

Perhaps this should check for POWER_SEQ_STOP instead?

> +		if ((err = power_seq_step_run(seq++))) {
> +			dev_err(dev, "error %d while running power sequence!\n",
> +				err);

For this kind of diagnostics it could be useful to have a name
associated with the power sequence. But I'm not sure that making the
power sequence code output an error here is the best solution. I find it
to be annoying when core code starts outputting too many error codes. In
this case it's particularily easy to catch the errors in the caller.

> +			return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(power_seq_run);
> +
> +#ifdef CONFIG_OF
> +static int of_parse_power_seq_step(struct device *dev, struct device_node *node,
> +				   struct platform_power_seq_step *step)
> +{
> +	if (of_property_read_string(node, "id", &step->id)) {
> +		dev_err(dev, "missing id property!\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!strcmp(node->name, "regulator")) {
> +		step->type = POWER_SEQ_REGULATOR;
> +#ifdef CONFIG_OF_GPIO
> +	} else if (!strcmp(node->name, "gpio")) {
> +		int gpio;
> +
> +		step->type = POWER_SEQ_GPIO;
> +		gpio = of_get_named_gpio(dev->of_node, step->id, 0);
> +		if (gpio < 0) {
> +			dev_err(dev, "cannot resolve gpio \"%s\"\n", step->id);
> +			return gpio;
> +		}
> +		step->gpio = gpio;
> +#endif /* CONFIG_OF_GPIO */
> +	} else if (!strcmp(node->name, "pwm")) {
> +		step->type = POWER_SEQ_PWM;
> +	} else {
> +		dev_err(dev, "invalid power seq step type!\n");
> +		return -EINVAL;
> +	}
> +
> +	if (of_find_property(node, "enable", NULL)) {
> +		step->params.enable = 1;
> +	} else if (!of_find_property(node, "disable", NULL)) {
> +		dev_err(dev, "missing enable or disable property!\n");
> +		return -EINVAL;
> +	}
> +
> +	of_property_read_u32(node, "pre-delay", &step->params.pre_delay);
> +	of_property_read_u32(node, "post-delay", &step->params.post_delay);
> +
> +	return 0;
> +}
> +
> +platform_power_seq *of_parse_power_seq(struct device *dev,
> +				       struct device_node *node)
> +{
> +	struct device_node *child = NULL;
> +	platform_power_seq *ret;
> +	int cpt = 0;
> +	int err;
> +
> +	if (!node) return NULL;

Again, this should probably be split across two lines.

> +
> +	while ((child = of_get_next_child(node, child)))
> +		cpt++;

for_each_child_of_node()?

> +
> +	/* allocate one more step to signal end of sequence */
> +	ret = devm_kzalloc(dev, sizeof(*ret) * (cpt + 1), GFP_KERNEL);
> +	if (!ret)
> +		return ERR_PTR(-ENOMEM);
> +
> +	cpt = 0;
> +	while ((child = of_get_next_child(node, child))) {

Here as well.

> +		if ((err = of_parse_power_seq_step(dev, child, &ret[cpt++])))
> +			return ERR_PTR(err);
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(of_parse_power_seq);
> +#endif /* CONFIG_OF */
> +
> +static
> +struct power_seq_resource * power_seq_find_resource(power_seq_resources *ress,
> +					struct platform_power_seq_step *res)
> +{
> +	struct power_seq_resource *step;
> +
> +	list_for_each_entry(step, ress, list) {
> +		if (step->type != res->type) continue;
> +		switch (res->type) {
> +		case POWER_SEQ_GPIO:
> +			if (step->gpio == res->gpio)
> +				return step;
> +			break;
> +		default:
> +			if (!strcmp(step->id, res->id))
> +				return step;
> +			break;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static int power_seq_allocate_resource(struct device *dev,
> +				       struct power_seq_resource *res)
> +{
> +	int err;
> +
> +	switch (res->type) {
> +#ifdef CONFIG_REGULATOR
> +	case POWER_SEQ_REGULATOR:
> +		res->regulator = devm_regulator_get(dev, res->id);
> +		if (IS_ERR(res->regulator)) {
> +			dev_err(dev, "cannot get regulator \"%s\"\n", res->id);
> +			return PTR_ERR(res->regulator);
> +		}
> +		break;
> +#endif
> +#ifdef CONFIG_PWM
> +	case POWER_SEQ_PWM:
> +		res->pwm = pwm_get(dev, res->id);
> +		if (IS_ERR(res->pwm)) {
> +			dev_err(dev, "cannot get pwm \"%s\"\n", res->id);
> +			return PTR_ERR(res->pwm);
> +		}
> +		break;
> +#endif
> +#ifdef CONFIG_GPIOLIB
> +	case POWER_SEQ_GPIO:
> +		err = devm_gpio_request_one(dev, res->gpio, GPIOF_OUT_INIT_HIGH,
> +					    "backlight_gpio");
> +		if (err) {
> +			dev_err(dev, "cannot get gpio %d\n", res->gpio);
> +			return err;
> +		}
> +		break;
> +#endif
> +	default:
> +		dev_err(dev, "invalid resource type %d\n", res->type);
> +		return -EINVAL;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> +			   platform_power_seq *pseq)
> +{
> +	struct power_seq_step *seq = NULL, *ret;
> +	struct power_seq_resource *res;
> +	int cpt, err;
> +
> +	/* first pass to count the number of steps to allocate */
> +	for (cpt = 0; pseq[cpt].type != POWER_SEQ_STOP; cpt++);

Wouldn't it be easier to pass around the number of steps in the sequence
instead of having to count in various places? This would be more along
the lines of how struct platform_device defines associated resources.

> +
> +	if (!cpt)
> +		return seq;

Perhaps this should return an error-code as well? I find it nice to not
have to handle NULL specially when using ERR_PTR et al.

> +
> +	/* 1 more for the STOP step */
> +	ret = seq = devm_kzalloc(dev, sizeof(*seq) * (cpt + 1), GFP_KERNEL);
> +	if (!seq)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (; pseq->type != POWER_SEQ_STOP; pseq++, seq++) {
> +		/* create resource node if not referenced already */
> +		if (!(res = power_seq_find_resource(ress, pseq))) {
> +			res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
> +			if (!res)
> +				return ERR_PTR(-ENOMEM);
> +			res->type = pseq->type;
> +
> +			if (res->type == POWER_SEQ_GPIO)
> +				res->gpio = pseq->gpio;
> +			else
> +				res->id = pseq->id;
> +
> +			if ((err = power_seq_allocate_resource(dev, res)) < 0)
> +				return ERR_PTR(err);
> +
> +			list_add(&res->list, ress);
> +		}
> +		seq->resource = res;
> +		memcpy(&seq->params, &pseq->params, sizeof(seq->params));
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(power_seq_build);
> +
> +void power_seq_free_resources(power_seq_resources *ress) {

The brace needs to go on a line by itself.

> +	struct power_seq_resource *res;
> +
> +#ifdef CONFIG_PWM
> +	list_for_each_entry(res, ress, list) {
> +		if (res->type == POWER_SEQ_PWM)
> +			pwm_put(res->pwm);
> +	}
> +#endif
> +}
> +EXPORT_SYMBOL_GPL(power_seq_free_resources);
> +
> +MODULE_AUTHOR("Alexandre Courbot <acourbot@nvidia.com>");
> +MODULE_DESCRIPTION("Runtime Interpreted Power Sequences");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/power_seq.h b/include/linux/power_seq.h
> new file mode 100644
> index 0000000..da0593a
> --- /dev/null
> +++ b/include/linux/power_seq.h
> @@ -0,0 +1,139 @@
> +/*
> + * power_seq.h
> + *
> + * Simple interpreter for defining power sequences as platform data or device
> + * tree properties. Initially designed for use with backlight drivers.
> + *
> + * Power sequences are designed to replace the callbacks typically used in
> + * board-specific files that implement board-specific power sequences of devices
> + * such as backlights. A power sequence is an array of resources (which can a
> + * regulator, a GPIO, a PWM, ...) with an action to perform on it (enable or
> + * disable) and optional pre and post step delays. By having them interpreted
> + * instead of arbitrarily executed, it is possible to describe these in the
> + * device tree and thus remove board-specific code from the kernel.
> + *
> + * Author: Alexandre Courbot <acourbot@nvidia.com>
> + *
> + * Copyright (c) 2012 NVIDIA Corporation.
> + *
> + * 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; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + */
> +
> +#ifndef __LINUX_POWER_SEQ_H
> +#define __LINUX_POWER_SEQ_H
> +
> +#include <linux/types.h>
> +
> +struct device;
> +struct regulator;
> +struct pwm_device;
> +struct device_node;
> +
> +/**
> + * The different kinds of resources that can be controlled during the sequences.
> + */
> +typedef enum {
> +	POWER_SEQ_STOP = 0,
> +	POWER_SEQ_REGULATOR,
> +	POWER_SEQ_PWM,
> +	POWER_SEQ_GPIO,
> +	POWER_SEQ_MAX,
> +} power_res_type;

Maybe the prefix power_seq should be used here as well, so:
power_seq_res_type.

> +
> +struct power_seq_resource {
> +	power_res_type type;
> +	/* name to resolve for resources with a name (regulator, pwm) */
> +	const char *id;
> +	/* resolved resource */
> +	union {
> +		struct regulator *regulator;
> +		struct pwm_device *pwm;
> +		int gpio;
> +	};
> +	/* used to maintain the list of resources used by the driver */
> +	struct list_head list;
> +};
> +typedef struct list_head power_seq_resources;

No type definitions like this, please. Also, why define this particular
type globally?

> +
> +struct power_step_params {
> +	/* enable the resource if 1, disable if 0 */
> +	bool enable;
> +	/* delay (in ms) to wait before executing the step */
> +	int  pre_delay;
> +	/* delay (in ms) to wait after executing the step */
> +	int post_delay;

unsigned int for the delays?

> +};
> +
> +/**
> + * Platform definition of power sequences. A sequence is an array of these,
> + * terminated by a STOP instance.
> + */
> +struct platform_power_seq_step {
> +	power_res_type type;
> +	union {
> +		/* Used by REGULATOR and PWM types to name the resource */
> +		const char *id;
> +		/* Used by GPIO */
> +		int gpio;
> +	};
> +	struct power_step_params params;
> +};
> +typedef struct platform_power_seq_step platform_power_seq;

Why are the parameters kept in a separate structure? What are the
disadvantages of keeping the in the sequence step structure directly?

> +
> +/**
> + * Power sequence steps resolved against their resource. Built by
> + * power_seq_build and used to run the sequence.
> + */
> +struct power_seq_step {
> +	struct power_seq_resource *resource;
> +	struct power_step_params params;
> +};
> +typedef struct power_seq_step power_seq;

Would it make sense to make the struct power_seq opaque? I don't see why
anyone but the power_seq code should access the internals. For resource
managing it might also be easier to separate struct power_seq_step and
struct power_seq, making the power_seq basically something like:

	struct power_seq {
		struct power_seq_step *steps;
		unsigned int num_steps;
	};

Perhaps a name field can be included for diagnostic purposes.

> +
> +#ifdef CONFIG_OF
> +/**
> + * Build a platform data sequence from a device tree node. Memory for the
> + * sequence is allocated using devm_kzalloc on dev.
> + */
> +platform_power_seq *of_parse_power_seq(struct device *dev,
> +				       struct device_node *node);
> +#else
> +platform_power_seq *of_parse_power_seq(struct device *dev,
> +				       struct device_node *node)
> +{
> +	return NULL;
> +}
> +#endif
> +
> +/**
> + * Build a runnable power sequence from platform data, and add the resources
> + * it uses into ress. Memory for the sequence is allocated using devm_kzalloc
> + * on dev.
> + */
> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> +			   platform_power_seq *pseq);

I already mentioned this above: I fail to see why the ress parameter is
needed here. It is an internal implementation detail of the power
sequence code. Maybe a better place would be to include it within the
struct power_seq.

> +/**
> + * Free all the resources previously allocated by power_seq_allocate_resources.
> + */
> +void power_seq_free_resources(power_seq_resources *ress);
> +
> +/**
> + * Run the given power sequence. Returns 0 on success, error code in case of
> + * failure.
> + */
> +int power_seq_run(struct device *dev, power_seq *seq);

I think the API is too fine grained here. From a user's point of view,
I'd expect a sequence like this:

	seq = power_seq_build(dev, sequence);
	...
	power_seq_run(seq);
	...
	power_seq_free(seq);

Perhaps with managed variants where the power_seq_free() is executed
automatically:

	seq = devm_power_seq_build(dev, sequence);
	...
	power_seq_run(seq);

Generally I really like where this is going.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH 1/3] Move FIMD register headers to include/video/
From: Leela Krishna Amudala @ 2012-07-30 11:28 UTC (permalink / raw)
  To: Jingoo Han
  Cc: linux-arm-kernel, linux-samsung-soc, dri-devel, linux-fbdev,
	ben-linux, inki.dae, kgene.kim, joshi, Marek Szyprowski
In-Reply-To: <000001cd6e30$da849520$8f8dbf60$%han@samsung.com>

Hello Jingoo Han,

On Mon, Jul 30, 2012 at 2:23 PM, Jingoo Han <jg1.han@samsung.com> wrote:
> On Monday, July 30, 2012 5:45 PM, Leela Krishna Amudala wrote:
>>
>> Moved the contents of regs-fb-v4.h and regs-fb.h from arch side
>> to include/video/samsung_fimd.h
>>
>> Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
>> ---
>>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 -------
>>  arch/arm/plat-samsung/include/plat/regs-fb.h    |  403 -----------------
>>  include/video/samsung_fimd.h                    |  533 +++++++++++++++++++++++
>>  3 files changed, 533 insertions(+), 562 deletions(-)
>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
>>  create mode 100644 include/video/samsung_fimd.h
>>
>> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-
>> fb-v4.h
>> deleted file mode 100644
>> index 4c3647f..0000000
>> --- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
>> +++ /dev/null
>> @@ -1,159 +0,0 @@
>> -/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h
>> - *
>> - * Copyright 2008 Openmoko, Inc.
>> - * Copyright 2008 Simtec Electronics
>> - *      http://armlinux.simtec.co.uk/
>> - *      Ben Dooks <ben@simtec.co.uk>
>> - *
>> - * S3C64XX - new-style framebuffer register definitions
>> - *
>> - * This is the register set for the new style framebuffer interface
>> - * found from the S3C2443 onwards and specifically the S3C64XX series
>> - * S3C6400 and S3C6410.
>> - *
>> - * The file contains the cpu specific items which change between whichever
>> - * architecture is selected. See <plat/regs-fb.h> for the core definitions
>> - * that are the same.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License version 2 as
>> - * published by the Free Software Foundation.
>> -*/
>> -
>> -/* include the core definitions here, in case we really do need to
>> - * override them at a later date.
>> -*/
>> -
>> -#include <plat/regs-fb.h>
>> -
>> -#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
>> -#define VIDCON1_FSTATUS_EVEN (1 << 15)
>> -
>> -/* Video timing controls */
>> -#define VIDTCON0                             (0x10)
>> -#define VIDTCON1                             (0x14)
>> -#define VIDTCON2                             (0x18)
>> -
>> -/* Window position controls */
>> -
>> -#define WINCON(_win)                         (0x20 + ((_win) * 4))
>> -
>> -/* OSD1 and OSD4 do not have register D */
>> -
>> -#define VIDOSD_BASE                          (0x40)
>> -
>> -#define VIDINTCON0                           (0x130)
>> -
>> -/* WINCONx */
>> -
>> -#define WINCONx_CSCWIDTH_MASK                        (0x3 << 26)
>> -#define WINCONx_CSCWIDTH_SHIFT                       (26)
>> -#define WINCONx_CSCWIDTH_WIDE                        (0x0 << 26)
>> -#define WINCONx_CSCWIDTH_NARROW                      (0x3 << 26)
>> -
>> -#define WINCONx_ENLOCAL                              (1 << 22)
>> -#define WINCONx_BUFSTATUS                    (1 << 21)
>> -#define WINCONx_BUFSEL                               (1 << 20)
>> -#define WINCONx_BUFAUTOEN                    (1 << 19)
>> -#define WINCONx_YCbCr                                (1 << 13)
>> -
>> -#define WINCON1_LOCALSEL_CAMIF                       (1 << 23)
>> -
>> -#define WINCON2_LOCALSEL_CAMIF                       (1 << 23)
>> -#define WINCON2_BLD_PIX                              (1 << 6)
>> -
>> -#define WINCON2_ALPHA_SEL                    (1 << 1)
>> -#define WINCON2_BPPMODE_MASK                 (0xf << 2)
>> -#define WINCON2_BPPMODE_SHIFT                        (2)
>> -#define WINCON2_BPPMODE_1BPP                 (0x0 << 2)
>> -#define WINCON2_BPPMODE_2BPP                 (0x1 << 2)
>> -#define WINCON2_BPPMODE_4BPP                 (0x2 << 2)
>> -#define WINCON2_BPPMODE_8BPP_1232            (0x4 << 2)
>> -#define WINCON2_BPPMODE_16BPP_565            (0x5 << 2)
>> -#define WINCON2_BPPMODE_16BPP_A1555          (0x6 << 2)
>> -#define WINCON2_BPPMODE_16BPP_I1555          (0x7 << 2)
>> -#define WINCON2_BPPMODE_18BPP_666            (0x8 << 2)
>> -#define WINCON2_BPPMODE_18BPP_A1665          (0x9 << 2)
>> -#define WINCON2_BPPMODE_19BPP_A1666          (0xa << 2)
>> -#define WINCON2_BPPMODE_24BPP_888            (0xb << 2)
>> -#define WINCON2_BPPMODE_24BPP_A1887          (0xc << 2)
>> -#define WINCON2_BPPMODE_25BPP_A1888          (0xd << 2)
>> -#define WINCON2_BPPMODE_28BPP_A4888          (0xd << 2)
>> -
>> -#define WINCON3_BLD_PIX                              (1 << 6)
>> -
>> -#define WINCON3_ALPHA_SEL                    (1 << 1)
>> -#define WINCON3_BPPMODE_MASK                 (0xf << 2)
>> -#define WINCON3_BPPMODE_SHIFT                        (2)
>> -#define WINCON3_BPPMODE_1BPP                 (0x0 << 2)
>> -#define WINCON3_BPPMODE_2BPP                 (0x1 << 2)
>> -#define WINCON3_BPPMODE_4BPP                 (0x2 << 2)
>> -#define WINCON3_BPPMODE_16BPP_565            (0x5 << 2)
>> -#define WINCON3_BPPMODE_16BPP_A1555          (0x6 << 2)
>> -#define WINCON3_BPPMODE_16BPP_I1555          (0x7 << 2)
>> -#define WINCON3_BPPMODE_18BPP_666            (0x8 << 2)
>> -#define WINCON3_BPPMODE_18BPP_A1665          (0x9 << 2)
>> -#define WINCON3_BPPMODE_19BPP_A1666          (0xa << 2)
>> -#define WINCON3_BPPMODE_24BPP_888            (0xb << 2)
>> -#define WINCON3_BPPMODE_24BPP_A1887          (0xc << 2)
>> -#define WINCON3_BPPMODE_25BPP_A1888          (0xd << 2)
>> -#define WINCON3_BPPMODE_28BPP_A4888          (0xd << 2)
>> -
>> -#define VIDINTCON0_FIFIOSEL_WINDOW2          (0x10 << 5)
>> -#define VIDINTCON0_FIFIOSEL_WINDOW3          (0x20 << 5)
>> -#define VIDINTCON0_FIFIOSEL_WINDOW4          (0x40 << 5)
>> -
>> -#define DITHMODE                             (0x170)
>> -#define WINxMAP(_win)                                (0x180 + ((_win) * 4))
>> -
>> -
>> -#define DITHMODE_R_POS_MASK                  (0x3 << 5)
>> -#define DITHMODE_R_POS_SHIFT                 (5)
>> -#define DITHMODE_R_POS_8BIT                  (0x0 << 5)
>> -#define DITHMODE_R_POS_6BIT                  (0x1 << 5)
>> -#define DITHMODE_R_POS_5BIT                  (0x2 << 5)
>> -
>> -#define DITHMODE_G_POS_MASK                  (0x3 << 3)
>> -#define DITHMODE_G_POS_SHIFT                 (3)
>> -#define DITHMODE_G_POS_8BIT                  (0x0 << 3)
>> -#define DITHMODE_G_POS_6BIT                  (0x1 << 3)
>> -#define DITHMODE_G_POS_5BIT                  (0x2 << 3)
>> -
>> -#define DITHMODE_B_POS_MASK                  (0x3 << 1)
>> -#define DITHMODE_B_POS_SHIFT                 (1)
>> -#define DITHMODE_B_POS_8BIT                  (0x0 << 1)
>> -#define DITHMODE_B_POS_6BIT                  (0x1 << 1)
>> -#define DITHMODE_B_POS_5BIT                  (0x2 << 1)
>> -
>> -#define DITHMODE_DITH_EN                     (1 << 0)
>> -
>> -#define WPALCON                                      (0x1A0)
>> -
>> -/* Palette control */
>> -/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
>> - * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
>> -#define WPALCON_W4PAL_16BPP_A555             (1 << 8)
>> -#define WPALCON_W3PAL_16BPP_A555             (1 << 7)
>> -#define WPALCON_W2PAL_16BPP_A555             (1 << 6)
>> -
>> -
>> -/* Notes on per-window bpp settings
>> - *
>> - * Value     Win0     Win1     Win2     Win3     Win 4
>> - * 0000              1(P)     1(P)     1(P)     1(P)     1(P)
>> - * 0001              2(P)     2(P)     2(P)     2(P)     2(P)
>> - * 0010              4(P)     4(P)     4(P)     4(P)     -none-
>> - * 0011              8(P)     8(P)     -none-   -none-   -none-
>> - * 0100              -none-   8(A232)  8(A232)  -none-   -none-
>> - * 0101              16(565)  16(565)  16(565)  16(565)   16(565)
>> - * 0110              -none-   16(A555) 16(A555) 16(A555)  16(A555)
>> - * 0111              16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
>> - * 1000              18(666)  18(666)  18(666)  18(666)   18(666)
>> - * 1001              -none-   18(A665) 18(A665) 18(A665)  16(A665)
>> - * 1010              -none-   19(A666) 19(A666) 19(A666)  19(A666)
>> - * 1011              24(888)  24(888)  24(888)  24(888)   24(888)
>> - * 1100              -none-   24(A887) 24(A887) 24(A887)  24(A887)
>> - * 1101              -none-   25(A888) 25(A888) 25(A888)  25(A888)
>> - * 1110              -none-   -none-   -none-   -none-    -none-
>> - * 1111              -none-   -none-   -none-   -none-    -none-
>> -*/
>> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
>> deleted file mode 100644
>> index 9a78012..0000000
>> --- a/arch/arm/plat-samsung/include/plat/regs-fb.h
>> +++ /dev/null
>> @@ -1,403 +0,0 @@
>> -/* arch/arm/plat-samsung/include/plat/regs-fb.h
>> - *
>> - * Copyright 2008 Openmoko, Inc.
>> - * Copyright 2008 Simtec Electronics
>> - *      http://armlinux.simtec.co.uk/
>> - *      Ben Dooks <ben@simtec.co.uk>
>> - *
>> - * S3C Platform - new-style framebuffer register definitions
>> - *
>> - * This is the register set for the new style framebuffer interface
>> - * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
>> - * S3C64XX series such as the S3C6400 and S3C6410.
>> - *
>> - * The file does not contain the cpu specific items which are based on
>> - * whichever architecture is selected, it only contains the core of the
>> - * register set. See <mach/regs-fb.h> to get the specifics.
>> - *
>> - * Note, we changed to using regs-fb.h as it avoids any clashes with
>> - * the original regs-lcd.h so out of the way of regs-lcd.h as well as
>> - * indicating the newer block is much more than just an LCD interface.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License version 2 as
>> - * published by the Free Software Foundation.
>> -*/
>> -
>> -/* Please do not include this file directly, use <mach/regs-fb.h> to
>> - * ensure all the localised SoC support is included as necessary.
>> -*/
>> -
>> -/* VIDCON0 */
>> -
>> -#define VIDCON0                                      (0x00)
>> -#define VIDCON0_INTERLACE                    (1 << 29)
>> -#define VIDCON0_VIDOUT_MASK                  (0x3 << 26)
>> -#define VIDCON0_VIDOUT_SHIFT                 (26)
>> -#define VIDCON0_VIDOUT_RGB                   (0x0 << 26)
>> -#define VIDCON0_VIDOUT_TV                    (0x1 << 26)
>> -#define VIDCON0_VIDOUT_I80_LDI0                      (0x2 << 26)
>> -#define VIDCON0_VIDOUT_I80_LDI1                      (0x3 << 26)
>> -
>> -#define VIDCON0_L1_DATA_MASK                 (0x7 << 23)
>> -#define VIDCON0_L1_DATA_SHIFT                        (23)
>> -#define VIDCON0_L1_DATA_16BPP                        (0x0 << 23)
>> -#define VIDCON0_L1_DATA_18BPP16                      (0x1 << 23)
>> -#define VIDCON0_L1_DATA_18BPP9                       (0x2 << 23)
>> -#define VIDCON0_L1_DATA_24BPP                        (0x3 << 23)
>> -#define VIDCON0_L1_DATA_18BPP                        (0x4 << 23)
>> -#define VIDCON0_L1_DATA_16BPP8                       (0x5 << 23)
>> -
>> -#define VIDCON0_L0_DATA_MASK                 (0x7 << 20)
>> -#define VIDCON0_L0_DATA_SHIFT                        (20)
>> -#define VIDCON0_L0_DATA_16BPP                        (0x0 << 20)
>> -#define VIDCON0_L0_DATA_18BPP16                      (0x1 << 20)
>> -#define VIDCON0_L0_DATA_18BPP9                       (0x2 << 20)
>> -#define VIDCON0_L0_DATA_24BPP                        (0x3 << 20)
>> -#define VIDCON0_L0_DATA_18BPP                        (0x4 << 20)
>> -#define VIDCON0_L0_DATA_16BPP8                       (0x5 << 20)
>> -
>> -#define VIDCON0_PNRMODE_MASK                 (0x3 << 17)
>> -#define VIDCON0_PNRMODE_SHIFT                        (17)
>> -#define VIDCON0_PNRMODE_RGB                  (0x0 << 17)
>> -#define VIDCON0_PNRMODE_BGR                  (0x1 << 17)
>> -#define VIDCON0_PNRMODE_SERIAL_RGB           (0x2 << 17)
>> -#define VIDCON0_PNRMODE_SERIAL_BGR           (0x3 << 17)
>> -
>> -#define VIDCON0_CLKVALUP                     (1 << 16)
>> -#define VIDCON0_CLKVAL_F_MASK                        (0xff << 6)
>> -#define VIDCON0_CLKVAL_F_SHIFT                       (6)
>> -#define VIDCON0_CLKVAL_F_LIMIT                       (0xff)
>> -#define VIDCON0_CLKVAL_F(_x)                 ((_x) << 6)
>> -#define VIDCON0_VLCKFREE                     (1 << 5)
>> -#define VIDCON0_CLKDIR                               (1 << 4)
>> -
>> -#define VIDCON0_CLKSEL_MASK                  (0x3 << 2)
>> -#define VIDCON0_CLKSEL_SHIFT                 (2)
>> -#define VIDCON0_CLKSEL_HCLK                  (0x0 << 2)
>> -#define VIDCON0_CLKSEL_LCD                   (0x1 << 2)
>> -#define VIDCON0_CLKSEL_27M                   (0x3 << 2)
>> -
>> -#define VIDCON0_ENVID                                (1 << 1)
>> -#define VIDCON0_ENVID_F                              (1 << 0)
>> -
>> -#define VIDCON1                                      (0x04)
>> -#define VIDCON1_LINECNT_MASK                 (0x7ff << 16)
>> -#define VIDCON1_LINECNT_SHIFT                        (16)
>> -#define VIDCON1_LINECNT_GET(_v)                      (((_v) >> 16) & 0x7ff)
>> -#define VIDCON1_VSTATUS_MASK                 (0x3 << 13)
>> -#define VIDCON1_VSTATUS_SHIFT                        (13)
>> -#define VIDCON1_VSTATUS_VSYNC                        (0x0 << 13)
>> -#define VIDCON1_VSTATUS_BACKPORCH            (0x1 << 13)
>> -#define VIDCON1_VSTATUS_ACTIVE                       (0x2 << 13)
>> -#define VIDCON1_VSTATUS_FRONTPORCH           (0x0 << 13)
>> -#define VIDCON1_VCLK_MASK                    (0x3 << 9)
>> -#define VIDCON1_VCLK_HOLD                    (0x0 << 9)
>> -#define VIDCON1_VCLK_RUN                     (0x1 << 9)
>> -
>> -#define VIDCON1_INV_VCLK                     (1 << 7)
>> -#define VIDCON1_INV_HSYNC                    (1 << 6)
>> -#define VIDCON1_INV_VSYNC                    (1 << 5)
>> -#define VIDCON1_INV_VDEN                     (1 << 4)
>> -
>> -/* VIDCON2 */
>> -
>> -#define VIDCON2                                      (0x08)
>> -#define VIDCON2_EN601                                (1 << 23)
>> -#define VIDCON2_TVFMTSEL_SW                  (1 << 14)
>> -
>> -#define VIDCON2_TVFMTSEL1_MASK                       (0x3 << 12)
>> -#define VIDCON2_TVFMTSEL1_SHIFT                      (12)
>> -#define VIDCON2_TVFMTSEL1_RGB                        (0x0 << 12)
>> -#define VIDCON2_TVFMTSEL1_YUV422             (0x1 << 12)
>> -#define VIDCON2_TVFMTSEL1_YUV444             (0x2 << 12)
>> -
>> -#define VIDCON2_ORGYCbCr                     (1 << 8)
>> -#define VIDCON2_YUVORDCrCb                   (1 << 7)
>> -
>> -/* PRTCON (S3C6410, S5PC100)
>> - * Might not be present in the S3C6410 documentation,
>> - * but tests prove it's there almost for sure; shouldn't hurt in any case.
>> - */
>> -#define PRTCON                                       (0x0c)
>> -#define PRTCON_PROTECT                               (1 << 11)
>> -
>> -/* VIDTCON0 */
>> -
>> -#define VIDTCON0_VBPDE_MASK                  (0xff << 24)
>> -#define VIDTCON0_VBPDE_SHIFT                 (24)
>> -#define VIDTCON0_VBPDE_LIMIT                 (0xff)
>> -#define VIDTCON0_VBPDE(_x)                   ((_x) << 24)
>> -
>> -#define VIDTCON0_VBPD_MASK                   (0xff << 16)
>> -#define VIDTCON0_VBPD_SHIFT                  (16)
>> -#define VIDTCON0_VBPD_LIMIT                  (0xff)
>> -#define VIDTCON0_VBPD(_x)                    ((_x) << 16)
>> -
>> -#define VIDTCON0_VFPD_MASK                   (0xff << 8)
>> -#define VIDTCON0_VFPD_SHIFT                  (8)
>> -#define VIDTCON0_VFPD_LIMIT                  (0xff)
>> -#define VIDTCON0_VFPD(_x)                    ((_x) << 8)
>> -
>> -#define VIDTCON0_VSPW_MASK                   (0xff << 0)
>> -#define VIDTCON0_VSPW_SHIFT                  (0)
>> -#define VIDTCON0_VSPW_LIMIT                  (0xff)
>> -#define VIDTCON0_VSPW(_x)                    ((_x) << 0)
>> -
>> -/* VIDTCON1 */
>> -
>> -#define VIDTCON1_VFPDE_MASK                  (0xff << 24)
>> -#define VIDTCON1_VFPDE_SHIFT                 (24)
>> -#define VIDTCON1_VFPDE_LIMIT                 (0xff)
>> -#define VIDTCON1_VFPDE(_x)                   ((_x) << 24)
>> -
>> -#define VIDTCON1_HBPD_MASK                   (0xff << 16)
>> -#define VIDTCON1_HBPD_SHIFT                  (16)
>> -#define VIDTCON1_HBPD_LIMIT                  (0xff)
>> -#define VIDTCON1_HBPD(_x)                    ((_x) << 16)
>> -
>> -#define VIDTCON1_HFPD_MASK                   (0xff << 8)
>> -#define VIDTCON1_HFPD_SHIFT                  (8)
>> -#define VIDTCON1_HFPD_LIMIT                  (0xff)
>> -#define VIDTCON1_HFPD(_x)                    ((_x) << 8)
>> -
>> -#define VIDTCON1_HSPW_MASK                   (0xff << 0)
>> -#define VIDTCON1_HSPW_SHIFT                  (0)
>> -#define VIDTCON1_HSPW_LIMIT                  (0xff)
>> -#define VIDTCON1_HSPW(_x)                    ((_x) << 0)
>> -
>> -#define VIDTCON2                             (0x18)
>> -#define VIDTCON2_LINEVAL_E(_x)                       ((((_x) & 0x800) >> 11) << 23)
>> -#define VIDTCON2_LINEVAL_MASK                        (0x7ff << 11)
>> -#define VIDTCON2_LINEVAL_SHIFT                       (11)
>> -#define VIDTCON2_LINEVAL_LIMIT                       (0x7ff)
>> -#define VIDTCON2_LINEVAL(_x)                 (((_x) & 0x7ff) << 11)
>> -
>> -#define VIDTCON2_HOZVAL_E(_x)                        ((((_x) & 0x800) >> 11) << 22)
>> -#define VIDTCON2_HOZVAL_MASK                 (0x7ff << 0)
>> -#define VIDTCON2_HOZVAL_SHIFT                        (0)
>> -#define VIDTCON2_HOZVAL_LIMIT                        (0x7ff)
>> -#define VIDTCON2_HOZVAL(_x)                  (((_x) & 0x7ff) << 0)
>> -
>> -/* WINCONx */
>> -
>> -
>> -#define WINCONx_BITSWP                               (1 << 18)
>> -#define WINCONx_BYTSWP                               (1 << 17)
>> -#define WINCONx_HAWSWP                               (1 << 16)
>> -#define WINCONx_WSWP                         (1 << 15)
>> -#define WINCONx_BURSTLEN_MASK                        (0x3 << 9)
>> -#define WINCONx_BURSTLEN_SHIFT                       (9)
>> -#define WINCONx_BURSTLEN_16WORD                      (0x0 << 9)
>> -#define WINCONx_BURSTLEN_8WORD                       (0x1 << 9)
>> -#define WINCONx_BURSTLEN_4WORD                       (0x2 << 9)
>> -
>> -#define WINCONx_ENWIN                                (1 << 0)
>> -#define WINCON0_BPPMODE_MASK                 (0xf << 2)
>> -#define WINCON0_BPPMODE_SHIFT                        (2)
>> -#define WINCON0_BPPMODE_1BPP                 (0x0 << 2)
>> -#define WINCON0_BPPMODE_2BPP                 (0x1 << 2)
>> -#define WINCON0_BPPMODE_4BPP                 (0x2 << 2)
>> -#define WINCON0_BPPMODE_8BPP_PALETTE         (0x3 << 2)
>> -#define WINCON0_BPPMODE_16BPP_565            (0x5 << 2)
>> -#define WINCON0_BPPMODE_16BPP_1555           (0x7 << 2)
>> -#define WINCON0_BPPMODE_18BPP_666            (0x8 << 2)
>> -#define WINCON0_BPPMODE_24BPP_888            (0xb << 2)
>> -
>> -#define WINCON1_BLD_PIX                              (1 << 6)
>> -
>> -#define WINCON1_ALPHA_SEL                    (1 << 1)
>> -#define WINCON1_BPPMODE_MASK                 (0xf << 2)
>> -#define WINCON1_BPPMODE_SHIFT                        (2)
>> -#define WINCON1_BPPMODE_1BPP                 (0x0 << 2)
>> -#define WINCON1_BPPMODE_2BPP                 (0x1 << 2)
>> -#define WINCON1_BPPMODE_4BPP                 (0x2 << 2)
>> -#define WINCON1_BPPMODE_8BPP_PALETTE         (0x3 << 2)
>> -#define WINCON1_BPPMODE_8BPP_1232            (0x4 << 2)
>> -#define WINCON1_BPPMODE_16BPP_565            (0x5 << 2)
>> -#define WINCON1_BPPMODE_16BPP_A1555          (0x6 << 2)
>> -#define WINCON1_BPPMODE_16BPP_I1555          (0x7 << 2)
>> -#define WINCON1_BPPMODE_18BPP_666            (0x8 << 2)
>> -#define WINCON1_BPPMODE_18BPP_A1665          (0x9 << 2)
>> -#define WINCON1_BPPMODE_19BPP_A1666          (0xa << 2)
>> -#define WINCON1_BPPMODE_24BPP_888            (0xb << 2)
>> -#define WINCON1_BPPMODE_24BPP_A1887          (0xc << 2)
>> -#define WINCON1_BPPMODE_25BPP_A1888          (0xd << 2)
>> -#define WINCON1_BPPMODE_28BPP_A4888          (0xd << 2)
>> -
>> -/* S5PV210 */
>> -#define SHADOWCON                            (0x34)
>> -#define SHADOWCON_WINx_PROTECT(_win)         (1 << (10 + (_win)))
>> -/* DMA channels (all windows) */
>> -#define SHADOWCON_CHx_ENABLE(_win)           (1 << (_win))
>> -/* Local input channels (windows 0-2) */
>> -#define SHADOWCON_CHx_LOCAL_ENABLE(_win)     (1 << (5 + (_win)))
>> -
>> -#define VIDOSDxA_TOPLEFT_X_E(_x)             ((((_x) & 0x800) >> 11) << 23)
>> -#define VIDOSDxA_TOPLEFT_X_MASK                      (0x7ff << 11)
>> -#define VIDOSDxA_TOPLEFT_X_SHIFT             (11)
>> -#define VIDOSDxA_TOPLEFT_X_LIMIT             (0x7ff)
>> -#define VIDOSDxA_TOPLEFT_X(_x)                       (((_x) & 0x7ff) << 11)
>> -
>> -#define VIDOSDxA_TOPLEFT_Y_E(_x)             ((((_x) & 0x800) >> 11) << 22)
>> -#define VIDOSDxA_TOPLEFT_Y_MASK                      (0x7ff << 0)
>> -#define VIDOSDxA_TOPLEFT_Y_SHIFT             (0)
>> -#define VIDOSDxA_TOPLEFT_Y_LIMIT             (0x7ff)
>> -#define VIDOSDxA_TOPLEFT_Y(_x)                       (((_x) & 0x7ff) << 0)
>> -
>> -#define VIDOSDxB_BOTRIGHT_X_E(_x)            ((((_x) & 0x800) >> 11) << 23)
>> -#define VIDOSDxB_BOTRIGHT_X_MASK             (0x7ff << 11)
>> -#define VIDOSDxB_BOTRIGHT_X_SHIFT            (11)
>> -#define VIDOSDxB_BOTRIGHT_X_LIMIT            (0x7ff)
>> -#define VIDOSDxB_BOTRIGHT_X(_x)                      (((_x) & 0x7ff) << 11)
>> -
>> -#define VIDOSDxB_BOTRIGHT_Y_E(_x)            ((((_x) & 0x800) >> 11) << 22)
>> -#define VIDOSDxB_BOTRIGHT_Y_MASK             (0x7ff << 0)
>> -#define VIDOSDxB_BOTRIGHT_Y_SHIFT            (0)
>> -#define VIDOSDxB_BOTRIGHT_Y_LIMIT            (0x7ff)
>> -#define VIDOSDxB_BOTRIGHT_Y(_x)                      (((_x) & 0x7ff) << 0)
>> -
>> -/* For VIDOSD[1..4]C */
>> -#define VIDISD14C_ALPHA0_R(_x)                       ((_x) << 20)
>> -#define VIDISD14C_ALPHA0_G_MASK                      (0xf << 16)
>> -#define VIDISD14C_ALPHA0_G_SHIFT             (16)
>> -#define VIDISD14C_ALPHA0_G_LIMIT             (0xf)
>> -#define VIDISD14C_ALPHA0_G(_x)                       ((_x) << 16)
>> -#define VIDISD14C_ALPHA0_B_MASK                      (0xf << 12)
>> -#define VIDISD14C_ALPHA0_B_SHIFT             (12)
>> -#define VIDISD14C_ALPHA0_B_LIMIT             (0xf)
>> -#define VIDISD14C_ALPHA0_B(_x)                       ((_x) << 12)
>> -#define VIDISD14C_ALPHA1_R_MASK                      (0xf << 8)
>> -#define VIDISD14C_ALPHA1_R_SHIFT             (8)
>> -#define VIDISD14C_ALPHA1_R_LIMIT             (0xf)
>> -#define VIDISD14C_ALPHA1_R(_x)                       ((_x) << 8)
>> -#define VIDISD14C_ALPHA1_G_MASK                      (0xf << 4)
>> -#define VIDISD14C_ALPHA1_G_SHIFT             (4)
>> -#define VIDISD14C_ALPHA1_G_LIMIT             (0xf)
>> -#define VIDISD14C_ALPHA1_G(_x)                       ((_x) << 4)
>> -#define VIDISD14C_ALPHA1_B_MASK                      (0xf << 0)
>> -#define VIDISD14C_ALPHA1_B_SHIFT             (0)
>> -#define VIDISD14C_ALPHA1_B_LIMIT             (0xf)
>> -#define VIDISD14C_ALPHA1_B(_x)                       ((_x) << 0)
>> -
>> -/* Video buffer addresses */
>> -#define VIDW_BUF_START(_buff)                        (0xA0 + ((_buff) * 8))
>> -#define VIDW_BUF_START1(_buff)                       (0xA4 + ((_buff) * 8))
>> -#define VIDW_BUF_END(_buff)                  (0xD0 + ((_buff) * 8))
>> -#define VIDW_BUF_END1(_buff)                 (0xD4 + ((_buff) * 8))
>> -#define VIDW_BUF_SIZE(_buff)                 (0x100 + ((_buff) * 4))
>> -
>> -#define VIDW_BUF_SIZE_OFFSET_E(_x)           ((((_x) & 0x2000) >> 13) << 27)
>> -#define VIDW_BUF_SIZE_OFFSET_MASK            (0x1fff << 13)
>> -#define VIDW_BUF_SIZE_OFFSET_SHIFT           (13)
>> -#define VIDW_BUF_SIZE_OFFSET_LIMIT           (0x1fff)
>> -#define VIDW_BUF_SIZE_OFFSET(_x)             (((_x) & 0x1fff) << 13)
>> -
>> -#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)                ((((_x) & 0x2000) >> 13) << 26)
>> -#define VIDW_BUF_SIZE_PAGEWIDTH_MASK         (0x1fff << 0)
>> -#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT                (0)
>> -#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT                (0x1fff)
>> -#define VIDW_BUF_SIZE_PAGEWIDTH(_x)          (((_x) & 0x1fff) << 0)
>> -
>> -/* Interrupt controls and status */
>> -
>> -#define VIDINTCON0_FIFOINTERVAL_MASK         (0x3f << 20)
>> -#define VIDINTCON0_FIFOINTERVAL_SHIFT                (20)
>> -#define VIDINTCON0_FIFOINTERVAL_LIMIT                (0x3f)
>> -#define VIDINTCON0_FIFOINTERVAL(_x)          ((_x) << 20)
>> -
>> -#define VIDINTCON0_INT_SYSMAINCON            (1 << 19)
>> -#define VIDINTCON0_INT_SYSSUBCON             (1 << 18)
>> -#define VIDINTCON0_INT_I80IFDONE             (1 << 17)
>> -
>> -#define VIDINTCON0_FRAMESEL0_MASK            (0x3 << 15)
>> -#define VIDINTCON0_FRAMESEL0_SHIFT           (15)
>> -#define VIDINTCON0_FRAMESEL0_BACKPORCH               (0x0 << 15)
>> -#define VIDINTCON0_FRAMESEL0_VSYNC           (0x1 << 15)
>> -#define VIDINTCON0_FRAMESEL0_ACTIVE          (0x2 << 15)
>> -#define VIDINTCON0_FRAMESEL0_FRONTPORCH              (0x3 << 15)
>> -
>> -#define VIDINTCON0_FRAMESEL1                 (1 << 13)
>> -#define VIDINTCON0_FRAMESEL1_MASK            (0x3 << 13)
>> -#define VIDINTCON0_FRAMESEL1_NONE            (0x0 << 13)
>> -#define VIDINTCON0_FRAMESEL1_BACKPORCH               (0x1 << 13)
>> -#define VIDINTCON0_FRAMESEL1_VSYNC           (0x2 << 13)
>> -#define VIDINTCON0_FRAMESEL1_FRONTPORCH              (0x3 << 13)
>> -
>> -#define VIDINTCON0_INT_FRAME                 (1 << 12)
>> -#define VIDINTCON0_FIFIOSEL_MASK             (0x7f << 5)
>> -#define VIDINTCON0_FIFIOSEL_SHIFT            (5)
>> -#define VIDINTCON0_FIFIOSEL_WINDOW0          (0x1 << 5)
>> -#define VIDINTCON0_FIFIOSEL_WINDOW1          (0x2 << 5)
>> -
>> -#define VIDINTCON0_FIFOLEVEL_MASK            (0x7 << 2)
>> -#define VIDINTCON0_FIFOLEVEL_SHIFT           (2)
>> -#define VIDINTCON0_FIFOLEVEL_TO25PC          (0x0 << 2)
>> -#define VIDINTCON0_FIFOLEVEL_TO50PC          (0x1 << 2)
>> -#define VIDINTCON0_FIFOLEVEL_TO75PC          (0x2 << 2)
>> -#define VIDINTCON0_FIFOLEVEL_EMPTY           (0x3 << 2)
>> -#define VIDINTCON0_FIFOLEVEL_FULL            (0x4 << 2)
>> -
>> -#define VIDINTCON0_INT_FIFO_MASK             (0x3 << 0)
>> -#define VIDINTCON0_INT_FIFO_SHIFT            (0)
>> -#define VIDINTCON0_INT_ENABLE                        (1 << 0)
>> -
>> -#define VIDINTCON1                           (0x134)
>> -#define VIDINTCON1_INT_I180                  (1 << 2)
>> -#define VIDINTCON1_INT_FRAME                 (1 << 1)
>> -#define VIDINTCON1_INT_FIFO                  (1 << 0)
>> -
>> -/* Window colour-key control registers */
>> -#define WKEYCON                                      (0x140) /* 6410,V210 */
>> -
>> -#define WKEYCON0                             (0x00)
>> -#define WKEYCON1                             (0x04)
>> -
>> -#define WxKEYCON0_KEYBL_EN                   (1 << 26)
>> -#define WxKEYCON0_KEYEN_F                    (1 << 25)
>> -#define WxKEYCON0_DIRCON                     (1 << 24)
>> -#define WxKEYCON0_COMPKEY_MASK                       (0xffffff << 0)
>> -#define WxKEYCON0_COMPKEY_SHIFT                      (0)
>> -#define WxKEYCON0_COMPKEY_LIMIT                      (0xffffff)
>> -#define WxKEYCON0_COMPKEY(_x)                        ((_x) << 0)
>> -#define WxKEYCON1_COLVAL_MASK                        (0xffffff << 0)
>> -#define WxKEYCON1_COLVAL_SHIFT                       (0)
>> -#define WxKEYCON1_COLVAL_LIMIT                       (0xffffff)
>> -#define WxKEYCON1_COLVAL(_x)                 ((_x) << 0)
>> -
>> -
>> -/* Window blanking (MAP) */
>> -
>> -#define WINxMAP_MAP                          (1 << 24)
>> -#define WINxMAP_MAP_COLOUR_MASK                      (0xffffff << 0)
>> -#define WINxMAP_MAP_COLOUR_SHIFT             (0)
>> -#define WINxMAP_MAP_COLOUR_LIMIT             (0xffffff)
>> -#define WINxMAP_MAP_COLOUR(_x)                       ((_x) << 0)
>> -
>> -#define WPALCON_PAL_UPDATE                   (1 << 9)
>> -#define WPALCON_W1PAL_MASK                   (0x7 << 3)
>> -#define WPALCON_W1PAL_SHIFT                  (3)
>> -#define WPALCON_W1PAL_25BPP_A888             (0x0 << 3)
>> -#define WPALCON_W1PAL_24BPP                  (0x1 << 3)
>> -#define WPALCON_W1PAL_19BPP_A666             (0x2 << 3)
>> -#define WPALCON_W1PAL_18BPP_A665             (0x3 << 3)
>> -#define WPALCON_W1PAL_18BPP                  (0x4 << 3)
>> -#define WPALCON_W1PAL_16BPP_A555             (0x5 << 3)
>> -#define WPALCON_W1PAL_16BPP_565                      (0x6 << 3)
>> -
>> -#define WPALCON_W0PAL_MASK                   (0x7 << 0)
>> -#define WPALCON_W0PAL_SHIFT                  (0)
>> -#define WPALCON_W0PAL_25BPP_A888             (0x0 << 0)
>> -#define WPALCON_W0PAL_24BPP                  (0x1 << 0)
>> -#define WPALCON_W0PAL_19BPP_A666             (0x2 << 0)
>> -#define WPALCON_W0PAL_18BPP_A665             (0x3 << 0)
>> -#define WPALCON_W0PAL_18BPP                  (0x4 << 0)
>> -#define WPALCON_W0PAL_16BPP_A555             (0x5 << 0)
>> -#define WPALCON_W0PAL_16BPP_565                      (0x6 << 0)
>> -
>> -/* Blending equation control */
>> -#define BLENDCON                             (0x260)
>> -#define BLENDCON_NEW_MASK                    (1 << 0)
>> -#define BLENDCON_NEW_8BIT_ALPHA_VALUE                (1 << 0)
>> -#define BLENDCON_NEW_4BIT_ALPHA_VALUE                (0 << 0)
>> -
>> diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
>> new file mode 100644
>> index 0000000..1b5ff4c
>> --- /dev/null
>> +++ b/include/video/samsung_fimd.h
>> @@ -0,0 +1,533 @@
>> +/* include/video/samsung_fimd.h
>> + *
>> + * Copyright 2008 Openmoko, Inc.
>> + * Copyright 2008 Simtec Electronics
>> + *      http://armlinux.simtec.co.uk/
>> + *      Ben Dooks <ben@simtec.co.uk>
>> + *
>> + * S3C Platform - new-style fimd and framebuffer register definitions
>> + *
>> + * This is the register set for the fimd and new style framebuffer interface
>> + * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
>> + * S3C64XX series such as the S3C6400 and S3C6410.
>> + *
>> + * The file does not contain the cpu specific items which are based on
>> + * whichever architecture is selected, it only contains the core of the
>> + * register set. See <mach/regs-fb.h> to get the specifics.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> +*/
>> +
>> +/* VIDCON0 */
>> +
>> +#define VIDCON0                                      (0x00)
>> +#define VIDCON0_INTERLACE                    (1 << 29)
>> +#define VIDCON0_VIDOUT_MASK                  (0x3 << 26)
>> +#define VIDCON0_VIDOUT_SHIFT                 (26)
>> +#define VIDCON0_VIDOUT_RGB                   (0x0 << 26)
>> +#define VIDCON0_VIDOUT_TV                    (0x1 << 26)
>> +#define VIDCON0_VIDOUT_I80_LDI0                      (0x2 << 26)
>> +#define VIDCON0_VIDOUT_I80_LDI1                      (0x3 << 26)
>> +
>> +#define VIDCON0_L1_DATA_MASK                 (0x7 << 23)
>> +#define VIDCON0_L1_DATA_SHIFT                        (23)
>> +#define VIDCON0_L1_DATA_16BPP                        (0x0 << 23)
>> +#define VIDCON0_L1_DATA_18BPP16                      (0x1 << 23)
>> +#define VIDCON0_L1_DATA_18BPP9                       (0x2 << 23)
>> +#define VIDCON0_L1_DATA_24BPP                        (0x3 << 23)
>> +#define VIDCON0_L1_DATA_18BPP                        (0x4 << 23)
>> +#define VIDCON0_L1_DATA_16BPP8                       (0x5 << 23)
>> +
>> +#define VIDCON0_L0_DATA_MASK                 (0x7 << 20)
>> +#define VIDCON0_L0_DATA_SHIFT                        (20)
>> +#define VIDCON0_L0_DATA_16BPP                        (0x0 << 20)
>> +#define VIDCON0_L0_DATA_18BPP16                      (0x1 << 20)
>> +#define VIDCON0_L0_DATA_18BPP9                       (0x2 << 20)
>> +#define VIDCON0_L0_DATA_24BPP                        (0x3 << 20)
>> +#define VIDCON0_L0_DATA_18BPP                        (0x4 << 20)
>> +#define VIDCON0_L0_DATA_16BPP8                       (0x5 << 20)
>> +
>> +#define VIDCON0_PNRMODE_MASK                 (0x3 << 17)
>> +#define VIDCON0_PNRMODE_SHIFT                        (17)
>> +#define VIDCON0_PNRMODE_RGB                  (0x0 << 17)
>> +#define VIDCON0_PNRMODE_BGR                  (0x1 << 17)
>> +#define VIDCON0_PNRMODE_SERIAL_RGB           (0x2 << 17)
>> +#define VIDCON0_PNRMODE_SERIAL_BGR           (0x3 << 17)
>> +
>> +#define VIDCON0_CLKVALUP                     (1 << 16)
>> +#define VIDCON0_CLKVAL_F_MASK                        (0xff << 6)
>> +#define VIDCON0_CLKVAL_F_SHIFT                       (6)
>> +#define VIDCON0_CLKVAL_F_LIMIT                       (0xff)
>> +#define VIDCON0_CLKVAL_F(_x)                 ((_x) << 6)
>> +#define VIDCON0_VLCKFREE                     (1 << 5)
>> +#define VIDCON0_CLKDIR                               (1 << 4)
>> +
>> +#define VIDCON0_CLKSEL_MASK                  (0x3 << 2)
>> +#define VIDCON0_CLKSEL_SHIFT                 (2)
>> +#define VIDCON0_CLKSEL_HCLK                  (0x0 << 2)
>> +#define VIDCON0_CLKSEL_LCD                   (0x1 << 2)
>> +#define VIDCON0_CLKSEL_27M                   (0x3 << 2)
>> +
>> +#define VIDCON0_ENVID                                (1 << 1)
>> +#define VIDCON0_ENVID_F                              (1 << 0)
>> +
>> +#define VIDCON1                                      (0x04)
>> +#define VIDCON1_LINECNT_MASK                 (0x7ff << 16)
>> +#define VIDCON1_LINECNT_SHIFT                        (16)
>> +#define VIDCON1_LINECNT_GET(_v)                      (((_v) >> 16) & 0x7ff)
>> +#define VIDCON1_VSTATUS_MASK                 (0x3 << 13)
>> +#define VIDCON1_VSTATUS_SHIFT                        (13)
>> +#define VIDCON1_VSTATUS_VSYNC                        (0x0 << 13)
>> +#define VIDCON1_VSTATUS_BACKPORCH            (0x1 << 13)
>> +#define VIDCON1_VSTATUS_ACTIVE                       (0x2 << 13)
>> +#define VIDCON1_VSTATUS_FRONTPORCH           (0x0 << 13)
>> +#define VIDCON1_VCLK_MASK                    (0x3 << 9)
>> +#define VIDCON1_VCLK_HOLD                    (0x0 << 9)
>> +#define VIDCON1_VCLK_RUN                     (0x1 << 9)
>> +
>> +#define VIDCON1_INV_VCLK                     (1 << 7)
>> +#define VIDCON1_INV_HSYNC                    (1 << 6)
>> +#define VIDCON1_INV_VSYNC                    (1 << 5)
>> +#define VIDCON1_INV_VDEN                     (1 << 4)
>> +
>> +/* VIDCON2 */
>> +
>> +#define VIDCON2                                      (0x08)
>> +#define VIDCON2_EN601                                (1 << 23)
>> +#define VIDCON2_TVFMTSEL_SW                  (1 << 14)
>> +
>> +#define VIDCON2_TVFMTSEL1_MASK                       (0x3 << 12)
>> +#define VIDCON2_TVFMTSEL1_SHIFT                      (12)
>> +#define VIDCON2_TVFMTSEL1_RGB                        (0x0 << 12)
>> +#define VIDCON2_TVFMTSEL1_YUV422             (0x1 << 12)
>> +#define VIDCON2_TVFMTSEL1_YUV444             (0x2 << 12)
>> +
>> +#define VIDCON2_ORGYCbCr                     (1 << 8)
>> +#define VIDCON2_YUVORDCrCb                   (1 << 7)
>> +
>> +/* PRTCON (S3C6410, S5PC100)
>> + * Might not be present in the S3C6410 documentation,
>> + * but tests prove it's there almost for sure; shouldn't hurt in any case.
>> + */
>> +#define PRTCON                                       (0x0c)
>> +#define PRTCON_PROTECT                               (1 << 11)
>> +
>> +/* VIDTCON0 */
>> +
>> +#define VIDTCON0_VBPDE_MASK                  (0xff << 24)
>> +#define VIDTCON0_VBPDE_SHIFT                 (24)
>> +#define VIDTCON0_VBPDE_LIMIT                 (0xff)
>> +#define VIDTCON0_VBPDE(_x)                   ((_x) << 24)
>> +
>> +#define VIDTCON0_VBPD_MASK                   (0xff << 16)
>> +#define VIDTCON0_VBPD_SHIFT                  (16)
>> +#define VIDTCON0_VBPD_LIMIT                  (0xff)
>> +#define VIDTCON0_VBPD(_x)                    ((_x) << 16)
>> +
>> +#define VIDTCON0_VFPD_MASK                   (0xff << 8)
>> +#define VIDTCON0_VFPD_SHIFT                  (8)
>> +#define VIDTCON0_VFPD_LIMIT                  (0xff)
>> +#define VIDTCON0_VFPD(_x)                    ((_x) << 8)
>> +
>> +#define VIDTCON0_VSPW_MASK                   (0xff << 0)
>> +#define VIDTCON0_VSPW_SHIFT                  (0)
>> +#define VIDTCON0_VSPW_LIMIT                  (0xff)
>> +#define VIDTCON0_VSPW(_x)                    ((_x) << 0)
>> +
>> +/* VIDTCON1 */
>> +
>> +#define VIDTCON1_VFPDE_MASK                  (0xff << 24)
>> +#define VIDTCON1_VFPDE_SHIFT                 (24)
>> +#define VIDTCON1_VFPDE_LIMIT                 (0xff)
>> +#define VIDTCON1_VFPDE(_x)                   ((_x) << 24)
>> +
>> +#define VIDTCON1_HBPD_MASK                   (0xff << 16)
>> +#define VIDTCON1_HBPD_SHIFT                  (16)
>> +#define VIDTCON1_HBPD_LIMIT                  (0xff)
>> +#define VIDTCON1_HBPD(_x)                    ((_x) << 16)
>> +
>> +#define VIDTCON1_HFPD_MASK                   (0xff << 8)
>> +#define VIDTCON1_HFPD_SHIFT                  (8)
>> +#define VIDTCON1_HFPD_LIMIT                  (0xff)
>> +#define VIDTCON1_HFPD(_x)                    ((_x) << 8)
>> +
>> +#define VIDTCON1_HSPW_MASK                   (0xff << 0)
>> +#define VIDTCON1_HSPW_SHIFT                  (0)
>> +#define VIDTCON1_HSPW_LIMIT                  (0xff)
>> +#define VIDTCON1_HSPW(_x)                    ((_x) << 0)
>> +
>> +#define VIDTCON2                             (0x18)
>> +#define VIDTCON2_LINEVAL_E(_x)                       ((((_x) & 0x800) >> 11) << 23)
>> +#define VIDTCON2_LINEVAL_MASK                        (0x7ff << 11)
>> +#define VIDTCON2_LINEVAL_SHIFT                       (11)
>> +#define VIDTCON2_LINEVAL_LIMIT                       (0x7ff)
>> +#define VIDTCON2_LINEVAL(_x)                 (((_x) & 0x7ff) << 11)
>> +
>> +#define VIDTCON2_HOZVAL_E(_x)                        ((((_x) & 0x800) >> 11) << 22)
>> +#define VIDTCON2_HOZVAL_MASK                 (0x7ff << 0)
>> +#define VIDTCON2_HOZVAL_SHIFT                        (0)
>> +#define VIDTCON2_HOZVAL_LIMIT                        (0x7ff)
>> +#define VIDTCON2_HOZVAL(_x)                  (((_x) & 0x7ff) << 0)
>> +
>> +/* WINCONx */
>> +
>> +
>> +#define WINCONx_BITSWP                               (1 << 18)
>> +#define WINCONx_BYTSWP                               (1 << 17)
>> +#define WINCONx_HAWSWP                               (1 << 16)
>> +#define WINCONx_WSWP                         (1 << 15)
>> +#define WINCONx_BURSTLEN_MASK                        (0x3 << 9)
>> +#define WINCONx_BURSTLEN_SHIFT                       (9)
>> +#define WINCONx_BURSTLEN_16WORD                      (0x0 << 9)
>> +#define WINCONx_BURSTLEN_8WORD                       (0x1 << 9)
>> +#define WINCONx_BURSTLEN_4WORD                       (0x2 << 9)
>> +
>> +#define WINCONx_ENWIN                                (1 << 0)
>> +#define WINCON0_BPPMODE_MASK                 (0xf << 2)
>> +#define WINCON0_BPPMODE_SHIFT                        (2)
>> +#define WINCON0_BPPMODE_1BPP                 (0x0 << 2)
>> +#define WINCON0_BPPMODE_2BPP                 (0x1 << 2)
>> +#define WINCON0_BPPMODE_4BPP                 (0x2 << 2)
>> +#define WINCON0_BPPMODE_8BPP_PALETTE         (0x3 << 2)
>> +#define WINCON0_BPPMODE_16BPP_565            (0x5 << 2)
>> +#define WINCON0_BPPMODE_16BPP_1555           (0x7 << 2)
>> +#define WINCON0_BPPMODE_18BPP_666            (0x8 << 2)
>> +#define WINCON0_BPPMODE_24BPP_888            (0xb << 2)
>> +
>> +#define WINCON1_BLD_PIX                              (1 << 6)
>> +
>> +#define WINCON1_ALPHA_SEL                    (1 << 1)
>> +#define WINCON1_BPPMODE_MASK                 (0xf << 2)
>> +#define WINCON1_BPPMODE_SHIFT                        (2)
>> +#define WINCON1_BPPMODE_1BPP                 (0x0 << 2)
>> +#define WINCON1_BPPMODE_2BPP                 (0x1 << 2)
>> +#define WINCON1_BPPMODE_4BPP                 (0x2 << 2)
>> +#define WINCON1_BPPMODE_8BPP_PALETTE         (0x3 << 2)
>> +#define WINCON1_BPPMODE_8BPP_1232            (0x4 << 2)
>> +#define WINCON1_BPPMODE_16BPP_565            (0x5 << 2)
>> +#define WINCON1_BPPMODE_16BPP_A1555          (0x6 << 2)
>> +#define WINCON1_BPPMODE_16BPP_I1555          (0x7 << 2)
>> +#define WINCON1_BPPMODE_18BPP_666            (0x8 << 2)
>> +#define WINCON1_BPPMODE_18BPP_A1665          (0x9 << 2)
>> +#define WINCON1_BPPMODE_19BPP_A1666          (0xa << 2)
>> +#define WINCON1_BPPMODE_24BPP_888            (0xb << 2)
>> +#define WINCON1_BPPMODE_24BPP_A1887          (0xc << 2)
>> +#define WINCON1_BPPMODE_25BPP_A1888          (0xd << 2)
>> +#define WINCON1_BPPMODE_28BPP_A4888          (0xd << 2)
>> +
>> +/* S5PV210 */
>> +#define SHADOWCON                            (0x34)
>> +#define SHADOWCON_WINx_PROTECT(_win)         (1 << (10 + (_win)))
>> +/* DMA channels (all windows) */
>> +#define SHADOWCON_CHx_ENABLE(_win)           (1 << (_win))
>> +/* Local input channels (windows 0-2) */
>> +#define SHADOWCON_CHx_LOCAL_ENABLE(_win)     (1 << (5 + (_win)))
>> +
>> +#define VIDOSDxA_TOPLEFT_X_E(_x)             ((((_x) & 0x800) >> 11) << 23)
>> +#define VIDOSDxA_TOPLEFT_X_MASK                      (0x7ff << 11)
>> +#define VIDOSDxA_TOPLEFT_X_SHIFT             (11)
>> +#define VIDOSDxA_TOPLEFT_X_LIMIT             (0x7ff)
>> +#define VIDOSDxA_TOPLEFT_X(_x)                       (((_x) & 0x7ff) << 11)
>> +
>> +#define VIDOSDxA_TOPLEFT_Y_E(_x)             ((((_x) & 0x800) >> 11) << 22)
>> +#define VIDOSDxA_TOPLEFT_Y_MASK                      (0x7ff << 0)
>> +#define VIDOSDxA_TOPLEFT_Y_SHIFT             (0)
>> +#define VIDOSDxA_TOPLEFT_Y_LIMIT             (0x7ff)
>> +#define VIDOSDxA_TOPLEFT_Y(_x)                       (((_x) & 0x7ff) << 0)
>> +
>> +#define VIDOSDxB_BOTRIGHT_X_E(_x)            ((((_x) & 0x800) >> 11) << 23)
>> +#define VIDOSDxB_BOTRIGHT_X_MASK             (0x7ff << 11)
>> +#define VIDOSDxB_BOTRIGHT_X_SHIFT            (11)
>> +#define VIDOSDxB_BOTRIGHT_X_LIMIT            (0x7ff)
>> +#define VIDOSDxB_BOTRIGHT_X(_x)                      (((_x) & 0x7ff) << 11)
>> +
>> +#define VIDOSDxB_BOTRIGHT_Y_E(_x)            ((((_x) & 0x800) >> 11) << 22)
>> +#define VIDOSDxB_BOTRIGHT_Y_MASK             (0x7ff << 0)
>> +#define VIDOSDxB_BOTRIGHT_Y_SHIFT            (0)
>> +#define VIDOSDxB_BOTRIGHT_Y_LIMIT            (0x7ff)
>> +#define VIDOSDxB_BOTRIGHT_Y(_x)                      (((_x) & 0x7ff) << 0)
>> +
>> +/* For VIDOSD[1..4]C */
>> +#define VIDISD14C_ALPHA0_R(_x)                       ((_x) << 20)
>> +#define VIDISD14C_ALPHA0_G_MASK                      (0xf << 16)
>> +#define VIDISD14C_ALPHA0_G_SHIFT             (16)
>> +#define VIDISD14C_ALPHA0_G_LIMIT             (0xf)
>> +#define VIDISD14C_ALPHA0_G(_x)                       ((_x) << 16)
>> +#define VIDISD14C_ALPHA0_B_MASK                      (0xf << 12)
>> +#define VIDISD14C_ALPHA0_B_SHIFT             (12)
>> +#define VIDISD14C_ALPHA0_B_LIMIT             (0xf)
>> +#define VIDISD14C_ALPHA0_B(_x)                       ((_x) << 12)
>> +#define VIDISD14C_ALPHA1_R_MASK                      (0xf << 8)
>> +#define VIDISD14C_ALPHA1_R_SHIFT             (8)
>> +#define VIDISD14C_ALPHA1_R_LIMIT             (0xf)
>> +#define VIDISD14C_ALPHA1_R(_x)                       ((_x) << 8)
>> +#define VIDISD14C_ALPHA1_G_MASK                      (0xf << 4)
>> +#define VIDISD14C_ALPHA1_G_SHIFT             (4)
>> +#define VIDISD14C_ALPHA1_G_LIMIT             (0xf)
>> +#define VIDISD14C_ALPHA1_G(_x)                       ((_x) << 4)
>> +#define VIDISD14C_ALPHA1_B_MASK                      (0xf << 0)
>> +#define VIDISD14C_ALPHA1_B_SHIFT             (0)
>> +#define VIDISD14C_ALPHA1_B_LIMIT             (0xf)
>> +#define VIDISD14C_ALPHA1_B(_x)                       ((_x) << 0)
>> +
>> +/* Video buffer addresses */
>> +#define VIDW_BUF_START(_buff)                        (0xA0 + ((_buff) * 8))
>> +#define VIDW_BUF_START1(_buff)                       (0xA4 + ((_buff) * 8))
>> +#define VIDW_BUF_END(_buff)                  (0xD0 + ((_buff) * 8))
>> +#define VIDW_BUF_END1(_buff)                 (0xD4 + ((_buff) * 8))
>> +#define VIDW_BUF_SIZE(_buff)                 (0x100 + ((_buff) * 4))
>> +
>> +#define VIDW_BUF_SIZE_OFFSET_E(_x)           ((((_x) & 0x2000) >> 13) << 27)
>> +#define VIDW_BUF_SIZE_OFFSET_MASK            (0x1fff << 13)
>> +#define VIDW_BUF_SIZE_OFFSET_SHIFT           (13)
>> +#define VIDW_BUF_SIZE_OFFSET_LIMIT           (0x1fff)
>> +#define VIDW_BUF_SIZE_OFFSET(_x)             (((_x) & 0x1fff) << 13)
>> +
>> +#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)                ((((_x) & 0x2000) >> 13) << 26)
>> +#define VIDW_BUF_SIZE_PAGEWIDTH_MASK         (0x1fff << 0)
>> +#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT                (0)
>> +#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT                (0x1fff)
>> +#define VIDW_BUF_SIZE_PAGEWIDTH(_x)          (((_x) & 0x1fff) << 0)
>> +
>> +/* Interrupt controls and status */
>> +
>> +#define VIDINTCON0_FIFOINTERVAL_MASK         (0x3f << 20)
>> +#define VIDINTCON0_FIFOINTERVAL_SHIFT                (20)
>> +#define VIDINTCON0_FIFOINTERVAL_LIMIT                (0x3f)
>> +#define VIDINTCON0_FIFOINTERVAL(_x)          ((_x) << 20)
>> +
>> +#define VIDINTCON0_INT_SYSMAINCON            (1 << 19)
>> +#define VIDINTCON0_INT_SYSSUBCON             (1 << 18)
>> +#define VIDINTCON0_INT_I80IFDONE             (1 << 17)
>> +
>> +#define VIDINTCON0_FRAMESEL0_MASK            (0x3 << 15)
>> +#define VIDINTCON0_FRAMESEL0_SHIFT           (15)
>> +#define VIDINTCON0_FRAMESEL0_BACKPORCH               (0x0 << 15)
>> +#define VIDINTCON0_FRAMESEL0_VSYNC           (0x1 << 15)
>> +#define VIDINTCON0_FRAMESEL0_ACTIVE          (0x2 << 15)
>> +#define VIDINTCON0_FRAMESEL0_FRONTPORCH              (0x3 << 15)
>> +
>> +#define VIDINTCON0_FRAMESEL1                 (1 << 13)
>> +#define VIDINTCON0_FRAMESEL1_MASK            (0x3 << 13)
>> +#define VIDINTCON0_FRAMESEL1_NONE            (0x0 << 13)
>> +#define VIDINTCON0_FRAMESEL1_BACKPORCH               (0x1 << 13)
>> +#define VIDINTCON0_FRAMESEL1_VSYNC           (0x2 << 13)
>> +#define VIDINTCON0_FRAMESEL1_FRONTPORCH              (0x3 << 13)
>> +
>> +#define VIDINTCON0_INT_FRAME                 (1 << 12)
>> +#define VIDINTCON0_FIFIOSEL_MASK             (0x7f << 5)
>> +#define VIDINTCON0_FIFIOSEL_SHIFT            (5)
>> +#define VIDINTCON0_FIFIOSEL_WINDOW0          (0x1 << 5)
>> +#define VIDINTCON0_FIFIOSEL_WINDOW1          (0x2 << 5)
>> +
>> +#define VIDINTCON0_FIFOLEVEL_MASK            (0x7 << 2)
>> +#define VIDINTCON0_FIFOLEVEL_SHIFT           (2)
>> +#define VIDINTCON0_FIFOLEVEL_TO25PC          (0x0 << 2)
>> +#define VIDINTCON0_FIFOLEVEL_TO50PC          (0x1 << 2)
>> +#define VIDINTCON0_FIFOLEVEL_TO75PC          (0x2 << 2)
>> +#define VIDINTCON0_FIFOLEVEL_EMPTY           (0x3 << 2)
>> +#define VIDINTCON0_FIFOLEVEL_FULL            (0x4 << 2)
>> +
>> +#define VIDINTCON0_INT_FIFO_MASK             (0x3 << 0)
>> +#define VIDINTCON0_INT_FIFO_SHIFT            (0)
>> +#define VIDINTCON0_INT_ENABLE                        (1 << 0)
>> +
>> +#define VIDINTCON1                           (0x134)
>> +#define VIDINTCON1_INT_I180                  (1 << 2)
>> +#define VIDINTCON1_INT_FRAME                 (1 << 1)
>> +#define VIDINTCON1_INT_FIFO                  (1 << 0)
>> +
>> +/* Window colour-key control registers */
>> +#define WKEYCON                                      (0x140) /* 6410,V210 */
>> +
>> +#define WKEYCON0                             (0x00)
>> +#define WKEYCON1                             (0x04)
>> +
>> +#define WxKEYCON0_KEYBL_EN                   (1 << 26)
>> +#define WxKEYCON0_KEYEN_F                    (1 << 25)
>> +#define WxKEYCON0_DIRCON                     (1 << 24)
>> +#define WxKEYCON0_COMPKEY_MASK                       (0xffffff << 0)
>> +#define WxKEYCON0_COMPKEY_SHIFT                      (0)
>> +#define WxKEYCON0_COMPKEY_LIMIT                      (0xffffff)
>> +#define WxKEYCON0_COMPKEY(_x)                        ((_x) << 0)
>> +#define WxKEYCON1_COLVAL_MASK                        (0xffffff << 0)
>> +#define WxKEYCON1_COLVAL_SHIFT                       (0)
>> +#define WxKEYCON1_COLVAL_LIMIT                       (0xffffff)
>> +#define WxKEYCON1_COLVAL(_x)                 ((_x) << 0)
>> +
>> +
>> +/* Window blanking (MAP) */
>> +
>> +#define WINxMAP_MAP                          (1 << 24)
>> +#define WINxMAP_MAP_COLOUR_MASK                      (0xffffff << 0)
>> +#define WINxMAP_MAP_COLOUR_SHIFT             (0)
>> +#define WINxMAP_MAP_COLOUR_LIMIT             (0xffffff)
>> +#define WINxMAP_MAP_COLOUR(_x)                       ((_x) << 0)
>> +
>> +#define WPALCON_PAL_UPDATE                   (1 << 9)
>> +#define WPALCON_W1PAL_MASK                   (0x7 << 3)
>> +#define WPALCON_W1PAL_SHIFT                  (3)
>> +#define WPALCON_W1PAL_25BPP_A888             (0x0 << 3)
>> +#define WPALCON_W1PAL_24BPP                  (0x1 << 3)
>> +#define WPALCON_W1PAL_19BPP_A666             (0x2 << 3)
>> +#define WPALCON_W1PAL_18BPP_A665             (0x3 << 3)
>> +#define WPALCON_W1PAL_18BPP                  (0x4 << 3)
>> +#define WPALCON_W1PAL_16BPP_A555             (0x5 << 3)
>> +#define WPALCON_W1PAL_16BPP_565                      (0x6 << 3)
>> +
>> +#define WPALCON_W0PAL_MASK                   (0x7 << 0)
>> +#define WPALCON_W0PAL_SHIFT                  (0)
>> +#define WPALCON_W0PAL_25BPP_A888             (0x0 << 0)
>> +#define WPALCON_W0PAL_24BPP                  (0x1 << 0)
>> +#define WPALCON_W0PAL_19BPP_A666             (0x2 << 0)
>> +#define WPALCON_W0PAL_18BPP_A665             (0x3 << 0)
>> +#define WPALCON_W0PAL_18BPP                  (0x4 << 0)
>> +#define WPALCON_W0PAL_16BPP_A555             (0x5 << 0)
>> +#define WPALCON_W0PAL_16BPP_565                      (0x6 << 0)
>> +
>> +/* Blending equation control */
>> +#define BLENDCON                             (0x260)
>> +#define BLENDCON_NEW_MASK                    (1 << 0)
>> +#define BLENDCON_NEW_8BIT_ALPHA_VALUE                (1 << 0)
>> +#define BLENDCON_NEW_4BIT_ALPHA_VALUE                (0 << 0)
>> +
>> +#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
>> +#define VIDCON1_FSTATUS_EVEN (1 << 15)
>> +
>> +/* Video timing controls */
>> +#define VIDTCON0                             (0x10)
>> +#define VIDTCON1                             (0x14)
>> +#define VIDTCON2                             (0x18)
>> +
>> +/* Window position controls */
>> +
>> +#define WINCON(_win)                         (0x20 + ((_win) * 4))
>> +
>> +/* OSD1 and OSD4 do not have register D */
>> +
>> +#define VIDOSD_BASE                          (0x40)
>> +
>> +#define VIDINTCON0                           (0x130)
>> +
>> +/* WINCONx */
>> +
>> +#define WINCONx_CSCWIDTH_MASK                        (0x3 << 26)
>> +#define WINCONx_CSCWIDTH_SHIFT                       (26)
>> +#define WINCONx_CSCWIDTH_WIDE                        (0x0 << 26)
>> +#define WINCONx_CSCWIDTH_NARROW                      (0x3 << 26)
>> +
>> +#define WINCONx_ENLOCAL                              (1 << 22)
>> +#define WINCONx_BUFSTATUS                    (1 << 21)
>> +#define WINCONx_BUFSEL                               (1 << 20)
>> +#define WINCONx_BUFAUTOEN                    (1 << 19)
>> +#define WINCONx_YCbCr                                (1 << 13)
>> +
>> +#define WINCON1_LOCALSEL_CAMIF                       (1 << 23)
>> +
>> +#define WINCON2_LOCALSEL_CAMIF                       (1 << 23)
>> +#define WINCON2_BLD_PIX                              (1 << 6)
>> +
>> +#define WINCON2_ALPHA_SEL                    (1 << 1)
>> +#define WINCON2_BPPMODE_MASK                 (0xf << 2)
>> +#define WINCON2_BPPMODE_SHIFT                        (2)
>> +#define WINCON2_BPPMODE_1BPP                 (0x0 << 2)
>> +#define WINCON2_BPPMODE_2BPP                 (0x1 << 2)
>> +#define WINCON2_BPPMODE_4BPP                 (0x2 << 2)
>> +#define WINCON2_BPPMODE_8BPP_1232            (0x4 << 2)
>> +#define WINCON2_BPPMODE_16BPP_565            (0x5 << 2)
>> +#define WINCON2_BPPMODE_16BPP_A1555          (0x6 << 2)
>> +#define WINCON2_BPPMODE_16BPP_I1555          (0x7 << 2)
>> +#define WINCON2_BPPMODE_18BPP_666            (0x8 << 2)
>> +#define WINCON2_BPPMODE_18BPP_A1665          (0x9 << 2)
>> +#define WINCON2_BPPMODE_19BPP_A1666          (0xa << 2)
>> +#define WINCON2_BPPMODE_24BPP_888            (0xb << 2)
>> +#define WINCON2_BPPMODE_24BPP_A1887          (0xc << 2)
>> +#define WINCON2_BPPMODE_25BPP_A1888          (0xd << 2)
>> +#define WINCON2_BPPMODE_28BPP_A4888          (0xd << 2)
>> +
>> +#define WINCON3_BLD_PIX                              (1 << 6)
>> +
>> +#define WINCON3_ALPHA_SEL                    (1 << 1)
>> +#define WINCON3_BPPMODE_MASK                 (0xf << 2)
>> +#define WINCON3_BPPMODE_SHIFT                        (2)
>> +#define WINCON3_BPPMODE_1BPP                 (0x0 << 2)
>> +#define WINCON3_BPPMODE_2BPP                 (0x1 << 2)
>> +#define WINCON3_BPPMODE_4BPP                 (0x2 << 2)
>> +#define WINCON3_BPPMODE_16BPP_565            (0x5 << 2)
>> +#define WINCON3_BPPMODE_16BPP_A1555          (0x6 << 2)
>> +#define WINCON3_BPPMODE_16BPP_I1555          (0x7 << 2)
>> +#define WINCON3_BPPMODE_18BPP_666            (0x8 << 2)
>> +#define WINCON3_BPPMODE_18BPP_A1665          (0x9 << 2)
>> +#define WINCON3_BPPMODE_19BPP_A1666          (0xa << 2)
>> +#define WINCON3_BPPMODE_24BPP_888            (0xb << 2)
>> +#define WINCON3_BPPMODE_24BPP_A1887          (0xc << 2)
>> +#define WINCON3_BPPMODE_25BPP_A1888          (0xd << 2)
>> +#define WINCON3_BPPMODE_28BPP_A4888          (0xd << 2)
>> +
>> +#define VIDINTCON0_FIFIOSEL_WINDOW2          (0x10 << 5)
>> +#define VIDINTCON0_FIFIOSEL_WINDOW3          (0x20 << 5)
>> +#define VIDINTCON0_FIFIOSEL_WINDOW4          (0x40 << 5)
>> +
>> +#define DITHMODE                             (0x170)
>> +#define WINxMAP(_win)                                (0x180 + ((_win) * 4))
>> +
>> +
>> +#define DITHMODE_R_POS_MASK                  (0x3 << 5)
>> +#define DITHMODE_R_POS_SHIFT                 (5)
>> +#define DITHMODE_R_POS_8BIT                  (0x0 << 5)
>> +#define DITHMODE_R_POS_6BIT                  (0x1 << 5)
>> +#define DITHMODE_R_POS_5BIT                  (0x2 << 5)
>> +
>> +#define DITHMODE_G_POS_MASK                  (0x3 << 3)
>> +#define DITHMODE_G_POS_SHIFT                 (3)
>> +#define DITHMODE_G_POS_8BIT                  (0x0 << 3)
>> +#define DITHMODE_G_POS_6BIT                  (0x1 << 3)
>> +#define DITHMODE_G_POS_5BIT                  (0x2 << 3)
>> +
>> +#define DITHMODE_B_POS_MASK                  (0x3 << 1)
>> +#define DITHMODE_B_POS_SHIFT                 (1)
>> +#define DITHMODE_B_POS_8BIT                  (0x0 << 1)
>> +#define DITHMODE_B_POS_6BIT                  (0x1 << 1)
>> +#define DITHMODE_B_POS_5BIT                  (0x2 << 1)
>> +
>> +#define DITHMODE_DITH_EN                     (1 << 0)
>> +
>> +#define WPALCON                                      (0x1A0)
>> +
>> +/* Palette control */
>> +/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
>> + * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
>> +#define WPALCON_W4PAL_16BPP_A555             (1 << 8)
>> +#define WPALCON_W3PAL_16BPP_A555             (1 << 7)
>> +#define WPALCON_W2PAL_16BPP_A555             (1 << 6)
>> +
>> +
>> +/* Notes on per-window bpp settings
>> + *
>> + * Value     Win0     Win1     Win2     Win3     Win 4
>> + * 0000              1(P)     1(P)     1(P)     1(P)     1(P)
>> + * 0001              2(P)     2(P)     2(P)     2(P)     2(P)
>> + * 0010              4(P)     4(P)     4(P)     4(P)     -none-
>> + * 0011              8(P)     8(P)     -none-   -none-   -none-
>> + * 0100              -none-   8(A232)  8(A232)  -none-   -none-
>> + * 0101              16(565)  16(565)  16(565)  16(565)   16(565)
>> + * 0110              -none-   16(A555) 16(A555) 16(A555)  16(A555)
>> + * 0111              16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
>> + * 1000              18(666)  18(666)  18(666)  18(666)   18(666)
>> + * 1001              -none-   18(A665) 18(A665) 18(A665)  16(A665)
>> + * 1010              -none-   19(A666) 19(A666) 19(A666)  19(A666)
>> + * 1011              24(888)  24(888)  24(888)  24(888)   24(888)
>> + * 1100              -none-   24(A887) 24(A887) 24(A887)  24(A887)
>> + * 1101              -none-   25(A888) 25(A888) 25(A888)  25(A888)
>> + * 1110              -none-   -none-   -none-   -none-    -none-
>> + * 1111              -none-   -none-   -none-   -none-    -none-
>> +*/
>> +
>> +/*FIMD V8 REG OFFSET */
>> +#define FIMD_V8_VIDTCON0     (0x20010)
>> +#define FIMD_V8_VIDTCON1     (0x20014)
>> +#define FIMD_V8_VIDTCON2     (0x20018)
>> +#define FIMD_V8_VIDTCON3     (0x2001C)
>> +#define FIMD_V8_VIDCON1              (0x20004)
>
>
> CC'ed Marek.
>
> To Leela Krishna Amudala,
>
> Don't add these definitions for FIMD_V8_xxx registers, which are not related to current "regs-fb-v4.h and regs-fb.h".
> Just "move" and "merge" regs-fb-v4.h and regs-fb.h to one header file, not "add" new definitions.
> If you want to add these definitions, please make new patch for this.
>

Will do it in the suggested way,


> Also, "#define FIMD_V8_xxx" is ugly.
> I think that there is better way.
> Please, find other way.
>
>

I used FIMD_V8_xxx instead of  EXYNOS5_FIMD_*, because in future,
there is a possibility that version 8 FIMD can be used in other
application processors also.
Thanks for reviewing the patch.

Best Wishes,
Leela Krishna.

>> --
>> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/3] Move FIMD register headers to include/video/
From: Leela Krishna Amudala @ 2012-07-30 11:17 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-arm-kernel, linux-samsung-soc, dri-devel, linux-fbdev,
	ben-linux, inki.dae, kgene.kim, joshi, Jingoo Han,
	Marek Szyprowski
In-Reply-To: <50164A8B.3070907@samsung.com>

Hello Sylwester,

On Mon, Jul 30, 2012 at 2:19 PM, Sylwester Nawrocki
<s.nawrocki@samsung.com> wrote:
>
> Hi,
>
> On 07/30/2012 10:45 AM, Leela Krishna Amudala wrote:
> > Moved the contents of regs-fb-v4.h and regs-fb.h from arch side
> > to include/video/samsung_fimd.h
> >
> > Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
> > ---
> >  arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 -------
> >  arch/arm/plat-samsung/include/plat/regs-fb.h    |  403 -----------------
> >  include/video/samsung_fimd.h                    |  533 +++++++++++++++++++++++
> >  3 files changed, 533 insertions(+), 562 deletions(-)
> >  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
> >  create mode 100644 include/video/samsung_fimd.h
>
> Thanks for taking care if this. However you might need to split this
> patch in two, so there is no build and git bisection breakage. In the
> first patch a new header file would be added, then the patch updating
> users of the FIMD headers would be applied, and finally the regs-fb*.h
> files would be removed.
>
> Also it helps to use -M option to git format-patch when creating patches
> that mainly move files.
>

Will do it in the suggested way,
Thanks for reviewing the patch.

> --
>
> Regards,
> Sylwester
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Simon Glass @ 2012-07-30 11:00 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: Stephen Warren, Thierry Reding, Grant Likely, Rob Herring,
	Greg Kroah-Hartman, Mark Brown, Arnd Bergmann,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1343390750-3642-2-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Hi,

On Fri, Jul 27, 2012 at 1:05 PM, Alexandre Courbot <acourbot@nvidia.com> wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
>
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.

This all looks very reasonable to me, just a few comments.

>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  Documentation/power/power_seq.txt | 120 +++++++++++++++
>  drivers/base/Kconfig              |   4 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>  include/linux/power_seq.h         | 139 ++++++++++++++++++
>  5 files changed, 564 insertions(+)
>  create mode 100644 Documentation/power/power_seq.txt
>  create mode 100644 drivers/base/power_seq.c
>  create mode 100644 include/linux/power_seq.h
>
> diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
> new file mode 100644
> index 0000000..aa2ceb5
> --- /dev/null
> +++ b/Documentation/power/power_seq.txt
> @@ -0,0 +1,120 @@
> +Runtime Interpreted Power Sequences
> +-----------------------------------
> +
> +Problem
> +-------
> +One very common board-dependent code is the out-of-driver code that is used to
> +turn a device on or off. For instance, SoC boards very commonly use a GPIO
> +(abstracted to a regulator or not) to control the power supply of a backlight,
> +disabling it when the backlight is not used in order to save power. The GPIO
> +that should be used, however, as well as the exact power sequence that may
> +involve different resources, is board-dependent and thus unknown of the driver.
> +
> +This has been addressed so far by using hooks in the device's platform data that
> +are called whenever the state of the device might reflect a power change. This
> +approach, however, introduces board-dependant code into the kernel and is not
> +compatible with the device tree.
> +
> +The Runtime Interpreted Power Sequences (or power sequences for short) aim at
> +turning this code into platform data or device tree nodes. Power sequences are
> +described using a simple format and run by a simple interpreter whenever needed.
> +This allows to remove the callback mechanism and makes the kernel less
> +board-dependant.
> +
> +Sequences Format
> +----------------
> +Power sequences are a series of sequential steps during which an action is
> +performed on a resource. The supported resources so far are:
> +- GPIOs
> +- Regulators
> +- PWMs
> +
> +Each step designates a resource and the following parameters:
> +- Whether the step should enable or disable the resource,
> +- Delay to wait before performing the action,
> +- Delay to wait after performing the action.
> +
> +Both new resources and parameters can be introduced, but the goal is of course
> +to keep things as simple and compact as possible.
> +
> +The platform data is a simple array of platform_power_seq_step instances, each
> +instance describing a step. The type as well as one of id or gpio members
> +(depending on the type) must be specified. The last step must be of type
> +POWER_SEQ_STOP. Regulator and PWM resources are identified by name. GPIO are
> +identified by number. For example, the following sequence will turn on the
> +"power" regulator of the device, wait 10ms, and set GPIO number 110 to 1:

For the delay, I think milliseconds is reasonable. I suppose there is
no reasonable need for microseconds?

> +
> +struct platform_power_seq_step power_on_seq[] = {
> +       {
> +               .type = POWER_SEQ_REGULATOR,
> +               .id = "power",
> +               .params = {
> +                       .enable = 1,
> +                       .post_delay = 10,
> +               },
> +       },
> +       {
> +               .type = POWER_SEQ_GPIO,
> +               .gpio = 110,
> +               .params = {
> +                       .enable = 1,
> +               },
> +       },
> +       {
> +               .type = POWER_SEQ_STOP,
> +       },
> +};
> +
> +Usage by Drivers and Resources Management
> +-----------------------------------------
> +Power sequences make use of resources that must be properly allocated and
> +managed. The power_seq_build() function takes care of resolving the resources as
> +they are met in the sequence and to allocate them if needed:
> +
> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> +                          platform_power_seq *pseq);
> +
> +You will need an instance of power_seq_resources to keep track of the resources
> +that are already allocated. On success, the function returns a devm allocated
> +resolved sequence that is ready to be passed to power_seq_run(). In case of
> +failure, and error code is returned.
> +
> +A resolved power sequence returned by power_seq_build can be run by
> +power_run_run():
> +
> +int power_seq_run(struct device *dev, power_seq *seq);
> +
> +It returns 0 if the sequence has successfully been run, or an error code if a
> +problem occured.
> +
> +Finally, some resources that cannot be allocated through devm need to be freed
> +manually. Therefore, be sure to call power_seq_free_resources() in your device
> +remove function:
> +
> +void power_seq_free_resources(power_seq_resources *ress);
> +
> +Device tree
> +-----------
> +All the same, power sequences can be encoded as device tree nodes. The following
> +properties and nodes are equivalent to the platform data defined previously:
> +
> +               power-supply = <&mydevice_reg>;
> +               enable-gpio = <&gpio 6 0>;
> +
> +               power-on-sequence {
> +                       regulator@0 {
> +                               id = "power";

Is there a reason not to put the phandle here, like:

                                   id = <&mydevice_reg>;

(or maybe 'device' instead of id?)

> +                               enable;
> +                               post-delay = <10>;
> +                       };
> +                       gpio@1 {
> +                               id = "enable-gpio";
> +                               enable;
> +                       };
> +               };
> +
> +Note that first, the phandles of the regulator and gpio used in the sequences
> +are defined as properties. Then the sequence references them through the id
> +property of every step. The name of sub-properties defines the type of the step.
> +Valid names are "regulator", "gpio" and "pwm". Steps must be numbered
> +sequentially.

For the regulator and gpio types I think you only have an enable. For
the pwm, what is the intended binding? Is that documented elsewhere?

Also it might be worth mentioning how you get a struct power_seq from
an fdt node, and perhaps given an example of a device which has an
attached node, so we can see how it is referenced from the device
(of_parse_power_seq I think). Do put the sequence inside the device
node or reference it with a phandle?

Finally, should you use typedefs?

Regards,
Simon

^ permalink raw reply

* [PATCH] Fix newport con crashes
From: Thomas Bogendoerfer @ 2012-07-30 10:54 UTC (permalink / raw)
  To: linux-mips, linux-fbdev; +Cc: ralf, FlorianSchandinat

Because of commit e84de0c61905030a0fe66b7210b6f1bb7c3e1eab
[MIPS: GIO bus support for SGI IP22/28] newport con is now taking over
console from dummy con, therefore it's necessary to resize the VC to
the correct size to avoid crashes and garbage on console

Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---

 drivers/video/console/newport_con.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 6d15966..b05afd0 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -327,9 +327,16 @@ out_unmap:
 
 static void newport_init(struct vc_data *vc, int init)
 {
-	vc->vc_cols = newport_xsize / 8;
-	vc->vc_rows = newport_ysize / 16;
+	int cols, rows;
+
+	cols = newport_xsize / 8;
+	rows = newport_ysize / 16;
 	vc->vc_can_do_color = 1;
+	if (init) {
+		vc->vc_cols = cols;
+		vc->vc_rows = rows;
+	} else
+		vc_resize(vc, cols, rows);
 }
 
 static void newport_deinit(struct vc_data *c)

^ permalink raw reply related

* Re: [PATCH 1/3] Move FIMD register headers to include/video/
From: Sylwester Nawrocki @ 2012-07-30  9:09 UTC (permalink / raw)
  To: Jingoo Han
  Cc: 'Leela Krishna Amudala', linux-arm-kernel,
	linux-samsung-soc, dri-devel, linux-fbdev, ben-linux, inki.dae,
	kgene.kim, joshi, 'Marek Szyprowski'
In-Reply-To: <000001cd6e30$da849520$8f8dbf60$%han@samsung.com>

Hi,

On 07/30/2012 10:53 AM, Jingoo Han wrote:
>> +/*FIMD V8 REG OFFSET */
>> +#define FIMD_V8_VIDTCON0	(0x20010)
>> +#define FIMD_V8_VIDTCON1	(0x20014)
>> +#define FIMD_V8_VIDTCON2	(0x20018)
>> +#define FIMD_V8_VIDTCON3	(0x2001C)
>> +#define FIMD_V8_VIDCON1		(0x20004)
> 
> 
> CC'ed Marek.
> 
> To Leela Krishna Amudala,
> 
> Don't add these definitions for FIMD_V8_xxx registers, which are 
> not related to current "regs-fb-v4.h and regs-fb.h".
> Just "move" and "merge" regs-fb-v4.h and regs-fb.h to one header 
> file, not "add" new definitions.
> If you want to add these definitions, please make new patch for this.

Good point.

> Also, "#define FIMD_V8_xxx" is ugly.
> I think that there is better way.
> Please, find other way.

Instead of just telling that something is wrong and you don't like it, 
perhaps it would be kind to give at least a slight suggestion of what 
would have been good enough to your taste...respecting someone else's
time and effort.

So what would you like to see there instead, EXYNOS5_FIMD_* ?

BTW, your e-mails are badly word wrapped, I had to manually correct it.

-- 

Regards,
Sylwester

^ permalink raw reply

* [PATCH 3/3] driver: Include the modified FIMD header file
From: Leela Krishna Amudala @ 2012-07-30  8:57 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: dri-devel, linux-fbdev, ben-linux, inki.dae, kgene.kim, joshi,
	jg1.han
In-Reply-To: <1343637905-17764-1-git-send-email-l.krishna@samsung.com>

The fimd register headers have been moved to include/video/
hence, modifying the driver files accordingly.

Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c |    2 +-
 drivers/video/s3c-fb.c                   |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 29fdbfe..8da90f9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -20,7 +20,7 @@
 #include <linux/pm_runtime.h>
 
 #include <drm/exynos_drm.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fbdev.h"
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 69bf9d0..1226fdd 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -26,7 +26,7 @@
 #include <linux/pm_runtime.h>
 
 #include <mach/map.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/fb.h>
 
 /* This driver will export a number of framebuffer interfaces depending
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/3] arm: samsung: Include the modified FIMD header file
From: Leela Krishna Amudala @ 2012-07-30  8:57 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: dri-devel, linux-fbdev, ben-linux, inki.dae, kgene.kim, joshi,
	jg1.han
In-Reply-To: <1343637905-17764-1-git-send-email-l.krishna@samsung.com>

The fimd register headers have been moved to include/video/
hence, modifying the machine files accordingly.

Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
---
 arch/arm/mach-exynos/mach-nuri.c           |    2 +-
 arch/arm/mach-exynos/mach-origen.c         |    2 +-
 arch/arm/mach-exynos/mach-smdk4x12.c       |    2 +-
 arch/arm/mach-exynos/mach-smdkv310.c       |    2 +-
 arch/arm/mach-exynos/mach-universal_c210.c |    2 +-
 arch/arm/mach-exynos/setup-fimd0.c         |    2 +-
 arch/arm/mach-s3c24xx/mach-smdk2416.c      |    2 +-
 arch/arm/mach-s3c64xx/mach-anw6410.c       |    2 +-
 arch/arm/mach-s3c64xx/mach-crag6410.c      |    2 +-
 arch/arm/mach-s3c64xx/mach-hmt.c           |    2 +-
 arch/arm/mach-s3c64xx/mach-mini6410.c      |    2 +-
 arch/arm/mach-s3c64xx/mach-ncp.c           |    2 +-
 arch/arm/mach-s3c64xx/mach-real6410.c      |    2 +-
 arch/arm/mach-s3c64xx/mach-smartq5.c       |    2 +-
 arch/arm/mach-s3c64xx/mach-smartq7.c       |    2 +-
 arch/arm/mach-s3c64xx/mach-smdk6410.c      |    2 +-
 arch/arm/mach-s5p64x0/mach-smdk6440.c      |    2 +-
 arch/arm/mach-s5p64x0/mach-smdk6450.c      |    2 +-
 arch/arm/mach-s5pc100/mach-smdkc100.c      |    2 +-
 arch/arm/mach-s5pv210/mach-aquila.c        |    2 +-
 arch/arm/mach-s5pv210/mach-goni.c          |    2 +-
 arch/arm/mach-s5pv210/mach-smdkv210.c      |    2 +-
 22 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index f98a83a..573a0c4 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -39,7 +39,7 @@
 #include <asm/mach-types.h>
 
 #include <plat/adc.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/regs-serial.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 5a12dc2..c69707e 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -31,7 +31,7 @@
 #include <video/platform_lcd.h>
 
 #include <plat/regs-serial.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index b26beb1..8a8acff 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -35,7 +35,7 @@
 #include <plat/iic.h>
 #include <plat/keypad.h>
 #include <plat/mfc.h>
-#include <plat/regs-fb.h>
+#include <video/samsung_fimd.h>
 #include <plat/regs-serial.h>
 #include <plat/sdhci.h>
 
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 3cfa688..c2df6e8 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -28,7 +28,7 @@
 #include <video/platform_lcd.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 4d1f40d..e6fb471 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -39,7 +39,7 @@
 #include <plat/fb.h>
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/fimc-core.h>
 #include <plat/s5p-time.h>
 #include <plat/camport.h>
diff --git a/arch/arm/mach-exynos/setup-fimd0.c b/arch/arm/mach-exynos/setup-fimd0.c
index 07a6dbe..53c4c51 100644
--- a/arch/arm/mach-exynos/setup-fimd0.c
+++ b/arch/arm/mach-exynos/setup-fimd0.c
@@ -14,7 +14,7 @@
 #include <linux/gpio.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include <mach/map.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index c3100a0..c8d5f51 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -52,7 +52,7 @@
 #include <plat/udc.h>
 #include <linux/platform_data/s3c-hsudc.h>
 
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/fb.h>
 
 #include <plat/common-smdk.h>
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index ffa29dd..27e3087 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -44,7 +44,7 @@
 #include <plat/regs-serial.h>
 #include <plat/iic.h>
 #include <plat/fb.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include <plat/clock.h>
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 09cd812..66e8c69 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -57,7 +57,7 @@
 #include <mach/regs-gpio-memport.h>
 
 #include <plat/regs-serial.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index 6890881..ab78c5e 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -41,7 +41,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 5539a25..4b9a9ff 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -41,7 +41,7 @@
 #include <plat/nand.h>
 #include <plat/regs-serial.h>
 #include <plat/ts.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include <video/platform_lcd.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index cad2e05..d4c8af0 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -43,7 +43,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 326b216..05f05d2 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -42,7 +42,7 @@
 #include <plat/nand.h>
 #include <plat/regs-serial.h>
 #include <plat/ts.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include <video/platform_lcd.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index d6266d8..aa225ff 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -28,7 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 #include "mach-smartq.h"
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index 0957d2a..6e9c070 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -28,7 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 #include "mach-smartq.h"
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 0fe4f15..1803192 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -72,7 +72,7 @@
 #include <plat/ts.h>
 #include <plat/keypad.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 92fefad..0db0bdd 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -52,7 +52,7 @@
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
-#include <plat/regs-fb.h>
+#include <video/smasung_fimd.h>
 #include <plat/sdhci.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index e2335ec..c641d33 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -52,7 +52,7 @@
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
-#include <plat/regs-fb.h>
+#include <video/samsung_fimd.h>
 #include <plat/sdhci.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 0c3ae38..e4df3d0 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -51,7 +51,7 @@
 #include <plat/ts.h>
 #include <plat/audio.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 78028df..8cbe4ac 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -39,7 +39,7 @@
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
 #include <plat/s5p-time.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 822a559..e799a02 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -49,7 +49,7 @@
 #include <plat/clock.h>
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/camport.h>
 
 #include <media/v4l2-mediabus.h>
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 918b23d..3c569e5 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -46,7 +46,7 @@
 #include <plat/fb.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
+#include <video/samsung_fimd.h>
 #include <plat/mfc.h>
 #include <plat/clock.h>
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/3] Move FIMD register headers to include/video/
From: Leela Krishna Amudala @ 2012-07-30  8:57 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: dri-devel, linux-fbdev, ben-linux, inki.dae, kgene.kim, joshi,
	jg1.han
In-Reply-To: <1343637905-17764-1-git-send-email-l.krishna@samsung.com>

Moved the contents of regs-fb-v4.h and regs-fb.h from arch side
to include/video/samsung_fimd.h

Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
---
 arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 -------
 arch/arm/plat-samsung/include/plat/regs-fb.h    |  403 -----------------
 include/video/samsung_fimd.h                    |  533 +++++++++++++++++++++++
 3 files changed, 533 insertions(+), 562 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
 delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
 create mode 100644 include/video/samsung_fimd.h

diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
deleted file mode 100644
index 4c3647f..0000000
--- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - new-style framebuffer register definitions
- *
- * This is the register set for the new style framebuffer interface
- * found from the S3C2443 onwards and specifically the S3C64XX series
- * S3C6400 and S3C6410.
- *
- * The file contains the cpu specific items which change between whichever
- * architecture is selected. See <plat/regs-fb.h> for the core definitions
- * that are the same.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* include the core definitions here, in case we really do need to
- * override them at a later date.
-*/
-
-#include <plat/regs-fb.h>
-
-#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
-#define VIDCON1_FSTATUS_EVEN	(1 << 15)
-
-/* Video timing controls */
-#define VIDTCON0				(0x10)
-#define VIDTCON1				(0x14)
-#define VIDTCON2				(0x18)
-
-/* Window position controls */
-
-#define WINCON(_win)				(0x20 + ((_win) * 4))
-
-/* OSD1 and OSD4 do not have register D */
-
-#define VIDOSD_BASE				(0x40)
-
-#define VIDINTCON0				(0x130)
-
-/* WINCONx */
-
-#define WINCONx_CSCWIDTH_MASK			(0x3 << 26)
-#define WINCONx_CSCWIDTH_SHIFT			(26)
-#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26)
-#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26)
-
-#define WINCONx_ENLOCAL				(1 << 22)
-#define WINCONx_BUFSTATUS			(1 << 21)
-#define WINCONx_BUFSEL				(1 << 20)
-#define WINCONx_BUFAUTOEN			(1 << 19)
-#define WINCONx_YCbCr				(1 << 13)
-
-#define WINCON1_LOCALSEL_CAMIF			(1 << 23)
-
-#define WINCON2_LOCALSEL_CAMIF			(1 << 23)
-#define WINCON2_BLD_PIX				(1 << 6)
-
-#define WINCON2_ALPHA_SEL			(1 << 1)
-#define WINCON2_BPPMODE_MASK			(0xf << 2)
-#define WINCON2_BPPMODE_SHIFT			(2)
-#define WINCON2_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON2_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON2_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2)
-#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON2_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define WINCON3_BLD_PIX				(1 << 6)
-
-#define WINCON3_ALPHA_SEL			(1 << 1)
-#define WINCON3_BPPMODE_MASK			(0xf << 2)
-#define WINCON3_BPPMODE_SHIFT			(2)
-#define WINCON3_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON3_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON3_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON3_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5)
-
-#define DITHMODE				(0x170)
-#define WINxMAP(_win)				(0x180 + ((_win) * 4))
-
-
-#define DITHMODE_R_POS_MASK			(0x3 << 5)
-#define DITHMODE_R_POS_SHIFT			(5)
-#define DITHMODE_R_POS_8BIT			(0x0 << 5)
-#define DITHMODE_R_POS_6BIT			(0x1 << 5)
-#define DITHMODE_R_POS_5BIT			(0x2 << 5)
-
-#define DITHMODE_G_POS_MASK			(0x3 << 3)
-#define DITHMODE_G_POS_SHIFT			(3)
-#define DITHMODE_G_POS_8BIT			(0x0 << 3)
-#define DITHMODE_G_POS_6BIT			(0x1 << 3)
-#define DITHMODE_G_POS_5BIT			(0x2 << 3)
-
-#define DITHMODE_B_POS_MASK			(0x3 << 1)
-#define DITHMODE_B_POS_SHIFT			(1)
-#define DITHMODE_B_POS_8BIT			(0x0 << 1)
-#define DITHMODE_B_POS_6BIT			(0x1 << 1)
-#define DITHMODE_B_POS_5BIT			(0x2 << 1)
-
-#define DITHMODE_DITH_EN			(1 << 0)
-
-#define WPALCON					(0x1A0)
-
-/* Palette control */
-/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
- * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
-#define WPALCON_W4PAL_16BPP_A555		(1 << 8)
-#define WPALCON_W3PAL_16BPP_A555		(1 << 7)
-#define WPALCON_W2PAL_16BPP_A555		(1 << 6)
-
-
-/* Notes on per-window bpp settings
- *
- * Value	Win0	 Win1	  Win2	   Win3	    Win 4
- * 0000		1(P)	 1(P)	  1(P)	   1(P)	    1(P)
- * 0001		2(P)	 2(P)     2(P)	   2(P)	    2(P)
- * 0010		4(P)	 4(P)     4(P)	   4(P)     -none-
- * 0011		8(P)	 8(P)     -none-   -none-   -none-
- * 0100		-none-	 8(A232)  8(A232)  -none-   -none-
- * 0101		16(565)	 16(565)  16(565)  16(565)   16(565)
- * 0110		-none-	 16(A555) 16(A555) 16(A555)  16(A555)
- * 0111		16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
- * 1000		18(666)	 18(666)  18(666)  18(666)   18(666)
- * 1001		-none-	 18(A665) 18(A665) 18(A665)  16(A665)
- * 1010		-none-	 19(A666) 19(A666) 19(A666)  19(A666)
- * 1011		24(888)	 24(888)  24(888)  24(888)   24(888)
- * 1100		-none-	 24(A887) 24(A887) 24(A887)  24(A887)
- * 1101		-none-	 25(A888) 25(A888) 25(A888)  25(A888)
- * 1110		-none-	 -none-	  -none-   -none-    -none-
- * 1111		-none-	 -none-   -none-   -none-    -none-
-*/
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
deleted file mode 100644
index 9a78012..0000000
--- a/arch/arm/plat-samsung/include/plat/regs-fb.h
+++ /dev/null
@@ -1,403 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/regs-fb.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C Platform - new-style framebuffer register definitions
- *
- * This is the register set for the new style framebuffer interface
- * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
- * S3C64XX series such as the S3C6400 and S3C6410.
- *
- * The file does not contain the cpu specific items which are based on
- * whichever architecture is selected, it only contains the core of the
- * register set. See <mach/regs-fb.h> to get the specifics.
- *
- * Note, we changed to using regs-fb.h as it avoids any clashes with
- * the original regs-lcd.h so out of the way of regs-lcd.h as well as
- * indicating the newer block is much more than just an LCD interface.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* Please do not include this file directly, use <mach/regs-fb.h> to
- * ensure all the localised SoC support is included as necessary.
-*/
-
-/* VIDCON0 */
-
-#define VIDCON0					(0x00)
-#define VIDCON0_INTERLACE			(1 << 29)
-#define VIDCON0_VIDOUT_MASK			(0x3 << 26)
-#define VIDCON0_VIDOUT_SHIFT			(26)
-#define VIDCON0_VIDOUT_RGB			(0x0 << 26)
-#define VIDCON0_VIDOUT_TV			(0x1 << 26)
-#define VIDCON0_VIDOUT_I80_LDI0			(0x2 << 26)
-#define VIDCON0_VIDOUT_I80_LDI1			(0x3 << 26)
-
-#define VIDCON0_L1_DATA_MASK			(0x7 << 23)
-#define VIDCON0_L1_DATA_SHIFT			(23)
-#define VIDCON0_L1_DATA_16BPP			(0x0 << 23)
-#define VIDCON0_L1_DATA_18BPP16			(0x1 << 23)
-#define VIDCON0_L1_DATA_18BPP9			(0x2 << 23)
-#define VIDCON0_L1_DATA_24BPP			(0x3 << 23)
-#define VIDCON0_L1_DATA_18BPP			(0x4 << 23)
-#define VIDCON0_L1_DATA_16BPP8			(0x5 << 23)
-
-#define VIDCON0_L0_DATA_MASK			(0x7 << 20)
-#define VIDCON0_L0_DATA_SHIFT			(20)
-#define VIDCON0_L0_DATA_16BPP			(0x0 << 20)
-#define VIDCON0_L0_DATA_18BPP16			(0x1 << 20)
-#define VIDCON0_L0_DATA_18BPP9			(0x2 << 20)
-#define VIDCON0_L0_DATA_24BPP			(0x3 << 20)
-#define VIDCON0_L0_DATA_18BPP			(0x4 << 20)
-#define VIDCON0_L0_DATA_16BPP8			(0x5 << 20)
-
-#define VIDCON0_PNRMODE_MASK			(0x3 << 17)
-#define VIDCON0_PNRMODE_SHIFT			(17)
-#define VIDCON0_PNRMODE_RGB			(0x0 << 17)
-#define VIDCON0_PNRMODE_BGR			(0x1 << 17)
-#define VIDCON0_PNRMODE_SERIAL_RGB		(0x2 << 17)
-#define VIDCON0_PNRMODE_SERIAL_BGR		(0x3 << 17)
-
-#define VIDCON0_CLKVALUP			(1 << 16)
-#define VIDCON0_CLKVAL_F_MASK			(0xff << 6)
-#define VIDCON0_CLKVAL_F_SHIFT			(6)
-#define VIDCON0_CLKVAL_F_LIMIT			(0xff)
-#define VIDCON0_CLKVAL_F(_x)			((_x) << 6)
-#define VIDCON0_VLCKFREE			(1 << 5)
-#define VIDCON0_CLKDIR				(1 << 4)
-
-#define VIDCON0_CLKSEL_MASK			(0x3 << 2)
-#define VIDCON0_CLKSEL_SHIFT			(2)
-#define VIDCON0_CLKSEL_HCLK			(0x0 << 2)
-#define VIDCON0_CLKSEL_LCD			(0x1 << 2)
-#define VIDCON0_CLKSEL_27M			(0x3 << 2)
-
-#define VIDCON0_ENVID				(1 << 1)
-#define VIDCON0_ENVID_F				(1 << 0)
-
-#define VIDCON1					(0x04)
-#define VIDCON1_LINECNT_MASK			(0x7ff << 16)
-#define VIDCON1_LINECNT_SHIFT			(16)
-#define VIDCON1_LINECNT_GET(_v)			(((_v) >> 16) & 0x7ff)
-#define VIDCON1_VSTATUS_MASK			(0x3 << 13)
-#define VIDCON1_VSTATUS_SHIFT			(13)
-#define VIDCON1_VSTATUS_VSYNC			(0x0 << 13)
-#define VIDCON1_VSTATUS_BACKPORCH		(0x1 << 13)
-#define VIDCON1_VSTATUS_ACTIVE			(0x2 << 13)
-#define VIDCON1_VSTATUS_FRONTPORCH		(0x0 << 13)
-#define VIDCON1_VCLK_MASK			(0x3 << 9)
-#define VIDCON1_VCLK_HOLD			(0x0 << 9)
-#define VIDCON1_VCLK_RUN			(0x1 << 9)
-
-#define VIDCON1_INV_VCLK			(1 << 7)
-#define VIDCON1_INV_HSYNC			(1 << 6)
-#define VIDCON1_INV_VSYNC			(1 << 5)
-#define VIDCON1_INV_VDEN			(1 << 4)
-
-/* VIDCON2 */
-
-#define VIDCON2					(0x08)
-#define VIDCON2_EN601				(1 << 23)
-#define VIDCON2_TVFMTSEL_SW			(1 << 14)
-
-#define VIDCON2_TVFMTSEL1_MASK			(0x3 << 12)
-#define VIDCON2_TVFMTSEL1_SHIFT			(12)
-#define VIDCON2_TVFMTSEL1_RGB			(0x0 << 12)
-#define VIDCON2_TVFMTSEL1_YUV422		(0x1 << 12)
-#define VIDCON2_TVFMTSEL1_YUV444		(0x2 << 12)
-
-#define VIDCON2_ORGYCbCr			(1 << 8)
-#define VIDCON2_YUVORDCrCb			(1 << 7)
-
-/* PRTCON (S3C6410, S5PC100)
- * Might not be present in the S3C6410 documentation,
- * but tests prove it's there almost for sure; shouldn't hurt in any case.
- */
-#define PRTCON					(0x0c)
-#define PRTCON_PROTECT				(1 << 11)
-
-/* VIDTCON0 */
-
-#define VIDTCON0_VBPDE_MASK			(0xff << 24)
-#define VIDTCON0_VBPDE_SHIFT			(24)
-#define VIDTCON0_VBPDE_LIMIT			(0xff)
-#define VIDTCON0_VBPDE(_x)			((_x) << 24)
-
-#define VIDTCON0_VBPD_MASK			(0xff << 16)
-#define VIDTCON0_VBPD_SHIFT			(16)
-#define VIDTCON0_VBPD_LIMIT			(0xff)
-#define VIDTCON0_VBPD(_x)			((_x) << 16)
-
-#define VIDTCON0_VFPD_MASK			(0xff << 8)
-#define VIDTCON0_VFPD_SHIFT			(8)
-#define VIDTCON0_VFPD_LIMIT			(0xff)
-#define VIDTCON0_VFPD(_x)			((_x) << 8)
-
-#define VIDTCON0_VSPW_MASK			(0xff << 0)
-#define VIDTCON0_VSPW_SHIFT			(0)
-#define VIDTCON0_VSPW_LIMIT			(0xff)
-#define VIDTCON0_VSPW(_x)			((_x) << 0)
-
-/* VIDTCON1 */
-
-#define VIDTCON1_VFPDE_MASK			(0xff << 24)
-#define VIDTCON1_VFPDE_SHIFT			(24)
-#define VIDTCON1_VFPDE_LIMIT			(0xff)
-#define VIDTCON1_VFPDE(_x)			((_x) << 24)
-
-#define VIDTCON1_HBPD_MASK			(0xff << 16)
-#define VIDTCON1_HBPD_SHIFT			(16)
-#define VIDTCON1_HBPD_LIMIT			(0xff)
-#define VIDTCON1_HBPD(_x)			((_x) << 16)
-
-#define VIDTCON1_HFPD_MASK			(0xff << 8)
-#define VIDTCON1_HFPD_SHIFT			(8)
-#define VIDTCON1_HFPD_LIMIT			(0xff)
-#define VIDTCON1_HFPD(_x)			((_x) << 8)
-
-#define VIDTCON1_HSPW_MASK			(0xff << 0)
-#define VIDTCON1_HSPW_SHIFT			(0)
-#define VIDTCON1_HSPW_LIMIT			(0xff)
-#define VIDTCON1_HSPW(_x)			((_x) << 0)
-
-#define VIDTCON2				(0x18)
-#define VIDTCON2_LINEVAL_E(_x)			((((_x) & 0x800) >> 11) << 23)
-#define VIDTCON2_LINEVAL_MASK			(0x7ff << 11)
-#define VIDTCON2_LINEVAL_SHIFT			(11)
-#define VIDTCON2_LINEVAL_LIMIT			(0x7ff)
-#define VIDTCON2_LINEVAL(_x)			(((_x) & 0x7ff) << 11)
-
-#define VIDTCON2_HOZVAL_E(_x)			((((_x) & 0x800) >> 11) << 22)
-#define VIDTCON2_HOZVAL_MASK			(0x7ff << 0)
-#define VIDTCON2_HOZVAL_SHIFT			(0)
-#define VIDTCON2_HOZVAL_LIMIT			(0x7ff)
-#define VIDTCON2_HOZVAL(_x)			(((_x) & 0x7ff) << 0)
-
-/* WINCONx */
-
-
-#define WINCONx_BITSWP				(1 << 18)
-#define WINCONx_BYTSWP				(1 << 17)
-#define WINCONx_HAWSWP				(1 << 16)
-#define WINCONx_WSWP				(1 << 15)
-#define WINCONx_BURSTLEN_MASK			(0x3 << 9)
-#define WINCONx_BURSTLEN_SHIFT			(9)
-#define WINCONx_BURSTLEN_16WORD			(0x0 << 9)
-#define WINCONx_BURSTLEN_8WORD			(0x1 << 9)
-#define WINCONx_BURSTLEN_4WORD			(0x2 << 9)
-
-#define WINCONx_ENWIN				(1 << 0)
-#define WINCON0_BPPMODE_MASK			(0xf << 2)
-#define WINCON0_BPPMODE_SHIFT			(2)
-#define WINCON0_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON0_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON0_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON0_BPPMODE_8BPP_PALETTE		(0x3 << 2)
-#define WINCON0_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON0_BPPMODE_16BPP_1555		(0x7 << 2)
-#define WINCON0_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON0_BPPMODE_24BPP_888		(0xb << 2)
-
-#define WINCON1_BLD_PIX				(1 << 6)
-
-#define WINCON1_ALPHA_SEL			(1 << 1)
-#define WINCON1_BPPMODE_MASK			(0xf << 2)
-#define WINCON1_BPPMODE_SHIFT			(2)
-#define WINCON1_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON1_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON1_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON1_BPPMODE_8BPP_PALETTE		(0x3 << 2)
-#define WINCON1_BPPMODE_8BPP_1232		(0x4 << 2)
-#define WINCON1_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON1_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON1_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON1_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON1_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON1_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON1_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON1_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON1_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON1_BPPMODE_28BPP_A4888		(0xd << 2)
-
-/* S5PV210 */
-#define SHADOWCON				(0x34)
-#define SHADOWCON_WINx_PROTECT(_win)		(1 << (10 + (_win)))
-/* DMA channels (all windows) */
-#define SHADOWCON_CHx_ENABLE(_win)		(1 << (_win))
-/* Local input channels (windows 0-2) */
-#define SHADOWCON_CHx_LOCAL_ENABLE(_win)	(1 << (5 + (_win)))
-
-#define VIDOSDxA_TOPLEFT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
-#define VIDOSDxA_TOPLEFT_X_MASK			(0x7ff << 11)
-#define VIDOSDxA_TOPLEFT_X_SHIFT		(11)
-#define VIDOSDxA_TOPLEFT_X_LIMIT		(0x7ff)
-#define VIDOSDxA_TOPLEFT_X(_x)			(((_x) & 0x7ff) << 11)
-
-#define VIDOSDxA_TOPLEFT_Y_E(_x)		((((_x) & 0x800) >> 11) << 22)
-#define VIDOSDxA_TOPLEFT_Y_MASK			(0x7ff << 0)
-#define VIDOSDxA_TOPLEFT_Y_SHIFT		(0)
-#define VIDOSDxA_TOPLEFT_Y_LIMIT		(0x7ff)
-#define VIDOSDxA_TOPLEFT_Y(_x)			(((_x) & 0x7ff) << 0)
-
-#define VIDOSDxB_BOTRIGHT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
-#define VIDOSDxB_BOTRIGHT_X_MASK		(0x7ff << 11)
-#define VIDOSDxB_BOTRIGHT_X_SHIFT		(11)
-#define VIDOSDxB_BOTRIGHT_X_LIMIT		(0x7ff)
-#define VIDOSDxB_BOTRIGHT_X(_x)			(((_x) & 0x7ff) << 11)
-
-#define VIDOSDxB_BOTRIGHT_Y_E(_x)		((((_x) & 0x800) >> 11) << 22)
-#define VIDOSDxB_BOTRIGHT_Y_MASK		(0x7ff << 0)
-#define VIDOSDxB_BOTRIGHT_Y_SHIFT		(0)
-#define VIDOSDxB_BOTRIGHT_Y_LIMIT		(0x7ff)
-#define VIDOSDxB_BOTRIGHT_Y(_x)			(((_x) & 0x7ff) << 0)
-
-/* For VIDOSD[1..4]C */
-#define VIDISD14C_ALPHA0_R(_x)			((_x) << 20)
-#define VIDISD14C_ALPHA0_G_MASK			(0xf << 16)
-#define VIDISD14C_ALPHA0_G_SHIFT		(16)
-#define VIDISD14C_ALPHA0_G_LIMIT		(0xf)
-#define VIDISD14C_ALPHA0_G(_x)			((_x) << 16)
-#define VIDISD14C_ALPHA0_B_MASK			(0xf << 12)
-#define VIDISD14C_ALPHA0_B_SHIFT		(12)
-#define VIDISD14C_ALPHA0_B_LIMIT		(0xf)
-#define VIDISD14C_ALPHA0_B(_x)			((_x) << 12)
-#define VIDISD14C_ALPHA1_R_MASK			(0xf << 8)
-#define VIDISD14C_ALPHA1_R_SHIFT		(8)
-#define VIDISD14C_ALPHA1_R_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_R(_x)			((_x) << 8)
-#define VIDISD14C_ALPHA1_G_MASK			(0xf << 4)
-#define VIDISD14C_ALPHA1_G_SHIFT		(4)
-#define VIDISD14C_ALPHA1_G_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_G(_x)			((_x) << 4)
-#define VIDISD14C_ALPHA1_B_MASK			(0xf << 0)
-#define VIDISD14C_ALPHA1_B_SHIFT		(0)
-#define VIDISD14C_ALPHA1_B_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_B(_x)			((_x) << 0)
-
-/* Video buffer addresses */
-#define VIDW_BUF_START(_buff)			(0xA0 + ((_buff) * 8))
-#define VIDW_BUF_START1(_buff)			(0xA4 + ((_buff) * 8))
-#define VIDW_BUF_END(_buff)			(0xD0 + ((_buff) * 8))
-#define VIDW_BUF_END1(_buff)			(0xD4 + ((_buff) * 8))
-#define VIDW_BUF_SIZE(_buff)			(0x100 + ((_buff) * 4))
-
-#define VIDW_BUF_SIZE_OFFSET_E(_x)		((((_x) & 0x2000) >> 13) << 27)
-#define VIDW_BUF_SIZE_OFFSET_MASK		(0x1fff << 13)
-#define VIDW_BUF_SIZE_OFFSET_SHIFT		(13)
-#define VIDW_BUF_SIZE_OFFSET_LIMIT		(0x1fff)
-#define VIDW_BUF_SIZE_OFFSET(_x)		(((_x) & 0x1fff) << 13)
-
-#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)		((((_x) & 0x2000) >> 13) << 26)
-#define VIDW_BUF_SIZE_PAGEWIDTH_MASK		(0x1fff << 0)
-#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT		(0)
-#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT		(0x1fff)
-#define VIDW_BUF_SIZE_PAGEWIDTH(_x)		(((_x) & 0x1fff) << 0)
-
-/* Interrupt controls and status */
-
-#define VIDINTCON0_FIFOINTERVAL_MASK		(0x3f << 20)
-#define VIDINTCON0_FIFOINTERVAL_SHIFT		(20)
-#define VIDINTCON0_FIFOINTERVAL_LIMIT		(0x3f)
-#define VIDINTCON0_FIFOINTERVAL(_x)		((_x) << 20)
-
-#define VIDINTCON0_INT_SYSMAINCON		(1 << 19)
-#define VIDINTCON0_INT_SYSSUBCON		(1 << 18)
-#define VIDINTCON0_INT_I80IFDONE		(1 << 17)
-
-#define VIDINTCON0_FRAMESEL0_MASK		(0x3 << 15)
-#define VIDINTCON0_FRAMESEL0_SHIFT		(15)
-#define VIDINTCON0_FRAMESEL0_BACKPORCH		(0x0 << 15)
-#define VIDINTCON0_FRAMESEL0_VSYNC		(0x1 << 15)
-#define VIDINTCON0_FRAMESEL0_ACTIVE		(0x2 << 15)
-#define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
-
-#define VIDINTCON0_FRAMESEL1			(1 << 13)
-#define VIDINTCON0_FRAMESEL1_MASK		(0x3 << 13)
-#define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 13)
-#define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 13)
-#define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 13)
-#define VIDINTCON0_FRAMESEL1_FRONTPORCH		(0x3 << 13)
-
-#define VIDINTCON0_INT_FRAME			(1 << 12)
-#define VIDINTCON0_FIFIOSEL_MASK		(0x7f << 5)
-#define VIDINTCON0_FIFIOSEL_SHIFT		(5)
-#define VIDINTCON0_FIFIOSEL_WINDOW0		(0x1 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW1		(0x2 << 5)
-
-#define VIDINTCON0_FIFOLEVEL_MASK		(0x7 << 2)
-#define VIDINTCON0_FIFOLEVEL_SHIFT		(2)
-#define VIDINTCON0_FIFOLEVEL_TO25PC		(0x0 << 2)
-#define VIDINTCON0_FIFOLEVEL_TO50PC		(0x1 << 2)
-#define VIDINTCON0_FIFOLEVEL_TO75PC		(0x2 << 2)
-#define VIDINTCON0_FIFOLEVEL_EMPTY		(0x3 << 2)
-#define VIDINTCON0_FIFOLEVEL_FULL		(0x4 << 2)
-
-#define VIDINTCON0_INT_FIFO_MASK		(0x3 << 0)
-#define VIDINTCON0_INT_FIFO_SHIFT		(0)
-#define VIDINTCON0_INT_ENABLE			(1 << 0)
-
-#define VIDINTCON1				(0x134)
-#define VIDINTCON1_INT_I180			(1 << 2)
-#define VIDINTCON1_INT_FRAME			(1 << 1)
-#define VIDINTCON1_INT_FIFO			(1 << 0)
-
-/* Window colour-key control registers */
-#define WKEYCON					(0x140)	/* 6410,V210 */
-
-#define WKEYCON0				(0x00)
-#define WKEYCON1				(0x04)
-
-#define WxKEYCON0_KEYBL_EN			(1 << 26)
-#define WxKEYCON0_KEYEN_F			(1 << 25)
-#define WxKEYCON0_DIRCON			(1 << 24)
-#define WxKEYCON0_COMPKEY_MASK			(0xffffff << 0)
-#define WxKEYCON0_COMPKEY_SHIFT			(0)
-#define WxKEYCON0_COMPKEY_LIMIT			(0xffffff)
-#define WxKEYCON0_COMPKEY(_x)			((_x) << 0)
-#define WxKEYCON1_COLVAL_MASK			(0xffffff << 0)
-#define WxKEYCON1_COLVAL_SHIFT			(0)
-#define WxKEYCON1_COLVAL_LIMIT			(0xffffff)
-#define WxKEYCON1_COLVAL(_x)			((_x) << 0)
-
-
-/* Window blanking (MAP) */
-
-#define WINxMAP_MAP				(1 << 24)
-#define WINxMAP_MAP_COLOUR_MASK			(0xffffff << 0)
-#define WINxMAP_MAP_COLOUR_SHIFT		(0)
-#define WINxMAP_MAP_COLOUR_LIMIT		(0xffffff)
-#define WINxMAP_MAP_COLOUR(_x)			((_x) << 0)
-
-#define WPALCON_PAL_UPDATE			(1 << 9)
-#define WPALCON_W1PAL_MASK			(0x7 << 3)
-#define WPALCON_W1PAL_SHIFT			(3)
-#define WPALCON_W1PAL_25BPP_A888		(0x0 << 3)
-#define WPALCON_W1PAL_24BPP			(0x1 << 3)
-#define WPALCON_W1PAL_19BPP_A666		(0x2 << 3)
-#define WPALCON_W1PAL_18BPP_A665		(0x3 << 3)
-#define WPALCON_W1PAL_18BPP			(0x4 << 3)
-#define WPALCON_W1PAL_16BPP_A555		(0x5 << 3)
-#define WPALCON_W1PAL_16BPP_565			(0x6 << 3)
-
-#define WPALCON_W0PAL_MASK			(0x7 << 0)
-#define WPALCON_W0PAL_SHIFT			(0)
-#define WPALCON_W0PAL_25BPP_A888		(0x0 << 0)
-#define WPALCON_W0PAL_24BPP			(0x1 << 0)
-#define WPALCON_W0PAL_19BPP_A666		(0x2 << 0)
-#define WPALCON_W0PAL_18BPP_A665		(0x3 << 0)
-#define WPALCON_W0PAL_18BPP			(0x4 << 0)
-#define WPALCON_W0PAL_16BPP_A555		(0x5 << 0)
-#define WPALCON_W0PAL_16BPP_565			(0x6 << 0)
-
-/* Blending equation control */
-#define BLENDCON				(0x260)
-#define BLENDCON_NEW_MASK			(1 << 0)
-#define BLENDCON_NEW_8BIT_ALPHA_VALUE		(1 << 0)
-#define BLENDCON_NEW_4BIT_ALPHA_VALUE		(0 << 0)
-
diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
new file mode 100644
index 0000000..1b5ff4c
--- /dev/null
+++ b/include/video/samsung_fimd.h
@@ -0,0 +1,533 @@
+/* include/video/samsung_fimd.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - new-style fimd and framebuffer register definitions
+ *
+ * This is the register set for the fimd and new style framebuffer interface
+ * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
+ * S3C64XX series such as the S3C6400 and S3C6410.
+ *
+ * The file does not contain the cpu specific items which are based on
+ * whichever architecture is selected, it only contains the core of the
+ * register set. See <mach/regs-fb.h> to get the specifics.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* VIDCON0 */
+
+#define VIDCON0					(0x00)
+#define VIDCON0_INTERLACE			(1 << 29)
+#define VIDCON0_VIDOUT_MASK			(0x3 << 26)
+#define VIDCON0_VIDOUT_SHIFT			(26)
+#define VIDCON0_VIDOUT_RGB			(0x0 << 26)
+#define VIDCON0_VIDOUT_TV			(0x1 << 26)
+#define VIDCON0_VIDOUT_I80_LDI0			(0x2 << 26)
+#define VIDCON0_VIDOUT_I80_LDI1			(0x3 << 26)
+
+#define VIDCON0_L1_DATA_MASK			(0x7 << 23)
+#define VIDCON0_L1_DATA_SHIFT			(23)
+#define VIDCON0_L1_DATA_16BPP			(0x0 << 23)
+#define VIDCON0_L1_DATA_18BPP16			(0x1 << 23)
+#define VIDCON0_L1_DATA_18BPP9			(0x2 << 23)
+#define VIDCON0_L1_DATA_24BPP			(0x3 << 23)
+#define VIDCON0_L1_DATA_18BPP			(0x4 << 23)
+#define VIDCON0_L1_DATA_16BPP8			(0x5 << 23)
+
+#define VIDCON0_L0_DATA_MASK			(0x7 << 20)
+#define VIDCON0_L0_DATA_SHIFT			(20)
+#define VIDCON0_L0_DATA_16BPP			(0x0 << 20)
+#define VIDCON0_L0_DATA_18BPP16			(0x1 << 20)
+#define VIDCON0_L0_DATA_18BPP9			(0x2 << 20)
+#define VIDCON0_L0_DATA_24BPP			(0x3 << 20)
+#define VIDCON0_L0_DATA_18BPP			(0x4 << 20)
+#define VIDCON0_L0_DATA_16BPP8			(0x5 << 20)
+
+#define VIDCON0_PNRMODE_MASK			(0x3 << 17)
+#define VIDCON0_PNRMODE_SHIFT			(17)
+#define VIDCON0_PNRMODE_RGB			(0x0 << 17)
+#define VIDCON0_PNRMODE_BGR			(0x1 << 17)
+#define VIDCON0_PNRMODE_SERIAL_RGB		(0x2 << 17)
+#define VIDCON0_PNRMODE_SERIAL_BGR		(0x3 << 17)
+
+#define VIDCON0_CLKVALUP			(1 << 16)
+#define VIDCON0_CLKVAL_F_MASK			(0xff << 6)
+#define VIDCON0_CLKVAL_F_SHIFT			(6)
+#define VIDCON0_CLKVAL_F_LIMIT			(0xff)
+#define VIDCON0_CLKVAL_F(_x)			((_x) << 6)
+#define VIDCON0_VLCKFREE			(1 << 5)
+#define VIDCON0_CLKDIR				(1 << 4)
+
+#define VIDCON0_CLKSEL_MASK			(0x3 << 2)
+#define VIDCON0_CLKSEL_SHIFT			(2)
+#define VIDCON0_CLKSEL_HCLK			(0x0 << 2)
+#define VIDCON0_CLKSEL_LCD			(0x1 << 2)
+#define VIDCON0_CLKSEL_27M			(0x3 << 2)
+
+#define VIDCON0_ENVID				(1 << 1)
+#define VIDCON0_ENVID_F				(1 << 0)
+
+#define VIDCON1					(0x04)
+#define VIDCON1_LINECNT_MASK			(0x7ff << 16)
+#define VIDCON1_LINECNT_SHIFT			(16)
+#define VIDCON1_LINECNT_GET(_v)			(((_v) >> 16) & 0x7ff)
+#define VIDCON1_VSTATUS_MASK			(0x3 << 13)
+#define VIDCON1_VSTATUS_SHIFT			(13)
+#define VIDCON1_VSTATUS_VSYNC			(0x0 << 13)
+#define VIDCON1_VSTATUS_BACKPORCH		(0x1 << 13)
+#define VIDCON1_VSTATUS_ACTIVE			(0x2 << 13)
+#define VIDCON1_VSTATUS_FRONTPORCH		(0x0 << 13)
+#define VIDCON1_VCLK_MASK			(0x3 << 9)
+#define VIDCON1_VCLK_HOLD			(0x0 << 9)
+#define VIDCON1_VCLK_RUN			(0x1 << 9)
+
+#define VIDCON1_INV_VCLK			(1 << 7)
+#define VIDCON1_INV_HSYNC			(1 << 6)
+#define VIDCON1_INV_VSYNC			(1 << 5)
+#define VIDCON1_INV_VDEN			(1 << 4)
+
+/* VIDCON2 */
+
+#define VIDCON2					(0x08)
+#define VIDCON2_EN601				(1 << 23)
+#define VIDCON2_TVFMTSEL_SW			(1 << 14)
+
+#define VIDCON2_TVFMTSEL1_MASK			(0x3 << 12)
+#define VIDCON2_TVFMTSEL1_SHIFT			(12)
+#define VIDCON2_TVFMTSEL1_RGB			(0x0 << 12)
+#define VIDCON2_TVFMTSEL1_YUV422		(0x1 << 12)
+#define VIDCON2_TVFMTSEL1_YUV444		(0x2 << 12)
+
+#define VIDCON2_ORGYCbCr			(1 << 8)
+#define VIDCON2_YUVORDCrCb			(1 << 7)
+
+/* PRTCON (S3C6410, S5PC100)
+ * Might not be present in the S3C6410 documentation,
+ * but tests prove it's there almost for sure; shouldn't hurt in any case.
+ */
+#define PRTCON					(0x0c)
+#define PRTCON_PROTECT				(1 << 11)
+
+/* VIDTCON0 */
+
+#define VIDTCON0_VBPDE_MASK			(0xff << 24)
+#define VIDTCON0_VBPDE_SHIFT			(24)
+#define VIDTCON0_VBPDE_LIMIT			(0xff)
+#define VIDTCON0_VBPDE(_x)			((_x) << 24)
+
+#define VIDTCON0_VBPD_MASK			(0xff << 16)
+#define VIDTCON0_VBPD_SHIFT			(16)
+#define VIDTCON0_VBPD_LIMIT			(0xff)
+#define VIDTCON0_VBPD(_x)			((_x) << 16)
+
+#define VIDTCON0_VFPD_MASK			(0xff << 8)
+#define VIDTCON0_VFPD_SHIFT			(8)
+#define VIDTCON0_VFPD_LIMIT			(0xff)
+#define VIDTCON0_VFPD(_x)			((_x) << 8)
+
+#define VIDTCON0_VSPW_MASK			(0xff << 0)
+#define VIDTCON0_VSPW_SHIFT			(0)
+#define VIDTCON0_VSPW_LIMIT			(0xff)
+#define VIDTCON0_VSPW(_x)			((_x) << 0)
+
+/* VIDTCON1 */
+
+#define VIDTCON1_VFPDE_MASK			(0xff << 24)
+#define VIDTCON1_VFPDE_SHIFT			(24)
+#define VIDTCON1_VFPDE_LIMIT			(0xff)
+#define VIDTCON1_VFPDE(_x)			((_x) << 24)
+
+#define VIDTCON1_HBPD_MASK			(0xff << 16)
+#define VIDTCON1_HBPD_SHIFT			(16)
+#define VIDTCON1_HBPD_LIMIT			(0xff)
+#define VIDTCON1_HBPD(_x)			((_x) << 16)
+
+#define VIDTCON1_HFPD_MASK			(0xff << 8)
+#define VIDTCON1_HFPD_SHIFT			(8)
+#define VIDTCON1_HFPD_LIMIT			(0xff)
+#define VIDTCON1_HFPD(_x)			((_x) << 8)
+
+#define VIDTCON1_HSPW_MASK			(0xff << 0)
+#define VIDTCON1_HSPW_SHIFT			(0)
+#define VIDTCON1_HSPW_LIMIT			(0xff)
+#define VIDTCON1_HSPW(_x)			((_x) << 0)
+
+#define VIDTCON2				(0x18)
+#define VIDTCON2_LINEVAL_E(_x)			((((_x) & 0x800) >> 11) << 23)
+#define VIDTCON2_LINEVAL_MASK			(0x7ff << 11)
+#define VIDTCON2_LINEVAL_SHIFT			(11)
+#define VIDTCON2_LINEVAL_LIMIT			(0x7ff)
+#define VIDTCON2_LINEVAL(_x)			(((_x) & 0x7ff) << 11)
+
+#define VIDTCON2_HOZVAL_E(_x)			((((_x) & 0x800) >> 11) << 22)
+#define VIDTCON2_HOZVAL_MASK			(0x7ff << 0)
+#define VIDTCON2_HOZVAL_SHIFT			(0)
+#define VIDTCON2_HOZVAL_LIMIT			(0x7ff)
+#define VIDTCON2_HOZVAL(_x)			(((_x) & 0x7ff) << 0)
+
+/* WINCONx */
+
+
+#define WINCONx_BITSWP				(1 << 18)
+#define WINCONx_BYTSWP				(1 << 17)
+#define WINCONx_HAWSWP				(1 << 16)
+#define WINCONx_WSWP				(1 << 15)
+#define WINCONx_BURSTLEN_MASK			(0x3 << 9)
+#define WINCONx_BURSTLEN_SHIFT			(9)
+#define WINCONx_BURSTLEN_16WORD			(0x0 << 9)
+#define WINCONx_BURSTLEN_8WORD			(0x1 << 9)
+#define WINCONx_BURSTLEN_4WORD			(0x2 << 9)
+
+#define WINCONx_ENWIN				(1 << 0)
+#define WINCON0_BPPMODE_MASK			(0xf << 2)
+#define WINCON0_BPPMODE_SHIFT			(2)
+#define WINCON0_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON0_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON0_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON0_BPPMODE_8BPP_PALETTE		(0x3 << 2)
+#define WINCON0_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON0_BPPMODE_16BPP_1555		(0x7 << 2)
+#define WINCON0_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON0_BPPMODE_24BPP_888		(0xb << 2)
+
+#define WINCON1_BLD_PIX				(1 << 6)
+
+#define WINCON1_ALPHA_SEL			(1 << 1)
+#define WINCON1_BPPMODE_MASK			(0xf << 2)
+#define WINCON1_BPPMODE_SHIFT			(2)
+#define WINCON1_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON1_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON1_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON1_BPPMODE_8BPP_PALETTE		(0x3 << 2)
+#define WINCON1_BPPMODE_8BPP_1232		(0x4 << 2)
+#define WINCON1_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON1_BPPMODE_16BPP_A1555		(0x6 << 2)
+#define WINCON1_BPPMODE_16BPP_I1555		(0x7 << 2)
+#define WINCON1_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON1_BPPMODE_18BPP_A1665		(0x9 << 2)
+#define WINCON1_BPPMODE_19BPP_A1666		(0xa << 2)
+#define WINCON1_BPPMODE_24BPP_888		(0xb << 2)
+#define WINCON1_BPPMODE_24BPP_A1887		(0xc << 2)
+#define WINCON1_BPPMODE_25BPP_A1888		(0xd << 2)
+#define WINCON1_BPPMODE_28BPP_A4888		(0xd << 2)
+
+/* S5PV210 */
+#define SHADOWCON				(0x34)
+#define SHADOWCON_WINx_PROTECT(_win)		(1 << (10 + (_win)))
+/* DMA channels (all windows) */
+#define SHADOWCON_CHx_ENABLE(_win)		(1 << (_win))
+/* Local input channels (windows 0-2) */
+#define SHADOWCON_CHx_LOCAL_ENABLE(_win)	(1 << (5 + (_win)))
+
+#define VIDOSDxA_TOPLEFT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
+#define VIDOSDxA_TOPLEFT_X_MASK			(0x7ff << 11)
+#define VIDOSDxA_TOPLEFT_X_SHIFT		(11)
+#define VIDOSDxA_TOPLEFT_X_LIMIT		(0x7ff)
+#define VIDOSDxA_TOPLEFT_X(_x)			(((_x) & 0x7ff) << 11)
+
+#define VIDOSDxA_TOPLEFT_Y_E(_x)		((((_x) & 0x800) >> 11) << 22)
+#define VIDOSDxA_TOPLEFT_Y_MASK			(0x7ff << 0)
+#define VIDOSDxA_TOPLEFT_Y_SHIFT		(0)
+#define VIDOSDxA_TOPLEFT_Y_LIMIT		(0x7ff)
+#define VIDOSDxA_TOPLEFT_Y(_x)			(((_x) & 0x7ff) << 0)
+
+#define VIDOSDxB_BOTRIGHT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
+#define VIDOSDxB_BOTRIGHT_X_MASK		(0x7ff << 11)
+#define VIDOSDxB_BOTRIGHT_X_SHIFT		(11)
+#define VIDOSDxB_BOTRIGHT_X_LIMIT		(0x7ff)
+#define VIDOSDxB_BOTRIGHT_X(_x)			(((_x) & 0x7ff) << 11)
+
+#define VIDOSDxB_BOTRIGHT_Y_E(_x)		((((_x) & 0x800) >> 11) << 22)
+#define VIDOSDxB_BOTRIGHT_Y_MASK		(0x7ff << 0)
+#define VIDOSDxB_BOTRIGHT_Y_SHIFT		(0)
+#define VIDOSDxB_BOTRIGHT_Y_LIMIT		(0x7ff)
+#define VIDOSDxB_BOTRIGHT_Y(_x)			(((_x) & 0x7ff) << 0)
+
+/* For VIDOSD[1..4]C */
+#define VIDISD14C_ALPHA0_R(_x)			((_x) << 20)
+#define VIDISD14C_ALPHA0_G_MASK			(0xf << 16)
+#define VIDISD14C_ALPHA0_G_SHIFT		(16)
+#define VIDISD14C_ALPHA0_G_LIMIT		(0xf)
+#define VIDISD14C_ALPHA0_G(_x)			((_x) << 16)
+#define VIDISD14C_ALPHA0_B_MASK			(0xf << 12)
+#define VIDISD14C_ALPHA0_B_SHIFT		(12)
+#define VIDISD14C_ALPHA0_B_LIMIT		(0xf)
+#define VIDISD14C_ALPHA0_B(_x)			((_x) << 12)
+#define VIDISD14C_ALPHA1_R_MASK			(0xf << 8)
+#define VIDISD14C_ALPHA1_R_SHIFT		(8)
+#define VIDISD14C_ALPHA1_R_LIMIT		(0xf)
+#define VIDISD14C_ALPHA1_R(_x)			((_x) << 8)
+#define VIDISD14C_ALPHA1_G_MASK			(0xf << 4)
+#define VIDISD14C_ALPHA1_G_SHIFT		(4)
+#define VIDISD14C_ALPHA1_G_LIMIT		(0xf)
+#define VIDISD14C_ALPHA1_G(_x)			((_x) << 4)
+#define VIDISD14C_ALPHA1_B_MASK			(0xf << 0)
+#define VIDISD14C_ALPHA1_B_SHIFT		(0)
+#define VIDISD14C_ALPHA1_B_LIMIT		(0xf)
+#define VIDISD14C_ALPHA1_B(_x)			((_x) << 0)
+
+/* Video buffer addresses */
+#define VIDW_BUF_START(_buff)			(0xA0 + ((_buff) * 8))
+#define VIDW_BUF_START1(_buff)			(0xA4 + ((_buff) * 8))
+#define VIDW_BUF_END(_buff)			(0xD0 + ((_buff) * 8))
+#define VIDW_BUF_END1(_buff)			(0xD4 + ((_buff) * 8))
+#define VIDW_BUF_SIZE(_buff)			(0x100 + ((_buff) * 4))
+
+#define VIDW_BUF_SIZE_OFFSET_E(_x)		((((_x) & 0x2000) >> 13) << 27)
+#define VIDW_BUF_SIZE_OFFSET_MASK		(0x1fff << 13)
+#define VIDW_BUF_SIZE_OFFSET_SHIFT		(13)
+#define VIDW_BUF_SIZE_OFFSET_LIMIT		(0x1fff)
+#define VIDW_BUF_SIZE_OFFSET(_x)		(((_x) & 0x1fff) << 13)
+
+#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)		((((_x) & 0x2000) >> 13) << 26)
+#define VIDW_BUF_SIZE_PAGEWIDTH_MASK		(0x1fff << 0)
+#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT		(0)
+#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT		(0x1fff)
+#define VIDW_BUF_SIZE_PAGEWIDTH(_x)		(((_x) & 0x1fff) << 0)
+
+/* Interrupt controls and status */
+
+#define VIDINTCON0_FIFOINTERVAL_MASK		(0x3f << 20)
+#define VIDINTCON0_FIFOINTERVAL_SHIFT		(20)
+#define VIDINTCON0_FIFOINTERVAL_LIMIT		(0x3f)
+#define VIDINTCON0_FIFOINTERVAL(_x)		((_x) << 20)
+
+#define VIDINTCON0_INT_SYSMAINCON		(1 << 19)
+#define VIDINTCON0_INT_SYSSUBCON		(1 << 18)
+#define VIDINTCON0_INT_I80IFDONE		(1 << 17)
+
+#define VIDINTCON0_FRAMESEL0_MASK		(0x3 << 15)
+#define VIDINTCON0_FRAMESEL0_SHIFT		(15)
+#define VIDINTCON0_FRAMESEL0_BACKPORCH		(0x0 << 15)
+#define VIDINTCON0_FRAMESEL0_VSYNC		(0x1 << 15)
+#define VIDINTCON0_FRAMESEL0_ACTIVE		(0x2 << 15)
+#define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
+
+#define VIDINTCON0_FRAMESEL1			(1 << 13)
+#define VIDINTCON0_FRAMESEL1_MASK		(0x3 << 13)
+#define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 13)
+#define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 13)
+#define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 13)
+#define VIDINTCON0_FRAMESEL1_FRONTPORCH		(0x3 << 13)
+
+#define VIDINTCON0_INT_FRAME			(1 << 12)
+#define VIDINTCON0_FIFIOSEL_MASK		(0x7f << 5)
+#define VIDINTCON0_FIFIOSEL_SHIFT		(5)
+#define VIDINTCON0_FIFIOSEL_WINDOW0		(0x1 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW1		(0x2 << 5)
+
+#define VIDINTCON0_FIFOLEVEL_MASK		(0x7 << 2)
+#define VIDINTCON0_FIFOLEVEL_SHIFT		(2)
+#define VIDINTCON0_FIFOLEVEL_TO25PC		(0x0 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO50PC		(0x1 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO75PC		(0x2 << 2)
+#define VIDINTCON0_FIFOLEVEL_EMPTY		(0x3 << 2)
+#define VIDINTCON0_FIFOLEVEL_FULL		(0x4 << 2)
+
+#define VIDINTCON0_INT_FIFO_MASK		(0x3 << 0)
+#define VIDINTCON0_INT_FIFO_SHIFT		(0)
+#define VIDINTCON0_INT_ENABLE			(1 << 0)
+
+#define VIDINTCON1				(0x134)
+#define VIDINTCON1_INT_I180			(1 << 2)
+#define VIDINTCON1_INT_FRAME			(1 << 1)
+#define VIDINTCON1_INT_FIFO			(1 << 0)
+
+/* Window colour-key control registers */
+#define WKEYCON					(0x140)	/* 6410,V210 */
+
+#define WKEYCON0				(0x00)
+#define WKEYCON1				(0x04)
+
+#define WxKEYCON0_KEYBL_EN			(1 << 26)
+#define WxKEYCON0_KEYEN_F			(1 << 25)
+#define WxKEYCON0_DIRCON			(1 << 24)
+#define WxKEYCON0_COMPKEY_MASK			(0xffffff << 0)
+#define WxKEYCON0_COMPKEY_SHIFT			(0)
+#define WxKEYCON0_COMPKEY_LIMIT			(0xffffff)
+#define WxKEYCON0_COMPKEY(_x)			((_x) << 0)
+#define WxKEYCON1_COLVAL_MASK			(0xffffff << 0)
+#define WxKEYCON1_COLVAL_SHIFT			(0)
+#define WxKEYCON1_COLVAL_LIMIT			(0xffffff)
+#define WxKEYCON1_COLVAL(_x)			((_x) << 0)
+
+
+/* Window blanking (MAP) */
+
+#define WINxMAP_MAP				(1 << 24)
+#define WINxMAP_MAP_COLOUR_MASK			(0xffffff << 0)
+#define WINxMAP_MAP_COLOUR_SHIFT		(0)
+#define WINxMAP_MAP_COLOUR_LIMIT		(0xffffff)
+#define WINxMAP_MAP_COLOUR(_x)			((_x) << 0)
+
+#define WPALCON_PAL_UPDATE			(1 << 9)
+#define WPALCON_W1PAL_MASK			(0x7 << 3)
+#define WPALCON_W1PAL_SHIFT			(3)
+#define WPALCON_W1PAL_25BPP_A888		(0x0 << 3)
+#define WPALCON_W1PAL_24BPP			(0x1 << 3)
+#define WPALCON_W1PAL_19BPP_A666		(0x2 << 3)
+#define WPALCON_W1PAL_18BPP_A665		(0x3 << 3)
+#define WPALCON_W1PAL_18BPP			(0x4 << 3)
+#define WPALCON_W1PAL_16BPP_A555		(0x5 << 3)
+#define WPALCON_W1PAL_16BPP_565			(0x6 << 3)
+
+#define WPALCON_W0PAL_MASK			(0x7 << 0)
+#define WPALCON_W0PAL_SHIFT			(0)
+#define WPALCON_W0PAL_25BPP_A888		(0x0 << 0)
+#define WPALCON_W0PAL_24BPP			(0x1 << 0)
+#define WPALCON_W0PAL_19BPP_A666		(0x2 << 0)
+#define WPALCON_W0PAL_18BPP_A665		(0x3 << 0)
+#define WPALCON_W0PAL_18BPP			(0x4 << 0)
+#define WPALCON_W0PAL_16BPP_A555		(0x5 << 0)
+#define WPALCON_W0PAL_16BPP_565			(0x6 << 0)
+
+/* Blending equation control */
+#define BLENDCON				(0x260)
+#define BLENDCON_NEW_MASK			(1 << 0)
+#define BLENDCON_NEW_8BIT_ALPHA_VALUE		(1 << 0)
+#define BLENDCON_NEW_4BIT_ALPHA_VALUE		(0 << 0)
+
+#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
+#define VIDCON1_FSTATUS_EVEN	(1 << 15)
+
+/* Video timing controls */
+#define VIDTCON0				(0x10)
+#define VIDTCON1				(0x14)
+#define VIDTCON2				(0x18)
+
+/* Window position controls */
+
+#define WINCON(_win)				(0x20 + ((_win) * 4))
+
+/* OSD1 and OSD4 do not have register D */
+
+#define VIDOSD_BASE				(0x40)
+
+#define VIDINTCON0				(0x130)
+
+/* WINCONx */
+
+#define WINCONx_CSCWIDTH_MASK			(0x3 << 26)
+#define WINCONx_CSCWIDTH_SHIFT			(26)
+#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26)
+#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26)
+
+#define WINCONx_ENLOCAL				(1 << 22)
+#define WINCONx_BUFSTATUS			(1 << 21)
+#define WINCONx_BUFSEL				(1 << 20)
+#define WINCONx_BUFAUTOEN			(1 << 19)
+#define WINCONx_YCbCr				(1 << 13)
+
+#define WINCON1_LOCALSEL_CAMIF			(1 << 23)
+
+#define WINCON2_LOCALSEL_CAMIF			(1 << 23)
+#define WINCON2_BLD_PIX				(1 << 6)
+
+#define WINCON2_ALPHA_SEL			(1 << 1)
+#define WINCON2_BPPMODE_MASK			(0xf << 2)
+#define WINCON2_BPPMODE_SHIFT			(2)
+#define WINCON2_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON2_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON2_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2)
+#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2)
+#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2)
+#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2)
+#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2)
+#define WINCON2_BPPMODE_24BPP_888		(0xb << 2)
+#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2)
+#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2)
+#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2)
+
+#define WINCON3_BLD_PIX				(1 << 6)
+
+#define WINCON3_ALPHA_SEL			(1 << 1)
+#define WINCON3_BPPMODE_MASK			(0xf << 2)
+#define WINCON3_BPPMODE_SHIFT			(2)
+#define WINCON3_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON3_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON3_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2)
+#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2)
+#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2)
+#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2)
+#define WINCON3_BPPMODE_24BPP_888		(0xb << 2)
+#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2)
+#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2)
+#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2)
+
+#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5)
+
+#define DITHMODE				(0x170)
+#define WINxMAP(_win)				(0x180 + ((_win) * 4))
+
+
+#define DITHMODE_R_POS_MASK			(0x3 << 5)
+#define DITHMODE_R_POS_SHIFT			(5)
+#define DITHMODE_R_POS_8BIT			(0x0 << 5)
+#define DITHMODE_R_POS_6BIT			(0x1 << 5)
+#define DITHMODE_R_POS_5BIT			(0x2 << 5)
+
+#define DITHMODE_G_POS_MASK			(0x3 << 3)
+#define DITHMODE_G_POS_SHIFT			(3)
+#define DITHMODE_G_POS_8BIT			(0x0 << 3)
+#define DITHMODE_G_POS_6BIT			(0x1 << 3)
+#define DITHMODE_G_POS_5BIT			(0x2 << 3)
+
+#define DITHMODE_B_POS_MASK			(0x3 << 1)
+#define DITHMODE_B_POS_SHIFT			(1)
+#define DITHMODE_B_POS_8BIT			(0x0 << 1)
+#define DITHMODE_B_POS_6BIT			(0x1 << 1)
+#define DITHMODE_B_POS_5BIT			(0x2 << 1)
+
+#define DITHMODE_DITH_EN			(1 << 0)
+
+#define WPALCON					(0x1A0)
+
+/* Palette control */
+/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
+ * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
+#define WPALCON_W4PAL_16BPP_A555		(1 << 8)
+#define WPALCON_W3PAL_16BPP_A555		(1 << 7)
+#define WPALCON_W2PAL_16BPP_A555		(1 << 6)
+
+
+/* Notes on per-window bpp settings
+ *
+ * Value	Win0	 Win1	  Win2	   Win3	    Win 4
+ * 0000		1(P)	 1(P)	  1(P)	   1(P)	    1(P)
+ * 0001		2(P)	 2(P)     2(P)	   2(P)	    2(P)
+ * 0010		4(P)	 4(P)     4(P)	   4(P)     -none-
+ * 0011		8(P)	 8(P)     -none-   -none-   -none-
+ * 0100		-none-	 8(A232)  8(A232)  -none-   -none-
+ * 0101		16(565)	 16(565)  16(565)  16(565)   16(565)
+ * 0110		-none-	 16(A555) 16(A555) 16(A555)  16(A555)
+ * 0111		16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
+ * 1000		18(666)	 18(666)  18(666)  18(666)   18(666)
+ * 1001		-none-	 18(A665) 18(A665) 18(A665)  16(A665)
+ * 1010		-none-	 19(A666) 19(A666) 19(A666)  19(A666)
+ * 1011		24(888)	 24(888)  24(888)  24(888)   24(888)
+ * 1100		-none-	 24(A887) 24(A887) 24(A887)  24(A887)
+ * 1101		-none-	 25(A888) 25(A888) 25(A888)  25(A888)
+ * 1110		-none-	 -none-	  -none-   -none-    -none-
+ * 1111		-none-	 -none-   -none-   -none-    -none-
+*/
+
+/*FIMD V8 REG OFFSET */
+#define FIMD_V8_VIDTCON0	(0x20010)
+#define FIMD_V8_VIDTCON1	(0x20014)
+#define FIMD_V8_VIDTCON2	(0x20018)
+#define FIMD_V8_VIDTCON3	(0x2001C)
+#define FIMD_V8_VIDCON1		(0x20004)
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 0/3] ARM: SAMSUNG: Move FIMD headers to include/video/
From: Leela Krishna Amudala @ 2012-07-30  8:57 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: dri-devel, linux-fbdev, ben-linux, inki.dae, kgene.kim, joshi,
	jg1.han

This patchset moves the contents of regs-fb-v4.h and regs-fb.h from arch side
to include/video/samsung_fimd.h

This patchset is created and rebased against master branch of torvalds tree.
Tested on smdk5250 board, build tested for other boards.

Leela Krishna Amudala (3):
  Move FIMD register headers to include/video/
  arm: samsung: Include the modified FIMD header file
  driver: Include the modified FIMD header file

 arch/arm/mach-exynos/mach-nuri.c                |    2 +-
 arch/arm/mach-exynos/mach-origen.c              |    2 +-
 arch/arm/mach-exynos/mach-smdk4x12.c            |    2 +-
 arch/arm/mach-exynos/mach-smdkv310.c            |    2 +-
 arch/arm/mach-exynos/mach-universal_c210.c      |    2 +-
 arch/arm/mach-exynos/setup-fimd0.c              |    2 +-
 arch/arm/mach-s3c24xx/mach-smdk2416.c           |    2 +-
 arch/arm/mach-s3c64xx/mach-anw6410.c            |    2 +-
 arch/arm/mach-s3c64xx/mach-crag6410.c           |    2 +-
 arch/arm/mach-s3c64xx/mach-hmt.c                |    2 +-
 arch/arm/mach-s3c64xx/mach-mini6410.c           |    2 +-
 arch/arm/mach-s3c64xx/mach-ncp.c                |    2 +-
 arch/arm/mach-s3c64xx/mach-real6410.c           |    2 +-
 arch/arm/mach-s3c64xx/mach-smartq5.c            |    2 +-
 arch/arm/mach-s3c64xx/mach-smartq7.c            |    2 +-
 arch/arm/mach-s3c64xx/mach-smdk6410.c           |    2 +-
 arch/arm/mach-s5p64x0/mach-smdk6440.c           |    2 +-
 arch/arm/mach-s5p64x0/mach-smdk6450.c           |    2 +-
 arch/arm/mach-s5pc100/mach-smdkc100.c           |    2 +-
 arch/arm/mach-s5pv210/mach-aquila.c             |    2 +-
 arch/arm/mach-s5pv210/mach-goni.c               |    2 +-
 arch/arm/mach-s5pv210/mach-smdkv210.c           |    2 +-
 arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 -------
 arch/arm/plat-samsung/include/plat/regs-fb.h    |  403 -----------------
 drivers/gpu/drm/exynos/exynos_drm_fimd.c        |    2 +-
 drivers/video/s3c-fb.c                          |    2 +-
 include/video/samsung_fimd.h                    |  533 +++++++++++++++++++++++
 27 files changed, 557 insertions(+), 586 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
 delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
 create mode 100644 include/video/samsung_fimd.h


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox