/****************主屏背光节点***************/
backlight {
compatible = “pwm-backlight”;
pwms = <&pwm0 0 5000000>;
brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255>;
default-brightness-level = <200>;
enable-gpios = <&gpio7 GPIO_A2 GPIO_ACTIVE_HIGH>;
};
/****************副屏背光节点***************/
backlight2 {
compatible = “pwm2-backlight”;
pwms = <&pwm2 0 5000000>;
enable-gpios = <&gpio0 GPIO_B5 GPIO_ACTIVE_HIGH>;
pwmnumber = <2>; /代码中用于区分主副屏背光节点。副屏背光等级与主屏屏一致。
};
代码详解:
static struct of_device_id pwm_backlight_of_match[] = {
{ .compatible = “pwm-backlight” },
{ .compatible = “pwm2-backlight” },
{ }
};//增加设备名。与是副屏背光节点可以与其进行匹配。
设备与驱动匹配成功后进入pwm_backlight_probe()函数。
of_property_read_u32(pdev->dev.of_node,”pwmnumber”,&pwmnum);
if(!pwmnum)
storenode = pdev->dev.of_node;
增加以上代码用于判断节点为哪一个背光节点。0为主屏背光节点。非零为副屏背光节点。并保存主屏背光节点的 pdev->dev.of_node的值。这里的storenode要声明为全局变量。struct device_node *storenode;
pwm_backlight_parse_dt 读取dts中的brightness-levels, default-brightness-level以及enable-gpios。这里在进入函数时增加如下代码
if(pwmnum)
node = storenode;
判断当前匹配的节点是主屏还是副屏。判断为副屏时需将在前面保存的主屏的节点读取出来。将主屏的各项值赋值给副屏。data->enable_gpio = of_get_named_gpio_flags(dev->of_node, “enable-gpios”, 0, &flags);因主副屏的背光io口不同。需将代码给为上行所示。
pb->pwm = devm_pwm_get(&pdev->dev, NULL); //获得pwm
if(!pwmnum)
dev_set_name(&pdev->dev, “rk28_bl”);
else
dev_set_name(&pdev->dev, “rk28_bl2”);
rk28_bl这个名字不可以改。会在/sys/calss/backlight/rk28_bl创建节点。用于上层控制屏幕背光。调试时可以adb cat 或者echo 读取背光值或者写入背光值。
backlight_device_register -> //注册标准背光设备
if(!pwmnum)
backlight_update_status(bl); //用默认值更新.
**(bd->ops->update_status ->
pwm_backlight_update_status ->
compute_duty_cycle //计算占空比,下面会分析.
pwm_config //配置pwm
pwm_backlight_power_on //enable背光)**
else
pb_share = pb;
platform_set_drvdata(pdev, bl);
probe函数最后增加如上代码。判断是否为主屏。主屏时直接使用默认值更新。而副屏是先不更新。这样副屏的背光会在主屏背光亮了之后两秒左右才亮。因为系统起来后android会改变背光等级default-brightness-level进行更新。这样可以避免副屏在刚亮时可能会出现屏闪、雪花屏的现象。
如何做到同时改变主副屏的背光的呢?android只做到了向主屏rk28_bl节点写入背光值。这是有两个方法可以解决。1、更改android。让其也向rk28_bl2节点写值。(我用的是另外一个方法,这个方法读者可以自行尝试一下)2、用一个struct pwm_bl_data *pb_share;结构体。从名字可以看出。这是用来分享pb的。在probe结束时进行赋值。在下面函数中会用到。
static int pwm_backlight_update_status(struct backlight_device *bl)
{
struct pwm_bl_data *pb = bl_get_data(bl);
int brightness = bl->props.brightness;
int duty_cycle;
if (bl->props.power != FB_BLANK_UNBLANK ||
bl->props.fb_blank != FB_BLANK_UNBLANK ||
bl->props.state & BL_CORE_FBBLANK)
brightness = 0;
if (pb->notify)
brightness = pb->notify(pb->dev, brightness);
if (brightness > 0) {
if (brightness < 21) {
brightness = 20;
}
duty_cycle = compute_duty_cycle(pb, brightness);
if (pb_share != NULL) {
pwm_config(pb_share->pwm, duty_cycle, pb_share->period);
pwm_backlight_power_on(pb_share, brightness);
}
pwm_config(pb->pwm, duty_cycle, pb->period);
pwm_backlight_power_on(pb, brightness);
} else
pwm_backlight_power_off(pb);
if (pb->notify_after)
pb->notify_after(pb->dev, brightness);
return 0;
}
在主屏更改背光时必会执行此函数。所以我们在其中增加判断。if (pb_share != NULL) {
pwm_config(pb_share->pwm, duty_cycle, pb_share->period);
pwm_backlight_power_on(pb_share, brightness);
}
这样的话我们就可以实现在主屏更改背光时副屏的背光也跟着改动了。
其中的数据共享需要仔细弄清楚。这样才能改好pwm_bl。
(第一篇博客,写的不好请多指教)