1 // SPDX-License-Identifier: GPL-2.0
2 // TI LM3532 LED driver
3 // Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
4 // http://www.ti.com/lit/ds/symlink/lm3532.pdf
7 #include <linux/leds.h>
8 #include <linux/slab.h>
9 #include <linux/regmap.h>
10 #include <linux/types.h>
11 #include <linux/regulator/consumer.h>
12 #include <linux/module.h>
13 #include <uapi/linux/uleds.h>
14 #include <linux/gpio/consumer.h>
16 #define LM3532_NAME "lm3532-led"
17 #define LM3532_BL_MODE_MANUAL 0x00
18 #define LM3532_BL_MODE_ALS 0x01
20 #define LM3532_REG_OUTPUT_CFG 0x10
21 #define LM3532_REG_STARTSHUT_RAMP 0x11
22 #define LM3532_REG_RT_RAMP 0x12
23 #define LM3532_REG_PWM_A_CFG 0x13
24 #define LM3532_REG_PWM_B_CFG 0x14
25 #define LM3532_REG_PWM_C_CFG 0x15
26 #define LM3532_REG_ZONE_CFG_A 0x16
27 #define LM3532_REG_CTRL_A_FS_CURR 0x17
28 #define LM3532_REG_ZONE_CFG_B 0x18
29 #define LM3532_REG_CTRL_B_FS_CURR 0x19
30 #define LM3532_REG_ZONE_CFG_C 0x1a
31 #define LM3532_REG_CTRL_C_FS_CURR 0x1b
32 #define LM3532_REG_ENABLE 0x1d
33 #define LM3532_ALS_CONFIG 0x23
34 #define LM3532_REG_ZN_0_HI 0x60
35 #define LM3532_REG_ZN_0_LO 0x61
36 #define LM3532_REG_ZN_1_HI 0x62
37 #define LM3532_REG_ZN_1_LO 0x63
38 #define LM3532_REG_ZN_2_HI 0x64
39 #define LM3532_REG_ZN_2_LO 0x65
40 #define LM3532_REG_ZN_3_HI 0x66
41 #define LM3532_REG_ZN_3_LO 0x67
42 #define LM3532_REG_ZONE_TRGT_A 0x70
43 #define LM3532_REG_ZONE_TRGT_B 0x75
44 #define LM3532_REG_ZONE_TRGT_C 0x7a
45 #define LM3532_REG_MAX 0x7e
48 #define LM3532_CTRL_A_ENABLE BIT(0)
49 #define LM3532_CTRL_B_ENABLE BIT(1)
50 #define LM3532_CTRL_C_ENABLE BIT(2)
52 /* PWM Zone Control */
53 #define LM3532_PWM_ZONE_MASK 0x7c
54 #define LM3532_PWM_ZONE_0_EN BIT(2)
55 #define LM3532_PWM_ZONE_1_EN BIT(3)
56 #define LM3532_PWM_ZONE_2_EN BIT(4)
57 #define LM3532_PWM_ZONE_3_EN BIT(5)
58 #define LM3532_PWM_ZONE_4_EN BIT(6)
60 /* Brightness Configuration */
61 #define LM3532_I2C_CTRL BIT(0)
62 #define LM3532_ALS_CTRL 0
63 #define LM3532_LINEAR_MAP BIT(1)
64 #define LM3532_ZONE_MASK (BIT(2) | BIT(3) | BIT(4))
65 #define LM3532_ZONE_0 0
66 #define LM3532_ZONE_1 BIT(2)
67 #define LM3532_ZONE_2 BIT(3)
68 #define LM3532_ZONE_3 (BIT(2) | BIT(3))
69 #define LM3532_ZONE_4 BIT(4)
71 #define LM3532_ENABLE_ALS BIT(3)
72 #define LM3532_ALS_SEL_SHIFT 6
74 /* Zone Boundary Register */
75 #define LM3532_ALS_WINDOW_mV 2000
76 #define LM3532_ALS_ZB_MAX 4
77 #define LM3532_ALS_OFFSET_mV 2
79 #define LM3532_CONTROL_A 0
80 #define LM3532_CONTROL_B 1
81 #define LM3532_CONTROL_C 2
82 #define LM3532_MAX_CONTROL_BANKS 3
83 #define LM3532_MAX_LED_STRINGS 3
85 #define LM3532_OUTPUT_CFG_MASK 0x3
86 #define LM3532_BRT_VAL_ADJUST 8
87 #define LM3532_RAMP_DOWN_SHIFT 3
89 #define LM3532_NUM_RAMP_VALS 8
90 #define LM3532_NUM_AVG_VALS 8
91 #define LM3532_NUM_IMP_VALS 32
93 #define LM3532_FS_CURR_MIN 5000
94 #define LM3532_FS_CURR_MAX 29800
95 #define LM3532_FS_CURR_STEP 800
98 * struct lm3532_als_data
99 * @config - value of ALS configuration register
100 * @als1_imp_sel - value of ALS1 resistor select register
101 * @als2_imp_sel - value of ALS2 resistor select register
102 * @als_avrg_time - ALS averaging time
103 * @als_input_mode - ALS input mode for brightness control
104 * @als_vmin - Minimum ALS voltage
105 * @als_vmax - Maximum ALS voltage
106 * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
107 * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
109 struct lm3532_als_data
{
117 u8 zones_lo
[LM3532_ALS_ZB_MAX
];
118 u8 zones_hi
[LM3532_ALS_ZB_MAX
];
123 * @led_dev: led class device
124 * @priv - Pointer the device data structure
125 * @control_bank - Control bank the LED is associated to
126 * @mode - Mode of the LED string
127 * @ctrl_brt_pointer - Zone target register that controls the sink
128 * @num_leds - Number of LED strings are supported in this array
129 * @full_scale_current - The full-scale current setting for the current sink.
130 * @led_strings - The LED strings supported in this array
131 * @enabled - Enabled status
135 struct led_classdev led_dev
;
136 struct lm3532_data
*priv
;
140 int ctrl_brt_pointer
;
142 int full_scale_current
;
143 unsigned int enabled
:1;
144 u32 led_strings
[LM3532_MAX_CONTROL_BANKS
];
145 char label
[LED_MAX_NAME_SIZE
];
150 * @enable_gpio - Hardware enable gpio
151 * @regulator: regulator
152 * @client: i2c client
153 * @regmap - Devices register map
154 * @dev - Pointer to the devices device struct
155 * @lock - Lock for reading/writing the device
156 * @als_data - Pointer to the als data struct
157 * @runtime_ramp_up - Runtime ramp up setting
158 * @runtime_ramp_down - Runtime ramp down setting
159 * @leds - Array of LED strings
162 struct gpio_desc
*enable_gpio
;
163 struct regulator
*regulator
;
164 struct i2c_client
*client
;
165 struct regmap
*regmap
;
169 struct lm3532_als_data
*als_data
;
172 u32 runtime_ramp_down
;
174 struct lm3532_led leds
[];
177 static const struct reg_default lm3532_reg_defs
[] = {
178 {LM3532_REG_OUTPUT_CFG
, 0xe4},
179 {LM3532_REG_STARTSHUT_RAMP
, 0xc0},
180 {LM3532_REG_RT_RAMP
, 0xc0},
181 {LM3532_REG_PWM_A_CFG
, 0x82},
182 {LM3532_REG_PWM_B_CFG
, 0x82},
183 {LM3532_REG_PWM_C_CFG
, 0x82},
184 {LM3532_REG_ZONE_CFG_A
, 0xf1},
185 {LM3532_REG_CTRL_A_FS_CURR
, 0xf3},
186 {LM3532_REG_ZONE_CFG_B
, 0xf1},
187 {LM3532_REG_CTRL_B_FS_CURR
, 0xf3},
188 {LM3532_REG_ZONE_CFG_C
, 0xf1},
189 {LM3532_REG_CTRL_C_FS_CURR
, 0xf3},
190 {LM3532_REG_ENABLE
, 0xf8},
191 {LM3532_ALS_CONFIG
, 0x44},
192 {LM3532_REG_ZN_0_HI
, 0x35},
193 {LM3532_REG_ZN_0_LO
, 0x33},
194 {LM3532_REG_ZN_1_HI
, 0x6a},
195 {LM3532_REG_ZN_1_LO
, 0x66},
196 {LM3532_REG_ZN_2_HI
, 0xa1},
197 {LM3532_REG_ZN_2_LO
, 0x99},
198 {LM3532_REG_ZN_3_HI
, 0xdc},
199 {LM3532_REG_ZN_3_LO
, 0xcc},
202 static const struct regmap_config lm3532_regmap_config
= {
206 .max_register
= LM3532_REG_MAX
,
207 .reg_defaults
= lm3532_reg_defs
,
208 .num_reg_defaults
= ARRAY_SIZE(lm3532_reg_defs
),
209 .cache_type
= REGCACHE_FLAT
,
212 static const int als_imp_table
[LM3532_NUM_IMP_VALS
] = {37000, 18500, 12330,
213 92500, 7400, 6170, 5290,
214 4630, 4110, 3700, 3360,
215 3080, 2850, 2640, 2440,
216 2310, 2180, 2060, 1950,
217 1850, 1760, 1680, 1610,
218 1540, 1480, 1420, 1370,
219 1320, 1280, 1230, 1190};
220 static int lm3532_get_als_imp_index(int als_imped
)
224 if (als_imped
> als_imp_table
[1])
227 if (als_imped
< als_imp_table
[LM3532_NUM_IMP_VALS
- 1])
228 return LM3532_NUM_IMP_VALS
- 1;
230 for (i
= 1; i
< LM3532_NUM_IMP_VALS
; i
++) {
231 if (als_imped
== als_imp_table
[i
])
234 /* Find an approximate index by looking up the table */
235 if (als_imped
< als_imp_table
[i
- 1] &&
236 als_imped
> als_imp_table
[i
]) {
237 if (als_imped
- als_imp_table
[i
- 1] <
238 als_imp_table
[i
] - als_imped
)
248 static int lm3532_get_index(const int table
[], int size
, int value
)
252 for (i
= 1; i
< size
; i
++) {
253 if (value
== table
[i
])
256 /* Find an approximate index by looking up the table */
257 if (value
> table
[i
- 1] &&
259 if (value
- table
[i
- 1] < table
[i
] - value
)
269 static const int als_avrg_table
[LM3532_NUM_AVG_VALS
] = {17920, 35840, 71680,
270 1433360, 286720, 573440,
272 static int lm3532_get_als_avg_index(int avg_time
)
274 if (avg_time
<= als_avrg_table
[0])
277 if (avg_time
> als_avrg_table
[LM3532_NUM_AVG_VALS
- 1])
278 return LM3532_NUM_AVG_VALS
- 1;
280 return lm3532_get_index(&als_avrg_table
[0], LM3532_NUM_AVG_VALS
,
284 static const int ramp_table
[LM3532_NUM_RAMP_VALS
] = { 8, 1024, 2048, 4096, 8192,
285 16384, 32768, 65536};
286 static int lm3532_get_ramp_index(int ramp_time
)
288 if (ramp_time
<= ramp_table
[0])
291 if (ramp_time
> ramp_table
[LM3532_NUM_RAMP_VALS
- 1])
292 return LM3532_NUM_RAMP_VALS
- 1;
294 return lm3532_get_index(&ramp_table
[0], LM3532_NUM_RAMP_VALS
,
298 /* Caller must take care of locking */
299 static int lm3532_led_enable(struct lm3532_led
*led_data
)
301 int ctrl_en_val
= BIT(led_data
->control_bank
);
304 if (led_data
->enabled
)
307 ret
= regmap_update_bits(led_data
->priv
->regmap
, LM3532_REG_ENABLE
,
308 ctrl_en_val
, ctrl_en_val
);
310 dev_err(led_data
->priv
->dev
, "Failed to set ctrl:%d\n", ret
);
314 ret
= regulator_enable(led_data
->priv
->regulator
);
318 led_data
->enabled
= 1;
323 /* Caller must take care of locking */
324 static int lm3532_led_disable(struct lm3532_led
*led_data
)
326 int ctrl_en_val
= BIT(led_data
->control_bank
);
329 if (!led_data
->enabled
)
332 ret
= regmap_update_bits(led_data
->priv
->regmap
, LM3532_REG_ENABLE
,
335 dev_err(led_data
->priv
->dev
, "Failed to set ctrl:%d\n", ret
);
339 ret
= regulator_disable(led_data
->priv
->regulator
);
343 led_data
->enabled
= 0;
348 static int lm3532_brightness_set(struct led_classdev
*led_cdev
,
349 enum led_brightness brt_val
)
351 struct lm3532_led
*led
=
352 container_of(led_cdev
, struct lm3532_led
, led_dev
);
356 mutex_lock(&led
->priv
->lock
);
358 if (led
->mode
== LM3532_ALS_CTRL
) {
359 if (brt_val
> LED_OFF
)
360 ret
= lm3532_led_enable(led
);
362 ret
= lm3532_led_disable(led
);
367 if (brt_val
== LED_OFF
) {
368 ret
= lm3532_led_disable(led
);
372 ret
= lm3532_led_enable(led
);
376 brightness_reg
= LM3532_REG_ZONE_TRGT_A
+ led
->control_bank
* 5 +
377 (led
->ctrl_brt_pointer
>> 2);
379 ret
= regmap_write(led
->priv
->regmap
, brightness_reg
, brt_val
);
382 mutex_unlock(&led
->priv
->lock
);
386 static int lm3532_init_registers(struct lm3532_led
*led
)
388 struct lm3532_data
*drvdata
= led
->priv
;
389 unsigned int runtime_ramp_val
;
390 unsigned int output_cfg_val
= 0;
391 unsigned int output_cfg_shift
= 0;
392 unsigned int output_cfg_mask
= 0;
393 unsigned int brightness_config_reg
;
394 unsigned int brightness_config_val
;
399 if (drvdata
->enable_gpio
)
400 gpiod_direction_output(drvdata
->enable_gpio
, 1);
402 brightness_config_reg
= LM3532_REG_ZONE_CFG_A
+ led
->control_bank
* 2;
404 * This could be hard coded to the default value but the control
405 * brightness register may have changed during boot.
407 ret
= regmap_read(drvdata
->regmap
, brightness_config_reg
,
408 &led
->ctrl_brt_pointer
);
412 led
->ctrl_brt_pointer
&= LM3532_ZONE_MASK
;
413 brightness_config_val
= led
->ctrl_brt_pointer
| led
->mode
;
414 ret
= regmap_write(drvdata
->regmap
, brightness_config_reg
,
415 brightness_config_val
);
419 if (led
->full_scale_current
) {
420 fs_current_reg
= LM3532_REG_CTRL_A_FS_CURR
+ led
->control_bank
* 2;
421 fs_current_val
= (led
->full_scale_current
- LM3532_FS_CURR_MIN
) /
424 ret
= regmap_write(drvdata
->regmap
, fs_current_reg
,
430 for (i
= 0; i
< led
->num_leds
; i
++) {
431 output_cfg_shift
= led
->led_strings
[i
] * 2;
432 output_cfg_val
|= (led
->control_bank
<< output_cfg_shift
);
433 output_cfg_mask
|= LM3532_OUTPUT_CFG_MASK
<< output_cfg_shift
;
436 ret
= regmap_update_bits(drvdata
->regmap
, LM3532_REG_OUTPUT_CFG
,
437 output_cfg_mask
, output_cfg_val
);
441 runtime_ramp_val
= drvdata
->runtime_ramp_up
|
442 (drvdata
->runtime_ramp_down
<< LM3532_RAMP_DOWN_SHIFT
);
444 return regmap_write(drvdata
->regmap
, LM3532_REG_RT_RAMP
,
448 static int lm3532_als_configure(struct lm3532_data
*priv
,
449 struct lm3532_led
*led
)
451 struct lm3532_als_data
*als
= priv
->als_data
;
452 u32 als_vmin
, als_vmax
, als_vstep
;
453 int zone_reg
= LM3532_REG_ZN_0_HI
;
457 als_vmin
= als
->als_vmin
;
458 als_vmax
= als
->als_vmax
;
460 als_vstep
= (als_vmax
- als_vmin
) / ((LM3532_ALS_ZB_MAX
+ 1) * 2);
462 for (i
= 0; i
< LM3532_ALS_ZB_MAX
; i
++) {
463 als
->zones_lo
[i
] = ((als_vmin
+ als_vstep
+ (i
* als_vstep
)) *
465 als
->zones_hi
[i
] = ((als_vmin
+ LM3532_ALS_OFFSET_mV
+
466 als_vstep
+ (i
* als_vstep
)) * LED_FULL
) / 1000;
468 zone_reg
= LM3532_REG_ZN_0_HI
+ i
* 2;
469 ret
= regmap_write(priv
->regmap
, zone_reg
, als
->zones_lo
[i
]);
474 ret
= regmap_write(priv
->regmap
, zone_reg
, als
->zones_hi
[i
]);
479 als
->config
= (als
->als_avrg_time
| (LM3532_ENABLE_ALS
) |
480 (als
->als_input_mode
<< LM3532_ALS_SEL_SHIFT
));
482 return regmap_write(priv
->regmap
, LM3532_ALS_CONFIG
, als
->config
);
485 static int lm3532_parse_als(struct lm3532_data
*priv
)
487 struct lm3532_als_data
*als
;
492 als
= devm_kzalloc(priv
->dev
, sizeof(*als
), GFP_KERNEL
);
496 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als-vmin",
501 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als-vmax",
504 als
->als_vmax
= LM3532_ALS_WINDOW_mV
;
506 if (als
->als_vmax
> LM3532_ALS_WINDOW_mV
) {
511 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als1-imp-sel",
514 als
->als1_imp_sel
= 0;
516 als
->als1_imp_sel
= lm3532_get_als_imp_index(als_impedance
);
518 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als2-imp-sel",
521 als
->als2_imp_sel
= 0;
523 als
->als2_imp_sel
= lm3532_get_als_imp_index(als_impedance
);
525 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als-avrg-time-us",
528 als
->als_avrg_time
= 0;
530 als
->als_avrg_time
= lm3532_get_als_avg_index(als_avg_time
);
532 ret
= device_property_read_u8(&priv
->client
->dev
, "ti,als-input-mode",
533 &als
->als_input_mode
);
535 als
->als_input_mode
= 0;
537 if (als
->als_input_mode
> LM3532_BL_MODE_ALS
) {
542 priv
->als_data
= als
;
547 static int lm3532_parse_node(struct lm3532_data
*priv
)
549 struct fwnode_handle
*child
= NULL
;
550 struct lm3532_led
*led
;
557 priv
->enable_gpio
= devm_gpiod_get_optional(&priv
->client
->dev
,
558 "enable", GPIOD_OUT_LOW
);
559 if (IS_ERR(priv
->enable_gpio
))
560 priv
->enable_gpio
= NULL
;
562 priv
->regulator
= devm_regulator_get(&priv
->client
->dev
, "vin");
563 if (IS_ERR(priv
->regulator
))
564 priv
->regulator
= NULL
;
566 ret
= device_property_read_u32(&priv
->client
->dev
, "ramp-up-us",
569 dev_info(&priv
->client
->dev
, "ramp-up-ms property missing\n");
571 priv
->runtime_ramp_up
= lm3532_get_ramp_index(ramp_time
);
573 ret
= device_property_read_u32(&priv
->client
->dev
, "ramp-down-us",
576 dev_info(&priv
->client
->dev
, "ramp-down-ms property missing\n");
578 priv
->runtime_ramp_down
= lm3532_get_ramp_index(ramp_time
);
580 device_for_each_child_node(priv
->dev
, child
) {
581 struct led_init_data idata
= {
583 .default_label
= ":",
584 .devicename
= priv
->client
->name
,
587 led
= &priv
->leds
[i
];
589 ret
= fwnode_property_read_u32(child
, "reg", &control_bank
);
591 dev_err(&priv
->client
->dev
, "reg property missing\n");
592 fwnode_handle_put(child
);
596 if (control_bank
> LM3532_CONTROL_C
) {
597 dev_err(&priv
->client
->dev
, "Control bank invalid\n");
601 led
->control_bank
= control_bank
;
603 ret
= fwnode_property_read_u32(child
, "ti,led-mode",
606 dev_err(&priv
->client
->dev
, "ti,led-mode property missing\n");
607 fwnode_handle_put(child
);
611 if (fwnode_property_present(child
, "led-max-microamp") &&
612 fwnode_property_read_u32(child
, "led-max-microamp",
613 &led
->full_scale_current
))
614 dev_err(&priv
->client
->dev
,
615 "Failed getting led-max-microamp\n");
617 led
->full_scale_current
= min(led
->full_scale_current
,
620 if (led
->mode
== LM3532_BL_MODE_ALS
) {
621 led
->mode
= LM3532_ALS_CTRL
;
622 ret
= lm3532_parse_als(priv
);
624 dev_err(&priv
->client
->dev
, "Failed to parse als\n");
626 lm3532_als_configure(priv
, led
);
628 led
->mode
= LM3532_I2C_CTRL
;
631 led
->num_leds
= fwnode_property_count_u32(child
, "led-sources");
632 if (led
->num_leds
> LM3532_MAX_LED_STRINGS
) {
633 dev_err(&priv
->client
->dev
, "Too many LED string defined\n");
637 ret
= fwnode_property_read_u32_array(child
, "led-sources",
641 dev_err(&priv
->client
->dev
, "led-sources property missing\n");
642 fwnode_handle_put(child
);
646 fwnode_property_read_string(child
, "linux,default-trigger",
647 &led
->led_dev
.default_trigger
);
649 ret
= fwnode_property_read_string(child
, "label", &name
);
651 snprintf(led
->label
, sizeof(led
->label
),
652 "%s::", priv
->client
->name
);
654 snprintf(led
->label
, sizeof(led
->label
),
655 "%s:%s", priv
->client
->name
, name
);
658 led
->led_dev
.name
= led
->label
;
659 led
->led_dev
.brightness_set_blocking
= lm3532_brightness_set
;
661 ret
= devm_led_classdev_register_ext(priv
->dev
, &led
->led_dev
, &idata
);
663 dev_err(&priv
->client
->dev
, "led register err: %d\n",
665 fwnode_handle_put(child
);
669 ret
= lm3532_init_registers(led
);
671 dev_err(&priv
->client
->dev
, "register init err: %d\n",
673 fwnode_handle_put(child
);
684 static int lm3532_probe(struct i2c_client
*client
,
685 const struct i2c_device_id
*id
)
687 struct lm3532_data
*drvdata
;
691 count
= device_get_child_node_count(&client
->dev
);
693 dev_err(&client
->dev
, "LEDs are not defined in device tree!");
697 drvdata
= devm_kzalloc(&client
->dev
, struct_size(drvdata
, leds
, count
),
702 drvdata
->client
= client
;
703 drvdata
->dev
= &client
->dev
;
705 drvdata
->regmap
= devm_regmap_init_i2c(client
, &lm3532_regmap_config
);
706 if (IS_ERR(drvdata
->regmap
)) {
707 ret
= PTR_ERR(drvdata
->regmap
);
708 dev_err(&client
->dev
, "Failed to allocate register map: %d\n",
713 mutex_init(&drvdata
->lock
);
714 i2c_set_clientdata(client
, drvdata
);
716 ret
= lm3532_parse_node(drvdata
);
718 dev_err(&client
->dev
, "Failed to parse node\n");
725 static int lm3532_remove(struct i2c_client
*client
)
727 struct lm3532_data
*drvdata
= i2c_get_clientdata(client
);
729 mutex_destroy(&drvdata
->lock
);
731 if (drvdata
->enable_gpio
)
732 gpiod_direction_output(drvdata
->enable_gpio
, 0);
737 static const struct of_device_id of_lm3532_leds_match
[] = {
738 { .compatible
= "ti,lm3532", },
741 MODULE_DEVICE_TABLE(of
, of_lm3532_leds_match
);
743 static const struct i2c_device_id lm3532_id
[] = {
747 MODULE_DEVICE_TABLE(i2c
, lm3532_id
);
749 static struct i2c_driver lm3532_i2c_driver
= {
750 .probe
= lm3532_probe
,
751 .remove
= lm3532_remove
,
752 .id_table
= lm3532_id
,
755 .of_match_table
= of_lm3532_leds_match
,
758 module_i2c_driver(lm3532_i2c_driver
);
760 MODULE_DESCRIPTION("Back Light driver for LM3532");
761 MODULE_LICENSE("GPL v2");
762 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");