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_device.h> 13 #include <linux/of_address.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) 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 u8 v[2]; 235 236 v[0] = brightness & 0xff; 237 v[1] = (brightness >> 8) & 0xf; 238 239 for (i = 0; i < wled->cfg.num_strings; ++i) { 240 rc = regmap_bulk_write(wled->regmap, wled->ctrl_addr + 241 WLED3_SINK_REG_BRIGHT(i), v, 2); 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 u8 v[2]; 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[0] = brightness & 0xff; 260 v[1] = (brightness >> 8) & 0xf; 261 262 for (i = 0; i < wled->cfg.num_strings; ++i) { 263 rc = regmap_bulk_write(wled->regmap, wled->sink_addr + 264 WLED4_SINK_REG_BRIGHT(i), v, 2); 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 u8 v[2]; 277 278 /* WLED5's lower limit is 0.1% */ 279 if (brightness < low_limit) 280 brightness = low_limit; 281 282 v[0] = brightness & 0xff; 283 v[1] = (brightness >> 8) & 0x7f; 284 285 offset = (wled->cfg.mod_sel == MOD_A) ? 286 WLED5_SINK_REG_MOD_A_BRIGHTNESS_LSB : 287 WLED5_SINK_REG_MOD_B_BRIGHTNESS_LSB; 288 289 rc = regmap_bulk_write(wled->regmap, wled->sink_addr + offset, 290 v, 2); 291 return rc; 292 } 293 294 static void wled_ovp_work(struct work_struct *work) 295 { 296 struct wled *wled = container_of(work, 297 struct wled, ovp_work.work); 298 enable_irq(wled->ovp_irq); 299 } 300 301 static int wled_module_enable(struct wled *wled, int val) 302 { 303 int rc; 304 305 if (wled->disabled_by_short) 306 return -ENXIO; 307 308 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 309 WLED3_CTRL_REG_MOD_EN, 310 WLED3_CTRL_REG_MOD_EN_MASK, 311 val << WLED3_CTRL_REG_MOD_EN_SHIFT); 312 if (rc < 0) 313 return rc; 314 315 if (wled->ovp_irq > 0) { 316 if (val) { 317 /* 318 * The hardware generates a storm of spurious OVP 319 * interrupts during soft start operations. So defer 320 * enabling the IRQ for 10ms to ensure that the 321 * soft start is complete. 322 */ 323 schedule_delayed_work(&wled->ovp_work, HZ / 100); 324 } else { 325 if (!cancel_delayed_work_sync(&wled->ovp_work)) 326 disable_irq(wled->ovp_irq); 327 } 328 } 329 330 return 0; 331 } 332 333 static int wled3_sync_toggle(struct wled *wled) 334 { 335 int rc; 336 unsigned int mask = GENMASK(wled->max_string_count - 1, 0); 337 338 rc = regmap_update_bits(wled->regmap, 339 wled->ctrl_addr + WLED3_SINK_REG_SYNC, 340 mask, mask); 341 if (rc < 0) 342 return rc; 343 344 rc = regmap_update_bits(wled->regmap, 345 wled->ctrl_addr + WLED3_SINK_REG_SYNC, 346 mask, WLED3_SINK_REG_SYNC_CLEAR); 347 348 return rc; 349 } 350 351 static int wled5_sync_toggle(struct wled *wled) 352 { 353 int rc; 354 u8 val; 355 356 val = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_REG_SYNC_MOD_A_BIT : 357 WLED5_SINK_REG_SYNC_MOD_B_BIT; 358 rc = regmap_update_bits(wled->regmap, 359 wled->sink_addr + WLED5_SINK_REG_MOD_SYNC_BIT, 360 WLED5_SINK_REG_SYNC_MASK, val); 361 if (rc < 0) 362 return rc; 363 364 return regmap_update_bits(wled->regmap, 365 wled->sink_addr + WLED5_SINK_REG_MOD_SYNC_BIT, 366 WLED5_SINK_REG_SYNC_MASK, 0); 367 } 368 369 static int wled_ovp_fault_status(struct wled *wled, bool *fault_set) 370 { 371 int rc; 372 u32 int_rt_sts, fault_sts; 373 374 *fault_set = false; 375 rc = regmap_read(wled->regmap, 376 wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, 377 &int_rt_sts); 378 if (rc < 0) { 379 dev_err(wled->dev, "Failed to read INT_RT_STS rc=%d\n", rc); 380 return rc; 381 } 382 383 rc = regmap_read(wled->regmap, 384 wled->ctrl_addr + WLED3_CTRL_REG_FAULT_STATUS, 385 &fault_sts); 386 if (rc < 0) { 387 dev_err(wled->dev, "Failed to read FAULT_STATUS rc=%d\n", rc); 388 return rc; 389 } 390 391 if (int_rt_sts & WLED3_CTRL_REG_OVP_FAULT_STATUS) 392 *fault_set = true; 393 394 if (wled->version == 4 && (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT)) 395 *fault_set = true; 396 397 if (wled->version == 5 && (fault_sts & (WLED3_CTRL_REG_OVP_FAULT_BIT | 398 WLED5_CTRL_REG_OVP_PRE_ALARM_BIT))) 399 *fault_set = true; 400 401 if (*fault_set) 402 dev_dbg(wled->dev, "WLED OVP fault detected, int_rt_sts=0x%x fault_sts=0x%x\n", 403 int_rt_sts, fault_sts); 404 405 return rc; 406 } 407 408 static int wled4_ovp_delay(struct wled *wled) 409 { 410 return WLED_SOFT_START_DLY_US; 411 } 412 413 static int wled5_ovp_delay(struct wled *wled) 414 { 415 int rc, delay_us; 416 u32 val; 417 u8 ovp_timer_ms[8] = {1, 2, 4, 8, 12, 16, 20, 24}; 418 419 /* For WLED5, get the delay based on OVP timer */ 420 rc = regmap_read(wled->regmap, wled->ctrl_addr + 421 WLED5_CTRL_REG_OVP_INT_CTL, &val); 422 if (rc < 0) 423 delay_us = 424 ovp_timer_ms[val & WLED5_CTRL_REG_OVP_INT_TIMER_MASK] * 1000; 425 else 426 delay_us = 2 * WLED_SOFT_START_DLY_US; 427 428 dev_dbg(wled->dev, "delay_time_us: %d\n", delay_us); 429 430 return delay_us; 431 } 432 433 static int wled_update_status(struct backlight_device *bl) 434 { 435 struct wled *wled = bl_get_data(bl); 436 u16 brightness = backlight_get_brightness(bl); 437 int rc = 0; 438 439 mutex_lock(&wled->lock); 440 if (brightness) { 441 rc = wled->wled_set_brightness(wled, brightness); 442 if (rc < 0) { 443 dev_err(wled->dev, "wled failed to set brightness rc:%d\n", 444 rc); 445 goto unlock_mutex; 446 } 447 448 rc = wled->wled_sync_toggle(wled); 449 if (rc < 0) { 450 dev_err(wled->dev, "wled sync failed rc:%d\n", rc); 451 goto unlock_mutex; 452 } 453 } 454 455 if (!!brightness != !!wled->brightness) { 456 rc = wled_module_enable(wled, !!brightness); 457 if (rc < 0) { 458 dev_err(wled->dev, "wled enable failed rc:%d\n", rc); 459 goto unlock_mutex; 460 } 461 } 462 463 wled->brightness = brightness; 464 465 unlock_mutex: 466 mutex_unlock(&wled->lock); 467 468 return rc; 469 } 470 471 static int wled4_cabc_config(struct wled *wled, bool enable) 472 { 473 int i, j, rc; 474 u8 val; 475 476 for (i = 0; i < wled->cfg.num_strings; i++) { 477 j = wled->cfg.enabled_strings[i]; 478 479 val = enable ? WLED4_SINK_REG_STR_CABC_MASK : 0; 480 rc = regmap_update_bits(wled->regmap, wled->sink_addr + 481 WLED4_SINK_REG_STR_CABC(j), 482 WLED4_SINK_REG_STR_CABC_MASK, val); 483 if (rc < 0) 484 return rc; 485 } 486 487 return 0; 488 } 489 490 static int wled5_cabc_config(struct wled *wled, bool enable) 491 { 492 int rc, offset; 493 u8 reg; 494 495 if (wled->cabc_disabled) 496 return 0; 497 498 reg = enable ? wled->cfg.cabc_sel : 0; 499 offset = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_REG_MOD_A_SRC_SEL : 500 WLED5_SINK_REG_MOD_B_SRC_SEL; 501 502 rc = regmap_update_bits(wled->regmap, wled->sink_addr + offset, 503 WLED5_SINK_REG_MOD_SRC_SEL_MASK, reg); 504 if (rc < 0) { 505 pr_err("Error in configuring CABC rc=%d\n", rc); 506 return rc; 507 } 508 509 if (!wled->cfg.cabc_sel) 510 wled->cabc_disabled = true; 511 512 return 0; 513 } 514 515 #define WLED_SHORT_DLY_MS 20 516 #define WLED_SHORT_CNT_MAX 5 517 #define WLED_SHORT_RESET_CNT_DLY_US USEC_PER_SEC 518 519 static irqreturn_t wled_short_irq_handler(int irq, void *_wled) 520 { 521 struct wled *wled = _wled; 522 int rc; 523 s64 elapsed_time; 524 525 wled->short_count++; 526 mutex_lock(&wled->lock); 527 rc = wled_module_enable(wled, false); 528 if (rc < 0) { 529 dev_err(wled->dev, "wled disable failed rc:%d\n", rc); 530 goto unlock_mutex; 531 } 532 533 elapsed_time = ktime_us_delta(ktime_get(), 534 wled->last_short_event); 535 if (elapsed_time > WLED_SHORT_RESET_CNT_DLY_US) 536 wled->short_count = 1; 537 538 if (wled->short_count > WLED_SHORT_CNT_MAX) { 539 dev_err(wled->dev, "Short triggered %d times, disabling WLED forever!\n", 540 wled->short_count); 541 wled->disabled_by_short = true; 542 goto unlock_mutex; 543 } 544 545 wled->last_short_event = ktime_get(); 546 547 msleep(WLED_SHORT_DLY_MS); 548 rc = wled_module_enable(wled, true); 549 if (rc < 0) 550 dev_err(wled->dev, "wled enable failed rc:%d\n", rc); 551 552 unlock_mutex: 553 mutex_unlock(&wled->lock); 554 555 return IRQ_HANDLED; 556 } 557 558 #define AUTO_DETECT_BRIGHTNESS 200 559 560 static void wled_auto_string_detection(struct wled *wled) 561 { 562 int rc = 0, i, delay_time_us; 563 u32 sink_config = 0; 564 u8 sink_test = 0, sink_valid = 0, val; 565 bool fault_set; 566 567 /* Read configured sink configuration */ 568 rc = regmap_read(wled->regmap, wled->sink_addr + 569 WLED4_SINK_REG_CURR_SINK, &sink_config); 570 if (rc < 0) { 571 dev_err(wled->dev, "Failed to read SINK configuration rc=%d\n", 572 rc); 573 goto failed_detect; 574 } 575 576 /* Disable the module before starting detection */ 577 rc = regmap_update_bits(wled->regmap, 578 wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, 579 WLED3_CTRL_REG_MOD_EN_MASK, 0); 580 if (rc < 0) { 581 dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", rc); 582 goto failed_detect; 583 } 584 585 /* Set low brightness across all sinks */ 586 rc = wled4_set_brightness(wled, AUTO_DETECT_BRIGHTNESS); 587 if (rc < 0) { 588 dev_err(wled->dev, "Failed to set brightness for auto detection rc=%d\n", 589 rc); 590 goto failed_detect; 591 } 592 593 if (wled->cfg.cabc) { 594 rc = wled->wled_cabc_config(wled, false); 595 if (rc < 0) 596 goto failed_detect; 597 } 598 599 /* Disable all sinks */ 600 rc = regmap_write(wled->regmap, 601 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 0); 602 if (rc < 0) { 603 dev_err(wled->dev, "Failed to disable all sinks rc=%d\n", rc); 604 goto failed_detect; 605 } 606 607 /* Iterate through the strings one by one */ 608 for (i = 0; i < wled->cfg.num_strings; i++) { 609 sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + i)); 610 611 /* Enable feedback control */ 612 rc = regmap_write(wled->regmap, wled->ctrl_addr + 613 WLED3_CTRL_REG_FEEDBACK_CONTROL, i + 1); 614 if (rc < 0) { 615 dev_err(wled->dev, "Failed to enable feedback for SINK %d rc = %d\n", 616 i + 1, rc); 617 goto failed_detect; 618 } 619 620 /* Enable the sink */ 621 rc = regmap_write(wled->regmap, wled->sink_addr + 622 WLED4_SINK_REG_CURR_SINK, sink_test); 623 if (rc < 0) { 624 dev_err(wled->dev, "Failed to configure SINK %d rc=%d\n", 625 i + 1, rc); 626 goto failed_detect; 627 } 628 629 /* Enable the module */ 630 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 631 WLED3_CTRL_REG_MOD_EN, 632 WLED3_CTRL_REG_MOD_EN_MASK, 633 WLED3_CTRL_REG_MOD_EN_MASK); 634 if (rc < 0) { 635 dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", 636 rc); 637 goto failed_detect; 638 } 639 640 delay_time_us = wled->wled_ovp_delay(wled); 641 usleep_range(delay_time_us, delay_time_us + 1000); 642 643 rc = wled_ovp_fault_status(wled, &fault_set); 644 if (rc < 0) { 645 dev_err(wled->dev, "Error in getting OVP fault_sts, rc=%d\n", 646 rc); 647 goto failed_detect; 648 } 649 650 if (fault_set) 651 dev_dbg(wled->dev, "WLED OVP fault detected with SINK %d\n", 652 i + 1); 653 else 654 sink_valid |= sink_test; 655 656 /* Disable the module */ 657 rc = regmap_update_bits(wled->regmap, 658 wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, 659 WLED3_CTRL_REG_MOD_EN_MASK, 0); 660 if (rc < 0) { 661 dev_err(wled->dev, "Failed to disable WLED module rc=%d\n", 662 rc); 663 goto failed_detect; 664 } 665 } 666 667 if (!sink_valid) { 668 dev_err(wled->dev, "No valid WLED sinks found\n"); 669 wled->disabled_by_short = true; 670 goto failed_detect; 671 } 672 673 if (sink_valid != sink_config) { 674 dev_warn(wled->dev, "%x is not a valid sink configuration - using %x instead\n", 675 sink_config, sink_valid); 676 sink_config = sink_valid; 677 } 678 679 /* Write the new sink configuration */ 680 rc = regmap_write(wled->regmap, 681 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 682 sink_config); 683 if (rc < 0) { 684 dev_err(wled->dev, "Failed to reconfigure the default sink rc=%d\n", 685 rc); 686 goto failed_detect; 687 } 688 689 /* Enable valid sinks */ 690 if (wled->version == 4) { 691 for (i = 0; i < wled->cfg.num_strings; i++) { 692 if (sink_config & 693 BIT(WLED4_SINK_REG_CURR_SINK_SHFT + i)) 694 val = WLED4_SINK_REG_STR_MOD_MASK; 695 else 696 /* Disable modulator_en for unused sink */ 697 val = 0; 698 699 rc = regmap_write(wled->regmap, wled->sink_addr + 700 WLED4_SINK_REG_STR_MOD_EN(i), val); 701 if (rc < 0) { 702 dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n", 703 rc); 704 goto failed_detect; 705 } 706 } 707 } 708 709 /* Enable CABC */ 710 rc = wled->wled_cabc_config(wled, true); 711 if (rc < 0) 712 goto failed_detect; 713 714 /* Restore the feedback setting */ 715 rc = regmap_write(wled->regmap, 716 wled->ctrl_addr + WLED3_CTRL_REG_FEEDBACK_CONTROL, 0); 717 if (rc < 0) { 718 dev_err(wled->dev, "Failed to restore feedback setting rc=%d\n", 719 rc); 720 goto failed_detect; 721 } 722 723 /* Restore brightness */ 724 rc = wled4_set_brightness(wled, wled->brightness); 725 if (rc < 0) { 726 dev_err(wled->dev, "Failed to set brightness after auto detection rc=%d\n", 727 rc); 728 goto failed_detect; 729 } 730 731 rc = regmap_update_bits(wled->regmap, 732 wled->ctrl_addr + WLED3_CTRL_REG_MOD_EN, 733 WLED3_CTRL_REG_MOD_EN_MASK, 734 WLED3_CTRL_REG_MOD_EN_MASK); 735 if (rc < 0) { 736 dev_err(wled->dev, "Failed to enable WLED module rc=%d\n", rc); 737 goto failed_detect; 738 } 739 740 failed_detect: 741 return; 742 } 743 744 #define WLED_AUTO_DETECT_OVP_COUNT 5 745 #define WLED_AUTO_DETECT_CNT_DLY_US USEC_PER_SEC 746 747 static bool wled4_auto_detection_required(struct wled *wled) 748 { 749 s64 elapsed_time_us; 750 751 if (!wled->cfg.auto_detection_enabled) 752 return false; 753 754 /* 755 * Check if the OVP fault was an occasional one 756 * or if it's firing continuously, the latter qualifies 757 * for an auto-detection check. 758 */ 759 if (!wled->auto_detection_ovp_count) { 760 wled->start_ovp_fault_time = ktime_get(); 761 wled->auto_detection_ovp_count++; 762 } else { 763 elapsed_time_us = ktime_us_delta(ktime_get(), 764 wled->start_ovp_fault_time); 765 if (elapsed_time_us > WLED_AUTO_DETECT_CNT_DLY_US) 766 wled->auto_detection_ovp_count = 0; 767 else 768 wled->auto_detection_ovp_count++; 769 770 if (wled->auto_detection_ovp_count >= 771 WLED_AUTO_DETECT_OVP_COUNT) { 772 wled->auto_detection_ovp_count = 0; 773 return true; 774 } 775 } 776 777 return false; 778 } 779 780 static bool wled5_auto_detection_required(struct wled *wled) 781 { 782 if (!wled->cfg.auto_detection_enabled) 783 return false; 784 785 /* 786 * Unlike WLED4, WLED5 has OVP fault density interrupt configuration 787 * i.e. to count the number of OVP alarms for a certain duration before 788 * triggering OVP fault interrupt. By default, number of OVP fault 789 * events counted before an interrupt is fired is 32 and the time 790 * interval is 12 ms. If we see one OVP fault interrupt, then that 791 * should qualify for a real OVP fault condition to run auto detection 792 * algorithm. 793 */ 794 return true; 795 } 796 797 static int wled_auto_detection_at_init(struct wled *wled) 798 { 799 int rc; 800 bool fault_set; 801 802 if (!wled->cfg.auto_detection_enabled) 803 return 0; 804 805 rc = wled_ovp_fault_status(wled, &fault_set); 806 if (rc < 0) { 807 dev_err(wled->dev, "Error in getting OVP fault_sts, rc=%d\n", 808 rc); 809 return rc; 810 } 811 812 if (fault_set) { 813 mutex_lock(&wled->lock); 814 wled_auto_string_detection(wled); 815 mutex_unlock(&wled->lock); 816 } 817 818 return rc; 819 } 820 821 static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled) 822 { 823 struct wled *wled = _wled; 824 int rc; 825 u32 int_sts, fault_sts; 826 827 rc = regmap_read(wled->regmap, 828 wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS, &int_sts); 829 if (rc < 0) { 830 dev_err(wled->dev, "Error in reading WLED3_INT_RT_STS rc=%d\n", 831 rc); 832 return IRQ_HANDLED; 833 } 834 835 rc = regmap_read(wled->regmap, wled->ctrl_addr + 836 WLED3_CTRL_REG_FAULT_STATUS, &fault_sts); 837 if (rc < 0) { 838 dev_err(wled->dev, "Error in reading WLED_FAULT_STATUS rc=%d\n", 839 rc); 840 return IRQ_HANDLED; 841 } 842 843 if (fault_sts & (WLED3_CTRL_REG_OVP_FAULT_BIT | 844 WLED3_CTRL_REG_ILIM_FAULT_BIT)) 845 dev_dbg(wled->dev, "WLED OVP fault detected, int_sts=%x fault_sts= %x\n", 846 int_sts, fault_sts); 847 848 if (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT) { 849 if (wled->wled_auto_detection_required(wled)) { 850 mutex_lock(&wled->lock); 851 wled_auto_string_detection(wled); 852 mutex_unlock(&wled->lock); 853 } 854 } 855 856 return IRQ_HANDLED; 857 } 858 859 static int wled3_setup(struct wled *wled) 860 { 861 u16 addr; 862 u8 sink_en = 0; 863 int rc, i, j; 864 865 rc = regmap_update_bits(wled->regmap, 866 wled->ctrl_addr + WLED3_CTRL_REG_OVP, 867 WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); 868 if (rc) 869 return rc; 870 871 rc = regmap_update_bits(wled->regmap, 872 wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, 873 WLED3_CTRL_REG_ILIMIT_MASK, 874 wled->cfg.boost_i_limit); 875 if (rc) 876 return rc; 877 878 rc = regmap_update_bits(wled->regmap, 879 wled->ctrl_addr + WLED3_CTRL_REG_FREQ, 880 WLED3_CTRL_REG_FREQ_MASK, 881 wled->cfg.switch_freq); 882 if (rc) 883 return rc; 884 885 for (i = 0; i < wled->cfg.num_strings; ++i) { 886 j = wled->cfg.enabled_strings[i]; 887 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_EN(j); 888 rc = regmap_update_bits(wled->regmap, addr, 889 WLED3_SINK_REG_STR_MOD_MASK, 890 WLED3_SINK_REG_STR_MOD_MASK); 891 if (rc) 892 return rc; 893 894 if (wled->cfg.ext_gen) { 895 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_SRC(j); 896 rc = regmap_update_bits(wled->regmap, addr, 897 WLED3_SINK_REG_STR_MOD_SRC_MASK, 898 WLED3_SINK_REG_STR_MOD_SRC_EXT); 899 if (rc) 900 return rc; 901 } 902 903 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_FULL_SCALE_CURR(j); 904 rc = regmap_update_bits(wled->regmap, addr, 905 WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK, 906 wled->cfg.string_i_limit); 907 if (rc) 908 return rc; 909 910 addr = wled->ctrl_addr + WLED3_SINK_REG_STR_CABC(j); 911 rc = regmap_update_bits(wled->regmap, addr, 912 WLED3_SINK_REG_STR_CABC_MASK, 913 wled->cfg.cabc ? 914 WLED3_SINK_REG_STR_CABC_MASK : 0); 915 if (rc) 916 return rc; 917 918 sink_en |= BIT(j + WLED3_SINK_REG_CURR_SINK_SHFT); 919 } 920 921 rc = regmap_update_bits(wled->regmap, 922 wled->ctrl_addr + WLED3_SINK_REG_CURR_SINK, 923 WLED3_SINK_REG_CURR_SINK_MASK, sink_en); 924 if (rc) 925 return rc; 926 927 return 0; 928 } 929 930 static const struct wled_config wled3_config_defaults = { 931 .boost_i_limit = 3, 932 .string_i_limit = 20, 933 .ovp = 2, 934 .num_strings = 3, 935 .switch_freq = 5, 936 .cs_out_en = false, 937 .ext_gen = false, 938 .cabc = false, 939 .enabled_strings = {0, 1, 2, 3}, 940 }; 941 942 static int wled4_setup(struct wled *wled) 943 { 944 int rc, temp, i, j; 945 u16 addr; 946 u8 sink_en = 0; 947 u32 sink_cfg; 948 949 rc = regmap_update_bits(wled->regmap, 950 wled->ctrl_addr + WLED3_CTRL_REG_OVP, 951 WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); 952 if (rc < 0) 953 return rc; 954 955 rc = regmap_update_bits(wled->regmap, 956 wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, 957 WLED3_CTRL_REG_ILIMIT_MASK, 958 wled->cfg.boost_i_limit); 959 if (rc < 0) 960 return rc; 961 962 rc = regmap_update_bits(wled->regmap, 963 wled->ctrl_addr + WLED3_CTRL_REG_FREQ, 964 WLED3_CTRL_REG_FREQ_MASK, 965 wled->cfg.switch_freq); 966 if (rc < 0) 967 return rc; 968 969 if (wled->cfg.external_pfet) { 970 /* Unlock the secure register access */ 971 rc = regmap_write(wled->regmap, wled->ctrl_addr + 972 WLED4_CTRL_REG_SEC_ACCESS, 973 WLED4_CTRL_REG_SEC_UNLOCK); 974 if (rc < 0) 975 return rc; 976 977 rc = regmap_write(wled->regmap, 978 wled->ctrl_addr + WLED4_CTRL_REG_TEST1, 979 WLED4_CTRL_REG_TEST1_EXT_FET_DTEST2); 980 if (rc < 0) 981 return rc; 982 } 983 984 rc = regmap_read(wled->regmap, wled->sink_addr + 985 WLED4_SINK_REG_CURR_SINK, &sink_cfg); 986 if (rc < 0) 987 return rc; 988 989 for (i = 0; i < wled->cfg.num_strings; i++) { 990 j = wled->cfg.enabled_strings[i]; 991 temp = j + WLED4_SINK_REG_CURR_SINK_SHFT; 992 sink_en |= 1 << temp; 993 } 994 995 if (sink_cfg == sink_en) { 996 rc = wled_auto_detection_at_init(wled); 997 return rc; 998 } 999 1000 rc = regmap_update_bits(wled->regmap, 1001 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 1002 WLED4_SINK_REG_CURR_SINK_MASK, 0); 1003 if (rc < 0) 1004 return rc; 1005 1006 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 1007 WLED3_CTRL_REG_MOD_EN, 1008 WLED3_CTRL_REG_MOD_EN_MASK, 0); 1009 if (rc < 0) 1010 return rc; 1011 1012 /* Per sink/string configuration */ 1013 for (i = 0; i < wled->cfg.num_strings; i++) { 1014 j = wled->cfg.enabled_strings[i]; 1015 1016 addr = wled->sink_addr + 1017 WLED4_SINK_REG_STR_MOD_EN(j); 1018 rc = regmap_update_bits(wled->regmap, addr, 1019 WLED4_SINK_REG_STR_MOD_MASK, 1020 WLED4_SINK_REG_STR_MOD_MASK); 1021 if (rc < 0) 1022 return rc; 1023 1024 addr = wled->sink_addr + 1025 WLED4_SINK_REG_STR_FULL_SCALE_CURR(j); 1026 rc = regmap_update_bits(wled->regmap, addr, 1027 WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK, 1028 wled->cfg.string_i_limit); 1029 if (rc < 0) 1030 return rc; 1031 } 1032 1033 rc = wled4_cabc_config(wled, wled->cfg.cabc); 1034 if (rc < 0) 1035 return rc; 1036 1037 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 1038 WLED3_CTRL_REG_MOD_EN, 1039 WLED3_CTRL_REG_MOD_EN_MASK, 1040 WLED3_CTRL_REG_MOD_EN_MASK); 1041 if (rc < 0) 1042 return rc; 1043 1044 rc = regmap_update_bits(wled->regmap, 1045 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 1046 WLED4_SINK_REG_CURR_SINK_MASK, sink_en); 1047 if (rc < 0) 1048 return rc; 1049 1050 rc = wled->wled_sync_toggle(wled); 1051 if (rc < 0) { 1052 dev_err(wled->dev, "Failed to toggle sync reg rc:%d\n", rc); 1053 return rc; 1054 } 1055 1056 rc = wled_auto_detection_at_init(wled); 1057 1058 return rc; 1059 } 1060 1061 static const struct wled_config wled4_config_defaults = { 1062 .boost_i_limit = 4, 1063 .string_i_limit = 10, 1064 .ovp = 1, 1065 .num_strings = 4, 1066 .switch_freq = 11, 1067 .cabc = false, 1068 .external_pfet = false, 1069 .auto_detection_enabled = false, 1070 }; 1071 1072 static int wled5_setup(struct wled *wled) 1073 { 1074 int rc, temp, i, j, offset; 1075 u8 sink_en = 0; 1076 u16 addr; 1077 u32 val; 1078 1079 rc = regmap_update_bits(wled->regmap, 1080 wled->ctrl_addr + WLED3_CTRL_REG_OVP, 1081 WLED5_CTRL_REG_OVP_MASK, wled->cfg.ovp); 1082 if (rc < 0) 1083 return rc; 1084 1085 rc = regmap_update_bits(wled->regmap, 1086 wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, 1087 WLED3_CTRL_REG_ILIMIT_MASK, 1088 wled->cfg.boost_i_limit); 1089 if (rc < 0) 1090 return rc; 1091 1092 rc = regmap_update_bits(wled->regmap, 1093 wled->ctrl_addr + WLED3_CTRL_REG_FREQ, 1094 WLED3_CTRL_REG_FREQ_MASK, 1095 wled->cfg.switch_freq); 1096 if (rc < 0) 1097 return rc; 1098 1099 /* Per sink/string configuration */ 1100 for (i = 0; i < wled->cfg.num_strings; ++i) { 1101 j = wled->cfg.enabled_strings[i]; 1102 addr = wled->sink_addr + 1103 WLED4_SINK_REG_STR_FULL_SCALE_CURR(j); 1104 rc = regmap_update_bits(wled->regmap, addr, 1105 WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK, 1106 wled->cfg.string_i_limit); 1107 if (rc < 0) 1108 return rc; 1109 1110 addr = wled->sink_addr + WLED5_SINK_REG_STR_SRC_SEL(j); 1111 rc = regmap_update_bits(wled->regmap, addr, 1112 WLED5_SINK_REG_SRC_SEL_MASK, 1113 wled->cfg.mod_sel == MOD_A ? 1114 WLED5_SINK_REG_SRC_SEL_MOD_A : 1115 WLED5_SINK_REG_SRC_SEL_MOD_B); 1116 1117 temp = j + WLED4_SINK_REG_CURR_SINK_SHFT; 1118 sink_en |= 1 << temp; 1119 } 1120 1121 rc = wled5_cabc_config(wled, wled->cfg.cabc_sel ? true : false); 1122 if (rc < 0) 1123 return rc; 1124 1125 /* Enable one of the modulators A or B based on mod_sel */ 1126 addr = wled->sink_addr + WLED5_SINK_REG_MOD_A_EN; 1127 val = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_REG_MOD_EN_MASK : 0; 1128 rc = regmap_update_bits(wled->regmap, addr, 1129 WLED5_SINK_REG_MOD_EN_MASK, val); 1130 if (rc < 0) 1131 return rc; 1132 1133 addr = wled->sink_addr + WLED5_SINK_REG_MOD_B_EN; 1134 val = (wled->cfg.mod_sel == MOD_B) ? WLED5_SINK_REG_MOD_EN_MASK : 0; 1135 rc = regmap_update_bits(wled->regmap, addr, 1136 WLED5_SINK_REG_MOD_EN_MASK, val); 1137 if (rc < 0) 1138 return rc; 1139 1140 offset = (wled->cfg.mod_sel == MOD_A) ? 1141 WLED5_SINK_REG_MOD_A_BRIGHTNESS_WIDTH_SEL : 1142 WLED5_SINK_REG_MOD_B_BRIGHTNESS_WIDTH_SEL; 1143 1144 addr = wled->sink_addr + offset; 1145 val = (wled->max_brightness == WLED5_SINK_REG_BRIGHT_MAX_15B) ? 1146 WLED5_SINK_REG_BRIGHTNESS_WIDTH_15B : 1147 WLED5_SINK_REG_BRIGHTNESS_WIDTH_12B; 1148 rc = regmap_write(wled->regmap, addr, val); 1149 if (rc < 0) 1150 return rc; 1151 1152 rc = regmap_update_bits(wled->regmap, 1153 wled->sink_addr + WLED4_SINK_REG_CURR_SINK, 1154 WLED4_SINK_REG_CURR_SINK_MASK, sink_en); 1155 if (rc < 0) 1156 return rc; 1157 1158 /* This updates only FSC configuration in WLED5 */ 1159 rc = wled->wled_sync_toggle(wled); 1160 if (rc < 0) { 1161 pr_err("Failed to toggle sync reg rc:%d\n", rc); 1162 return rc; 1163 } 1164 1165 rc = wled_auto_detection_at_init(wled); 1166 if (rc < 0) 1167 return rc; 1168 1169 return 0; 1170 } 1171 1172 static const struct wled_config wled5_config_defaults = { 1173 .boost_i_limit = 5, 1174 .string_i_limit = 10, 1175 .ovp = 4, 1176 .num_strings = 4, 1177 .switch_freq = 11, 1178 .mod_sel = 0, 1179 .cabc_sel = 0, 1180 .cabc = false, 1181 .external_pfet = false, 1182 .auto_detection_enabled = false, 1183 }; 1184 1185 static const u32 wled3_boost_i_limit_values[] = { 1186 105, 385, 525, 805, 980, 1260, 1400, 1680, 1187 }; 1188 1189 static const struct wled_var_cfg wled3_boost_i_limit_cfg = { 1190 .values = wled3_boost_i_limit_values, 1191 .size = ARRAY_SIZE(wled3_boost_i_limit_values), 1192 }; 1193 1194 static const u32 wled4_boost_i_limit_values[] = { 1195 105, 280, 450, 620, 970, 1150, 1300, 1500, 1196 }; 1197 1198 static const struct wled_var_cfg wled4_boost_i_limit_cfg = { 1199 .values = wled4_boost_i_limit_values, 1200 .size = ARRAY_SIZE(wled4_boost_i_limit_values), 1201 }; 1202 1203 static inline u32 wled5_boost_i_limit_values_fn(u32 idx) 1204 { 1205 return 525 + (idx * 175); 1206 } 1207 1208 static const struct wled_var_cfg wled5_boost_i_limit_cfg = { 1209 .fn = wled5_boost_i_limit_values_fn, 1210 .size = 8, 1211 }; 1212 1213 static const u32 wled3_ovp_values[] = { 1214 35, 32, 29, 27, 1215 }; 1216 1217 static const struct wled_var_cfg wled3_ovp_cfg = { 1218 .values = wled3_ovp_values, 1219 .size = ARRAY_SIZE(wled3_ovp_values), 1220 }; 1221 1222 static const u32 wled4_ovp_values[] = { 1223 31100, 29600, 19600, 18100, 1224 }; 1225 1226 static const struct wled_var_cfg wled4_ovp_cfg = { 1227 .values = wled4_ovp_values, 1228 .size = ARRAY_SIZE(wled4_ovp_values), 1229 }; 1230 1231 static inline u32 wled5_ovp_values_fn(u32 idx) 1232 { 1233 /* 1234 * 0000 - 38.5 V 1235 * 0001 - 37 V .. 1236 * 1111 - 16 V 1237 */ 1238 return 38500 - (idx * 1500); 1239 } 1240 1241 static const struct wled_var_cfg wled5_ovp_cfg = { 1242 .fn = wled5_ovp_values_fn, 1243 .size = 16, 1244 }; 1245 1246 static u32 wled3_num_strings_values_fn(u32 idx) 1247 { 1248 return idx + 1; 1249 } 1250 1251 static const struct wled_var_cfg wled3_num_strings_cfg = { 1252 .fn = wled3_num_strings_values_fn, 1253 .size = 3, 1254 }; 1255 1256 static const struct wled_var_cfg wled4_num_strings_cfg = { 1257 .fn = wled3_num_strings_values_fn, 1258 .size = 4, 1259 }; 1260 1261 static u32 wled3_switch_freq_values_fn(u32 idx) 1262 { 1263 return 19200 / (2 * (1 + idx)); 1264 } 1265 1266 static const struct wled_var_cfg wled3_switch_freq_cfg = { 1267 .fn = wled3_switch_freq_values_fn, 1268 .size = 16, 1269 }; 1270 1271 static const struct wled_var_cfg wled3_string_i_limit_cfg = { 1272 .size = 26, 1273 }; 1274 1275 static const u32 wled4_string_i_limit_values[] = { 1276 0, 2500, 5000, 7500, 10000, 12500, 15000, 17500, 20000, 1277 22500, 25000, 27500, 30000, 1278 }; 1279 1280 static const struct wled_var_cfg wled4_string_i_limit_cfg = { 1281 .values = wled4_string_i_limit_values, 1282 .size = ARRAY_SIZE(wled4_string_i_limit_values), 1283 }; 1284 1285 static const struct wled_var_cfg wled5_mod_sel_cfg = { 1286 .size = 2, 1287 }; 1288 1289 static const struct wled_var_cfg wled5_cabc_sel_cfg = { 1290 .size = 4, 1291 }; 1292 1293 static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx) 1294 { 1295 if (idx >= cfg->size) 1296 return UINT_MAX; 1297 if (cfg->fn) 1298 return cfg->fn(idx); 1299 if (cfg->values) 1300 return cfg->values[idx]; 1301 return idx; 1302 } 1303 1304 static int wled_configure(struct wled *wled) 1305 { 1306 struct wled_config *cfg = &wled->cfg; 1307 struct device *dev = wled->dev; 1308 const __be32 *prop_addr; 1309 u32 size, val, c; 1310 int rc, i, j, string_len; 1311 1312 const struct wled_u32_opts *u32_opts = NULL; 1313 const struct wled_u32_opts wled3_opts[] = { 1314 { 1315 .name = "qcom,current-boost-limit", 1316 .val_ptr = &cfg->boost_i_limit, 1317 .cfg = &wled3_boost_i_limit_cfg, 1318 }, 1319 { 1320 .name = "qcom,current-limit", 1321 .val_ptr = &cfg->string_i_limit, 1322 .cfg = &wled3_string_i_limit_cfg, 1323 }, 1324 { 1325 .name = "qcom,ovp", 1326 .val_ptr = &cfg->ovp, 1327 .cfg = &wled3_ovp_cfg, 1328 }, 1329 { 1330 .name = "qcom,switching-freq", 1331 .val_ptr = &cfg->switch_freq, 1332 .cfg = &wled3_switch_freq_cfg, 1333 }, 1334 { 1335 .name = "qcom,num-strings", 1336 .val_ptr = &cfg->num_strings, 1337 .cfg = &wled3_num_strings_cfg, 1338 }, 1339 }; 1340 1341 const struct wled_u32_opts wled4_opts[] = { 1342 { 1343 .name = "qcom,current-boost-limit", 1344 .val_ptr = &cfg->boost_i_limit, 1345 .cfg = &wled4_boost_i_limit_cfg, 1346 }, 1347 { 1348 .name = "qcom,current-limit-microamp", 1349 .val_ptr = &cfg->string_i_limit, 1350 .cfg = &wled4_string_i_limit_cfg, 1351 }, 1352 { 1353 .name = "qcom,ovp-millivolt", 1354 .val_ptr = &cfg->ovp, 1355 .cfg = &wled4_ovp_cfg, 1356 }, 1357 { 1358 .name = "qcom,switching-freq", 1359 .val_ptr = &cfg->switch_freq, 1360 .cfg = &wled3_switch_freq_cfg, 1361 }, 1362 { 1363 .name = "qcom,num-strings", 1364 .val_ptr = &cfg->num_strings, 1365 .cfg = &wled4_num_strings_cfg, 1366 }, 1367 }; 1368 1369 const struct wled_u32_opts wled5_opts[] = { 1370 { 1371 .name = "qcom,current-boost-limit", 1372 .val_ptr = &cfg->boost_i_limit, 1373 .cfg = &wled5_boost_i_limit_cfg, 1374 }, 1375 { 1376 .name = "qcom,current-limit-microamp", 1377 .val_ptr = &cfg->string_i_limit, 1378 .cfg = &wled4_string_i_limit_cfg, 1379 }, 1380 { 1381 .name = "qcom,ovp-millivolt", 1382 .val_ptr = &cfg->ovp, 1383 .cfg = &wled5_ovp_cfg, 1384 }, 1385 { 1386 .name = "qcom,switching-freq", 1387 .val_ptr = &cfg->switch_freq, 1388 .cfg = &wled3_switch_freq_cfg, 1389 }, 1390 { 1391 .name = "qcom,num-strings", 1392 .val_ptr = &cfg->num_strings, 1393 .cfg = &wled4_num_strings_cfg, 1394 }, 1395 { 1396 .name = "qcom,modulator-sel", 1397 .val_ptr = &cfg->mod_sel, 1398 .cfg = &wled5_mod_sel_cfg, 1399 }, 1400 { 1401 .name = "qcom,cabc-sel", 1402 .val_ptr = &cfg->cabc_sel, 1403 .cfg = &wled5_cabc_sel_cfg, 1404 }, 1405 }; 1406 1407 const struct wled_bool_opts bool_opts[] = { 1408 { "qcom,cs-out", &cfg->cs_out_en, }, 1409 { "qcom,ext-gen", &cfg->ext_gen, }, 1410 { "qcom,cabc", &cfg->cabc, }, 1411 { "qcom,external-pfet", &cfg->external_pfet, }, 1412 { "qcom,auto-string-detection", &cfg->auto_detection_enabled, }, 1413 }; 1414 1415 prop_addr = of_get_address(dev->of_node, 0, NULL, NULL); 1416 if (!prop_addr) { 1417 dev_err(wled->dev, "invalid IO resources\n"); 1418 return -EINVAL; 1419 } 1420 wled->ctrl_addr = be32_to_cpu(*prop_addr); 1421 1422 rc = of_property_read_string(dev->of_node, "label", &wled->name); 1423 if (rc) 1424 wled->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); 1425 1426 switch (wled->version) { 1427 case 3: 1428 u32_opts = wled3_opts; 1429 size = ARRAY_SIZE(wled3_opts); 1430 *cfg = wled3_config_defaults; 1431 wled->wled_set_brightness = wled3_set_brightness; 1432 wled->wled_sync_toggle = wled3_sync_toggle; 1433 wled->max_string_count = 3; 1434 wled->sink_addr = wled->ctrl_addr; 1435 break; 1436 1437 case 4: 1438 u32_opts = wled4_opts; 1439 size = ARRAY_SIZE(wled4_opts); 1440 *cfg = wled4_config_defaults; 1441 wled->wled_set_brightness = wled4_set_brightness; 1442 wled->wled_sync_toggle = wled3_sync_toggle; 1443 wled->wled_cabc_config = wled4_cabc_config; 1444 wled->wled_ovp_delay = wled4_ovp_delay; 1445 wled->wled_auto_detection_required = 1446 wled4_auto_detection_required; 1447 wled->max_string_count = 4; 1448 1449 prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); 1450 if (!prop_addr) { 1451 dev_err(wled->dev, "invalid IO resources\n"); 1452 return -EINVAL; 1453 } 1454 wled->sink_addr = be32_to_cpu(*prop_addr); 1455 break; 1456 1457 case 5: 1458 u32_opts = wled5_opts; 1459 size = ARRAY_SIZE(wled5_opts); 1460 *cfg = wled5_config_defaults; 1461 wled->wled_set_brightness = wled5_set_brightness; 1462 wled->wled_sync_toggle = wled5_sync_toggle; 1463 wled->wled_cabc_config = wled5_cabc_config; 1464 wled->wled_ovp_delay = wled5_ovp_delay; 1465 wled->wled_auto_detection_required = 1466 wled5_auto_detection_required; 1467 wled->max_string_count = 4; 1468 1469 prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); 1470 if (!prop_addr) { 1471 dev_err(wled->dev, "invalid IO resources\n"); 1472 return -EINVAL; 1473 } 1474 wled->sink_addr = be32_to_cpu(*prop_addr); 1475 break; 1476 1477 default: 1478 dev_err(wled->dev, "Invalid WLED version\n"); 1479 return -EINVAL; 1480 } 1481 1482 for (i = 0; i < size; ++i) { 1483 rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val); 1484 if (rc == -EINVAL) { 1485 continue; 1486 } else if (rc) { 1487 dev_err(dev, "error reading '%s'\n", u32_opts[i].name); 1488 return rc; 1489 } 1490 1491 c = UINT_MAX; 1492 for (j = 0; c != val; j++) { 1493 c = wled_values(u32_opts[i].cfg, j); 1494 if (c == UINT_MAX) { 1495 dev_err(dev, "invalid value for '%s'\n", 1496 u32_opts[i].name); 1497 return -EINVAL; 1498 } 1499 1500 if (c == val) 1501 break; 1502 } 1503 1504 dev_dbg(dev, "'%s' = %u\n", u32_opts[i].name, c); 1505 *u32_opts[i].val_ptr = j; 1506 } 1507 1508 for (i = 0; i < ARRAY_SIZE(bool_opts); ++i) { 1509 if (of_property_read_bool(dev->of_node, bool_opts[i].name)) 1510 *bool_opts[i].val_ptr = true; 1511 } 1512 1513 cfg->num_strings = cfg->num_strings + 1; 1514 1515 string_len = of_property_count_elems_of_size(dev->of_node, 1516 "qcom,enabled-strings", 1517 sizeof(u32)); 1518 if (string_len > 0) 1519 of_property_read_u32_array(dev->of_node, 1520 "qcom,enabled-strings", 1521 wled->cfg.enabled_strings, 1522 sizeof(u32)); 1523 1524 return 0; 1525 } 1526 1527 static int wled_configure_short_irq(struct wled *wled, 1528 struct platform_device *pdev) 1529 { 1530 int rc; 1531 1532 if (!wled->has_short_detect) 1533 return 0; 1534 1535 rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + 1536 WLED4_CTRL_REG_SHORT_PROTECT, 1537 WLED4_CTRL_REG_SHORT_EN_MASK, 1538 WLED4_CTRL_REG_SHORT_EN_MASK); 1539 if (rc < 0) 1540 return rc; 1541 1542 wled->short_irq = platform_get_irq_byname(pdev, "short"); 1543 if (wled->short_irq < 0) { 1544 dev_dbg(&pdev->dev, "short irq is not used\n"); 1545 return 0; 1546 } 1547 1548 rc = devm_request_threaded_irq(wled->dev, wled->short_irq, 1549 NULL, wled_short_irq_handler, 1550 IRQF_ONESHOT, 1551 "wled_short_irq", wled); 1552 if (rc < 0) 1553 dev_err(wled->dev, "Unable to request short_irq (err:%d)\n", 1554 rc); 1555 1556 return rc; 1557 } 1558 1559 static int wled_configure_ovp_irq(struct wled *wled, 1560 struct platform_device *pdev) 1561 { 1562 int rc; 1563 u32 val; 1564 1565 wled->ovp_irq = platform_get_irq_byname(pdev, "ovp"); 1566 if (wled->ovp_irq < 0) { 1567 dev_dbg(&pdev->dev, "OVP IRQ not found - disabling automatic string detection\n"); 1568 return 0; 1569 } 1570 1571 rc = devm_request_threaded_irq(wled->dev, wled->ovp_irq, NULL, 1572 wled_ovp_irq_handler, IRQF_ONESHOT, 1573 "wled_ovp_irq", wled); 1574 if (rc < 0) { 1575 dev_err(wled->dev, "Unable to request ovp_irq (err:%d)\n", 1576 rc); 1577 wled->ovp_irq = 0; 1578 return 0; 1579 } 1580 1581 rc = regmap_read(wled->regmap, wled->ctrl_addr + 1582 WLED3_CTRL_REG_MOD_EN, &val); 1583 if (rc < 0) 1584 return rc; 1585 1586 /* Keep OVP irq disabled until module is enabled */ 1587 if (!(val & WLED3_CTRL_REG_MOD_EN_MASK)) 1588 disable_irq(wled->ovp_irq); 1589 1590 return 0; 1591 } 1592 1593 static const struct backlight_ops wled_ops = { 1594 .update_status = wled_update_status, 1595 }; 1596 1597 static int wled_probe(struct platform_device *pdev) 1598 { 1599 struct backlight_properties props; 1600 struct backlight_device *bl; 1601 struct wled *wled; 1602 struct regmap *regmap; 1603 u32 val; 1604 int rc; 1605 1606 regmap = dev_get_regmap(pdev->dev.parent, NULL); 1607 if (!regmap) { 1608 dev_err(&pdev->dev, "Unable to get regmap\n"); 1609 return -EINVAL; 1610 } 1611 1612 wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL); 1613 if (!wled) 1614 return -ENOMEM; 1615 1616 wled->regmap = regmap; 1617 wled->dev = &pdev->dev; 1618 1619 wled->version = (uintptr_t)of_device_get_match_data(&pdev->dev); 1620 if (!wled->version) { 1621 dev_err(&pdev->dev, "Unknown device version\n"); 1622 return -ENODEV; 1623 } 1624 1625 mutex_init(&wled->lock); 1626 rc = wled_configure(wled); 1627 if (rc) 1628 return rc; 1629 1630 val = WLED3_SINK_REG_BRIGHT_MAX; 1631 of_property_read_u32(pdev->dev.of_node, "max-brightness", &val); 1632 wled->max_brightness = val; 1633 1634 switch (wled->version) { 1635 case 3: 1636 wled->cfg.auto_detection_enabled = false; 1637 rc = wled3_setup(wled); 1638 if (rc) { 1639 dev_err(&pdev->dev, "wled3_setup failed\n"); 1640 return rc; 1641 } 1642 break; 1643 1644 case 4: 1645 wled->has_short_detect = true; 1646 rc = wled4_setup(wled); 1647 if (rc) { 1648 dev_err(&pdev->dev, "wled4_setup failed\n"); 1649 return rc; 1650 } 1651 break; 1652 1653 case 5: 1654 wled->has_short_detect = true; 1655 if (wled->cfg.cabc_sel) 1656 wled->max_brightness = WLED5_SINK_REG_BRIGHT_MAX_12B; 1657 1658 rc = wled5_setup(wled); 1659 if (rc) { 1660 dev_err(&pdev->dev, "wled5_setup failed\n"); 1661 return rc; 1662 } 1663 break; 1664 1665 default: 1666 dev_err(wled->dev, "Invalid WLED version\n"); 1667 break; 1668 } 1669 1670 INIT_DELAYED_WORK(&wled->ovp_work, wled_ovp_work); 1671 1672 rc = wled_configure_short_irq(wled, pdev); 1673 if (rc < 0) 1674 return rc; 1675 1676 rc = wled_configure_ovp_irq(wled, pdev); 1677 if (rc < 0) 1678 return rc; 1679 1680 val = WLED_DEFAULT_BRIGHTNESS; 1681 of_property_read_u32(pdev->dev.of_node, "default-brightness", &val); 1682 1683 memset(&props, 0, sizeof(struct backlight_properties)); 1684 props.type = BACKLIGHT_RAW; 1685 props.brightness = val; 1686 props.max_brightness = wled->max_brightness; 1687 bl = devm_backlight_device_register(&pdev->dev, wled->name, 1688 &pdev->dev, wled, 1689 &wled_ops, &props); 1690 return PTR_ERR_OR_ZERO(bl); 1691 }; 1692 1693 static int wled_remove(struct platform_device *pdev) 1694 { 1695 struct wled *wled = dev_get_drvdata(&pdev->dev); 1696 1697 mutex_destroy(&wled->lock); 1698 cancel_delayed_work_sync(&wled->ovp_work); 1699 disable_irq(wled->short_irq); 1700 disable_irq(wled->ovp_irq); 1701 1702 return 0; 1703 } 1704 1705 static const struct of_device_id wled_match_table[] = { 1706 { .compatible = "qcom,pm8941-wled", .data = (void *)3 }, 1707 { .compatible = "qcom,pmi8998-wled", .data = (void *)4 }, 1708 { .compatible = "qcom,pm660l-wled", .data = (void *)4 }, 1709 { .compatible = "qcom,pm8150l-wled", .data = (void *)5 }, 1710 {} 1711 }; 1712 MODULE_DEVICE_TABLE(of, wled_match_table); 1713 1714 static struct platform_driver wled_driver = { 1715 .probe = wled_probe, 1716 .remove = wled_remove, 1717 .driver = { 1718 .name = "qcom,wled", 1719 .of_match_table = wled_match_table, 1720 }, 1721 }; 1722 1723 module_platform_driver(wled_driver); 1724 1725 MODULE_DESCRIPTION("Qualcomm WLED driver"); 1726 MODULE_LICENSE("GPL v2"); 1727