Example #1
0
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;
}