Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae9d89bd authored by Shyam Kumar Thella's avatar Shyam Kumar Thella Committed by Gerrit - the friendly Code Review server
Browse files

leds: qti-flash: Add support for qti_flash_led_prepare()



qti_flash_led_prepare() API is used by flash clients (E.g. Camera) to
query maximum current available for flash. Add support for this API
which initially returns maximum current that is supported for flash
LED module (2000 mA). Also, add a sysfs parameter under switch devices
to show max available flash current.

Change-Id: I3aed009a0d7e0f34a6d05a45af34fcd0f37a6fe7
Signed-off-by: default avatarShyam Kumar Thella <sthella@codeaurora.org>
parent f9f02772
Loading
Loading
Loading
Loading
+87 −3
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/led-class-flash.h>
#include <linux/leds-qti-flash.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
@@ -65,6 +66,7 @@
#define IRES_12P5_UA		12500
#define IRES_5P0_UA		5000
#define IRES_DEFAULT_UA		IRES_12P5_UA
#define MAX_FLASH_CURRENT_MA		1000

enum flash_led_type {
	FLASH_LED_TYPE_UNKNOWN,
@@ -133,6 +135,7 @@ struct qti_flash_led {
	int			all_ramp_up_done_irq;
	int			all_ramp_down_done_irq;
	int			led_fault_irq;
	int			max_current;
	u16			base;
	u8		max_channels;
	u8		ref_count;
@@ -567,6 +570,65 @@ static void qti_flash_led_switch_brightness_set(
		snode->enabled = state;
}

static struct led_classdev *trigger_to_lcdev(struct led_trigger *trig)
{
	struct led_classdev *led_cdev;

	read_lock(&trig->leddev_list_lock);
	list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
		if (!strcmp(led_cdev->default_trigger, trig->name)) {
			read_unlock(&trig->leddev_list_lock);
			return led_cdev;
		}
	}

	read_unlock(&trig->leddev_list_lock);
	return NULL;
}

static ssize_t qti_flash_led_max_current_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct flash_switch_data *snode;
	struct led_classdev *led_cdev = dev_get_drvdata(dev);

	snode = container_of(led_cdev, struct flash_switch_data, cdev);

	return scnprintf(buf, PAGE_SIZE, "%d\n", snode->led->max_current);
}

int qti_flash_led_prepare(struct led_trigger *trig, int options,
				int *max_current)
{
	struct led_classdev *led_cdev;
	struct flash_switch_data *snode;

	if (!trig) {
		pr_err("Invalid led_trigger\n");
		return -EINVAL;
	}

	led_cdev = trigger_to_lcdev(trig);
	if (!led_cdev) {
		pr_err("Invalid led_cdev in trigger %s\n", trig->name);
		return -ENODEV;
	}

	snode = container_of(led_cdev, struct flash_switch_data, cdev);

	if (options & QUERY_MAX_AVAIL_CURRENT) {
		*max_current = snode->led->max_current;
		return 0;
	}

	return -EINVAL;
}
EXPORT_SYMBOL(qti_flash_led_prepare);

static struct device_attribute qti_flash_led_attrs[] = {
	__ATTR(max_current, 0664, qti_flash_led_max_current_show, NULL),
};

static int qti_flash_brightness_set_blocking(
		struct led_classdev *led_cdev, enum led_brightness value)
{
@@ -685,6 +747,8 @@ static int qti_flash_led_setup(struct qti_flash_led *led)
			return rc;
	}

	led->max_current = MAX_FLASH_CURRENT_MA;

	return rc;
}

@@ -768,7 +832,7 @@ static int qti_flash_led_register_interrupts(struct qti_flash_led *led)
static int register_switch_device(struct qti_flash_led *led,
		struct flash_switch_data *snode, struct device_node *node)
{
	int rc;
	int rc, i;

	rc = of_property_read_string(node, "qcom,led-name",
				&snode->cdev.name);
@@ -808,7 +872,22 @@ static int register_switch_device(struct qti_flash_led *led,
		return rc;
	}

	for (i = 0; i < ARRAY_SIZE(qti_flash_led_attrs); i++) {
		rc = sysfs_create_file(&snode->cdev.dev->kobj,
				&qti_flash_led_attrs[i].attr);
		if (rc < 0) {
			pr_err("Failed to create sysfs attrs, rc=%d\n", rc);
			goto sysfs_fail;
		}
	}

	return 0;

sysfs_fail:
	while (i >= 0)
		sysfs_remove_file(&snode->cdev.dev->kobj,
			&qti_flash_led_attrs[i--].attr);
	return rc;
}

static int register_flash_device(struct qti_flash_led *led,
@@ -1150,10 +1229,15 @@ static int qti_flash_led_probe(struct platform_device *pdev)
static int qti_flash_led_remove(struct platform_device *pdev)
{
	struct qti_flash_led *led = dev_get_drvdata(&pdev->dev);
	int i;
	int i, j;

	for (i = 0; (i < led->num_snodes); i++) {
		for (j = 0; j < ARRAY_SIZE(qti_flash_led_attrs); j++)
			sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
				&qti_flash_led_attrs[j].attr);

	for (i = 0; (i < led->num_snodes); i++)
		led_classdev_unregister(&led->snode[i].cdev);
	}

	for (i = 0; (i < led->num_fnodes); i++)
		led_classdev_flash_unregister(&led->fnode[i].fdev);
+23 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 */

#ifndef __LEDS_QTI_FLASH_H
#define __LEDS_QTI_FLASH_H

#include <linux/leds.h>

#define QUERY_MAX_AVAIL_CURRENT		BIT(0)

#if IS_ENABLED(CONFIG_LEDS_QTI_FLASH)
int qti_flash_led_prepare(struct led_trigger *trig,
			int options, int *max_current);
#else
static inline int qti_flash_led_prepare(struct led_trigger *trig,
					int options, int *max_current)
{
	return -EINVAL;
}
#endif
#endif