brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 3f49a51 Raw
183 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2010, 2011, 2016 The Linux Foundation. All rights reserved.3 */4#include <linux/leds.h>5#include <linux/module.h>6#include <linux/of.h>7#include <linux/platform_device.h>8#include <linux/pm.h>9#include <linux/regmap.h>10 11#define PM8058_LED_TYPE_COMMON	0x0012#define PM8058_LED_TYPE_KEYPAD	0x0113#define PM8058_LED_TYPE_FLASH	0x0214 15#define PM8058_LED_TYPE_COMMON_MASK	0xf816#define PM8058_LED_TYPE_KEYPAD_MASK	0xf017#define PM8058_LED_TYPE_COMMON_SHIFT	318#define PM8058_LED_TYPE_KEYPAD_SHIFT	419 20struct pm8058_led {21	struct regmap *map;22	u32 reg;23	u32 ledtype;24	struct led_classdev cdev;25};26 27static void pm8058_led_set(struct led_classdev *cled,28	enum led_brightness value)29{30	struct pm8058_led *led;31	int ret = 0;32	unsigned int mask = 0;33	unsigned int val = 0;34 35	led = container_of(cled, struct pm8058_led, cdev);36	switch (led->ledtype) {37	case PM8058_LED_TYPE_COMMON:38		mask = PM8058_LED_TYPE_COMMON_MASK;39		val = value << PM8058_LED_TYPE_COMMON_SHIFT;40		break;41	case PM8058_LED_TYPE_KEYPAD:42	case PM8058_LED_TYPE_FLASH:43		mask = PM8058_LED_TYPE_KEYPAD_MASK;44		val = value << PM8058_LED_TYPE_KEYPAD_SHIFT;45		break;46	default:47		break;48	}49 50	ret = regmap_update_bits(led->map, led->reg, mask, val);51	if (ret)52		pr_err("Failed to set LED brightness\n");53}54 55static enum led_brightness pm8058_led_get(struct led_classdev *cled)56{57	struct pm8058_led *led;58	int ret;59	unsigned int val;60 61	led = container_of(cled, struct pm8058_led, cdev);62 63	ret = regmap_read(led->map, led->reg, &val);64	if (ret) {65		pr_err("Failed to get LED brightness\n");66		return LED_OFF;67	}68 69	switch (led->ledtype) {70	case PM8058_LED_TYPE_COMMON:71		val &= PM8058_LED_TYPE_COMMON_MASK;72		val >>= PM8058_LED_TYPE_COMMON_SHIFT;73		break;74	case PM8058_LED_TYPE_KEYPAD:75	case PM8058_LED_TYPE_FLASH:76		val &= PM8058_LED_TYPE_KEYPAD_MASK;77		val >>= PM8058_LED_TYPE_KEYPAD_SHIFT;78		break;79	default:80		val = LED_OFF;81		break;82	}83 84	return val;85}86 87static int pm8058_led_probe(struct platform_device *pdev)88{89	struct led_init_data init_data = {};90	struct device *dev = &pdev->dev;91	struct pm8058_led *led;92	struct device_node *np;93	int ret;94	struct regmap *map;95	enum led_brightness maxbright;96	enum led_default_state state;97 98	led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);99	if (!led)100		return -ENOMEM;101 102	led->ledtype = (u32)(unsigned long)of_device_get_match_data(dev);103 104	map = dev_get_regmap(dev->parent, NULL);105	if (!map) {106		dev_err(dev, "Parent regmap unavailable.\n");107		return -ENXIO;108	}109	led->map = map;110 111	np = dev_of_node(dev);112 113	ret = of_property_read_u32(np, "reg", &led->reg);114	if (ret) {115		dev_err(dev, "no register offset specified\n");116		return -EINVAL;117	}118 119	led->cdev.brightness_set = pm8058_led_set;120	led->cdev.brightness_get = pm8058_led_get;121	if (led->ledtype == PM8058_LED_TYPE_COMMON)122		maxbright = 31; /* 5 bits */123	else124		maxbright = 15; /* 4 bits */125	led->cdev.max_brightness = maxbright;126 127	init_data.fwnode = of_fwnode_handle(np);128 129	state = led_init_default_state_get(init_data.fwnode);130	switch (state) {131	case LEDS_DEFSTATE_ON:132		led->cdev.brightness = maxbright;133		pm8058_led_set(&led->cdev, maxbright);134		break;135	case LEDS_DEFSTATE_KEEP:136		led->cdev.brightness = pm8058_led_get(&led->cdev);137		break;138	default:139		led->cdev.brightness = LED_OFF;140		pm8058_led_set(&led->cdev, LED_OFF);141	}142 143	if (led->ledtype == PM8058_LED_TYPE_KEYPAD ||144	    led->ledtype == PM8058_LED_TYPE_FLASH)145		led->cdev.flags	= LED_CORE_SUSPENDRESUME;146 147	ret = devm_led_classdev_register_ext(dev, &led->cdev, &init_data);148	if (ret)149		dev_err(dev, "Failed to register LED for %pOF\n", np);150 151	return ret;152}153 154static const struct of_device_id pm8058_leds_id_table[] = {155	{156		.compatible = "qcom,pm8058-led",157		.data = (void *)PM8058_LED_TYPE_COMMON158	},159	{160		.compatible = "qcom,pm8058-keypad-led",161		.data = (void *)PM8058_LED_TYPE_KEYPAD162	},163	{164		.compatible = "qcom,pm8058-flash-led",165		.data = (void *)PM8058_LED_TYPE_FLASH166	},167	{ },168};169MODULE_DEVICE_TABLE(of, pm8058_leds_id_table);170 171static struct platform_driver pm8058_led_driver = {172	.probe		= pm8058_led_probe,173	.driver		= {174		.name	= "pm8058-leds",175		.of_match_table = pm8058_leds_id_table,176	},177};178module_platform_driver(pm8058_led_driver);179 180MODULE_DESCRIPTION("PM8058 LEDs driver");181MODULE_LICENSE("GPL v2");182MODULE_ALIAS("platform:pm8058-leds");183