ktd2801背光控制器支持两种调光方式:
1. 可通过控制引脚输入一组脉冲信号作为控制命令,来确定一个输出强度。
2. 同时也支持在该控制引脚输入一个持续的PWM脉冲来确定一个输出强度。
后者等同于其他类型的PWM调光控制方式:背光打开时必须要有一个持续的PWM输入信号;通过调整PWM的占空比来调整背光亮度。这种方式下的持续的PWM信号据说会造成其他设备的信号干扰。而ktd2801的第一种调光方式可解决这个问题。
在第一种调光方式中,只有亮度调整时才会向控制引脚输入一组脉冲作为控制命令,当ktd2801接到这个命令后便会改变背光强度。此后该控制引脚不需要维持脉冲信号。
通常,在该方式下,AP侧会用一个gpio引脚连接到ktd2801的控制端。软件会对该gpio进行输出高、低的操作来模拟出一组脉冲信号作为控制命令。命令协议很简单,可参考ktd2801的datasheet。
工作中出现的问题是:软件对该gpio进行输出高、底的操作时会出现偶尔的脉冲宽度不一致。也就是偶尔出现脉冲宽度比我们期望的要大很多,这会导致ktd2801解析出现错误,表现为对该命令不响应。
分析:
1. 首先必须明确,用gpio模拟一个信号时,维持高低电平的时间必须忙等,也就是必须用udelay之类的函数,绝对不能用msleep。这个原因很浅显。
2. 其次每个命令周期必须用自旋锁包裹起来,不能被打断。否则就会出现延时比你期望的要长,导致命令错误。
先前的代码对2使用的是:
spin_lock(&bl_ctrl_lock);
spin_unlock(&bl_ctrl_lock);
用了这个锁后,还是出现了延时比期望的要长,可能是有中断发生导致的。
因此,换为下面的锁,该锁会屏蔽中断,问题解决!
spin_lock_irqsave(&bl_ctrl_lock, flags);
spin_unlock_irqrestore(&bl_ctrl_lock, flags);
======================附上源码:修改前================================
/*************** maintained by customer ***************************************/
#define CONFIG_BACKLIGHT_AMAZING 1
/*
* linux/drivers/video/backlight/s2c_bl.c
*
* 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.
*/
/*******************************************************************************
* Copyright 2010 Broadcom Corporation. All rights reserved.
*
* @file drivers/video/backlight/s2c_bl.c
*
* Unless you and Broadcom execute a separate written software license agreement
* governing use of this software, this software is licensed to you under the
* terms of the GNU General Public License version 2, available at
* http://www.gnu.org/copyleft/gpl.html (the "GPL").
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*******************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/ktd2801_bl.h>
#include <mach/gpio.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#ifdef CONFIG_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
static DEFINE_SPINLOCK(bl_ctrl_lock);
#define BACKLIGHT_DEBUG 1
#if BACKLIGHT_DEBUG
#define BLDBG(fmt, args...) printk(fmt, ## args)
#else
#define BLDBG(fmt, args...)
#endif
#define EXPRESSWIRE_DIMMING
#ifdef EXPRESSWIRE_DIMMING
#define EW_DELAY 200
#define EW_DETECT 300
#define EW_WINDOW 900
#define DATA_START 40
#define LOW_BIT_L 40
#define LOW_BIT_H 10
#define HIGH_BIT_L 10
#define HIGH_BIT_H 40
#define END_DATA_L 10
#define END_DATA_H 400
#endif
#define BACKLIGHT_DEV_NAME "sprd_backlight"
int BL_brightness;
int is_poweron = 1;
int current_brightness;
int wakeup_brightness;
#ifdef CONFIG_MACH_NEVISTD
#define GPIO_BL_CTRL 138
#else
#define GPIO_BL_CTRL 190
#endif
#ifdef CONFIG_MACH_NEVISTD
#define MAX_BRIGHTNESS 255
#define MIN_BRIGHTNESS 20
#define DEFAULT_BRIGHTNESS 130
#define DEFAULT_PULSE 20
#define DIMMING_VALUE 31
#define MAX_BRIGHTNESS_IN_BLU 32 // backlight-IC MAX VALUE
#else
#define MAX_BRIGHTNESS 255
#define MIN_BRIGHTNESS 20
#define DEFAULT_BRIGHTNESS 122
#define DEFAULT_PULSE 20
#define DIMMING_VALUE 31
#define MAX_BRIGHTNESS_IN_BLU 32 // backlight-IC MAX VALUE
#endif
static int lcd_brightness = DEFAULT_PULSE;
struct brt_value{
int level; // Platform setting values
int tune_level; // Chip Setting values
};
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend_BL;
#endif
struct brt_value brt_table_ktd[] = {
{ 255, 0 }, /* Max */
{ 250, 2 },
{ 245, 3 },
{ 240, 4 },
{ 235, 5 },
{ 230, 6 },
{ 220, 7 },
{ 210, 8 },
{ 200, 9 },
{ 190, 10 },
{ 180, 11 },
{ 170, 12 },
{ 160, 13 },
{ 150, 14 },
{ 140, 15 },
{ 130, 16 },
{ 120, 17 }, /* default */
{ 115, 18 },
{ 110, 19 },
{ 105, 20 },
{ 100, 21 },
{ 95, 22 },
{ 90, 23 },
{ 85, 24 },
{ 80, 25 },
{ 70, 26 }, /* Dimming */
{ 60, 27 },
{ 50, 28 },
{ 40, 29 },
{ 30, 30 },
{ 20, 31 },
{ 0, 31 }, /* Off */
};
#define NB_BRT_LEVEL (int)(sizeof(brt_table_ktd)/sizeof(struct brt_value))
#if defined(CONFIG_FB_SC8825) && defined(CONFIG_FB_LCD_NT35510_MIPI)
extern bool is_first_frame_done;
#endif
#ifdef CONFIG_MACH_NEVISTD
extern int spa_lpm_charging_mode_get(void);
#endif
#ifdef CONFIG_EARLYSUSPEND
static void ktd253_backlight_early_suspend(struct early_suspend *h)
{
is_poweron = 0;
ktd_backlight_set_brightness(0);
#ifdef EXPRESSWIRE_DIMMING
gpio_set_value(GPIO_BL_CTRL, 0);
#endif
return;
}
static void ktd253_backlight_late_resume(struct early_suspend *h)
{
int i = 0;
#if defined(CONFIG_FB_SC8825) && defined(CONFIG_FB_LCD_NT35510_MIPI)
while (i++ < 10 && !is_first_frame_done) {
printk(KERN_INFO "[Backlight] wait first vsync_done, sleep 200msec\n", __func__);
msleep(200);
}
#endif
#ifdef EXPRESSWIRE_DIMMING
spin_lock(&bl_ctrl_lock);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(200);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(300);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(400);
spin_unlock(&bl_ctrl_lock);
#endif
ktd_backlight_set_brightness(wakeup_brightness);
is_poweron = 1;
}
#endif
#ifdef EXPRESSWIRE_DIMMING
void ktd_backlight_set_brightness(int level)
{
int i = 0;
unsigned char brightness;
int bit_map[8];
brightness = level;
printk("set_brightness : level(%d)\n", brightness);
for(i = 0; i < 8; i++)
{
bit_map[i] = brightness & 0x01;
brightness >>= 1;
}
spin_lock(&bl_ctrl_lock);
#if 0
gpio_set_value(GPIO_BL_CTRL, 0);
msleep(10);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(200);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(300);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(400);
#endif
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(DATA_START);
for(i = 7; i >= 0; i--)
{
if(bit_map[i])
{
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(HIGH_BIT_L);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(HIGH_BIT_H);
}
else
{
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(LOW_BIT_L);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(LOW_BIT_H);
}
}
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(END_DATA_L);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(END_DATA_H);
spin_unlock(&bl_ctrl_lock);
return;
}
#else
void ktd_backlight_set_brightness(int level)
{
int tune_level = 0;
spin_lock(&bl_ctrl_lock);
if (level > 0) {
if (level < MIN_BRIGHTNESS) {
tune_level = DIMMING_VALUE; /* DIMMING */
} else {
int i;
for (i = 0; i < NB_BRT_LEVEL; i++) {
if (level <= brt_table_ktd[i].level
&& level > brt_table_ktd[i+1].level) {
tune_level = brt_table_ktd[i].tune_level;
break;
}
}
}
} /* BACKLIGHT is KTD model */
printk("set_brightness : level(%d) tune (%d)\n",level, tune_level);
current_brightness = level;
if (!level) {
gpio_set_value(GPIO_BL_CTRL, 0);
mdelay(3);
lcd_brightness = tune_level;
} else {
int pulse;
if (unlikely(lcd_brightness < 0)) {
int val = gpio_get_value(GPIO_BL_CTRL);
if (val) {
lcd_brightness = 0;
gpio_set_value(GPIO_BL_CTRL, 0);
mdelay(3);
printk(KERN_INFO "LCD Baklight init in boot time on kernel\n");
}
}
#ifdef CONFIG_MACH_NEVISTD
if(spa_lpm_charging_mode_get())
msleep(500);
#endif
if (!lcd_brightness) {
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(3);
lcd_brightness = MAX_BRIGHTNESS_IN_BLU;
}
pulse = (tune_level - lcd_brightness + MAX_BRIGHTNESS_IN_BLU)
% MAX_BRIGHTNESS_IN_BLU;
for (; pulse > 0; pulse--) {
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(3);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(3);
}
lcd_brightness = tune_level;
}
mdelay(1);
spin_unlock(&bl_ctrl_lock);
return;
}
#endif
static int ktd_backlight_update_status(struct backlight_device *bl)
{
int brightness = bl->props.brightness;
if (bl->props.power != FB_BLANK_UNBLANK)
brightness = 0;
if (bl->props.fb_blank != FB_BLANK_UNBLANK)
brightness = 0;
wakeup_brightness = brightness;
if (is_poweron == 1)
ktd_backlight_set_brightness(brightness);
else
BLDBG("[BACKLIGHT] warning : ignore set brightness\n");
return 0;
}
static int ktd_backlight_get_brightness(struct backlight_device *bl)
{
BLDBG("[BACKLIGHT] ktd_backlight_get_brightness\n");
BL_brightness = bl->props.brightness;
return BL_brightness;
}
static const struct backlight_ops ktd_backlight_ops = {
.update_status = ktd_backlight_update_status,
.get_brightness = ktd_backlight_get_brightness,
};
static int ktd_backlight_probe(struct platform_device *pdev)
{
// struct platform_ktd253b_backlight_data *data = pdev->dev.platform_data;
struct backlight_device *bl;
struct backlight_properties props;
printk("[BACKLIGHT] ktd253b_backlight_probe\n");
memset(&props, 0, sizeof(struct backlight_properties));
props.max_brightness = MAX_BRIGHTNESS;
props.type = BACKLIGHT_RAW;
bl = backlight_device_register(BACKLIGHT_DEV_NAME, &pdev->dev, NULL,
&ktd_backlight_ops, &props);
if (IS_ERR(bl))
{
dev_err(&pdev->dev, "failed to register backlight\n");
return PTR_ERR(bl);
}
bl->props.max_brightness = MAX_BRIGHTNESS;
bl->props.brightness = DEFAULT_BRIGHTNESS;
platform_set_drvdata(pdev, bl);
if(gpio_request(GPIO_BL_CTRL,"BL_CTRL"))
printk(KERN_ERR "Request GPIO failed,""gpio: %d \n", GPIO_BL_CTRL);
#ifdef EXPRESSWIRE_DIMMING
spin_lock(&bl_ctrl_lock);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(1500);
udelay(1500);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(200);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(300);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(400);
spin_unlock(&bl_ctrl_lock);
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
early_suspend_BL.suspend = ktd253_backlight_early_suspend;
early_suspend_BL.resume = ktd253_backlight_late_resume;
early_suspend_BL.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
register_early_suspend(&early_suspend_BL);
#endif
ktd_backlight_update_status(bl);
return 0;
out:
return 1;
}
static int ktd_backlight_remove(struct platform_device *pdev)
{
struct backlight_device *bl = platform_get_drvdata(pdev);
backlight_device_unregister(bl);
gpio_direction_output(GPIO_BL_CTRL, 0);
mdelay(3);
return 0;
}
void ktd_backlight_shutdown(struct platform_device *pdev)
{
printk("[coko] %s\n",__FUNCTION__);
gpio_direction_output(GPIO_BL_CTRL, 0);
mdelay(5);
}
static struct platform_driver ktd_backlight_driver = {
.driver = {
.name = BACKLIGHT_DEV_NAME,
.owner = THIS_MODULE,
},
.probe = ktd_backlight_probe,
.remove = ktd_backlight_remove,
.shutdown = ktd_backlight_shutdown,
};
static int __init ktd_backlight_init(void)
{
return platform_driver_register(&ktd_backlight_driver);
}
module_init(ktd_backlight_init);
static void __exit ktd_backlight_exit(void)
{
platform_driver_unregister(&ktd_backlight_driver);
}
module_exit(ktd_backlight_exit);
MODULE_DESCRIPTION("KTD based Backlight Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ktd-backlight");
/*************** maintained by customer ***************************************/
#define CONFIG_BACKLIGHT_AMAZING 1
/*
* linux/drivers/video/backlight/s2c_bl.c
*
* 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.
*/
/*******************************************************************************
* Copyright 2010 Broadcom Corporation. All rights reserved.
*
* @file drivers/video/backlight/s2c_bl.c
*
* Unless you and Broadcom execute a separate written software license agreement
* governing use of this software, this software is licensed to you under the
* terms of the GNU General Public License version 2, available at
* http://www.gnu.org/copyleft/gpl.html (the "GPL").
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*******************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/ktd2801_bl.h>
#include <mach/gpio.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#ifdef CONFIG_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
static DEFINE_SPINLOCK(bl_ctrl_lock);
#define BACKLIGHT_DEBUG 1
#if BACKLIGHT_DEBUG
#define BLDBG(fmt, args...) printk(fmt, ## args)
#else
#define BLDBG(fmt, args...)
#endif
#define EXPRESSWIRE_DIMMING
#ifdef EXPRESSWIRE_DIMMING
#define EW_DELAY 200
#define EW_DETECT 300
#define EW_WINDOW 900
#define DATA_START 10
#define LOW_BIT_L 15
#define LOW_BIT_H 5
#define HIGH_BIT_L 5
#define HIGH_BIT_H 15
#define END_DATA_L 10
#define END_DATA_H 400
#endif
#define BACKLIGHT_DEV_NAME "sprd_backlight"
int BL_brightness;
int is_poweron = 1;
int current_brightness;
int wakeup_brightness;
#ifdef CONFIG_MACH_NEVISTD
#define GPIO_BL_CTRL 138
#else
#define GPIO_BL_CTRL 190
#endif
#ifdef CONFIG_MACH_NEVISTD
#define MAX_BRIGHTNESS 255
#define MIN_BRIGHTNESS 20
#define DEFAULT_BRIGHTNESS 130
#define DEFAULT_PULSE 20
#define DIMMING_VALUE 31
#define MAX_BRIGHTNESS_IN_BLU 32 // backlight-IC MAX VALUE
#else
#define MAX_BRIGHTNESS 255
#define MIN_BRIGHTNESS 20
#define DEFAULT_BRIGHTNESS 122
#define DEFAULT_PULSE 20
#define DIMMING_VALUE 31
#define MAX_BRIGHTNESS_IN_BLU 32 // backlight-IC MAX VALUE
#endif
static int lcd_brightness = DEFAULT_PULSE;
struct brt_value{
int level; // Platform setting values
int tune_level; // Chip Setting values
};
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend_BL;
#endif
struct brt_value brt_table_ktd[] = {
{ 255, 0 }, /* Max */
{ 250, 2 },
{ 245, 3 },
{ 240, 4 },
{ 235, 5 },
{ 230, 6 },
{ 220, 7 },
{ 210, 8 },
{ 200, 9 },
{ 190, 10 },
{ 180, 11 },
{ 170, 12 },
{ 160, 13 },
{ 150, 14 },
{ 140, 15 },
{ 130, 16 },
{ 120, 17 }, /* default */
{ 115, 18 },
{ 110, 19 },
{ 105, 20 },
{ 100, 21 },
{ 95, 22 },
{ 90, 23 },
{ 85, 24 },
{ 80, 25 },
{ 70, 26 }, /* Dimming */
{ 60, 27 },
{ 50, 28 },
{ 40, 29 },
{ 30, 30 },
{ 20, 31 },
{ 0, 31 }, /* Off */
};
#define NB_BRT_LEVEL (int)(sizeof(brt_table_ktd)/sizeof(struct brt_value))
#if defined(CONFIG_FB_SC8825) && defined(CONFIG_FB_LCD_NT35510_MIPI)
extern bool is_first_frame_done;
#endif
#ifdef CONFIG_MACH_NEVISTD
extern int spa_lpm_charging_mode_get(void);
#endif
#ifdef CONFIG_EARLYSUSPEND
static void ktd253_backlight_early_suspend(struct early_suspend *h)
{
is_poweron = 0;
ktd_backlight_set_brightness(0);
#ifdef EXPRESSWIRE_DIMMING
gpio_set_value(GPIO_BL_CTRL, 0);
#endif
return;
}
static void ktd253_backlight_late_resume(struct early_suspend *h)
{
int i = 0;
unsigned long flags;
#if defined(CONFIG_FB_SC8825) && defined(CONFIG_FB_LCD_NT35510_MIPI)
while (i++ < 10 && !is_first_frame_done) {
printk(KERN_INFO "[Backlight] wait first vsync_done, sleep 200msec\n", __func__);
msleep(200);
}
#endif
#ifdef EXPRESSWIRE_DIMMING
//spin_lock(&bl_ctrl_lock);
spin_lock_irqsave(&bl_ctrl_lock, flags);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(200);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(300);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(400);
//spin_unlock(&bl_ctrl_lock);
spin_unlock_irqrestore(&bl_ctrl_lock, flags);
#endif
ktd_backlight_set_brightness(wakeup_brightness);
is_poweron = 1;
}
#endif
#ifdef EXPRESSWIRE_DIMMING
void ktd_backlight_set_brightness(int level)
{
int i = 0;
unsigned char brightness;
int bit_map[8];
brightness = level;
unsigned long flags;
printk("set_brightness : level(%d)\n", brightness);
for(i = 0; i < 8; i++)
{
bit_map[i] = brightness & 0x01;
brightness >>= 1;
}
//spin_lock(&bl_ctrl_lock);
spin_lock_irqsave(&bl_ctrl_lock, flags);
#if 0
gpio_set_value(GPIO_BL_CTRL, 0);
msleep(10);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(200);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(300);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(400);
#endif
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(DATA_START);
for(i = 7; i >= 0; i--)
{
if(bit_map[i])
{
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(HIGH_BIT_L);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(HIGH_BIT_H);
}
else
{
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(LOW_BIT_L);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(LOW_BIT_H);
}
}
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(END_DATA_L);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(END_DATA_H);
//spin_unlock(&bl_ctrl_lock);
spin_unlock_irqrestore(&bl_ctrl_lock, flags);
return;
}
#else
void ktd_backlight_set_brightness(int level)
{
int tune_level = 0;
spin_lock(&bl_ctrl_lock);
if (level > 0) {
if (level < MIN_BRIGHTNESS) {
tune_level = DIMMING_VALUE; /* DIMMING */
} else {
int i;
for (i = 0; i < NB_BRT_LEVEL; i++) {
if (level <= brt_table_ktd[i].level
&& level > brt_table_ktd[i+1].level) {
tune_level = brt_table_ktd[i].tune_level;
break;
}
}
}
} /* BACKLIGHT is KTD model */
printk("set_brightness : level(%d) tune (%d)\n",level, tune_level);
current_brightness = level;
if (!level) {
gpio_set_value(GPIO_BL_CTRL, 0);
mdelay(3);
lcd_brightness = tune_level;
} else {
int pulse;
if (unlikely(lcd_brightness < 0)) {
int val = gpio_get_value(GPIO_BL_CTRL);
if (val) {
lcd_brightness = 0;
gpio_set_value(GPIO_BL_CTRL, 0);
mdelay(3);
printk(KERN_INFO "LCD Baklight init in boot time on kernel\n");
}
}
#ifdef CONFIG_MACH_NEVISTD
if(spa_lpm_charging_mode_get())
msleep(500);
#endif
if (!lcd_brightness) {
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(3);
lcd_brightness = MAX_BRIGHTNESS_IN_BLU;
}
pulse = (tune_level - lcd_brightness + MAX_BRIGHTNESS_IN_BLU)
% MAX_BRIGHTNESS_IN_BLU;
for (; pulse > 0; pulse--) {
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(3);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(3);
}
lcd_brightness = tune_level;
}
mdelay(1);
spin_unlock(&bl_ctrl_lock);
return;
}
#endif
static int ktd_backlight_update_status(struct backlight_device *bl)
{
int brightness = bl->props.brightness;
if (bl->props.power != FB_BLANK_UNBLANK)
brightness = 0;
if (bl->props.fb_blank != FB_BLANK_UNBLANK)
brightness = 0;
wakeup_brightness = brightness;
if (is_poweron == 1)
ktd_backlight_set_brightness(brightness);
else
BLDBG("[BACKLIGHT] warning : ignore set brightness\n");
return 0;
}
static int ktd_backlight_get_brightness(struct backlight_device *bl)
{
BLDBG("[BACKLIGHT] ktd_backlight_get_brightness\n");
BL_brightness = bl->props.brightness;
return BL_brightness;
}
static const struct backlight_ops ktd_backlight_ops = {
.update_status = ktd_backlight_update_status,
.get_brightness = ktd_backlight_get_brightness,
};
static int ktd_backlight_probe(struct platform_device *pdev)
{
// struct platform_ktd253b_backlight_data *data = pdev->dev.platform_data;
struct backlight_device *bl;
struct backlight_properties props;
unsigned long flags;
printk("[BACKLIGHT] ktd253b_backlight_probe\n");
memset(&props, 0, sizeof(struct backlight_properties));
props.max_brightness = MAX_BRIGHTNESS;
props.type = BACKLIGHT_RAW;
bl = backlight_device_register(BACKLIGHT_DEV_NAME, &pdev->dev, NULL,
&ktd_backlight_ops, &props);
if (IS_ERR(bl))
{
dev_err(&pdev->dev, "failed to register backlight\n");
return PTR_ERR(bl);
}
bl->props.max_brightness = MAX_BRIGHTNESS;
bl->props.brightness = DEFAULT_BRIGHTNESS;
platform_set_drvdata(pdev, bl);
if(gpio_request(GPIO_BL_CTRL,"BL_CTRL"))
printk(KERN_ERR "Request GPIO failed,""gpio: %d \n", GPIO_BL_CTRL);
#ifdef EXPRESSWIRE_DIMMING
//spin_lock(&bl_ctrl_lock);
spin_lock_irqsave(&bl_ctrl_lock, flags);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(1500);
udelay(1500);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(200);
gpio_set_value(GPIO_BL_CTRL, 0);
udelay(300);
gpio_set_value(GPIO_BL_CTRL, 1);
udelay(400);
//spin_unlock(&bl_ctrl_lock);
spin_unlock_irqrestore(&bl_ctrl_lock, flags);
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
early_suspend_BL.suspend = ktd253_backlight_early_suspend;
early_suspend_BL.resume = ktd253_backlight_late_resume;
early_suspend_BL.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
register_early_suspend(&early_suspend_BL);
#endif
ktd_backlight_update_status(bl);
return 0;
out:
return 1;
}
static int ktd_backlight_remove(struct platform_device *pdev)
{
struct backlight_device *bl = platform_get_drvdata(pdev);
backlight_device_unregister(bl);
gpio_direction_output(GPIO_BL_CTRL, 0);
mdelay(3);
return 0;
}
void ktd_backlight_shutdown(struct platform_device *pdev)
{
printk("[coko] %s\n",__FUNCTION__);
gpio_direction_output(GPIO_BL_CTRL, 0);
mdelay(5);
}
static struct platform_driver ktd_backlight_driver = {
.driver = {
.name = BACKLIGHT_DEV_NAME,
.owner = THIS_MODULE,
},
.probe = ktd_backlight_probe,
.remove = ktd_backlight_remove,
.shutdown = ktd_backlight_shutdown,
};
static int __init ktd_backlight_init(void)
{
return platform_driver_register(&ktd_backlight_driver);
}
module_init(ktd_backlight_init);
static void __exit ktd_backlight_exit(void)
{
platform_driver_unregister(&ktd_backlight_driver);
}
module_exit(ktd_backlight_exit);
MODULE_DESCRIPTION("KTD based Backlight Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ktd-backlight");