1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2015, Sony Mobile Communications, AB. 3 */ 4 5 #include <linux/delay.h> 6 #include <linux/interrupt.h> 7 #include <linux/ktime.h> 8 #include <linux/kernel.h> 9 #include <linux/backlight.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_address.h> 13 #include <linux/platform_device.h> 14 #include <linux/regmap.h> 15 16 /* From DT binding */ 17 #define WLED_MAX_STRINGS 4 18 #define MOD_A 0 19 #define MOD_B 1 20 21 #define WLED_DEFAULT_BRIGHTNESS 2048 22 #define WLED_SOFT_START_DLY_US 10000 23 #define WLED3_SINK_REG_BRIGHT_MAX 0xFFF 24 #define WLED5_SINK_REG_BRIGHT_MAX_12B 0xFFF 25 #define WLED5_SINK_REG_BRIGHT_MAX_15B 0x7FFF 26 27 /* WLED3/WLED4 control registers */ 28 #define WLED3_CTRL_REG_FAULT_STATUS 0x08 29 #define WLED3_CTRL_REG_ILIM_FAULT_BIT BIT(0) 30 #define WLED3_CTRL_REG_OVP_FAULT_BIT BIT(1) 31 #define WLED4_CTRL_REG_SC_FAULT_BIT BIT(2) 32 #define WLED5_CTRL_REG_OVP_PRE_ALARM_BIT BIT(4) 33 34 #define WLED3_CTRL_REG_INT_RT_STS 0x10 35 #define WLED3_CTRL_REG_OVP_FAULT_STATUS BIT(1) 36 37 #define WLED3_CTRL_REG_MOD_EN 0x46 38 #define WLED3_CTRL_REG_MOD_EN_MASK BIT(7) 39 #define WLED3_CTRL_REG_MOD_EN_SHIFT 7 40 41 #define WLED3_CTRL_REG_FEEDBACK_CONTROL 0x48 42 43 #define WLED3_CTRL_REG_FREQ 0x4c 44 #define WLED3_CTRL_REG_FREQ_MASK GENMASK(3, 0) 45 46 #define WLED3_CTRL_REG_OVP 0x4d 47 #define WLED3_CTRL_REG_OVP_MASK GENMASK(1, 0) 48 #define WLED5_CTRL_REG_OVP_MASK GENMASK(3, 0) 49 50 #define WLED3_CTRL_REG_ILIMIT 0x4e 51 #define WLED3_CTRL_REG_ILIMIT_MASK GENMASK(2, 0) 52 53 /* WLED3/WLED4 sink registers */ 54 #define WLED3_SINK_REG_SYNC 0x47 55 #define WLED3_SINK_REG_SYNC_CLEAR 0x00 56 57 #define WLED3_SINK_REG_CURR_SINK 0x4f 58 #define WLED3_SINK_REG_CURR_SINK_MASK GENMASK(7, 5) 59 #define WLED3_SINK_REG_CURR_SINK_SHFT 5 60 61 /* WLED3 specific per-'string' registers below */ 62 #define WLED3_SINK_REG_BRIGHT(n) (0x40 + (n * 0x2)) 63 64 #define WLED3_SINK_REG_STR_MOD_EN(n) (0x60 + (n * 0x10)) 65 #define WLED3_SINK_REG_STR_MOD_MASK BIT(7) 66 67 #define WLED3_SINK_REG_STR_FULL_SCALE_CURR(n) (0x62 + (n * 0x10)) 68 #define WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK GENMASK(4, 0) 69 70 #define WLED3_SINK_REG_STR_MOD_SRC(n) (0x63 + (n * 0x10)) 71 #define WLED3_SINK_REG_STR_MOD_SRC_MASK BIT(0) 72 #define WLED3_SINK_REG_STR_MOD_SRC_INT 0x00 73 #define WLED3_SINK_REG_STR_MOD_SRC_EXT 0x01 74 75 #define WLED3_SINK_REG_STR_CABC(n) (0x66 + (n * 0x10)) 76 #define WLED3_SINK_REG_STR_CABC_MASK BIT(7) 77 78 /* WLED4 specific control registers */ 79 #define WLED4_CTRL_REG_SHORT_PROTECT 0x5e 80 #define WLED4_CTRL_REG_SHORT_EN_MASK BIT(7) 81 82 #define WLED4_CTRL_REG_SEC_ACCESS 0xd0 83 #define WLED4_CTRL_REG_SEC_UNLOCK 0xa5 84 85 #define WLED4_CTRL_REG_TEST1 0xe2 86 #define WLED4_CTRL_REG_TEST1_EXT_FET_DTEST2 0x09 87 88 /* WLED4 specific sink registers */ 89 #define WLED4_SINK_REG_CURR_SINK 0x46 90 #define WLED4_SINK_REG_CURR_SINK_MASK GENMASK(7, 4) 91 #define WLED4_SINK_REG_CURR_SINK_SHFT 4 92 93 /* WLED4 specific per-'string' registers below */ 94 #define WLED4_SINK_REG_STR_MOD_EN(n) (0x50 + (n * 0x10)) 95 #define WLED4_SINK_REG_STR_MOD_MASK BIT(7) 96 97 #define WLED4_SINK_REG_STR_FULL_SCALE_CURR(n) (0x52 + (n * 0x10)) 98 #define WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK GENMASK(3, 0) 99 100 #define WLED4_SINK_REG_STR_MOD_SRC(n) (0x53 + (n * 0x10)) 101 #define WLED4_SINK_REG_STR_MOD_SRC_MASK BIT(0) 102 #define WLED4_SINK_REG_STR_MOD_SRC_INT 0x00 103 #define WLED4_SINK_REG_STR_MOD_SRC_EXT 0x01 104 105 #define WLED4_SINK_REG_STR_CABC(n) (0x56 + (n * 0x10)) 106 #define WLED4_SINK_REG_STR_CABC_MASK BIT(7) 107 108 #define WLED4_SINK_REG_BRIGHT(n) (0x57 + (n * 0x10)) 109 110 /* WLED5 specific control registers */ 111 #define WLED5_CTRL_REG_OVP_INT_CTL 0x5f 112 #define WLED5_CTRL_REG_OVP_INT_TIMER_MASK GENMASK(2, 0) 113 114 /* WLED5 specific sink registers */ 115 #define WLED5_SINK_REG_MOD_A_EN 0x50 116 #define WLED5_SINK_REG_MOD_B_EN 0x60 117 #define WLED5_SINK_REG_MOD_EN_MASK BIT(7) 118 119 #define WLED5_SINK_REG_MOD_A_SRC_SEL 0x51 120 #define WLED5_SINK_REG_MOD_B_SRC_SEL 0x61 121 #define WLED5_SINK_REG_MOD_SRC_SEL_HIGH 0 122 #define WLED5_SINK_REG_MOD_SRC_SEL_EXT 0x03 123 #define WLED5_SINK_REG_MOD_SRC_SEL_MASK GENMASK(1, 0) 124 125 #define WLED5_SINK_REG_MOD_A_BRIGHTNESS_WIDTH_SEL 0x52 126 #define WLED5_SINK_REG_MOD_B_BRIGHTNESS_WIDTH_SEL 0x62 127 #define WLED5_SINK_REG_BRIGHTNESS_WIDTH_12B 0 128 #define WLED5_SINK_REG_BRIGHTNESS_WIDTH_15B 1 129 130 #define WLED5_SINK_REG_MOD_A_BRIGHTNESS_LSB 0x53 131 #define WLED5_SINK_REG_MOD_A_BRIGHTNESS_MSB 0x54 132 #define WLED5_SINK_REG_MOD_B_BRIGHTNESS_LSB 0x63 133 #define WLED5_SINK_REG_MOD_B_BRIGHTNESS_MSB 0x64 134 135 #define WLED5_SINK_REG_MOD_SYNC_BIT 0x65 136 #define WLED5_SINK_REG_SYNC_MOD_A_BIT BIT(0) 137 #define WLED5_SINK_REG_SYNC_MOD_B_BIT BIT(1) 138 #define WLED5_SINK_REG_SYNC_MASK GENMASK(1, 0) 139 140 /* WLED5 specific per-'string' registers below */ 141 #define WLED5_SINK_REG_STR_FULL_SCALE_CURR(n) (0x72 + (n * 0x10)) 142 143 #define WLED5_SINK_REG_STR_SRC_SEL(n) (0x73 + (n * 0x10)) 144 #define WLED5_SINK_REG_SRC_SEL_MOD_A 0 145 #define WLED5_SINK_REG_SRC_SEL_MOD_B 1 146 #define WLED5_SINK_REG_SRC_SEL_MASK GENMASK(1, 0) 147 148 struct wled_var_cfg { 149 const u32 *values; 150 u32 (*fn)(u32); 151 int size; 152 }; 153 154 struct wled_u32_opts { 155 const char *name; 156 u32 *val_ptr; 157 const struct wled_var_cfg *cfg; 158 }; 159 160 struct wled_bool_opts { 161 const char *name; 162 bool *val_ptr; 163 }; 164 165 struct wled_config { 166 u32 boost_i_limit; 167 u32 ovp; 168 u32 switch_freq; 169 u32 num_strings; 170 u32 string_i_limit; 171 u32 enabled_strings[WLED_MAX_STRINGS]; 172 u32 mod_sel; 173 u32 cabc_sel; 174 bool cs_out_en; 175 bool ext_gen; 176 bool cabc; 177 bool external_pfet; 178 bool auto_detection_enabled; 179 }; 180 181 struct wled { 182 const char *name; 183 struct device *dev; 184 struct regmap *regmap; 185 struct mutex lock; /* Lock to avoid race from thread irq handler */ 186 ktime_t last_short_event; 187 ktime_t start_ovp_fault_time; 188 u16 ctrl_addr; 189 u16 sink_addr; 190 u16 max_string_count; 191 u16 auto_detection_ovp_count; 192 u32 brightness; 193 u32 max_brightness; 194 u32 short_count; 195 u32 auto_detect_count; 196 u32 version; 197 bool disabled_by_short; 198 bool has_short_detect; 199 bool cabc_disabled; 200 int short_irq; 201 int ovp_irq; 202 203 struct wled_config cfg; 204 struct delayed_work ovp_work; 205 206 /* Configures the brightness. Applicable for wled3, wled4 and wled5 */ 207 int (*wled_set_brightness)(struct wled *wled, u16 brightness); 208 209 /* Configures the cabc register. Applicable for wled4 and wled5 */ 210 int (*wled_cabc_config)(struct wled *wled, bool enable); 211 212 /* 213 * Toggles the sync bit for the brightness update to take place. 214 * Applicable for WLED3, WLED4 and WLED5. 215 */ 216 int (*wled_sync_toggle)(struct wled *wled); 217 218 /* 219 * Time to wait before checking the OVP status after wled module enable. 220 * Applicable for WLED4 and WLED5. 221 */ 222 int (*wled_ovp_delay)(struct wled *wled); 223 224 /* 225 * Determines if the auto string detection is required. 226 * Applicable for WLED4 and WLED5 227 */ 228 bool (*wled_auto_detection_required)(struct wled *wled); 229 }; 230 231 static int wled3_set_brightness(struct wled *wled, u16 brightness) 232 { 233 int rc, i; 234 __le16 v; 235 236 v = cpu_to_le16(brightness & WLED3_SINK_REG_BRIGHT_MAX); 237 238 for (i = 0; i < wled->cfg.num_strings; ++i) { 239 rc = regmap_bulk_write(wled->regmap, wled->ctrl_addr + 240 WLED3_SINK_REG_BRIGHT(wled->cfg.enabled_strings[i]), 241 &v, sizeof(v)); 242 if (rc < 0) 243 return rc; 244 } 245 246 return 0; 247 } 248 249 static int wled4_set_brightness(struct wled *wled, u16 brightness) 250 { 251 int rc, i; 252 u16 low_limit = wled->max_brightness * 4 / 1000; 253 __le16 v; 254 255 /* WLED4's lower limit of operation is 0.4% */ 256 if (brightness > 0 && brightness < low_limit) 257 brightness = low_limit; 258 259 v = cpu_to_le16(brightness & WLED3_SINK_REG_BRIGHT_MAX); 260 261 for (i = 0; i < wled->cfg.num_strings; ++i) { 262 rc = regmap_bulk_write(wled->regmap, wled->sink_addr + 263 WLED4_SINK_REG_BRIGHT(wled->cfg.enabled_strings[i]), 264 &v, sizeof(v)); 265 if (rc < 0) 266 return rc; 267 } 268 269 return 0; 270 } 271 272 static int wled5_set_brightness(struct wled *wled, u16 brightness) 273 { 274 int rc, offset; 275 u16 low_limit = wled->max_brightness * 1 / 1000; 276 __le16 v; 277 278 /* WLED5's lower limit is 0.1% */ 279 if (brightness < low_limit) 280 brightness = low_limit; 281 282 v = cpu_to_le16(brightness & WLED5_SINK_REG_BRIGHT_MAX_15B); 283 284 offset = (wled->cfg.mod_sel == MOD_A) ? 285 WLED5_SINK_REG_MOD_A_BRIGHTNESS_LSB : 286 WLED5_SINK_REG_MOD_B_BRIGHTNESS_LSB; 287 288 rc = regmap_bulk_write(wled->regmap, wled->sink_addr + offset, 289 &v, sizeof(v)); 290 return rc; 291 } 292 293 static int wled_read_brightness(struct wled *wled) 294 { 295 u16 addr, mask; 296 __le16 v; 297 u32 val; 298 int rc; 299 300 rc = regmap_read(wled->regmap, wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, 301 &val); 302 if (rc < 0) 303 return rc; 304 305 if (!(val & WLED3_CTRL_REG_MOD_EN_MASK)) 306 return 0; 307 308 switch (wled->version) { 309 case 3: 310 addr = wled->sink_addr + 311 WLED3_SINK_REG_BRIGHT(wled->cfg.enabled_strings[0]); 312 mask = WLED3_SINK_REG_BRIGHT_MAX; 313 break; 314 case 4: 315 addr = wled->sink_addr + 316 WLED4_SINK_REG_BRIGHT(wled->cfg.enabled_strings[0]); 317 mask = WLED3_SINK_REG_BRIGHT_MAX; 318 break; 319 case 5: 320 addr = wled->sink_addr + (wled->cfg.mod_sel == MOD_A ? 321 WLED5_SINK_REG_MOD_A_BRIGHTNESS_LSB : 322 WLED5_SINK_REG_MOD_B_BRIGHTNESS_LSB); 323 mask = WLED5_SINK_REG_BRIGHT_MAX_15B; 324 break; 325 default: 326 dev_err(wled->dev, "Invalid WLED version\n"); 327 return -EINVAL; 328 } 329 330 rc = regmap_bulk_read(wled->regmap, addr, &v, sizeof(v)); 331 if (rc < 0) 332 return rc; 333 334 return min_t(u32, le16_to_cpu(v) & mask, wled->max_brightness); 335 } 336 337 static void wled_ovp_work(struct work_struct *work) 338 { 339 struct wled *wled = container_of(work, 340 struct wled, ovp_work.work); 341 enable_irq(wled->ovp_irq); 342 } 343 344 static int wled_module_enable(struct wled *wled, int val) 345 { 346 int rc; 347 348 if (wled->disabled_by_short) 349 return -ENXIO; 350 351 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 352 WLED3_CTRL_REG_MOD_EN, 353 WLED3_CTRL_REG_MOD_EN_MASK, 354 val << WLED3_CTRL_REG_MOD_EN_SHIFT); 355 if (rc < 0) 356 return rc; 357 358 if (wled->ovp_irq > 0) { 359 if (val) { 360 /* 361 * The hardware generates a storm of spurious OVP 362 * interrupts during soft start operations. So defer 363 * enabling the IRQ for 10ms to ensure that the 364 * soft start is complete. 365 */ 366 schedule_delayed_work(&wled->ovp_work, HZ / 100); 367 } else { 368 if (!cancel_delayed_work_sync(&wled->ovp_work)) 369 disable_irq(wled->ovp_irq); 370 } 371 } 372 373 return 0; 374 } 375 376 static int wled3_sync_toggle(struct wled *wled) 377 { 378 int rc; 379 unsigned int mask = GENMASK(wled->max_string_count - 1, 0); 380 381 rc = regmap_update_bits(wled->regmap, 382 wled->sink_addr + WLED3_SINK_REG_SYNC, 383 mask, WLED3_SINK_REG_SYNC_CLEAR); 384 if (rc < 0) 385 return rc; 386 387 rc = regmap_update_bits(wled->regmap, 388 wled->sink_addr + WLED3_SINK_REG_SYNC, 389 mask, mask); 390 391 return rc; 392 } 393 394 static int wled5_mod_sync_toggle(struct wled *wled) 395 { 396 int rc; 397 u8 val; 398 399 rc = regmap_update_bits(wled->regmap, 400 wled->sink_addr + WLED5_SINK_REG_MOD_SYNC_BIT, 401 WLED5_SINK_REG_SYNC_MASK, 0); 402 if (rc < 0) 403 return rc; 404 405 val = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_REG_SYNC_MOD_A_BIT : 406 WLED5_SINK_REG_SYNC_MOD_B_BIT; 407 return regmap_update_bits(wled->regmap, 408 wled->sink_addr + WLED5_SINK_REG_MOD_SYNC_BIT, 409 WLED5_SINK_REG_SYNC_MASK, val); 410 } 411 412 static int wled_ovp_fault_status(struct wled *wled, bool *fault_set) 413 { 414 int rc; 415 u32 int_rt_sts, fault_sts; 416 417 *fault_set = false; 418 rc = regmap_read(wled->regmap, 419 wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, 420 &int_rt_sts); 421 if (rc < 0) { 422 dev_err(wled->dev, "Failed to read INT_RT_STS rc=%d\n", rc); 423 return rc; 424 } 425 426 rc = regmap_read(wled->regmap, 427 wled->ctrl_addr + WLED3_CTRL_REG_FAULT_STATUS, 428 &fault_sts); 429 if (rc < 0) { 430 dev_err(wled->dev, "Failed to read FAULT_STATUS rc=%d\n", rc); 431 return rc; 432 } 433 434 if (int_rt_sts & WLED3_CTRL_REG_OVP_FAULT_STATUS) 435 *fault_set = true; 436 437 if (wled->version == 4 && (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT)) 438 *fault_set = true; 439 440 if (wled->version == 5 && (fault_sts & (WLED3_CTRL_REG_OVP_FAULT_BIT | 441 WLED5_CTRL_REG_OVP_PRE_ALARM_BIT))) 442 *fault_set = true; 443 444 if (*fault_set) 445 dev_dbg(wled->dev, "WLED OVP fault detected, int_rt_sts=0x%x fault_sts=0x%x\n", 446 int_rt_sts, fault_sts); 447 448 return rc; 449 } 450 451 static int wled4_ovp_delay(struct wled *wled) 452 { 453 return WLED_SOFT_START_DLY_US; 454 } 455 456 static int wled5_ovp_delay(struct wled *wled) 457 { 458 int rc, delay_us; 459 u32 val; 460 u8 ovp_timer_ms[8] = {1, 2, 4, 8, 12, 16, 20, 24}; 461 462 /* For WLED5, get the delay based on OVP timer */ 463 rc = regmap_read(wled->regmap, wled->ctrl_addr + 464 WLED5_CTRL_REG_OVP_INT_CTL, &val); 465 if (rc < 0) 466 delay_us = 467 ovp_timer_ms[val & WLED5_CTRL_REG_OVP_INT_TIMER_MASK] * 1000; 468 else 469 delay_us = 2 * WLED_SOFT_START_DLY_US; 470 471 dev_dbg(wled->dev, "delay_time_us: %d\n", delay_us); 472 473 return delay_us; 474 } 475 476 static int wled_update_status(struct backlight_device *bl) 477 { 478 struct wled *wled = bl_get_data(bl); 479 u16 brightness = backlight_get_brightness(bl); 480 int rc = 0; 481 482 mutex_lock(&wled->lock); 483 if (brightness) { 484 rc = wled->wled_set_brightness(wled, brightness); 485 if (rc < 0) { 486 dev_err(wled->dev, "wled failed to set brightness rc:%d\n", 487 rc); 488 goto unlock_mutex; 489 } 490 491 if (wled->version < 5) { 492 rc = wled->wled_sync_toggle(wled); 493 if (rc < 0) { 494 dev_err(wled->dev, "wled sync failed rc:%d\n", rc); 495 goto unlock_mutex; 496 } 497 } else { 498 /* 499 * For WLED5 toggling the MOD_SYNC_BIT updates the 500 * brightness 501 */ 502 rc = wled5_mod_sync_toggle(wled); 503 if (rc < 0) { 504 dev_err(wled->dev, "wled mod sync failed rc:%d\n", 505 rc); 506 goto unlock_mutex; 507 } 508 } 509 } 510 511 if (!!brightness != !!wled->brightness) { 512 rc = wled_module_enable(wled, !!brightness); 513 if (rc < 0) { 514 dev_err(wled->dev, "wled enable failed rc:%d\n", rc); 515 goto unlock_mutex; 516 } 517 } 518 519 wled->brightness = brightness; 520 521 unlock_mutex: 522 mutex_unlock(&wled->lock); 523 524 return rc; 525 } 526 527 static int wled_get_brightness(struct backlight_device *bl) 528 { 529 struct wled *wled = bl_get_data(bl); 530 int rc; 531 532 mutex_lock(&wled->lock); 533 rc = wled_read_brightness(wled); 534 mutex_unlock(&wled->lock); 535 536 return rc; 537 } 538 539 static int wled4_cabc_config(struct wled *wled, bool enable) 540 { 541 int i, j, rc; 542 u8 val; 543 544 for (i = 0; i < wled->cfg.num_strings; i++) { 545 j = wled->cfg.enabled_strings[i]; 546 547 val = enable ? WLED4_SINK_REG_STR_CABC_MASK : 0; 548 rc = regmap_update_bits(wled->regmap, wled->sink_addr + 549 WLED4_SINK_REG_STR_CABC(j), 550 WLED4_SINK_REG_STR_CABC_MASK, val); 551 if (rc < 0) 552 return rc; 553 } 554 555 return 0; 556 } 557 558 static int wled5_cabc_config(struct wled *wled, bool enable) 559 { 560 int rc, offset; 561 u8 reg; 562 563 if (wled->cabc_disabled) 564 return 0; 565 566 reg = enable ? wled->cfg.cabc_sel : 0; 567 offset = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_REG_MOD_A_SRC_SEL : 568 WLED5_SINK_REG_MOD_B_SRC_SEL; 569 570 rc = regmap_update_bits(wled->regmap, wled->sink_addr + offset, 571 WLED5_SINK_REG_MOD_SRC_SEL_MASK, reg); 572 if (rc < 0) { 573 pr_err("Error in configuring CABC rc=%d\n", rc); 574 return rc; 575 } 576 577 if (!wled->cfg.cabc_sel) 578 wled->cabc_disabled = true; 579 580 return 0; 581 } 582 583 #define WLED_SHORT_DLY_MS 20 584 #define WLED_SHORT_CNT_MAX 5 585 #define WLED_SHORT_RESET_CNT_DLY_US USEC_PER_SEC 586 587 static irqreturn_t wled_short_irq_handler(int irq, void *_wled) 588 { 589 struct wled *wled = _wled; 590 int rc; 591 s64 elapsed_time; 592 593 wled->short_count++; 594 mutex_lock(&wled->lock); 595 rc = wled_module_enable(wled, false); 596 if (rc < 0) { 597 dev_err(wled->dev, "wled disable failed rc:%d\n", rc); 598 goto unlock_mutex; 599 } 600 601 elapsed_time = ktime_us_delta(ktime_get(), 602 wled->last_short_event); 603 if (elapsed_time > WLED_SHORT_RESET_CNT_DLY_US) 604 wled->short_count = 1; 605 606 if (wled->short_count > WLED_SHORT_CNT_MAX) { 607 dev_err(wled->dev, "Short triggered %d times, disabling WLED forever!\n", 608 wled->short_count); 609 wled->disabled_by_short = true; 610 goto unlock_mutex; 611 } 612 613 wled->last_short_event = ktime_get(); 614 615 msleep(WLED_SHORT_DLY_MS); 616 rc = wled_module_enable(wled, true); 617 if (rc < 0) 618 dev_err(wled->dev, "wled enable failed rc:%d\n", rc); 619 620 unlock_mutex: 621 mutex_unlock(&wled->lock); 622 623 return IRQ_HANDLED; 624 } 625 626 #define AUTO_DETECT_BRIGHTNESS 200 627 628 static void wled_auto_string_detection(struct wled *wled) 629 { 630 int rc = 0, i, j, delay_time_us; 631 u32 sink_config = 0; 632 u8 sink_test = 0, sink_valid = 0, val; 633 bool fault_set; 634 635 /* Read configured sink configuration */ 636 rc = regmap_read(wled->regmap, wled->sink_addr + 637 WLED4_SINK_REG_CURR_SINK, &sink_config); 638 if (rc < 0) { 639 dev_err(wled->dev, "Failed to read SINK configuration rc=%d\n", 640 rc); 641 goto failed_detect; 642 } 643 644 /* Disable the module before starting detection */ 645 rc = regmap_update_bits(wled->regmap, 646 wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, 647 WLED3_CTRL_REG_MOD_EN_MASK, 0); 648 if (rc < 0) { 649 dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", rc); 650 goto failed_detect; 651 } 652 653 /* Set low brightness across all sinks */ 654 rc = wled4_set_brightness(wled, AUTO_DETECT_BRIGHTNESS); 655 if (rc < 0) { 656 dev_err(wled->dev, "Failed to set brightness for auto detection rc=%d\n", 657 rc); 658 goto failed_detect; 659 } 660 661 if (wled->cfg.cabc) { 662 rc = wled->wled_cabc_config(wled, false); 663 if (rc < 0) 664 goto failed_detect; 665 } 666 667 /* Disable all sinks */ 668 rc = regmap_write(wled->regmap, 669 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 0); 670 if (rc < 0) { 671 dev_err(wled->dev, "Failed to disable all sinks rc=%d\n", rc); 672 goto failed_detect; 673 } 674 675 /* Iterate through the strings one by one */ 676 for (i = 0; i < wled->cfg.num_strings; i++) { 677 j = wled->cfg.enabled_strings[i]; 678 sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + j)); 679 680 /* Enable feedback control */ 681 rc = regmap_write(wled->regmap, wled->ctrl_addr + 682 WLED3_CTRL_REG_FEEDBACK_CONTROL, j + 1); 683 if (rc < 0) { 684 dev_err(wled->dev, "Failed to enable feedback for SINK %d rc = %d\n", 685 j + 1, rc); 686 goto failed_detect; 687 } 688 689 /* Enable the sink */ 690 rc = regmap_write(wled->regmap, wled->sink_addr + 691 WLED4_SINK_REG_CURR_SINK, sink_test); 692 if (rc < 0) { 693 dev_err(wled->dev, "Failed to configure SINK %d rc=%d\n", 694 j + 1, rc); 695 goto failed_detect; 696 } 697 698 /* Enable the module */ 699 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 700 WLED3_CTRL_REG_MOD_EN, 701 WLED3_CTRL_REG_MOD_EN_MASK, 702 WLED3_CTRL_REG_MOD_EN_MASK); 703 if (rc < 0) { 704 dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", 705 rc); 706 goto failed_detect; 707 } 708 709 delay_time_us = wled->wled_ovp_delay(wled); 710 usleep_range(delay_time_us, delay_time_us + 1000); 711 712 rc = wled_ovp_fault_status(wled, &fault_set); 713 if (rc < 0) { 714 dev_err(wled->dev, "Error in getting OVP fault_sts, rc=%d\n", 715 rc); 716 goto failed_detect; 717 } 718 719 if (fault_set) 720 dev_dbg(wled->dev, "WLED OVP fault detected with SINK %d\n", 721 j + 1); 722 else 723 sink_valid |= sink_test; 724 725 /* Disable the module */ 726 rc = regmap_update_bits(wled->regmap, 727 wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, 728 WLED3_CTRL_REG_MOD_EN_MASK, 0); 729 if (rc < 0) { 730 dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", 731 rc); 732 goto failed_detect; 733 } 734 } 735 736 if (!sink_valid) { 737 dev_err(wled->dev, "No valid WLED sinks found\n"); 738 wled->disabled_by_short = true; 739 goto failed_detect; 740 } 741 742 if (sink_valid != sink_config) { 743 dev_warn(wled->dev, "%x is not a valid sink configuration - using %x instead\n", 744 sink_config, sink_valid); 745 sink_config = sink_valid; 746 } 747 748 /* Write the new sink configuration */ 749 rc = regmap_write(wled->regmap, 750 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 751 sink_config); 752 if (rc < 0) { 753 dev_err(wled->dev, "Failed to reconfigure the default sink rc=%d\n", 754 rc); 755 goto failed_detect; 756 } 757 758 /* Enable valid sinks */ 759 if (wled->version == 4) { 760 for (i = 0; i < wled->cfg.num_strings; i++) { 761 j = wled->cfg.enabled_strings[i]; 762 if (sink_config & 763 BIT(WLED4_SINK_REG_CURR_SINK_SHFT + j)) 764 val = WLED4_SINK_REG_STR_MOD_MASK; 765 else 766 /* Disable modulator_en for unused sink */ 767 val = 0; 768 769 rc = regmap_write(wled->regmap, wled->sink_addr + 770 WLED4_SINK_REG_STR_MOD_EN(j), val); 771 if (rc < 0) { 772 dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n", 773 rc); 774 goto failed_detect; 775 } 776 } 777 } 778 779 /* Enable CABC */ 780 rc = wled->wled_cabc_config(wled, true); 781 if (rc < 0) 782 goto failed_detect; 783 784 /* Restore the feedback setting */ 785 rc = regmap_write(wled->regmap, 786 wled->ctrl_addr + WLED3_CTRL_REG_FEEDBACK_CONTROL, 0); 787 if (rc < 0) { 788 dev_err(wled->dev, "Failed to restore feedback setting rc=%d\n", 789 rc); 790 goto failed_detect; 791 } 792 793 /* Restore brightness */ 794 rc = wled4_set_brightness(wled, wled->brightness); 795 if (rc < 0) { 796 dev_err(wled->dev, "Failed to set brightness after auto detection rc=%d\n", 797 rc); 798 goto failed_detect; 799 } 800 801 rc = regmap_update_bits(wled->regmap, 802 wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, 803 WLED3_CTRL_REG_MOD_EN_MASK, 804 WLED3_CTRL_REG_MOD_EN_MASK); 805 if (rc < 0) { 806 dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", rc); 807 goto failed_detect; 808 } 809 810 failed_detect: 811 return; 812 } 813 814 #define WLED_AUTO_DETECT_OVP_COUNT 5 815 #define WLED_AUTO_DETECT_CNT_DLY_US USEC_PER_SEC 816 817 static bool wled4_auto_detection_required(struct wled *wled) 818 { 819 s64 elapsed_time_us; 820 821 if (!wled->cfg.auto_detection_enabled) 822 return false; 823 824 /* 825 * Check if the OVP fault was an occasional one 826 * or if it's firing continuously, the latter qualifies 827 * for an auto-detection check. 828 */ 829 if (!wled->auto_detection_ovp_count) { 830 wled->start_ovp_fault_time = ktime_get(); 831 wled->auto_detection_ovp_count++; 832 } else { 833 elapsed_time_us = ktime_us_delta(ktime_get(), 834 wled->start_ovp_fault_time); 835 if (elapsed_time_us > WLED_AUTO_DETECT_CNT_DLY_US) 836 wled->auto_detection_ovp_count = 0; 837 else 838 wled->auto_detection_ovp_count++; 839 840 if (wled->auto_detection_ovp_count >= 841 WLED_AUTO_DETECT_OVP_COUNT) { 842 wled->auto_detection_ovp_count = 0; 843 return true; 844 } 845 } 846 847 return false; 848 } 849 850 static bool wled5_auto_detection_required(struct wled *wled) 851 { 852 if (!wled->cfg.auto_detection_enabled) 853 return false; 854 855 /* 856 * Unlike WLED4, WLED5 has OVP fault density interrupt configuration 857 * i.e. to count the number of OVP alarms for a certain duration before 858 * triggering OVP fault interrupt. By default, number of OVP fault 859 * events counted before an interrupt is fired is 32 and the time 860 * interval is 12 ms. If we see one OVP fault interrupt, then that 861 * should qualify for a real OVP fault condition to run auto detection 862 * algorithm. 863 */ 864 return true; 865 } 866 867 static int wled_auto_detection_at_init(struct wled *wled) 868 { 869 int rc; 870 bool fault_set; 871 872 if (!wled->cfg.auto_detection_enabled) 873 return 0; 874 875 rc = wled_ovp_fault_status(wled, &fault_set); 876 if (rc < 0) { 877 dev_err(wled->dev, "Error in getting OVP fault_sts, rc=%d\n", 878 rc); 879 return rc; 880 } 881 882 if (fault_set) { 883 mutex_lock(&wled->lock); 884 wled_auto_string_detection(wled); 885 mutex_unlock(&wled->lock); 886 } 887 888 return rc; 889 } 890 891 static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled) 892 { 893 struct wled *wled = _wled; 894 int rc; 895 u32 int_sts, fault_sts; 896 897 rc = regmap_read(wled->regmap, 898 wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, &int_sts); 899 if (rc < 0) { 900 dev_err(wled->dev, "Error in reading WLED3_INT_RT_STS rc=%d\n", 901 rc); 902 return IRQ_HANDLED; 903 } 904 905 rc = regmap_read(wled->regmap, wled->ctrl_addr + 906 WLED3_CTRL_REG_FAULT_STATUS, &fault_sts); 907 if (rc < 0) { 908 dev_err(wled->dev, "Error in reading WLED_FAULT_STATUS rc=%d\n", 909 rc); 910 return IRQ_HANDLED; 911 } 912 913 if (fault_sts & (WLED3_CTRL_REG_OVP_FAULT_BIT | 914 WLED3_CTRL_REG_ILIM_FAULT_BIT)) 915 dev_dbg(wled->dev, "WLED OVP fault detected, int_sts=%x fault_sts= %x\n", 916 int_sts, fault_sts); 917 918 if (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT) { 919 if (wled->wled_auto_detection_required(wled)) { 920 mutex_lock(&wled->lock); 921 wled_auto_string_detection(wled); 922 mutex_unlock(&wled->lock); 923 } 924 } 925 926 return IRQ_HANDLED; 927 } 928 929 static int wled3_setup(struct wled *wled) 930 { 931 u16 addr; 932 u8 sink_en = 0; 933 int rc, i, j; 934 935 rc = regmap_update_bits(wled->regmap, 936 wled->ctrl_addr + WLED3_CTRL_REG_OVP, 937 WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); 938 if (rc) 939 return rc; 940 941 rc = regmap_update_bits(wled->regmap, 942 wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, 943 WLED3_CTRL_REG_ILIMIT_MASK, 944 wled->cfg.boost_i_limit); 945 if (rc) 946 return rc; 947 948 rc = regmap_update_bits(wled->regmap, 949 wled->ctrl_addr + WLED3_CTRL_REG_FREQ, 950 WLED3_CTRL_REG_FREQ_MASK, 951 wled->cfg.switch_freq); 952 if (rc) 953 return rc; 954 955 for (i = 0; i < wled->cfg.num_strings; ++i) { 956 j = wled->cfg.enabled_strings[i]; 957 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_EN(j); 958 rc = regmap_update_bits(wled->regmap, addr, 959 WLED3_SINK_REG_STR_MOD_MASK, 960 WLED3_SINK_REG_STR_MOD_MASK); 961 if (rc) 962 return rc; 963 964 if (wled->cfg.ext_gen) { 965 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_SRC(j); 966 rc = regmap_update_bits(wled->regmap, addr, 967 WLED3_SINK_REG_STR_MOD_SRC_MASK, 968 WLED3_SINK_REG_STR_MOD_SRC_EXT); 969 if (rc) 970 return rc; 971 } 972 973 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_FULL_SCALE_CURR(j); 974 rc = regmap_update_bits(wled->regmap, addr, 975 WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK, 976 wled->cfg.string_i_limit); 977 if (rc) 978 return rc; 979 980 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_CABC(j); 981 rc = regmap_update_bits(wled->regmap, addr, 982 WLED3_SINK_REG_STR_CABC_MASK, 983 wled->cfg.cabc ? 984 WLED3_SINK_REG_STR_CABC_MASK : 0); 985 if (rc) 986 return rc; 987 988 sink_en |= BIT(j + WLED3_SINK_REG_CURR_SINK_SHFT); 989 } 990 991 rc = regmap_update_bits(wled->regmap, 992 wled->ctrl_addr + WLED3_SINK_REG_CURR_SINK, 993 WLED3_SINK_REG_CURR_SINK_MASK, sink_en); 994 if (rc) 995 return rc; 996 997 return 0; 998 } 999 1000 static const struct wled_config wled3_config_defaults = { 1001 .boost_i_limit = 3, 1002 .string_i_limit = 20, 1003 .ovp = 2, 1004 .num_strings = 3, 1005 .switch_freq = 5, 1006 .cs_out_en = false, 1007 .ext_gen = false, 1008 .cabc = false, 1009 .enabled_strings = {0, 1, 2}, 1010 }; 1011 1012 static int wled4_setup(struct wled *wled) 1013 { 1014 int rc, temp, i, j; 1015 u16 addr; 1016 u8 sink_en = 0; 1017 u32 sink_cfg; 1018 1019 rc = regmap_update_bits(wled->regmap, 1020 wled->ctrl_addr + WLED3_CTRL_REG_OVP, 1021 WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); 1022 if (rc < 0) 1023 return rc; 1024 1025 rc = regmap_update_bits(wled->regmap, 1026 wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, 1027 WLED3_CTRL_REG_ILIMIT_MASK, 1028 wled->cfg.boost_i_limit); 1029 if (rc < 0) 1030 return rc; 1031 1032 rc = regmap_update_bits(wled->regmap, 1033 wled->ctrl_addr + WLED3_CTRL_REG_FREQ, 1034 WLED3_CTRL_REG_FREQ_MASK, 1035 wled->cfg.switch_freq); 1036 if (rc < 0) 1037 return rc; 1038 1039 if (wled->cfg.external_pfet) { 1040 /* Unlock the secure register access */ 1041 rc = regmap_write(wled->regmap, wled->ctrl_addr + 1042 WLED4_CTRL_REG_SEC_ACCESS, 1043 WLED4_CTRL_REG_SEC_UNLOCK); 1044 if (rc < 0) 1045 return rc; 1046 1047 rc = regmap_write(wled->regmap, 1048 wled->ctrl_addr + WLED4_CTRL_REG_TEST1, 1049 WLED4_CTRL_REG_TEST1_EXT_FET_DTEST2); 1050 if (rc < 0) 1051 return rc; 1052 } 1053 1054 rc = regmap_read(wled->regmap, wled->sink_addr + 1055 WLED4_SINK_REG_CURR_SINK, &sink_cfg); 1056 if (rc < 0) 1057 return rc; 1058 1059 for (i = 0; i < wled->cfg.num_strings; i++) { 1060 j = wled->cfg.enabled_strings[i]; 1061 temp = j + WLED4_SINK_REG_CURR_SINK_SHFT; 1062 sink_en |= 1 << temp; 1063 } 1064 1065 if (sink_cfg == sink_en) { 1066 rc = wled_auto_detection_at_init(wled); 1067 return rc; 1068 } 1069 1070 rc = regmap_update_bits(wled->regmap, 1071 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 1072 WLED4_SINK_REG_CURR_SINK_MASK, 0); 1073 if (rc < 0) 1074 return rc; 1075 1076 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 1077 WLED3_CTRL_REG_MOD_EN, 1078 WLED3_CTRL_REG_MOD_EN_MASK, 0); 1079 if (rc < 0) 1080 return rc; 1081 1082 /* Per sink/string configuration */ 1083 for (i = 0; i < wled->cfg.num_strings; i++) { 1084 j = wled->cfg.enabled_strings[i]; 1085 1086 addr = wled->sink_addr + 1087 WLED4_SINK_REG_STR_MOD_EN(j); 1088 rc = regmap_update_bits(wled->regmap, addr, 1089 WLED4_SINK_REG_STR_MOD_MASK, 1090 WLED4_SINK_REG_STR_MOD_MASK); 1091 if (rc < 0) 1092 return rc; 1093 1094 addr = wled->sink_addr + 1095 WLED4_SINK_REG_STR_FULL_SCALE_CURR(j); 1096 rc = regmap_update_bits(wled->regmap, addr, 1097 WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK, 1098 wled->cfg.string_i_limit); 1099 if (rc < 0) 1100 return rc; 1101 } 1102 1103 rc = wled4_cabc_config(wled, wled->cfg.cabc); 1104 if (rc < 0) 1105 return rc; 1106 1107 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 1108 WLED3_CTRL_REG_MOD_EN, 1109 WLED3_CTRL_REG_MOD_EN_MASK, 1110 WLED3_CTRL_REG_MOD_EN_MASK); 1111 if (rc < 0) 1112 return rc; 1113 1114 rc = regmap_update_bits(wled->regmap, 1115 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 1116 WLED4_SINK_REG_CURR_SINK_MASK, sink_en); 1117 if (rc < 0) 1118 return rc; 1119 1120 rc = wled->wled_sync_toggle(wled); 1121 if (rc < 0) { 1122 dev_err(wled->dev, "Failed to toggle sync reg rc:%d\n", rc); 1123 return rc; 1124 } 1125 1126 rc = wled_auto_detection_at_init(wled); 1127 1128 return rc; 1129 } 1130 1131 static const struct wled_config wled4_config_defaults = { 1132 .boost_i_limit = 4, 1133 .string_i_limit = 10, 1134 .ovp = 1, 1135 .num_strings = 4, 1136 .switch_freq = 11, 1137 .cabc = false, 1138 .external_pfet = false, 1139 .auto_detection_enabled = false, 1140 .enabled_strings = {0, 1, 2, 3}, 1141 }; 1142 1143 static int wled5_setup(struct wled *wled) 1144 { 1145 int rc, temp, i, j, offset; 1146 u8 sink_en = 0; 1147 u16 addr; 1148 u32 val; 1149 1150 rc = regmap_update_bits(wled->regmap, 1151 wled->ctrl_addr + WLED3_CTRL_REG_OVP, 1152 WLED5_CTRL_REG_OVP_MASK, wled->cfg.ovp); 1153 if (rc < 0) 1154 return rc; 1155 1156 rc = regmap_update_bits(wled->regmap, 1157 wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, 1158 WLED3_CTRL_REG_ILIMIT_MASK, 1159 wled->cfg.boost_i_limit); 1160 if (rc < 0) 1161 return rc; 1162 1163 rc = regmap_update_bits(wled->regmap, 1164 wled->ctrl_addr + WLED3_CTRL_REG_FREQ, 1165 WLED3_CTRL_REG_FREQ_MASK, 1166 wled->cfg.switch_freq); 1167 if (rc < 0) 1168 return rc; 1169 1170 /* Per sink/string configuration */ 1171 for (i = 0; i < wled->cfg.num_strings; ++i) { 1172 j = wled->cfg.enabled_strings[i]; 1173 addr = wled->sink_addr + 1174 WLED4_SINK_REG_STR_FULL_SCALE_CURR(j); 1175 rc = regmap_update_bits(wled->regmap, addr, 1176 WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK, 1177 wled->cfg.string_i_limit); 1178 if (rc < 0) 1179 return rc; 1180 1181 addr = wled->sink_addr + WLED5_SINK_REG_STR_SRC_SEL(j); 1182 rc = regmap_update_bits(wled->regmap, addr, 1183 WLED5_SINK_REG_SRC_SEL_MASK, 1184 wled->cfg.mod_sel == MOD_A ? 1185 WLED5_SINK_REG_SRC_SEL_MOD_A : 1186 WLED5_SINK_REG_SRC_SEL_MOD_B); 1187 1188 temp = j + WLED4_SINK_REG_CURR_SINK_SHFT; 1189 sink_en |= 1 << temp; 1190 } 1191 1192 rc = wled5_cabc_config(wled, wled->cfg.cabc_sel ? true : false); 1193 if (rc < 0) 1194 return rc; 1195 1196 /* Enable one of the modulators A or B based on mod_sel */ 1197 addr = wled->sink_addr + WLED5_SINK_REG_MOD_A_EN; 1198 val = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_REG_MOD_EN_MASK : 0; 1199 rc = regmap_update_bits(wled->regmap, addr, 1200 WLED5_SINK_REG_MOD_EN_MASK, val); 1201 if (rc < 0) 1202 return rc; 1203 1204 addr = wled->sink_addr + WLED5_SINK_REG_MOD_B_EN; 1205 val = (wled->cfg.mod_sel == MOD_B) ? WLED5_SINK_REG_MOD_EN_MASK : 0; 1206 rc = regmap_update_bits(wled->regmap, addr, 1207 WLED5_SINK_REG_MOD_EN_MASK, val); 1208 if (rc < 0) 1209 return rc; 1210 1211 offset = (wled->cfg.mod_sel == MOD_A) ? 1212 WLED5_SINK_REG_MOD_A_BRIGHTNESS_WIDTH_SEL : 1213 WLED5_SINK_REG_MOD_B_BRIGHTNESS_WIDTH_SEL; 1214 1215 addr = wled->sink_addr + offset; 1216 val = (wled->max_brightness == WLED5_SINK_REG_BRIGHT_MAX_15B) ? 1217 WLED5_SINK_REG_BRIGHTNESS_WIDTH_15B : 1218 WLED5_SINK_REG_BRIGHTNESS_WIDTH_12B; 1219 rc = regmap_write(wled->regmap, addr, val); 1220 if (rc < 0) 1221 return rc; 1222 1223 rc = regmap_update_bits(wled->regmap, 1224 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 1225 WLED4_SINK_REG_CURR_SINK_MASK, sink_en); 1226 if (rc < 0) 1227 return rc; 1228 1229 /* This updates only FSC configuration in WLED5 */ 1230 rc = wled->wled_sync_toggle(wled); 1231 if (rc < 0) { 1232 pr_err("Failed to toggle sync reg rc:%d\n", rc); 1233 return rc; 1234 } 1235 1236 rc = wled_auto_detection_at_init(wled); 1237 if (rc < 0) 1238 return rc; 1239 1240 return 0; 1241 } 1242 1243 static const struct wled_config wled5_config_defaults = { 1244 .boost_i_limit = 5, 1245 .string_i_limit = 10, 1246 .ovp = 4, 1247 .num_strings = 4, 1248 .switch_freq = 11, 1249 .mod_sel = 0, 1250 .cabc_sel = 0, 1251 .cabc = false, 1252 .external_pfet = false, 1253 .auto_detection_enabled = false, 1254 .enabled_strings = {0, 1, 2, 3}, 1255 }; 1256 1257 static const u32 wled3_boost_i_limit_values[] = { 1258 105, 385, 525, 805, 980, 1260, 1400, 1680, 1259 }; 1260 1261 static const struct wled_var_cfg wled3_boost_i_limit_cfg = { 1262 .values = wled3_boost_i_limit_values, 1263 .size = ARRAY_SIZE(wled3_boost_i_limit_values), 1264 }; 1265 1266 static const u32 wled4_boost_i_limit_values[] = { 1267 105, 280, 450, 620, 970, 1150, 1300, 1500, 1268 }; 1269 1270 static const struct wled_var_cfg wled4_boost_i_limit_cfg = { 1271 .values = wled4_boost_i_limit_values, 1272 .size = ARRAY_SIZE(wled4_boost_i_limit_values), 1273 }; 1274 1275 static inline u32 wled5_boost_i_limit_values_fn(u32 idx) 1276 { 1277 return 525 + (idx * 175); 1278 } 1279 1280 static const struct wled_var_cfg wled5_boost_i_limit_cfg = { 1281 .fn = wled5_boost_i_limit_values_fn, 1282 .size = 8, 1283 }; 1284 1285 static const u32 wled3_ovp_values[] = { 1286 35, 32, 29, 27, 1287 }; 1288 1289 static const struct wled_var_cfg wled3_ovp_cfg = { 1290 .values = wled3_ovp_values, 1291 .size = ARRAY_SIZE(wled3_ovp_values), 1292 }; 1293 1294 static const u32 wled4_ovp_values[] = { 1295 31100, 29600, 19600, 18100, 1296 }; 1297 1298 static const struct wled_var_cfg wled4_ovp_cfg = { 1299 .values = wled4_ovp_values, 1300 .size = ARRAY_SIZE(wled4_ovp_values), 1301 }; 1302 1303 static const u32 pmi8994_wled_ovp_values[] = { 1304 31000, 29500, 19400, 17800, 1305 }; 1306 1307 static const struct wled_var_cfg pmi8994_wled_ovp_cfg = { 1308 .values = pmi8994_wled_ovp_values, 1309 .size = ARRAY_SIZE(pmi8994_wled_ovp_values), 1310 }; 1311 1312 static inline u32 wled5_ovp_values_fn(u32 idx) 1313 { 1314 /* 1315 * 0000 - 38.5 V 1316 * 0001 - 37 V .. 1317 * 1111 - 16 V 1318 */ 1319 return 38500 - (idx * 1500); 1320 } 1321 1322 static const struct wled_var_cfg wled5_ovp_cfg = { 1323 .fn = wled5_ovp_values_fn, 1324 .size = 16, 1325 }; 1326 1327 static u32 wled3_switch_freq_values_fn(u32 idx) 1328 { 1329 return 19200 / (2 * (1 + idx)); 1330 } 1331 1332 static const struct wled_var_cfg wled3_switch_freq_cfg = { 1333 .fn = wled3_switch_freq_values_fn, 1334 .size = 16, 1335 }; 1336 1337 static const struct wled_var_cfg wled3_string_i_limit_cfg = { 1338 .size = 26, 1339 }; 1340 1341 static const u32 wled4_string_i_limit_values[] = { 1342 0, 2500, 5000, 7500, 10000, 12500, 15000, 17500, 20000, 1343 22500, 25000, 27500, 30000, 1344 }; 1345 1346 static const struct wled_var_cfg wled4_string_i_limit_cfg = { 1347 .values = wled4_string_i_limit_values, 1348 .size = ARRAY_SIZE(wled4_string_i_limit_values), 1349 }; 1350 1351 static const struct wled_var_cfg wled5_mod_sel_cfg = { 1352 .size = 2, 1353 }; 1354 1355 static const struct wled_var_cfg wled5_cabc_sel_cfg = { 1356 .size = 4, 1357 }; 1358 1359 static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx) 1360 { 1361 if (idx >= cfg->size) 1362 return UINT_MAX; 1363 if (cfg->fn) 1364 return cfg->fn(idx); 1365 if (cfg->values) 1366 return cfg->values[idx]; 1367 return idx; 1368 } 1369 1370 static int wled_configure(struct wled *wled) 1371 { 1372 struct wled_config *cfg = &wled->cfg; 1373 struct device *dev = wled->dev; 1374 const __be32 *prop_addr; 1375 u32 size, val, c; 1376 int rc, i, j, string_len; 1377 1378 const struct wled_u32_opts *u32_opts = NULL; 1379 const struct wled_u32_opts wled3_opts[] = { 1380 { 1381 .name = "qcom,current-boost-limit", 1382 .val_ptr = &cfg->boost_i_limit, 1383 .cfg = &wled3_boost_i_limit_cfg, 1384 }, 1385 { 1386 .name = "qcom,current-limit", 1387 .val_ptr = &cfg->string_i_limit, 1388 .cfg = &wled3_string_i_limit_cfg, 1389 }, 1390 { 1391 .name = "qcom,ovp", 1392 .val_ptr = &cfg->ovp, 1393 .cfg = &wled3_ovp_cfg, 1394 }, 1395 { 1396 .name = "qcom,switching-freq", 1397 .val_ptr = &cfg->switch_freq, 1398 .cfg = &wled3_switch_freq_cfg, 1399 }, 1400 }; 1401 1402 const struct wled_u32_opts wled4_opts[] = { 1403 { 1404 .name = "qcom,current-boost-limit", 1405 .val_ptr = &cfg->boost_i_limit, 1406 .cfg = &wled4_boost_i_limit_cfg, 1407 }, 1408 { 1409 .name = "qcom,current-limit-microamp", 1410 .val_ptr = &cfg->string_i_limit, 1411 .cfg = &wled4_string_i_limit_cfg, 1412 }, 1413 { 1414 .name = "qcom,ovp-millivolt", 1415 .val_ptr = &cfg->ovp, 1416 .cfg = &wled4_ovp_cfg, 1417 }, 1418 { 1419 .name = "qcom,switching-freq", 1420 .val_ptr = &cfg->switch_freq, 1421 .cfg = &wled3_switch_freq_cfg, 1422 }, 1423 }; 1424 1425 const struct wled_u32_opts pmi8994_wled_opts[] = { 1426 { 1427 .name = "qcom,current-boost-limit", 1428 .val_ptr = &cfg->boost_i_limit, 1429 .cfg = &wled4_boost_i_limit_cfg, 1430 }, 1431 { 1432 .name = "qcom,current-limit-microamp", 1433 .val_ptr = &cfg->string_i_limit, 1434 .cfg = &wled4_string_i_limit_cfg, 1435 }, 1436 { 1437 .name = "qcom,ovp-millivolt", 1438 .val_ptr = &cfg->ovp, 1439 .cfg = &pmi8994_wled_ovp_cfg, 1440 }, 1441 { 1442 .name = "qcom,switching-freq", 1443 .val_ptr = &cfg->switch_freq, 1444 .cfg = &wled3_switch_freq_cfg, 1445 }, 1446 }; 1447 1448 const struct wled_u32_opts wled5_opts[] = { 1449 { 1450 .name = "qcom,current-boost-limit", 1451 .val_ptr = &cfg->boost_i_limit, 1452 .cfg = &wled5_boost_i_limit_cfg, 1453 }, 1454 { 1455 .name = "qcom,current-limit-microamp", 1456 .val_ptr = &cfg->string_i_limit, 1457 .cfg = &wled4_string_i_limit_cfg, 1458 }, 1459 { 1460 .name = "qcom,ovp-millivolt", 1461 .val_ptr = &cfg->ovp, 1462 .cfg = &wled5_ovp_cfg, 1463 }, 1464 { 1465 .name = "qcom,switching-freq", 1466 .val_ptr = &cfg->switch_freq, 1467 .cfg = &wled3_switch_freq_cfg, 1468 }, 1469 { 1470 .name = "qcom,modulator-sel", 1471 .val_ptr = &cfg->mod_sel, 1472 .cfg = &wled5_mod_sel_cfg, 1473 }, 1474 { 1475 .name = "qcom,cabc-sel", 1476 .val_ptr = &cfg->cabc_sel, 1477 .cfg = &wled5_cabc_sel_cfg, 1478 }, 1479 }; 1480 1481 const struct wled_bool_opts bool_opts[] = { 1482 { "qcom,cs-out", &cfg->cs_out_en, }, 1483 { "qcom,ext-gen", &cfg->ext_gen, }, 1484 { "qcom,cabc", &cfg->cabc, }, 1485 { "qcom,external-pfet", &cfg->external_pfet, }, 1486 { "qcom,auto-string-detection", &cfg->auto_detection_enabled, }, 1487 }; 1488 1489 prop_addr = of_get_address(dev->of_node, 0, NULL, NULL); 1490 if (!prop_addr) { 1491 dev_err(wled->dev, "invalid IO resources\n"); 1492 return -EINVAL; 1493 } 1494 wled->ctrl_addr = be32_to_cpu(*prop_addr); 1495 1496 rc = of_property_read_string(dev->of_node, "label", &wled->name); 1497 if (rc) { 1498 wled->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); 1499 if (!wled->name) 1500 return -ENOMEM; 1501 } 1502 switch (wled->version) { 1503 case 3: 1504 u32_opts = wled3_opts; 1505 size = ARRAY_SIZE(wled3_opts); 1506 *cfg = wled3_config_defaults; 1507 wled->wled_set_brightness = wled3_set_brightness; 1508 wled->wled_sync_toggle = wled3_sync_toggle; 1509 wled->max_string_count = 3; 1510 wled->sink_addr = wled->ctrl_addr; 1511 break; 1512 1513 case 4: 1514 if (of_device_is_compatible(dev->of_node, "qcom,pmi8950-wled") || 1515 of_device_is_compatible(dev->of_node, "qcom,pmi8994-wled")) { 1516 u32_opts = pmi8994_wled_opts; 1517 size = ARRAY_SIZE(pmi8994_wled_opts); 1518 } else { 1519 u32_opts = wled4_opts; 1520 size = ARRAY_SIZE(wled4_opts); 1521 } 1522 *cfg = wled4_config_defaults; 1523 wled->wled_set_brightness = wled4_set_brightness; 1524 wled->wled_sync_toggle = wled3_sync_toggle; 1525 wled->wled_cabc_config = wled4_cabc_config; 1526 wled->wled_ovp_delay = wled4_ovp_delay; 1527 wled->wled_auto_detection_required = 1528 wled4_auto_detection_required; 1529 wled->max_string_count = 4; 1530 1531 prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); 1532 if (!prop_addr) { 1533 dev_err(wled->dev, "invalid IO resources\n"); 1534 return -EINVAL; 1535 } 1536 wled->sink_addr = be32_to_cpu(*prop_addr); 1537 break; 1538 1539 case 5: 1540 u32_opts = wled5_opts; 1541 size = ARRAY_SIZE(wled5_opts); 1542 *cfg = wled5_config_defaults; 1543 wled->wled_set_brightness = wled5_set_brightness; 1544 wled->wled_sync_toggle = wled3_sync_toggle; 1545 wled->wled_cabc_config = wled5_cabc_config; 1546 wled->wled_ovp_delay = wled5_ovp_delay; 1547 wled->wled_auto_detection_required = 1548 wled5_auto_detection_required; 1549 wled->max_string_count = 4; 1550 1551 prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); 1552 if (!prop_addr) { 1553 dev_err(wled->dev, "invalid IO resources\n"); 1554 return -EINVAL; 1555 } 1556 wled->sink_addr = be32_to_cpu(*prop_addr); 1557 break; 1558 1559 default: 1560 dev_err(wled->dev, "Invalid WLED version\n"); 1561 return -EINVAL; 1562 } 1563 1564 for (i = 0; i < size; ++i) { 1565 rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val); 1566 if (rc == -EINVAL) { 1567 continue; 1568 } else if (rc) { 1569 dev_err(dev, "error reading '%s'\n", u32_opts[i].name); 1570 return rc; 1571 } 1572 1573 c = UINT_MAX; 1574 for (j = 0; c != val; j++) { 1575 c = wled_values(u32_opts[i].cfg, j); 1576 if (c == UINT_MAX) { 1577 dev_err(dev, "invalid value for '%s'\n", 1578 u32_opts[i].name); 1579 return -EINVAL; 1580 } 1581 1582 if (c == val) 1583 break; 1584 } 1585 1586 dev_dbg(dev, "'%s' = %u\n", u32_opts[i].name, c); 1587 *u32_opts[i].val_ptr = j; 1588 } 1589 1590 for (i = 0; i < ARRAY_SIZE(bool_opts); ++i) { 1591 if (of_property_read_bool(dev->of_node, bool_opts[i].name)) 1592 *bool_opts[i].val_ptr = true; 1593 } 1594 1595 string_len = of_property_count_elems_of_size(dev->of_node, 1596 "qcom,enabled-strings", 1597 sizeof(u32)); 1598 if (string_len > 0) { 1599 if (string_len > wled->max_string_count) { 1600 dev_err(dev, "Cannot have more than %d strings\n", 1601 wled->max_string_count); 1602 return -EINVAL; 1603 } 1604 1605 rc = of_property_read_u32_array(dev->of_node, 1606 "qcom,enabled-strings", 1607 wled->cfg.enabled_strings, 1608 string_len); 1609 if (rc) { 1610 dev_err(dev, "Failed to read %d elements from qcom,enabled-strings: %d\n", 1611 string_len, rc); 1612 return rc; 1613 } 1614 1615 for (i = 0; i < string_len; ++i) { 1616 if (wled->cfg.enabled_strings[i] >= wled->max_string_count) { 1617 dev_err(dev, 1618 "qcom,enabled-strings index %d at %d is out of bounds\n", 1619 wled->cfg.enabled_strings[i], i); 1620 return -EINVAL; 1621 } 1622 } 1623 1624 cfg->num_strings = string_len; 1625 } 1626 1627 rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); 1628 if (!rc) { 1629 if (val < 1 || val > wled->max_string_count) { 1630 dev_err(dev, "qcom,num-strings must be between 1 and %d\n", 1631 wled->max_string_count); 1632 return -EINVAL; 1633 } 1634 1635 if (string_len > 0) { 1636 dev_warn(dev, "Only one of qcom,num-strings or qcom,enabled-strings" 1637 " should be set\n"); 1638 if (val > string_len) { 1639 dev_err(dev, "qcom,num-strings exceeds qcom,enabled-strings\n"); 1640 return -EINVAL; 1641 } 1642 } 1643 1644 cfg->num_strings = val; 1645 } 1646 1647 return 0; 1648 } 1649 1650 static int wled_configure_short_irq(struct wled *wled, 1651 struct platform_device *pdev) 1652 { 1653 int rc; 1654 1655 if (!wled->has_short_detect) 1656 return 0; 1657 1658 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 1659 WLED4_CTRL_REG_SHORT_PROTECT, 1660 WLED4_CTRL_REG_SHORT_EN_MASK, 1661 WLED4_CTRL_REG_SHORT_EN_MASK); 1662 if (rc < 0) 1663 return rc; 1664 1665 wled->short_irq = platform_get_irq_byname(pdev, "short"); 1666 if (wled->short_irq < 0) { 1667 dev_dbg(&pdev->dev, "short irq is not used\n"); 1668 return 0; 1669 } 1670 1671 rc = devm_request_threaded_irq(wled->dev, wled->short_irq, 1672 NULL, wled_short_irq_handler, 1673 IRQF_ONESHOT, 1674 "wled_short_irq", wled); 1675 if (rc < 0) 1676 dev_err(wled->dev, "Unable to request short_irq (err:%d)\n", 1677 rc); 1678 1679 return rc; 1680 } 1681 1682 static int wled_configure_ovp_irq(struct wled *wled, 1683 struct platform_device *pdev) 1684 { 1685 int rc; 1686 1687 wled->ovp_irq = platform_get_irq_byname(pdev, "ovp"); 1688 if (wled->ovp_irq < 0) { 1689 dev_dbg(&pdev->dev, "OVP IRQ not found - disabling automatic string detection\n"); 1690 return 0; 1691 } 1692 1693 rc = devm_request_threaded_irq(wled->dev, wled->ovp_irq, NULL, 1694 wled_ovp_irq_handler, IRQF_ONESHOT, 1695 "wled_ovp_irq", wled); 1696 if (rc < 0) { 1697 wled->ovp_irq = 0; 1698 return 0; 1699 } 1700 1701 /* Keep the OVP irq disabled until the module is enabled */ 1702 if (!wled->brightness) 1703 disable_irq(wled->ovp_irq); 1704 1705 return 0; 1706 } 1707 1708 static const struct backlight_ops wled_ops = { 1709 .update_status = wled_update_status, 1710 .get_brightness = wled_get_brightness, 1711 }; 1712 1713 static int wled_probe(struct platform_device *pdev) 1714 { 1715 struct backlight_properties props; 1716 struct backlight_device *bl; 1717 struct wled *wled; 1718 struct regmap *regmap; 1719 u32 val; 1720 int rc; 1721 1722 regmap = dev_get_regmap(pdev->dev.parent, NULL); 1723 if (!regmap) { 1724 dev_err(&pdev->dev, "Unable to get regmap\n"); 1725 return -EINVAL; 1726 } 1727 1728 wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL); 1729 if (!wled) 1730 return -ENOMEM; 1731 1732 wled->regmap = regmap; 1733 wled->dev = &pdev->dev; 1734 platform_set_drvdata(pdev, wled); 1735 1736 wled->version = (uintptr_t)of_device_get_match_data(&pdev->dev); 1737 if (!wled->version) { 1738 dev_err(&pdev->dev, "Unknown device version\n"); 1739 return -ENODEV; 1740 } 1741 1742 mutex_init(&wled->lock); 1743 rc = wled_configure(wled); 1744 if (rc) 1745 return rc; 1746 1747 val = WLED3_SINK_REG_BRIGHT_MAX; 1748 of_property_read_u32(pdev->dev.of_node, "max-brightness", &val); 1749 wled->max_brightness = val; 1750 1751 switch (wled->version) { 1752 case 3: 1753 wled->cfg.auto_detection_enabled = false; 1754 rc = wled3_setup(wled); 1755 if (rc) { 1756 dev_err(&pdev->dev, "wled3_setup failed\n"); 1757 return rc; 1758 } 1759 break; 1760 1761 case 4: 1762 wled->has_short_detect = true; 1763 rc = wled4_setup(wled); 1764 if (rc) { 1765 dev_err(&pdev->dev, "wled4_setup failed\n"); 1766 return rc; 1767 } 1768 break; 1769 1770 case 5: 1771 wled->has_short_detect = true; 1772 if (wled->cfg.cabc_sel) 1773 wled->max_brightness = WLED5_SINK_REG_BRIGHT_MAX_12B; 1774 1775 rc = wled5_setup(wled); 1776 if (rc) { 1777 dev_err(&pdev->dev, "wled5_setup failed\n"); 1778 return rc; 1779 } 1780 break; 1781 1782 default: 1783 dev_err(wled->dev, "Invalid WLED version\n"); 1784 break; 1785 } 1786 1787 INIT_DELAYED_WORK(&wled->ovp_work, wled_ovp_work); 1788 1789 val = WLED_DEFAULT_BRIGHTNESS; 1790 of_property_read_u32(pdev->dev.of_node, "default-brightness", &val); 1791 1792 /* 1793 * The module may already be lit, either by the bootloader or by the 1794 * setup above. Start from what the hardware is driving, so that the 1795 * first brightness update does not step the brightness. 1796 */ 1797 rc = wled_read_brightness(wled); 1798 if (rc < 0) 1799 return rc; 1800 1801 wled->brightness = rc; 1802 1803 rc = wled_configure_short_irq(wled, pdev); 1804 if (rc < 0) 1805 return rc; 1806 1807 rc = wled_configure_ovp_irq(wled, pdev); 1808 if (rc < 0) 1809 return rc; 1810 1811 memset(&props, 0, sizeof(struct backlight_properties)); 1812 props.type = BACKLIGHT_RAW; 1813 props.brightness = wled->brightness ?: val; 1814 props.max_brightness = wled->max_brightness; 1815 bl = devm_backlight_device_register(&pdev->dev, wled->name, 1816 &pdev->dev, wled, 1817 &wled_ops, &props); 1818 return PTR_ERR_OR_ZERO(bl); 1819 }; 1820 1821 static void wled_remove(struct platform_device *pdev) 1822 { 1823 struct wled *wled = platform_get_drvdata(pdev); 1824 1825 mutex_destroy(&wled->lock); 1826 cancel_delayed_work_sync(&wled->ovp_work); 1827 disable_irq(wled->short_irq); 1828 disable_irq(wled->ovp_irq); 1829 } 1830 1831 static const struct of_device_id wled_match_table[] = { 1832 { .compatible = "qcom,pm8941-wled", .data = (void *)3 }, 1833 { .compatible = "qcom,pmi8950-wled", .data = (void *)4 }, 1834 { .compatible = "qcom,pmi8994-wled", .data = (void *)4 }, 1835 { .compatible = "qcom,pmi8998-wled", .data = (void *)4 }, 1836 { .compatible = "qcom,pm660l-wled", .data = (void *)4 }, 1837 { .compatible = "qcom,pm6150l-wled", .data = (void *)5 }, 1838 { .compatible = "qcom,pm8150l-wled", .data = (void *)5 }, 1839 {} 1840 }; 1841 MODULE_DEVICE_TABLE(of, wled_match_table); 1842 1843 static struct platform_driver wled_driver = { 1844 .probe = wled_probe, 1845 .remove = wled_remove, 1846 .driver = { 1847 .name = "qcom,wled", 1848 .of_match_table = wled_match_table, 1849 }, 1850 }; 1851 1852 module_platform_driver(wled_driver); 1853 1854 MODULE_DESCRIPTION("Qualcomm WLED driver"); 1855 MODULE_LICENSE("GPL v2"); 1856