xref: /OK3568_Linux_fs/kernel/drivers/leds/leds-ti-lmu-common.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright 2015 Texas Instruments
3*4882a593Smuzhiyun // Copyright 2018 Sebastian Reichel
4*4882a593Smuzhiyun // Copyright 2018 Pavel Machek <pavel@ucw.cz>
5*4882a593Smuzhiyun // TI LMU LED common framework, based on previous work from
6*4882a593Smuzhiyun // Milo Kim <milo.kim@ti.com>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/bitops.h>
9*4882a593Smuzhiyun #include <linux/err.h>
10*4882a593Smuzhiyun #include <linux/of_device.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/leds-ti-lmu-common.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun static const unsigned int ramp_table[16] = {2048, 262000, 524000, 1049000,
15*4882a593Smuzhiyun 				2090000, 4194000, 8389000, 16780000, 33550000,
16*4882a593Smuzhiyun 				41940000, 50330000, 58720000, 67110000,
17*4882a593Smuzhiyun 				83880000, 100660000, 117440000};
18*4882a593Smuzhiyun 
ti_lmu_common_update_brightness(struct ti_lmu_bank * lmu_bank,int brightness)19*4882a593Smuzhiyun static int ti_lmu_common_update_brightness(struct ti_lmu_bank *lmu_bank,
20*4882a593Smuzhiyun 					   int brightness)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	struct regmap *regmap = lmu_bank->regmap;
23*4882a593Smuzhiyun 	u8 reg, val;
24*4882a593Smuzhiyun 	int ret;
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun 	/*
27*4882a593Smuzhiyun 	 * Brightness register update
28*4882a593Smuzhiyun 	 *
29*4882a593Smuzhiyun 	 * 11 bit dimming: update LSB bits and write MSB byte.
30*4882a593Smuzhiyun 	 *		   MSB brightness should be shifted.
31*4882a593Smuzhiyun 	 *  8 bit dimming: write MSB byte.
32*4882a593Smuzhiyun 	 */
33*4882a593Smuzhiyun 	if (lmu_bank->max_brightness == MAX_BRIGHTNESS_11BIT) {
34*4882a593Smuzhiyun 		reg = lmu_bank->lsb_brightness_reg;
35*4882a593Smuzhiyun 		ret = regmap_update_bits(regmap, reg,
36*4882a593Smuzhiyun 					 LMU_11BIT_LSB_MASK,
37*4882a593Smuzhiyun 					 brightness);
38*4882a593Smuzhiyun 		if (ret)
39*4882a593Smuzhiyun 			return ret;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 		val = brightness >> LMU_11BIT_MSB_SHIFT;
42*4882a593Smuzhiyun 	} else {
43*4882a593Smuzhiyun 		val = brightness;
44*4882a593Smuzhiyun 	}
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	reg = lmu_bank->msb_brightness_reg;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	return regmap_write(regmap, reg, val);
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
ti_lmu_common_set_brightness(struct ti_lmu_bank * lmu_bank,int brightness)51*4882a593Smuzhiyun int ti_lmu_common_set_brightness(struct ti_lmu_bank *lmu_bank, int brightness)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	return ti_lmu_common_update_brightness(lmu_bank, brightness);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun EXPORT_SYMBOL(ti_lmu_common_set_brightness);
56*4882a593Smuzhiyun 
ti_lmu_common_convert_ramp_to_index(unsigned int usec)57*4882a593Smuzhiyun static unsigned int ti_lmu_common_convert_ramp_to_index(unsigned int usec)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	int size = ARRAY_SIZE(ramp_table);
60*4882a593Smuzhiyun 	int i;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	if (usec <= ramp_table[0])
63*4882a593Smuzhiyun 		return 0;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	if (usec > ramp_table[size - 1])
66*4882a593Smuzhiyun 		return size - 1;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	for (i = 1; i < size; i++) {
69*4882a593Smuzhiyun 		if (usec == ramp_table[i])
70*4882a593Smuzhiyun 			return i;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 		/* Find an approximate index by looking up the table */
73*4882a593Smuzhiyun 		if (usec > ramp_table[i - 1] && usec < ramp_table[i]) {
74*4882a593Smuzhiyun 			if (usec - ramp_table[i - 1] < ramp_table[i] - usec)
75*4882a593Smuzhiyun 				return i - 1;
76*4882a593Smuzhiyun 			else
77*4882a593Smuzhiyun 				return i;
78*4882a593Smuzhiyun 		}
79*4882a593Smuzhiyun 	}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	return 0;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
ti_lmu_common_set_ramp(struct ti_lmu_bank * lmu_bank)84*4882a593Smuzhiyun int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	struct regmap *regmap = lmu_bank->regmap;
87*4882a593Smuzhiyun 	u8 ramp, ramp_up, ramp_down;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	if (lmu_bank->ramp_up_usec == 0 && lmu_bank->ramp_down_usec == 0) {
90*4882a593Smuzhiyun 		ramp_up = 0;
91*4882a593Smuzhiyun 		ramp_down = 0;
92*4882a593Smuzhiyun 	} else {
93*4882a593Smuzhiyun 		ramp_up = ti_lmu_common_convert_ramp_to_index(lmu_bank->ramp_up_usec);
94*4882a593Smuzhiyun 		ramp_down = ti_lmu_common_convert_ramp_to_index(lmu_bank->ramp_down_usec);
95*4882a593Smuzhiyun 	}
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	ramp = (ramp_up << 4) | ramp_down;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	return regmap_write(regmap, lmu_bank->runtime_ramp_reg, ramp);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun EXPORT_SYMBOL(ti_lmu_common_set_ramp);
103*4882a593Smuzhiyun 
ti_lmu_common_get_ramp_params(struct device * dev,struct fwnode_handle * child,struct ti_lmu_bank * lmu_data)104*4882a593Smuzhiyun int ti_lmu_common_get_ramp_params(struct device *dev,
105*4882a593Smuzhiyun 				  struct fwnode_handle *child,
106*4882a593Smuzhiyun 				  struct ti_lmu_bank *lmu_data)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	int ret;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	ret = fwnode_property_read_u32(child, "ramp-up-us",
111*4882a593Smuzhiyun 				 &lmu_data->ramp_up_usec);
112*4882a593Smuzhiyun 	if (ret)
113*4882a593Smuzhiyun 		dev_warn(dev, "ramp-up-us property missing\n");
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	ret = fwnode_property_read_u32(child, "ramp-down-us",
117*4882a593Smuzhiyun 				 &lmu_data->ramp_down_usec);
118*4882a593Smuzhiyun 	if (ret)
119*4882a593Smuzhiyun 		dev_warn(dev, "ramp-down-us property missing\n");
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	return 0;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun EXPORT_SYMBOL(ti_lmu_common_get_ramp_params);
124*4882a593Smuzhiyun 
ti_lmu_common_get_brt_res(struct device * dev,struct fwnode_handle * child,struct ti_lmu_bank * lmu_data)125*4882a593Smuzhiyun int ti_lmu_common_get_brt_res(struct device *dev, struct fwnode_handle *child,
126*4882a593Smuzhiyun 				  struct ti_lmu_bank *lmu_data)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	int ret;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	ret = device_property_read_u32(dev, "ti,brightness-resolution",
131*4882a593Smuzhiyun 				       &lmu_data->max_brightness);
132*4882a593Smuzhiyun 	if (ret)
133*4882a593Smuzhiyun 		ret = fwnode_property_read_u32(child,
134*4882a593Smuzhiyun 					       "ti,brightness-resolution",
135*4882a593Smuzhiyun 					       &lmu_data->max_brightness);
136*4882a593Smuzhiyun 	if (lmu_data->max_brightness <= 0) {
137*4882a593Smuzhiyun 		lmu_data->max_brightness = MAX_BRIGHTNESS_8BIT;
138*4882a593Smuzhiyun 		return ret;
139*4882a593Smuzhiyun 	}
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	if (lmu_data->max_brightness > MAX_BRIGHTNESS_11BIT)
142*4882a593Smuzhiyun 			lmu_data->max_brightness = MAX_BRIGHTNESS_11BIT;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	return 0;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun EXPORT_SYMBOL(ti_lmu_common_get_brt_res);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun MODULE_DESCRIPTION("TI LMU common LED framework");
150*4882a593Smuzhiyun MODULE_AUTHOR("Sebastian Reichel");
151*4882a593Smuzhiyun MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
152*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
153*4882a593Smuzhiyun MODULE_ALIAS("ti-lmu-led-common");
154