/*******************************************************************************                     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\n", 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.\n",           |   |                             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)\n", 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\n");                                      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\n");                                               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\n");                               ret = PTR_ERR(pb->pwm);                                                                     goto err_pwm;                                                                               } else                                                                                          dev_dbg(&pdev->dev, "got pwm for backlight\n");                                             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\n");                |  |                  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\n", 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;
}                                                                                                   

am335x backlight相关推荐

  1. linux中替换的方法,linux vi 中s 替换方法

    vi/vim 中可以使用 :s 命令来替换字符 :s/vivian/sky/ 替换当前行第一个 vivian 为 sky :s/vivian/sky/g 替换当前行所有 vivian 为 sky :n ...

  2. AM335x kernel4.4.12 LCD 时钟翻转设置记录

    TI AM335x kernel 4.4.12 LCD display 时钟翻转记录 因为公司硬件上已经确定LCD 转LVDS 转换芯片上确认以上升沿时钟为基准,所以只能在软件上调整相关东西. 入口在 ...

  3. AM335x(TQ335x)学习笔记——Nandamp;amp;网卡驱动移植

    移植完成声卡驱动之后本想再接再励,移植网卡驱动,但没想到的是TI维护的内核太健壮,移植网卡驱动跟之前移植按键驱动一样简单,Nand驱动也是如此,于是,本人将Nand和网卡放在同一篇文章中介绍.介绍之前 ...

  4. am335x的网卡相关资料

    其他网站看到的am335x的网卡移植参考程序,不知道能不能用 http://www.deyisupport.com/question_answer/dsp_arm/sitara_arm/f/25/t/ ...

  5. AM335x—WM8960声卡驱动移植

    经过一段时间的调试,终于调好了TQ335x的声卡驱动.TQ335x采用的Codec是WM8960,本文来总结下WM8960驱动在AM335x平台上的移植方法.Linux声卡驱动架构有OSS和ALSA两 ...

  6. AM335X PWMSS 驱动指导

    脉宽调制子系统(Pluse-Width Modulation SubSystem--PWMSS)由增强高分辨率脉宽调制器(eHRPWM),强采集(eCAP),强正交编码脉冲(eQEP)三个模块构成. ...

  7. AM335x LCD驱动解析

    文章目录 1. LCD背景 2. LCD驱动 2.1 Device 2.2 Driver 2.2.1 fbmem_init() 2.2.2 register_framebuffer() 2.2.3 / ...

  8. AM335X——USB摄像头

    CSDN仅用于增加百度收录权重,排版未优化,日常不维护.请访问:www.hceng.cn 查看.评论. 本博文对应地址: https://hceng.cn/2019/06/23/AM335X--USB ...

  9. FreeBSD设备驱动管理介绍(BSP: Ti AM335x)

    这段时间一直在忙FreeBSD驱动移植的项目,因此对FreeBSD做了一定的了解,鉴于网上对于FreeBSD的设备驱动资料较少,在这里给出本人对于FreeBSD驱动管理的理解心得(主要是USB驱动管理 ...

最新文章

  1. Objective-C单例实现
  2. devi into python 笔记(一)字典 列表的简单操作
  3. could not create connection to database server.] with root cause
  4. Linux shell脚本中的命令正确写法
  5. 如何使用SSL pinning来使你的iOS APP更加安全
  6. Java读取Propertity文件
  7. Python中__init__和__new__的区别详解
  8. Ubuntu快速设置指南
  9. Java的深拷贝 vs 浅拷贝
  10. 小飞机安卓android手机设置教程,全民飞机大战叉叉助手安卓版设置步骤教程详解...
  11. Linux学习笔记——网络组成
  12. 20个PCB快捷键操作,提升绘图效率
  13. 迅雷不及掩耳 山寨版iPhone 5令人瞠目
  14. 批量创建文件夹并命名的方法
  15. 计算机处理器怎么看 64,怎么查看电脑处理器是32还是64位
  16. 2021年茶艺师(初级)试题及解析及茶艺师(初级)作业模拟考试
  17. 人类历史的进程vs互联网的进程
  18. PRISM 下载安装
  19. java数字音频最强教程之音频的王者之路(音频发烧友篇)
  20. 业务入云是一条不归路

热门文章

  1. poj 3260 The Fewest Coins(多重背包+完全背包)
  2. Windows 记事本的 Bug :-)
  3. 【python】面向对象类的继承
  4. Servlet 编写过滤器
  5. 03-13 微信小程序自动化测试
  6. 程序员笔试网上查答案,HR吐槽,网友:你们公司断网开发吗?
  7. 5条能让web前端至少手拿20万年薪的特性!
  8. arm Linux 低成本方案,参赛作品《低成本基于ARM+Linux平台搭建web服务器的物联网学习板》...
  9. 二元函数最大最小值定理证明_代数基本定理,用复数证明所有多项式函数都有根...
  10. ecshop插件_ECSHOP和SHOPEX快递单号查询中通快递插件V8.6专版