am335x backlight注册过程

来源:互联网 发布:券商的网络金融部 编辑:程序博客网 时间:2024/06/05 21:53
/****************************************************************************** *                     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;                                                                                       }                                                                                               
原创粉丝点击