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