DORMANTno replies

[PATCH] mx3fb: adds LCD backlight driver

From: Anatolij Gustschin <agust@denx.de>
Date: 2009-11-09 11:13:31
Subsystem: framebuffer layer, the rest · Maintainers: Helge Deller, Linus Torvalds

To activate this driver select CONFIG_BACKLIGHT_LCD_SUPPORT
in the kernel configuration. Backlight control interface
will be available under /sys/class/backlight/mx3fb/.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 drivers/video/mx3fb.c |  100 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 99 insertions(+), 1 deletions(-)
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 86312dd..f8f9338 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -30,6 +30,7 @@
 #include <mach/hardware.h>
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
+#include <linux/backlight.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -60,6 +61,12 @@
 #define SDC_COM_BG_EN		0x00000200UL
 #define SDC_COM_SHARP		0x00001000UL
 
+#define SDC_PWM_SRC_HSYNC_CLK	0x00000000UL
+#define SDC_PWM_SRC_PXL_CLK	0x02000000UL
+#define SDC_PWM_SRC_HSP_CLK	0x04000000UL
+#define SDC_PWM_CC_EN		0x01000000UL
+#define SDC_PWM_PWM_MSK		0x00FF0000UL
+
 #define SDC_V_SYNC_WIDTH_L	0x00000001UL
 
 /* Display Interface registers */
@@ -238,6 +245,7 @@ static const struct fb_videomode mx3fb_modedb[] = {
 struct mx3fb_data {
 	struct fb_info		*fbi;
 	int			backlight_level;
+	int			pwm_clk_src;	/* clock source for PWM */
 	void __iomem		*reg_base;
 	spinlock_t		lock;
 	struct device		*dev;
@@ -268,6 +276,7 @@ struct mx3fb_info {
 	struct scatterlist		sg[2];
 
 	u32				sync;	/* preserve var->sync flags */
+	struct backlight_device		*backlight;
 };
 
 static void mx3fb_dma_done(void *);
@@ -647,7 +656,9 @@ static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t a
 static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
 {
 	/* This might be board-specific */
-	mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
+	u32 reg = mx3fb->pwm_clk_src | SDC_PWM_CC_EN | value << 16;
+
+	mx3fb_write_reg(mx3fb, reg, SDC_PWM_CTRL);
 	return;
 }
 
@@ -1207,6 +1218,88 @@ static int mx3fb_resume(struct platform_device *pdev)
 #define mx3fb_resume    NULL
 #endif
 
+#ifdef CONFIG_BACKLIGHT_LCD_SUPPORT
+/*
+ * Backlight device
+ */
+static int mx3fb_bl_update_status(struct backlight_device *bl)
+{
+	struct mx3fb_info *fbi = bl_get_data(bl);
+	struct mx3fb_data *mx3fb = fbi->mx3fb;
+	int brightness;
+
+	if (bl->props.power != FB_BLANK_UNBLANK ||
+	    bl->props.fb_blank != FB_BLANK_UNBLANK)
+		brightness = 0;
+	else
+		brightness = bl->props.brightness;
+
+	mx3fb->backlight_level = brightness;
+	sdc_set_brightness(mx3fb, mx3fb->backlight_level);
+	return 0;
+}
+
+static int mx3fb_bl_get_brightness(struct backlight_device *bl)
+{
+	struct mx3fb_info *fbi = bl_get_data(bl);
+	struct mx3fb_data *mx3fb = fbi->mx3fb;
+	uint32_t reg;
+
+	reg = mx3fb_read_reg(mx3fb, SDC_PWM_CTRL);
+
+	return (reg & SDC_PWM_PWM_MSK) >> 16;
+}
+
+static struct backlight_ops mx3fb_bl_ops = {
+	.update_status = mx3fb_bl_update_status,
+	.get_brightness = mx3fb_bl_get_brightness,
+};
+
+static void mx3fb_init_backlight(struct mx3fb_info *fbi)
+{
+	struct backlight_device	*bl;
+	struct mx3fb_data *mx3fb = fbi->mx3fb;
+
+	/*
+	 * COM57H5M10XRC supports max. 300Hz for PDM, so
+	 * we use HSYNC as clock source.
+	 */
+	if (fb_mode && !strncmp(fb_mode, "COM57H5M10XRC", 13))
+		mx3fb->pwm_clk_src = SDC_PWM_SRC_HSYNC_CLK;
+
+	if (fbi->backlight)
+		return;
+
+	bl = backlight_device_register("mx3fb", mx3fb->dev,
+				       fbi, &mx3fb_bl_ops);
+	if (IS_ERR(bl)) {
+		dev_err(mx3fb->dev, "register backlight failed: %ld\n",
+			PTR_ERR(bl));
+		return;
+	}
+	fbi->backlight = bl;
+
+	bl->props.power = FB_BLANK_UNBLANK;
+	bl->props.fb_blank = FB_BLANK_UNBLANK;
+	bl->props.max_brightness = 0xff;
+	bl->props.brightness = 0xff;
+}
+
+static void mx3fb_exit_backlight(struct mx3fb_info *fbi)
+{
+	if (fbi->backlight)
+		backlight_device_unregister(fbi->backlight);
+}
+#else
+static inline void mx3fb_init_backlight(struct mx3fb_info *fbi)
+{
+}
+
+static inline void mx3fb_exit_backlight(struct mx3fb_info *fbi)
+{
+}
+#endif
+
 /*
  * Main framebuffer functions
  */
@@ -1390,6 +1483,8 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
 	if (ret < 0)
 		goto esetpar;
 
+	mx3fb_init_backlight(mx3fbi);
+
 	__blank(FB_BLANK_UNBLANK, fbi);
 
 	dev_info(dev, "registered, using mode %s\n", fb_mode);
@@ -1401,6 +1496,7 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
 	return 0;
 
 erfb:
+	mx3fb_exit_backlight(mx3fbi);
 esetpar:
 emode:
 	fb_dealloc_cmap(&fbi->cmap);
@@ -1487,6 +1583,7 @@ static int mx3fb_probe(struct platform_device *pdev)
 	}
 
 	mx3fb->backlight_level = 255;
+	mx3fb->pwm_clk_src = SDC_PWM_SRC_PXL_CLK;
 
 	ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
 	if (ret < 0)
@@ -1513,6 +1610,7 @@ static int mx3fb_remove(struct platform_device *dev)
 	struct dma_chan *chan;
 
 	chan = &mx3_fbi->idmac_channel->dma_chan;
+	mx3fb_exit_backlight(mx3_fbi);
 	release_fbi(fbi);
 
 	dma_release_channel(chan);
-- 
1.5.6.3


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help