@@ -253,6 +253,36 @@ static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev)
lcd_enabled = 0;
}
+/*
+ * PWMA/B register offsets (TWL4030_MODULE_PWMA)
+ */
+#define TWL_LED_EN 0x0
+#define TWL_LED_PWMON 0x0
+#define TWL_LED_PWMOFF 0x1
+
+static void omap3evm_set_bl_intensity(struct omap_dss_device *dssdev, int level)
+{
+ unsigned char c;
+
+ if (level > 100)
+ return;
+ /*
+ * Enable LEDA for backlight
+ */
+ twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_EN);
+
+ c = ((125 * (100 - level)) / 100);
+ if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) {
+ c += 1;
+ twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x7F, TWL_LED_PWMOFF);
+ twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_LED_PWMON);
+ } else {
+ c += 2;
+ twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x1, TWL_LED_PWMON);
+ twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_LED_PWMOFF);
+ }
+}
+
static struct omap_dss_device omap3_evm_lcd_device = {
.name = "lcd",
.driver_name = "sharp_ls_panel",
@@ -260,6 +290,8 @@ static struct omap_dss_device omap3_evm_lcd_device = {
.phy.dpi.data_lines = 18,
.platform_enable = omap3_evm_enable_lcd,
.platform_disable = omap3_evm_disable_lcd,
+ .max_backlight_level = 100,
+ .set_backlight = omap3evm_set_bl_intensity,
};
static int omap3_evm_enable_tv(struct omap_dss_device *dssdev)
@@ -20,10 +20,16 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
#include <linux/err.h>
#include <plat/display.h>
+struct sharp_data {
+ struct backlight_device *bl;
+};
+
static struct omap_video_timings sharp_ls_timings = {
.x_res = 480,
.y_res = 640,
@@ -39,18 +45,87 @@ static struct omap_video_timings sharp_ls_timings = {
.vbp = 1,
};
+static int sharp_ls_bl_update_status(struct backlight_device *bl)
+{
+ struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
+ int level;
+
+ if (!dssdev->set_backlight)
+ return -EINVAL;
+
+ if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
+ bl->props.power == FB_BLANK_UNBLANK)
+ level = bl->props.brightness;
+ else
+ level = 0;
+
+ return dssdev->set_backlight(dssdev, level);
+}
+
+static int sharp_ls_bl_get_brightness(struct backlight_device *bl)
+{
+ if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
+ bl->props.power == FB_BLANK_UNBLANK)
+ return bl->props.brightness;
+
+ return 0;
+}
+
+static const struct backlight_ops sharp_ls_bl_ops = {
+ .get_brightness = sharp_ls_bl_get_brightness,
+ .update_status = sharp_ls_bl_update_status,
+};
+
+
+
static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
{
+ struct backlight_device *bl;
+ struct sharp_data *sd;
+ int r;
+
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS;
dssdev->panel.acb = 0x28;
dssdev->panel.timings = sharp_ls_timings;
+ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+ if (!sd)
+ return -ENOMEM;
+
+ dev_set_drvdata(&dssdev->dev, sd);
+
+ bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
+ &sharp_ls_bl_ops);
+ if (IS_ERR(bl)) {
+ r = PTR_ERR(bl);
+ kfree(sd);
+ return r;
+ }
+ sd->bl = bl;
+
+ bl->props.fb_blank = FB_BLANK_UNBLANK;
+ bl->props.power = FB_BLANK_UNBLANK;
+ bl->props.max_brightness = dssdev->max_backlight_level;
+ bl->props.brightness = dssdev->max_backlight_level;
+
+ r = sharp_ls_bl_update_status(bl);
+ if (r < 0)
+ dev_err(&dssdev->dev, "failed to set lcd brightness\n");
+
return 0;
}
static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
{
+ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
+ struct backlight_device *bl = sd->bl;
+
+ bl->props.power = FB_BLANK_POWERDOWN;
+ sharp_ls_bl_update_status(bl);
+ backlight_device_unregister(bl);
+
+ kfree(sd);
}
static int sharp_ls_power_on(struct omap_dss_device *dssdev)