• am335x backlight


    /******************************************************************************
     *                     am335x backlight                                                              
     * 本文主要分析TI的am335x处理器,backlight注册过程。                                                                            
     *                                                                                                 
     *                                       Tony Liu, 2016-4-21, Shenzhen                             
    *******************************************************************************/                
    kernel/arcm/arm/omap2/board-am335xevm.c                                                             
    static int __init backlight_init(void)                                                              
    {                                                                                                   
        int index = 0;                                                                                  
                                                                                                        
    #if defined(CONFIG_OK335XD)                                                                         
        index = 0;                                                                                      
        am335x_backlight.dev.platform_data = &am335x_backlight_data0; ------+                           
    #elif defined(CONFIG_OK335XS)                                           |                           
        index = 2;                                                          |                           
        am335x_backlight.dev.platform_data = &am335x_backlight_data2;       |                           
    #endif                                                                  |                           
                                                                            |                           
        am33xx_register_ecap(index, &pwm_pdata[index]);  -------------------|----+                      
        platform_device_register(&am335x_backlight);                        |    |                      
                                          |                                 |    |                      
        return 0;                         |                                 |    |                      
    }                                     +---------------------------------|-+  |                      
    late_initcall(backlight_init);                                          | |  |                      
                                                                            | |  |                      
                                                                            | |  |                      
    static struct platform_pwm_backlight_data am335x_backlight_data0 = { <--+ |  |                      
        .pwm_id         = "ecap.0",                                           |  |                      
        .ch             = -1,                                                 |  |                      
        .lth_brightness    = 21,                                              |  |                      
        .max_brightness = AM335X_BACKLIGHT_MAX_BRIGHTNESS,                    |  |                      
        .dft_brightness = AM335X_BACKLIGHT_DEFAULT_BRIGHTNESS,                |  |                      
        .pwm_period_ns  = AM335X_PWM_PERIOD_NANO_SECONDS,                     |  |                      
    };                                                                        |  |                      
                                                                              |  |                      
    #define AM335X_BACKLIGHT_MAX_BRIGHTNESS        100                        |  |                      
    #define AM335X_BACKLIGHT_DEFAULT_BRIGHTNESS    60                         |  |                      
                                                                              |  |                      
    #define AM335X_PWM_PERIOD_NANO_SECONDS        (5000 * 10 * 100)           |  |                      
                                                                              |  |                      
    static struct platform_device am335x_backlight = {        <---------------+  |                      
        .name           = "pwm-backlight",                                       |                      
        .id             = -1,                                                    |                      
    };                                                                           |                      
                                                                                 |                      
    #define PWM_STR_LEN 10                                                       |                      
    int __init am33xx_register_ecap(int id, struct pwmss_platform_data *pdata) <-+                      
    {                                                                                                   
        struct platform_device *pdev;                                                                   
        struct omap_hwmod *oh;                                                                          
        char *oh_name = "ecap";                                                                         
        char dev_name[PWM_STR_LEN];                                                                     
                                                                                                        
        sprintf(dev_name, "ecap.%d", id);                                                               
        //查找链表中是否有同名的设备的寄存器信息                                                    
        oh = omap_hwmod_lookup(dev_name);          -------------------+                                 
        if (!oh) {                                                    |                                 
            pr_err("Could not look up %s hwmod
    ", dev_name);         |                                 
            return -ENODEV;                                           |                                 
        }                                                             |                                 
        //注册设备                                                    |                             
        pdev = omap_device_build(oh_name, id, oh, pdata,    ----------|---+                             
                sizeof(*pdata), NULL, 0, 0);                          |   |                             
                                                                      |   |                             
        if (IS_ERR(pdev)) {                                           |   |                             
            WARN(1, "Can't build omap_device for %s:%s.
    ",           |   |                             
                dev_name, oh->name);                                  |   |                             
            return PTR_ERR(pdev);                                     |   |                             
        }                                                             |   |                             
        return 0;                                                     |   |                             
    }                                                                 |   |                             
    //查找设备注册时的链表中是否有设备                                |   |             
    struct omap_hwmod *omap_hwmod_lookup(const char *name)    <-------+   |                             
    {                                                                     |                             
        struct omap_hwmod *oh;                                            |                             
                                                                          |                             
        if (!name)                                                        |                             
            return NULL;                                                  |                             
                                                                          |                             
        oh = _lookup(name);   ----+                                       |                             
                                  |                                       |                             
        return oh;                |                                       |                             
    }                             |                                       |                             
                                  V                                       |                             
    static struct omap_hwmod *_lookup(const char *name)                   |                             
    {                                                                     |              
        struct omap_hwmod *oh, *temp_oh;                                  |                 
                                                                          |                 
        oh = NULL;                                                        |                    
        //查找                                                            |              
        list_for_each_entry(temp_oh, &omap_hwmod_list, node) {            |                  
            if (!strcmp(name, temp_oh->name)) {                           |            
                oh = temp_oh;                                             |          
                break;                                                    |                
            }                                                             |               
        }                       +-----------------------------------------+            
                                |                                                      
        return oh;              |                                                       
    }                           |                                                        
                                V                                                        
    struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,                       
                          struct omap_hwmod *oh, void *pdata,                                           
                          int pdata_len,                                                                
                          struct omap_device_pm_latency *pm_lats,                                       
                          int pm_lats_cnt, int is_early_device)                                         
    {                                                                                                   
        struct omap_hwmod *ohs[] = { oh };                                                              
                                                                                                        
        if (!oh)                                                                                        
            return ERR_PTR(-EINVAL);                                                                    
                                                                                                        
        return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,                                  
                        pdata_len, pm_lats, pm_lats_cnt,                                                
                        is_early_device);                                                               
    }                           |                                                                       
                                V                                                                       
    struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,                    
                         struct omap_hwmod **ohs, int oh_cnt,                                           
                         void *pdata, int pdata_len,                                                    
                         struct omap_device_pm_latency *pm_lats,                                        
                         int pm_lats_cnt, int is_early_device)                                          
    {                                                                                                   
        int ret = -ENOMEM;                                                                              
        struct platform_device *pdev;                                                                   
        struct omap_device *od;                                                                         
                                                                                                        
        if (!ohs || oh_cnt == 0 || !pdev_name)                                                          
            return ERR_PTR(-EINVAL);                                                                    
                                                                                                        
        if (!pdata && pdata_len > 0)                                                                    
            return ERR_PTR(-EINVAL);                                                                    
                                                                                                        
        pdev = platform_device_alloc(pdev_name, pdev_id);                                               
        if (!pdev) {                                                                                    
            ret = -ENOMEM;                                                                              
            goto odbs_exit;                                                                             
        }                                                                                               
                                                                                                        
        /* Set the dev_name early to allow dev_xxx in omap_device_alloc */                              
        if (pdev->id != -1)                                                                             
            dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);                                   
        else                                                                                            
            dev_set_name(&pdev->dev, "%s", pdev->name);                                                 
                                                                                                        
        od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);                                
        if (!od)                                                                                        
            goto odbs_exit1;                                                                            
                                                                                                        
        ret = platform_device_add_data(pdev, pdata, pdata_len);                                         
        if (ret)                                                                                        
            goto odbs_exit2;                                                                            
                                                                                                        
        if (is_early_device)                                                                            
            ret = omap_early_device_register(pdev);                                                     
        else                                                                                            
            ret = omap_device_register(pdev);                                                           
        if (ret)                                                                                        
            goto odbs_exit2;                                                                            
                                                                                                        
        return pdev;                                                                                    
                                                                                                        
    odbs_exit2:                                                                                         
        omap_device_delete(od);                                                                         
    odbs_exit1:                                                                                         
        platform_device_put(pdev);                                                                      
    odbs_exit:                                                                                          
                                                                                                        
        pr_err("omap_device: %s: build failed (%d)
    ", pdev_name, ret);                                 
                                                                                                        
        return ERR_PTR(ret);                                                                            
    }                                                                                                   
                                                                                                        
    //驱动注册                                                                                            
    kernel/driver/video/backlight/pwm_bl.c                                                          
    static int __init pwm_backlight_init(void)                                                          
    {                                                                                                   
        return platform_driver_register(&pwm_backlight_driver);                                         
    }                                      |                                                            
                                           V                                                            
    static struct platform_driver pwm_backlight_driver = {                                              
        .driver        = {                                                                              
            .name    = "pwm-backlight",                                                                 
            .owner    = THIS_MODULE,                                                                    
        },                                                                                              
        .probe        = pwm_backlight_probe,           --------------+                                  
        .remove        = pwm_backlight_remove,                       |                                  
        .suspend    = pwm_backlight_suspend,                         |                                  
        .resume        = pwm_backlight_resume,                       |                                  
    };                                                               |                                  
                                                                     |                                  
    static int pwm_backlight_probe(struct platform_device *pdev) <---+                                  
    {                                                                                                   
        struct backlight_properties props;                                                              
        struct platform_pwm_backlight_data *data = pdev->dev.platform_data;                             
        struct backlight_device *bl;                                                                    
        struct pwm_bl_data *pb;                                                                         
        int ret;                                                                                        
                                                                                                        
        if (!data) {                                                                                    
            dev_err(&pdev->dev, "failed to find platform data
    ");                                      
            return -EINVAL;                                                                             
        }                                                                                               
                                                                                                        
        if (data->init) {                                                                               
            ret = data->init(&pdev->dev);                                                               
            if (ret < 0)                                                                                
                return ret;                                                                             
        }                                                                                               
                                                                                                        
        pb = kzalloc(sizeof(*pb), GFP_KERNEL);                                                          
        if (!pb) {                                                                                      
            dev_err(&pdev->dev, "no memory for state
    ");                                               
            ret = -ENOMEM;                                                                              
            goto err_alloc;                                                                             
        }                                                                                               
                                                                                                        
        pb->period = data->pwm_period_ns;                                                               
        pb->notify = data->notify;                                                                      
        pb->notify_after = data->notify_after;                                                          
        pb->check_fb = data->check_fb;                                                                  
        pb->lth_brightness = data->lth_brightness *                                                     
            (data->pwm_period_ns / data->max_brightness);                                               
        pb->dev = &pdev->dev;                                                                           
                                                                                                        
        pb->pwm = pwm_request(data->pwm_id, data->ch, "backlight");                                     
        if (IS_ERR(pb->pwm)) {                                                                          
            dev_err(&pdev->dev, "unable to request PWM for backlight
    ");                               
            ret = PTR_ERR(pb->pwm);                                                                     
            goto err_pwm;                                                                               
        } else                                                                                          
            dev_dbg(&pdev->dev, "got pwm for backlight
    ");                                             
                                                                                                        
        memset(&props, 0, sizeof(struct backlight_properties));                                         
        props.type = BACKLIGHT_RAW;                                                                     
        props.max_brightness = data->max_brightness;                                                    
        bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,   ---+                     
                           &pwm_backlight_ops, &props);                           |                     
                                    ----------------------------------------------|--+                  
        if (IS_ERR(bl)) {                                                         |  |                  
            dev_err(&pdev->dev, "failed to register backlight
    ");                |  |                  
            ret = PTR_ERR(bl);                                                    |  |                  
            goto err_bl;                                                          |  |                  
        }                                                                         |  |                  
                                                                                  |  |                  
        bl->props.brightness = data->dft_brightness;                              |  |                  
        backlight_update_status(bl);                                              |  | 
                                                                                  |  | 
        platform_set_drvdata(pdev, bl);                                           |  |                  
        return 0;                                                                 |  |                  
                                                                                  |  |                  
    err_bl:                                                                       |  |                  
        pwm_release(pb->pwm);                                                     |  |                  
    err_pwm:                                                                      |  |                  
        kfree(pb);                                                                |  |                  
    err_alloc:                                                                    |  |                  
        if (data->exit)                                                           |  |                  
            data->exit(&pdev->dev);                                               |  |                  
        return ret;                                                               |  |                  
    }                                                                             |  |                  
                                                                                  |  |                  
    struct backlight_device *backlight_device_register(const char *name,    <-----+  |                  
        struct device *parent, void *devdata, const struct backlight_ops *ops,       |                  
        const struct backlight_properties *props)                                    |                  
    {                                                                                |                  
        struct backlight_device *new_bd;                                             |                  
        int rc;                                                                      |                  
                                                                                     |                  
        pr_debug("backlight_device_register: name=%s
    ", name);                      |                  
                                                                                     |                  
        new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL);               |                  
        if (!new_bd)                                                                 |                  
            return ERR_PTR(-ENOMEM);                                                 |                  
                                                                                     |                  
        mutex_init(&new_bd->update_lock);                                            |                  
        mutex_init(&new_bd->ops_lock);                                               |                  
                                                                                     |                  
        new_bd->dev.class = backlight_class;                                         |                  
        new_bd->dev.parent = parent;                                                 |                  
        new_bd->dev.release = bl_device_release;                                     |                  
        dev_set_name(&new_bd->dev, name);                                            |                  
        dev_set_drvdata(&new_bd->dev, devdata);                                      |                  
                                                                                     |                  
        /* Set default properties */                                                 |                  
        if (props) {                                                                 |                  
            memcpy(&new_bd->props, props,                                            |                  
                   sizeof(struct backlight_properties));                             |                  
            if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) {             |                  
                WARN(1, "%s: invalid backlight type", name);                         |                  
                new_bd->props.type = BACKLIGHT_RAW;                                  |                  
            }                                                                        |                  
        } else {                                                                     |                  
            new_bd->props.type = BACKLIGHT_RAW;                                      |                  
        }                                                                            |                  
                                                                                     |                  
        rc = device_register(&new_bd->dev);                                          |                  
        if (rc) {                                                                    |                  
            kfree(new_bd);                                                           |                  
            return ERR_PTR(rc);                                                      |                  
        }                                                                            |                  
                                                                                     |                  
        rc = backlight_register_fb(new_bd);                                          |                  
        if (rc) {                                                                    |                  
            device_unregister(&new_bd->dev);                                         |                  
            return ERR_PTR(rc);                                                      |                  
        }                                                                            |                  
                                                                                     |                  
        new_bd->ops = ops;                                                           |                  
                                                                                     |                  
    #ifdef CONFIG_PMAC_BACKLIGHT                                                     |                  
        mutex_lock(&pmac_backlight_mutex);                                           |                  
        if (!pmac_backlight)                                                         |                  
            pmac_backlight = new_bd;                                                 |                  
        mutex_unlock(&pmac_backlight_mutex);                                         |                  
    #endif                                                                           |                  
                                                                                     |                  
        return new_bd;                                                               |                  
    }                                                                                |                  
                                                                                     |                  
    static const struct backlight_ops pwm_backlight_ops = {          <---------------+                  
        .update_status    = pwm_backlight_update_status,            -----------+                        
        .get_brightness    = pwm_backlight_get_brightness,                     |                        
        .check_fb    = pwm_backlight_check_fb,                                 |                        
    };                                                                         |                        
    //每次设置pwm都会调用下面的函数                                            |                        
    static int pwm_backlight_update_status(struct backlight_device *bl)  <-----+                        
    {                                                                                                   
        struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);                                             
        int brightness = bl->props.brightness;                                                          
        int max = bl->props.max_brightness;                                                             
                                                                                                        
        if (bl->props.power != FB_BLANK_UNBLANK)                                                        
            brightness = 0;                                                                             
                                                                                                        
        if (bl->props.fb_blank != FB_BLANK_UNBLANK)                                                     
            brightness = 0;                                                                             
                                                                                                        
        if (pb->notify)                                                                                 
            brightness = pb->notify(pb->dev, brightness);                                               
                                                                                                        
        if (brightness == 0) {                                                                          
            pwm_set_duty_ns(pb->pwm, 0);                                                                
            pwm_stop(pb->pwm);                                                                          
        } else {                                                                                        
            brightness = pb->lth_brightness +                                                           
                (brightness * (pb->period - pb->lth_brightness) / max);                                 
            pwm_set_period_ns(pb->pwm, pb->period);                                                     
            pwm_set_duty_ns(pb->pwm, brightness);                                                       
            pwm_start(pb->pwm);                                                                         
        }                                                                                               
                                                                                                        
        if (pb->notify_after)                                                                           
            pb->notify_after(pb->dev, brightness);                                                      
                                                                                                        
        return 0;                                                                                       
    }                                                                                                   
  • 相关阅读:
    小说下载器【追书接口】
    C#调用大漠插件,发送QQ和微信消息
    C# 终本案件、综合执行人、裁判文书爬虫
    追书神器API
    一个CookieContainer的拓展类
    利用BlockingCollection实现生产者和消费者队列,实现写文本
    EF SQLite的Like语句,生成为CHARINDEX的解决办法
    ClientKey实现登录QQ空间,并设置背景音乐
    DataTable转换为Model实体对象
    开通博客第一天!
  • 原文地址:https://www.cnblogs.com/helloworldtoyou/p/5417375.html
Copyright © 2020-2023  润新知