[RK3288][Android6.0] PWM backlight 驱动流程小结

Platform: RK3288
OS: Android 6.0
Kernel: 3.10.92


背光的亮暗通过pwm控制,驱动在文件pwm-rockchip.c中,这里不做描述.

dts各个配置参数意义:

backlight {
    /*设备名,会和驱动匹配.*/
    compatible = "pwm-backlight";
    /*使用哪个pwm channal, period*/
    pwms = <&pwm0 0 25000>;
    /*背光可调等级,比如这里是255级,实际反应到占空比就是当前值和数组中最大值的比值,
    例如当前是200,那么最终duty cycle就是200/255.*/

    brightness-levels = <255 254 253 252 251 250 249 248 247 246 245 244 243 242 241 240
         239 238 237 236 235 234 233 232 231 230 229 228 227 226 225 224 223 222 221 220
         219 218 217 216 215 214 213 212 211 210 209 208 207 206 205 204 203 202 201 200
         199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180
         179 178 177 176 175 174 173 172 171 170 169 168 167 166 165 164 163 162 161 160
         159 158 157 156 155 154 153 152 151 150 149 148 147 146 145 144 143 142 141 140
         139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120
         119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100
         99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70
         69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
         39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10
         9 8 7 6 5 4 3 2 1 0>;
    /*开机初始化默认等级,Android起来之后会改变它.*/
    default-brightness-level = <200>;
    /*backlight使能控制pin.*/
    enable-gpios = <&gpio7 GPIO_A2 GPIO_ACTIVE_HIGH>;
};

驱动流程:

pwm_backlight_probe ->     pwm_bl.c
    pwm_backlight_parse_dt    //读取上面dts中的brightness-levels, default-brightness-level以及enable-gpios,而pwms后面标准接口会解析.
    gpio_request_one    //申请背光使能gpio
    devm_pwm_get ->     core.c//获得一个pwm
        pwm_get ->
            of_pwm_get ->
                of_parse_phandle_with_args    解析上面dts中的pwms属性.
                of_node_to_pwmchip
                pwm = pc->of_xlate    //最终生成struct pwm_device类型.     
    pwm_request    //申请pwm,防止其他驱动也会使用.
    pwm_get_period    //获取period.
    dev_set_name(&pdev->dev, "rk28_bl");    //name不能改,用户空间会被用到:/sys/class/backlight/rk28_bl
    backlight_device_register    -> //注册标准背光设备
        device_register
        backlight_register_fb ->
            fb_register_client    //callback是fb_notifier_callback.
    backlight_update_status ->        //用默认值更新.
        bd->ops->update_status ->
            pwm_backlight_update_status ->
                compute_duty_cycle    //计算占空比,下面会分析.
                pwm_config    //配置pwm 
                pwm_backlight_power_on    //enable背光


compute_duty_cycle:

static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
{
    /*一般情况下这个值都为0*/
    unsigned int lth = pb->lth_brightness;
    int duty_cycle;
    /*pb->levels这个表格就是从dts节点brightness-levels中获取的,
    假设进来的参数brightness是254,那么得到的duty_cycle就是1,
    如果没有这个表格,那么就直接是进来的亮度值.*/

    if (pb->levels)
        duty_cycle = pb->levels[brightness];
    else
        duty_cycle = brightness;
    /*假设这里lth是0,那么公式就是duty_cycle * pb->period / pb->scale
     pb->scale为pb->levels数组中的最大值. pb->period也就是dts节点pwms
     的第三个参数周期值为25000, 所以这个公式就是按照将android的纯数值转换
     成事件周期值对应的占空比.*/

    return (duty_cycle * (pb->period - lth) / pb->scale) + lth;
}

小结:

其实不管用哪种方式都是调用backlight_update_status来改变背光,syfs也是,看下backlight.c
backlight_class_init ->    backlight.c
    class_create    //创建class,名字是backlight.
    backlight_class->dev_attrs = bl_device_attributes;
[cpp]  view plain  copy
  1. static struct device_attribute bl_device_attributes[] = {  
  2.     __ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),  
  3.     __ATTR(brightness, 0644, backlight_show_brightness,  
  4.              backlight_store_brightness),  
  5.     __ATTR(actual_brightness, 0444, backlight_show_actual_brightness,  
  6.              NULL),  
  7.     __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),  
  8.     __ATTR(type, 0444, backlight_show_type, NULL),  
  9.     __ATTR_NULL,  
  10. };  
其中backlight_store_brightness() 最终调用backlight_update_status().
还有一种情况是亮屏/灭屏时调用,记得前面有注册一个fb notify callback.
[cpp]  view plain  copy
  1. static int fb_notifier_callback(struct notifier_block *self,  
  2.                 unsigned long event, void *data)  
  3. {  
  4. ...  
  5.     /*只处理亮屏和灭屏事件.*/  
  6.     /* If we aren't interested in this event, skip it immediately ... */  
  7.     if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)  
  8.         return 0;  
  9. ...  
  10.     if (bd->ops)  
  11.         if (!bd->ops->check_fb ||  
  12.             bd->ops->check_fb(bd, evdata->info)) {  
  13.             bd->props.fb_blank = *(int *)evdata->data;  
  14.             //亮屏情况  
  15.             if (bd->props.fb_blank == FB_BLANK_UNBLANK)  
  16.                 bd->props.state &= ~BL_CORE_FBBLANK;  
  17.             //灭屏时  
  18.             else  
  19.                 bd->props.state |= BL_CORE_FBBLANK;  
  20.             backlight_update_status(bd);  
  21.         }  
  22. ...  
  23. }  
可以看到最后也是调用backlight_update_status().
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个可以用于SD卡启动的rk3288-evb-android-act8846-ed.dts示例,仅供参考: ``` /dts-v1/; /include/ "rk3288.dtsi" / { model = "Rockchip RK3288 EVB with act8846 and edp"; chosen { bootargs = "earlyprintk console=ttyS2,115200n8 root=/dev/mmcblk1p2 rw rootwait"; }; memory@60000000 { reg = <0x60000000 0x40000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; kernel@0 { reg = <0x60000000 0x02000000>; }; reserved@20000000 { reg = <0x20000000 0x20000000>; }; }; aliases { mmc0 = &sdmmc; }; sdmmc: sdmmc@fe310000 { compatible = "rockchip,rk3288-dw-mshc"; reg = <0xfe310000 0x1000>; interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cru PCLK_SDMMC0>, <&cru SCLK_SDMMC0>; clock-names = "pclk", "hclk"; dmas = <&pdma 12>, <&pdma 12>; dma-names = "rx", "tx"; pinctrl-0 = <&sdmmc_pins>; pinctrl-names = "default"; status = "okay"; }; sdmmc_pins: sdmmc@0 { rockchip,pins = < RK_GPIO1 1 RK_FUNC_2 RK_GPIO1 2 RK_FUNC_2 RK_GPIO1 3 RK_FUNC_2 RK_GPIO1 4 RK_FUNC_2 RK_GPIO1 5 RK_FUNC_2 RK_GPIO1 6 RK_FUNC_2 RK_GPIO1 7 RK_FUNC_2 RK_GPIO1 8 RK_FUNC_2 >; }; act8846: act8846@5b { compatible = "active-semi,act8846"; reg = <0x5b>; gpio-controller; #gpio-cells = <2>; interrupt-parent = <&gpio1>; interrupts = <14 IRQ_TYPE_EDGE_RISING>; pinctrl-names = "default"; pinctrl-0 = <&act8846_pins>; status = "okay"; }; act8846_pins: act8846@0 { rockchip,pins = < RK_GPIO4 3 RK_FUNC_GPIO RK_GPIO4 4 RK_FUNC_GPIO RK_GPIO4 5 RK_FUNC_GPIO >; }; edp: edp@1c19000 { compatible = "rockchip,rk3288-edp"; reg = <0x01c19000 0x1000>; interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cru SCLK_EDP>; clock-names = "edp"; status = "okay"; }; backlight: backlight { compatible = "pwm-backlight"; pwms = <&pwm2 0 5000>; brightness-levels = <0 14 28 42 56 70 84 100>; default-brightness-level = <7>; status = "okay"; }; }; ``` 这个示例中,sdmmc节点表示SD卡,act8846节点表示PMIC,edp节点表示eDP显示器接口,backlight节点表示背光控制。其中,bootargs设置了SD卡启动的相关参数。注意,这个示例是根据某个特定的rk3288 EVB开发板进行配置的,如果你的硬件不同,需要进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值