static void qpnp_led_set(struct led_classdev *led_cdev, enum led_brightness value) { int rc; struct qpnp_led_data *led; led = container_of(led_cdev, struct qpnp_led_data, cdev); if (value < LED_OFF || value > led->cdev.max_brightness) { dev_err(&led->spmi_dev->dev, "Invalid brightness value\n"); return; } spin_lock(&led->lock); led->cdev.brightness = value; switch (led->id) { case QPNP_ID_WLED: rc = qpnp_wled_set(led); if (rc < 0) dev_err(&led->spmi_dev->dev, "WLED set brightness failed (%d)\n", rc); break; case QPNP_ID_FLASH1_LED0: case QPNP_ID_FLASH1_LED1: rc = qpnp_flash_set(led); if (rc < 0) dev_err(&led->spmi_dev->dev, "FLASH set brightness failed (%d)\n", rc); break; case QPNP_ID_RGB_RED: case QPNP_ID_RGB_GREEN: case QPNP_ID_RGB_BLUE: rc = qpnp_rgb_set(led); if (rc < 0) dev_err(&led->spmi_dev->dev, "RGB set brightness failed (%d)\n", rc); break; default: dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id); break; } spin_unlock(&led->lock); }
static int qpnp_wled_probe(struct spmi_device *spmi) { struct qpnp_wled *wled; struct resource *wled_resource; int rc, i; wled = devm_kzalloc(&spmi->dev, sizeof(*wled), GFP_KERNEL); if (!wled) return -ENOMEM; wled->spmi = spmi; wled_resource = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM, QPNP_WLED_SINK_BASE); if (!wled_resource) { dev_err(&spmi->dev, "Unable to get wled sink base address\n"); return -EINVAL; } wled->sink_base = wled_resource->start; wled_resource = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM, QPNP_WLED_CTRL_BASE); if (!wled_resource) { dev_err(&spmi->dev, "Unable to get wled ctrl base address\n"); return -EINVAL; } wled->ctrl_base = wled_resource->start; wled_resource = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM, QPNP_WLED_IBB_BASE); if (!wled_resource) { dev_err(&spmi->dev, "Unable to get IBB base address\n"); return -EINVAL; } wled->ibb_base = wled_resource->start; wled_resource = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM, QPNP_WLED_LAB_BASE); if (!wled_resource) { dev_err(&spmi->dev, "Unable to get LAB base address\n"); return -EINVAL; } wled->lab_base = wled_resource->start; dev_set_drvdata(&spmi->dev, wled); rc = qpnp_wled_parse_dt(wled); if (rc) { dev_err(&spmi->dev, "DT parsing failed\n"); return rc; } rc = qpnp_wled_config(wled); if (rc) { dev_err(&spmi->dev, "wled config failed\n"); return rc; } if (wled->calc_curr) { rc = qpnp_wled_set_scale(wled); if (rc) { dev_err(&spmi->dev, "wled config failed\n"); return rc; } } mutex_init(&wled->lock); INIT_WORK(&wled->work, qpnp_wled_work); wled->ramp_ms = QPNP_WLED_RAMP_DLY_MS; wled->ramp_step = 1; wled->cdev.brightness_set = qpnp_wled_set; wled->cdev.brightness_get = qpnp_wled_get; wled->cdev.max_brightness = WLED_MAX_LEVEL_4095; rc = led_classdev_register(&spmi->dev, &wled->cdev); if (rc) { dev_err(&spmi->dev, "wled registration failed(%d)\n", rc); goto wled_register_fail; } for (i = 0; i < ARRAY_SIZE(qpnp_wled_attrs); i++) { rc = sysfs_create_file(&wled->cdev.dev->kobj, &qpnp_wled_attrs[i].attr); if (rc < 0) { dev_err(&spmi->dev, "sysfs creation failed\n"); goto sysfs_fail; } } gwled = wled; if (wled->init_br && !bl_on_in_boot) qpnp_wled_set(&wled->cdev, wled->init_br); return 0; sysfs_fail: for (i--; i >= 0; i--) sysfs_remove_file(&wled->cdev.dev->kobj, &qpnp_wled_attrs[i].attr); led_classdev_unregister(&wled->cdev); wled_register_fail: cancel_work_sync(&wled->work); mutex_destroy(&wled->lock); return rc; }