1 /* 2 * LED driver for TI lp3952 controller 3 * 4 * Copyright (C) 2016, DAQRI, LLC. 5 * Author: Tony Makkiel <tony.makkiel@daqri.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 */ 12 13 #include <linux/delay.h> 14 #include <linux/gpio.h> 15 #include <linux/i2c.h> 16 #include <linux/io.h> 17 #include <linux/kernel.h> 18 #include <linux/leds.h> 19 #include <linux/leds-lp3952.h> 20 #include <linux/module.h> 21 #include <linux/notifier.h> 22 #include <linux/platform_device.h> 23 #include <linux/pm.h> 24 #include <linux/reboot.h> 25 #include <linux/regmap.h> 26 27 static int lp3952_register_write(struct i2c_client *client, u8 reg, u8 val) 28 { 29 int ret; 30 struct lp3952_led_array *priv = i2c_get_clientdata(client); 31 32 ret = regmap_write(priv->regmap, reg, val); 33 34 if (ret) 35 dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", 36 __func__, reg, val, ret); 37 return ret; 38 } 39 40 static void lp3952_on_off(struct lp3952_led_array *priv, 41 enum lp3952_leds led_id, bool on) 42 { 43 int ret, val; 44 45 dev_dbg(&priv->client->dev, "%s LED %d to %d\n", __func__, led_id, on); 46 47 val = 1 << led_id; 48 if (led_id == LP3952_LED_ALL) 49 val = LP3952_LED_MASK_ALL; 50 51 ret = regmap_update_bits(priv->regmap, LP3952_REG_LED_CTRL, val, 52 on ? val : 0); 53 if (ret) 54 dev_err(&priv->client->dev, "%s, Error %d\n", __func__, ret); 55 } 56 57 /* 58 * Using Imax to control brightness. There are 4 possible 59 * setting 25, 50, 75 and 100 % of Imax. Possible values are 60 * values 0-4. 0 meaning turn off. 61 */ 62 static int lp3952_set_brightness(struct led_classdev *cdev, 63 enum led_brightness value) 64 { 65 unsigned int reg, shift_val; 66 struct lp3952_ctrl_hdl *led = container_of(cdev, 67 struct lp3952_ctrl_hdl, 68 cdev); 69 struct lp3952_led_array *priv = (struct lp3952_led_array *)led->priv; 70 71 dev_dbg(cdev->dev, "Brightness request: %d on %d\n", value, 72 led->channel); 73 74 if (value == LED_OFF) { 75 lp3952_on_off(priv, led->channel, false); 76 return 0; 77 } 78 79 if (led->channel > LP3952_RED_1) { 80 dev_err(cdev->dev, " %s Invalid LED requested", __func__); 81 return -EINVAL; 82 } 83 84 if (led->channel >= LP3952_BLUE_1) { 85 reg = LP3952_REG_RGB1_MAX_I_CTRL; 86 shift_val = (led->channel - LP3952_BLUE_1) * 2; 87 } else { 88 reg = LP3952_REG_RGB2_MAX_I_CTRL; 89 shift_val = led->channel * 2; 90 } 91 92 /* Enable the LED in case it is not enabled already */ 93 lp3952_on_off(priv, led->channel, true); 94 95 return regmap_update_bits(priv->regmap, reg, 3 << shift_val, 96 --value << shift_val); 97 } 98 99 static int lp3952_get_label(struct device *dev, const char *label, char *dest) 100 { 101 int ret; 102 const char *str; 103 104 ret = device_property_read_string(dev, label, &str); 105 if (ret) 106 return ret; 107 108 strncpy(dest, str, LP3952_LABEL_MAX_LEN); 109 return 0; 110 } 111 112 static int lp3952_register_led_classdev(struct lp3952_led_array *priv) 113 { 114 int i, acpi_ret, ret = -ENODEV; 115 static const char *led_name_hdl[LP3952_LED_ALL] = { 116 "blue2", 117 "green2", 118 "red2", 119 "blue1", 120 "green1", 121 "red1" 122 }; 123 124 for (i = 0; i < LP3952_LED_ALL; i++) { 125 acpi_ret = lp3952_get_label(&priv->client->dev, led_name_hdl[i], 126 priv->leds[i].name); 127 if (acpi_ret) 128 continue; 129 130 priv->leds[i].cdev.name = priv->leds[i].name; 131 priv->leds[i].cdev.brightness = LED_OFF; 132 priv->leds[i].cdev.max_brightness = LP3952_BRIGHT_MAX; 133 priv->leds[i].cdev.brightness_set_blocking = 134 lp3952_set_brightness; 135 priv->leds[i].channel = i; 136 priv->leds[i].priv = priv; 137 138 ret = devm_led_classdev_register(&priv->client->dev, 139 &priv->leds[i].cdev); 140 if (ret < 0) { 141 dev_err(&priv->client->dev, 142 "couldn't register LED %s\n", 143 priv->leds[i].cdev.name); 144 break; 145 } 146 } 147 return ret; 148 } 149 150 static int lp3952_set_pattern_gen_cmd(struct lp3952_led_array *priv, 151 u8 cmd_index, u8 r, u8 g, u8 b, 152 enum lp3952_tt tt, enum lp3952_cet cet) 153 { 154 int ret; 155 struct ptrn_gen_cmd line = { 156 { 157 { 158 .r = r, 159 .g = g, 160 .b = b, 161 .cet = cet, 162 .tt = tt 163 } 164 } 165 }; 166 167 if (cmd_index >= LP3952_CMD_REG_COUNT) 168 return -EINVAL; 169 170 ret = lp3952_register_write(priv->client, 171 LP3952_REG_CMD_0 + cmd_index * 2, 172 line.bytes.msb); 173 if (ret) 174 return ret; 175 176 return lp3952_register_write(priv->client, 177 LP3952_REG_CMD_0 + cmd_index * 2 + 1, 178 line.bytes.lsb); 179 } 180 181 static int lp3952_configure(struct lp3952_led_array *priv) 182 { 183 int ret; 184 185 /* Disable any LEDs on from any previous conf. */ 186 ret = lp3952_register_write(priv->client, LP3952_REG_LED_CTRL, 0); 187 if (ret) 188 return ret; 189 190 /* enable rgb patter, loop */ 191 ret = lp3952_register_write(priv->client, LP3952_REG_PAT_GEN_CTRL, 192 LP3952_PATRN_LOOP | LP3952_PATRN_GEN_EN); 193 if (ret) 194 return ret; 195 196 /* Update Bit 6 (Active mode), Select both Led sets, Bit [1:0] */ 197 ret = lp3952_register_write(priv->client, LP3952_REG_ENABLES, 198 LP3952_ACTIVE_MODE | LP3952_INT_B00ST_LDR); 199 if (ret) 200 return ret; 201 202 /* Set Cmd1 for RGB intensity,cmd and transition time */ 203 return lp3952_set_pattern_gen_cmd(priv, 0, I46, I71, I100, TT0, 204 CET197); 205 } 206 207 static const struct regmap_config lp3952_regmap = { 208 .reg_bits = 8, 209 .val_bits = 8, 210 .max_register = REG_MAX, 211 .cache_type = REGCACHE_RBTREE, 212 }; 213 214 static int lp3952_probe(struct i2c_client *client, 215 const struct i2c_device_id *id) 216 { 217 int status; 218 struct lp3952_led_array *priv; 219 220 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); 221 if (!priv) 222 return -ENOMEM; 223 224 priv->client = client; 225 226 priv->enable_gpio = devm_gpiod_get(&client->dev, "nrst", 227 GPIOD_OUT_HIGH); 228 if (IS_ERR(priv->enable_gpio)) { 229 status = PTR_ERR(priv->enable_gpio); 230 dev_err(&client->dev, "Failed to enable gpio: %d\n", status); 231 return status; 232 } 233 234 priv->regmap = devm_regmap_init_i2c(client, &lp3952_regmap); 235 if (IS_ERR(priv->regmap)) { 236 int err = PTR_ERR(priv->regmap); 237 238 dev_err(&client->dev, "Failed to allocate register map: %d\n", 239 err); 240 return err; 241 } 242 243 i2c_set_clientdata(client, priv); 244 245 status = lp3952_configure(priv); 246 if (status) { 247 dev_err(&client->dev, "Probe failed. Device not found (%d)\n", 248 status); 249 return status; 250 } 251 252 status = lp3952_register_led_classdev(priv); 253 if (status) { 254 dev_err(&client->dev, "Unable to register led_classdev: %d\n", 255 status); 256 return status; 257 } 258 259 return 0; 260 } 261 262 static int lp3952_remove(struct i2c_client *client) 263 { 264 struct lp3952_led_array *priv; 265 266 priv = i2c_get_clientdata(client); 267 lp3952_on_off(priv, LP3952_LED_ALL, false); 268 gpiod_set_value(priv->enable_gpio, 0); 269 270 return 0; 271 } 272 273 static const struct i2c_device_id lp3952_id[] = { 274 {LP3952_NAME, 0}, 275 {} 276 }; 277 MODULE_DEVICE_TABLE(i2c, lp3952_id); 278 279 static struct i2c_driver lp3952_i2c_driver = { 280 .driver = { 281 .name = LP3952_NAME, 282 }, 283 .probe = lp3952_probe, 284 .remove = lp3952_remove, 285 .id_table = lp3952_id, 286 }; 287 288 module_i2c_driver(lp3952_i2c_driver); 289 290 MODULE_AUTHOR("Tony Makkiel <tony.makkiel@daqri.com>"); 291 MODULE_DESCRIPTION("lp3952 I2C LED controller driver"); 292 MODULE_LICENSE("GPL v2"); 293