Monday, January 28, 2013

Enable LCD Brightness control feature for Generic DPI Panels


By default, the 'LCD brightness control' feature has not been added in the Generic DPI panel drivers.

Follow these steps , which will enable the brightness control for the Generic DPI panel drivers.

Kernel version : 3.0.21
Processor         : OMAP4460
Android O.S    : Ice Cream Sandwich (4.0.3)

List of files which requires modifications are.
1) LCD Driver File - panel-generic-dpi.c
2) Board file      - board-4430dsp.c
3) Kernel Config File.

Changes to the LCD Driver File
(/drivers/video/omap2/displays/panel-generic-dpi.c)

1)  #include <linux/backlight.h>

2) //brightness start
static int generic_bl_get_intensity(struct backlight_device *dev)
{
if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
dev->props.power == FB_BLANK_UNBLANK)
return dev->props.brightness;

return 0;
}

static int generic_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 const struct backlight_ops generic_bl_ops = {
.get_brightness = generic_bl_get_intensity,
.update_status  = generic_bl_update_status,
};


3) struct panel_drv_data {

struct omap_dss_device *dssdev;

struct panel_config *panel_config;

//brightness start
struct backlight_device *bldev;
//brightness end
};

4) static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
{
struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
struct panel_config *panel_config = NULL;
struct panel_drv_data *drv_data = NULL;

//brightness start
struct backlight_device *bldev = NULL ;
struct backlight_properties props ;
int iTemp = 0;

//brightness end

int i;

dev_dbg(&dssdev->dev, "probe\n");

if (!panel_data || !panel_data->name)
return -EINVAL;

for (i = 0; i < ARRAY_SIZE(generic_dpi_panels); i++) {
if (strcmp(panel_data->name, generic_dpi_panels[i].name) == 0) {
panel_config = &generic_dpi_panels[i];
break;
}
}

if (!panel_config)
return -EINVAL;

dssdev->panel.config = panel_config->config;
dssdev->panel.timings = panel_config->timings;
dssdev->panel.acb = panel_config->acb;
dssdev->panel.acbi = panel_config->acbi;

drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
if (!drv_data)
return -ENOMEM;

drv_data->dssdev = dssdev;
drv_data->panel_config = panel_config;

dev_set_drvdata(&dssdev->dev, drv_data);

//brightness start
/* if no platform set_backlight() defined, presume DSI backlight
* control */
memset(&props, 0, sizeof(struct backlight_properties));

       props.max_brightness = 255; //the brightness values have been in the range from 0 - 255
       props.type = BACKLIGHT_RAW;

//The sysfs entries will be created after the registration

bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
dssdev, &generic_bl_ops, &props);

if (IS_ERR(bldev))
{
int r = PTR_ERR(bldev);

printk("SANDEEP:generic_dpi_panel_probe() backlight device register didn't happenned \n");

}

bldev->props.fb_blank = FB_BLANK_UNBLANK;
bldev->props.power = FB_BLANK_UNBLANK;
bldev->props.brightness = dssdev->max_backlight_level;

iTemp = generic_bl_update_status(bldev);

if (iTemp < 0)
{
dev_err(&dssdev->dev, "failed to set lcd brightness\n");

printk("SANDEEP:generic_dpi_panel_probe() Failed to set the LCD brightness \n");

}
drv_data->bldev = bldev ; //Copying the backlight data to the driver data. So, that in the later stages this data can be used.

//brightness end

return 0;
}

5)
static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
{
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
//brightness start
struct backlight_device *bldev;
//brightness end
dev_dbg(&dssdev->dev, "remove\n");

//brightness start
if(NULL != drv_data->bldev)
{
bldev = drv_data->bldev ; //getting the backlight data back again.

bldev->props.power = FB_BLANK_POWERDOWN;

backlight_device_unregister(bldev);
}
//brightness end

kfree(drv_data);

dev_set_drvdata(&dssdev->dev, NULL);
}

Changes to the Board File

//brightness start

static int generic_set_backlight(struct omap_dss_device *dssdev, int level)
{
int r;

r = twl_i2c_write_u8(TWL_MODULE_PWM, 0x7F, LED_PWM2OFF);

if (r)
return r;

if (level > 1 && level >=20 && level < 255)
{
  if (level == 255)
                     level = 0x7F;
                else
//                         level = (~(level/2)) & 0x7F;
level = level /2 ; //dummy statement. Needs to check the side effect of this.

                r = twl_i2c_write_u8(TWL_MODULE_PWM, level, LED_PWM2ON);
                if (r)
                        return r;
                r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x30, TWL6030_TOGGLE3);
                if (r)
                        return r;
}
else if (level <= 1)
{
                  r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x08, TWL6030_TOGGLE3);
                if (r)
                        return r;
                r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x28, TWL6030_TOGGLE3);
                if (r)
                        return r;
                r = twl_i2c_write_u8(TWL6030_MODULE_ID1, 0x00, TWL6030_TOGGLE3);
                if (r)
                        return r;
        }
         return 0;
 }

//brightness end

2) struct omap_dss_device omap4_spanda_dvi_device = {
        .type                   = OMAP_DISPLAY_TYPE_DPI,
        .name                   = "generic",
        .driver_name            = "generic_dpi_panel",
        .data                   = &omap4_dvi_panel,
        .phy.dpi.data_lines     = 24,
        .reset_gpio             = PANDA_DVI_TFP410_POWER_DOWN_GPIO,
        .channel                = OMAP_DSS_CHANNEL_LCD2,
 //brightness  start
.set_backlight = generic_set_backlight,
//brightness end
};

Changes to Kernel Config File
CONFIG_BACKLIGHT_GENERIC = y




1 comment: