devs.c 或者 dev-device_type.c里面是放device的地方,在三星平台上。
想在板子上面写个背光驱动,但是估计自己写的又是IOCTL之类,接口肯定不标准,先看看kernel里面有没有标准的接口。
先在头文件里面看了相关的结构体:
struct backlight_ops {
/* Notify the backlight driver some property has changed */
int (*update_status)(struct backlight_device *);
/* Return the current backlight brightness (accounting for power,
fb_blank etc.) */
int (*get_brightness)(struct backlight_device *);
/* Check if given framebuffer device is the one bound to this backlight;
return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
int (*check_fb)(struct fb_info *);
};
/* This structure defines all the properties of a backlight */
struct backlight_properties {
/* Current User requested brightness (0 - max_brightness) */
int brightness;
/* Maximal value for brightness (read-only) */
int max_brightness;
/* Current FB Power mode (0: full on, 1..3: power saving
modes; 4: full off), see FB_BLANK_XXX */
int power;
/* FB Blanking active? (values as for power) */
int fb_blank;
};
struct backlight_device {
/* Backlight properties */
struct backlight_properties props;
/* Serialise access to update_status method */
struct mutex update_lock;
/* This protects the 'ops' field. If 'ops' is NULL, the driver that
registered this device has been unloaded, and if class_get_devdata()
points to something in the body of that driver, it is also invalid. */
struct mutex ops_lock;
struct backlight_ops *ops;
/* The framebuffer notifier block */
struct notifier_block fb_notif;
struct device dev;
};
pwm有两套写法,
一套是走PWM device support(PWM device support)(in System Type)【宏CONFIG_HAVE_PWM】
在mach-smdk6410.c中
#ifdef CONFIG_HAVE_PWM
&s3c_device_timer[0],
&s3c_device_timer[1],
#endif
#define DEFINE_S3C_TIMER(_tmr_no, _irq) /
.name = "s3c24xx-pwm", /
.id = _tmr_no, /
.num_resources = TIMER_RESOURCE_SIZE, /
.resource = TIMER_RESOURCE(_tmr_no, _irq), /
也就是说打开了s3c24xx-pwm设备。
对应的obj-$(CONFIG_HAVE_PWM) += pwm.o, 在arch/arm/plat-s3c24xx中,pwm.c被编译。
static struct platform_driver s3c_pwm_driver = {
.driver = {
.name = "s3c24xx-pwm",
.owner = THIS_MODULE,
},
.probe = s3c_pwm_probe,
.remove = __devexit_p(s3c_pwm_remove),
};
这个driver被注册。
driver即可和device绑定。
另外一套
一套是走PWM device support(Support old API)(in System Type)【宏CONFIG_S3C6410_PWM】
在s3cfb_fimd4x.c中,
#if defined(CONFIG_S3C6410_PWM)
void s3cfb_set_brightness(int val)
生效,即可在smdk_bl.c(2.6.24版本中有)调用。
先选择走第一套,因为发现smdk_backlight_device已经实现了,可以用现成的,现在只需要改pwm的频率,占空比。我们使用的pwm_id是0。
6410 PWM原理
TCNTB TCMPB
start的时候这两个值load到TCNT和TCMP中,然后开始递减,等TCNT的值与TCMP相同的时候,产生中断。
如果想增大PWM的输出占空比,就减小TCMP。
前提是output inverter没有打开。
其余的像什么DMA, double buffer之类的没有看了。
s3c24xx-pwm s3c24xx-pwm.0: config bits 04
s3c24xx-pwm s3c24xx-pwm.0: tin at 33250000, tdiv at 33250000, tin=divclk, base 0
s3c24xx-pwm s3c24xx-pwm.1: config bits 04
s3c24xx-pwm s3c24xx-pwm.1: tin at 33250000, tdiv at 33250000, tin=divclk, base 8
最初的PWM clock信息
PWM的clock source 是PCLK, 首先经过8-bit prescale,然后可以选择1/2/4/8/16的分频或者外部频率TCLK0/TCLK1,最后再通过TCMPB和TCNTB来决定输出波形。如下图:
结合
S3C64XX: HCLKx2=266000000, HCLK=133000000, PCLK=66500000
和
s3c24xx-pwm s3c24xx-pwm.0: tin at 33250000, tdiv at 33250000, tin=divclk, base 0
可以发现是二分频。
如果再往下分析应该也可以出来,但是因为别人已经有现成的可以用了,所以还是决定走第二套方法。因为lcd的屏参文件中间有backlight中的函数。另外老的一套API简单易懂,图稳妥还是先走老的一套,新的以后再说。
记录一下被我修改的文件,暂时不改回来。
#if defined(CONFIG_HAVE_PWM)
static struct platform_pwm_backlight_data smdk_backlight_data = {
// .pwm_id = 1, //zhangq modify
.pwm_id = 0,
.max_brightness = 255,
.dft_brightness = 255,
.pwm_period_ns = 78770,
};
static struct platform_device smdk_backlight_device = {
.name = "pwm-backlight",
.dev = {
// .parent = &s3c_device_timer[1].dev, //zhangq modify
.parent = &s3c_device_timer[0].dev,
.platform_data = &smdk_backlight_data,
},
};
就是从1改到0.
现在又发现保持lcd与backlight一致意义不大,还不如尝试用pwm,更符合整个kernel架构。
而且以前公司里面的做法也是这样的,在已有的pwm_backlight上制造一个给lcd函数用的开关背光的函数。