1
1
// SPDX-License-Identifier: GPL-2.0-only
2
2
/*
3
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
3
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
4
4
*/
5
5
6
6
#include <linux/bitfield.h>
14
14
#include <media/v4l2-flash-led-class.h>
15
15
16
16
/* registers definitions */
17
+ #define FLASH_REVISION_REG 0x00
18
+ #define FLASH_4CH_REVISION_V0P1 0x01
19
+
17
20
#define FLASH_TYPE_REG 0x04
18
21
#define FLASH_TYPE_VAL 0x18
19
22
73
76
74
77
#define UA_PER_MA 1000
75
78
79
+ /* thermal threshold constants */
80
+ #define OTST_3CH_MIN_VAL 3
81
+ #define OTST1_4CH_MIN_VAL 0
82
+ #define OTST1_4CH_V0P1_MIN_VAL 3
83
+ #define OTST2_4CH_MIN_VAL 0
84
+
85
+ #define OTST1_MAX_CURRENT_MA 1000
86
+ #define OTST2_MAX_CURRENT_MA 500
87
+ #define OTST3_MAX_CURRENT_MA 200
88
+
76
89
enum hw_type {
77
90
QCOM_MVFLASH_3CH ,
78
91
QCOM_MVFLASH_4CH ,
@@ -98,6 +111,9 @@ enum {
98
111
REG_IRESOLUTION ,
99
112
REG_CHAN_STROBE ,
100
113
REG_CHAN_EN ,
114
+ REG_THERM_THRSH1 ,
115
+ REG_THERM_THRSH2 ,
116
+ REG_THERM_THRSH3 ,
101
117
REG_MAX_COUNT ,
102
118
};
103
119
@@ -111,6 +127,9 @@ static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
111
127
REG_FIELD (0x47 , 0 , 5 ), /* iresolution */
112
128
REG_FIELD_ID (0x49 , 0 , 2 , 3 , 1 ), /* chan_strobe */
113
129
REG_FIELD (0x4c , 0 , 2 ), /* chan_en */
130
+ REG_FIELD (0x56 , 0 , 2 ), /* therm_thrsh1 */
131
+ REG_FIELD (0x57 , 0 , 2 ), /* therm_thrsh2 */
132
+ REG_FIELD (0x58 , 0 , 2 ), /* therm_thrsh3 */
114
133
};
115
134
116
135
static struct reg_field mvflash_4ch_regs [REG_MAX_COUNT ] = {
@@ -123,16 +142,20 @@ static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
123
142
REG_FIELD (0x49 , 0 , 3 ), /* iresolution */
124
143
REG_FIELD_ID (0x4a , 0 , 6 , 4 , 1 ), /* chan_strobe */
125
144
REG_FIELD (0x4e , 0 , 3 ), /* chan_en */
145
+ REG_FIELD (0x7a , 0 , 2 ), /* therm_thrsh1 */
146
+ REG_FIELD (0x78 , 0 , 2 ), /* therm_thrsh2 */
126
147
};
127
148
128
149
struct qcom_flash_data {
129
150
struct v4l2_flash * * v4l2_flash ;
130
151
struct regmap_field * r_fields [REG_MAX_COUNT ];
131
152
struct mutex lock ;
132
153
enum hw_type hw_type ;
154
+ u32 total_ma ;
133
155
u8 leds_count ;
134
156
u8 max_channels ;
135
157
u8 chan_en_bits ;
158
+ u8 revision ;
136
159
};
137
160
138
161
struct qcom_flash_led {
@@ -143,6 +166,7 @@ struct qcom_flash_led {
143
166
u32 max_timeout_ms ;
144
167
u32 flash_current_ma ;
145
168
u32 flash_timeout_ms ;
169
+ u32 current_in_use_ma ;
146
170
u8 * chan_id ;
147
171
u8 chan_count ;
148
172
bool enabled ;
@@ -172,6 +196,127 @@ static int set_flash_module_en(struct qcom_flash_led *led, bool en)
172
196
return rc ;
173
197
}
174
198
199
+ static int update_allowed_flash_current (struct qcom_flash_led * led , u32 * current_ma , bool strobe )
200
+ {
201
+ struct qcom_flash_data * flash_data = led -> flash_data ;
202
+ u32 therm_ma , avail_ma , thrsh [3 ], min_thrsh , sts ;
203
+ int rc = 0 ;
204
+
205
+ mutex_lock (& flash_data -> lock );
206
+ /*
207
+ * Put previously allocated current into allowed budget in either of these two cases:
208
+ * 1) LED is disabled;
209
+ * 2) LED is enabled repeatedly
210
+ */
211
+ if (!strobe || led -> current_in_use_ma != 0 ) {
212
+ if (flash_data -> total_ma >= led -> current_in_use_ma )
213
+ flash_data -> total_ma -= led -> current_in_use_ma ;
214
+ else
215
+ flash_data -> total_ma = 0 ;
216
+
217
+ led -> current_in_use_ma = 0 ;
218
+ if (!strobe )
219
+ goto unlock ;
220
+ }
221
+
222
+ /*
223
+ * Cache the default thermal threshold settings, and set them to the lowest levels before
224
+ * reading over-temp real time status. If over-temp has been triggered at the lowest
225
+ * threshold, it's very likely that it would be triggered at a higher (default) threshold
226
+ * when more flash current is requested. Prevent device from triggering over-temp condition
227
+ * by limiting the flash current for the new request.
228
+ */
229
+ rc = regmap_field_read (flash_data -> r_fields [REG_THERM_THRSH1 ], & thrsh [0 ]);
230
+ if (rc < 0 )
231
+ goto unlock ;
232
+
233
+ rc = regmap_field_read (flash_data -> r_fields [REG_THERM_THRSH2 ], & thrsh [1 ]);
234
+ if (rc < 0 )
235
+ goto unlock ;
236
+
237
+ if (flash_data -> hw_type == QCOM_MVFLASH_3CH ) {
238
+ rc = regmap_field_read (flash_data -> r_fields [REG_THERM_THRSH3 ], & thrsh [2 ]);
239
+ if (rc < 0 )
240
+ goto unlock ;
241
+ }
242
+
243
+ min_thrsh = OTST_3CH_MIN_VAL ;
244
+ if (flash_data -> hw_type == QCOM_MVFLASH_4CH )
245
+ min_thrsh = (flash_data -> revision == FLASH_4CH_REVISION_V0P1 ) ?
246
+ OTST1_4CH_V0P1_MIN_VAL : OTST1_4CH_MIN_VAL ;
247
+
248
+ rc = regmap_field_write (flash_data -> r_fields [REG_THERM_THRSH1 ], min_thrsh );
249
+ if (rc < 0 )
250
+ goto unlock ;
251
+
252
+ if (flash_data -> hw_type == QCOM_MVFLASH_4CH )
253
+ min_thrsh = OTST2_4CH_MIN_VAL ;
254
+
255
+ /*
256
+ * The default thermal threshold settings have been updated hence
257
+ * restore them if any fault happens starting from here.
258
+ */
259
+ rc = regmap_field_write (flash_data -> r_fields [REG_THERM_THRSH2 ], min_thrsh );
260
+ if (rc < 0 )
261
+ goto restore ;
262
+
263
+ if (flash_data -> hw_type == QCOM_MVFLASH_3CH ) {
264
+ rc = regmap_field_write (flash_data -> r_fields [REG_THERM_THRSH3 ], min_thrsh );
265
+ if (rc < 0 )
266
+ goto restore ;
267
+ }
268
+
269
+ /* Read thermal level status to get corresponding derating flash current */
270
+ rc = regmap_field_read (flash_data -> r_fields [REG_STATUS2 ], & sts );
271
+ if (rc )
272
+ goto restore ;
273
+
274
+ therm_ma = FLASH_TOTAL_CURRENT_MAX_UA / 1000 ;
275
+ if (flash_data -> hw_type == QCOM_MVFLASH_3CH ) {
276
+ if (sts & FLASH_STS_3CH_OTST3 )
277
+ therm_ma = OTST3_MAX_CURRENT_MA ;
278
+ else if (sts & FLASH_STS_3CH_OTST2 )
279
+ therm_ma = OTST2_MAX_CURRENT_MA ;
280
+ else if (sts & FLASH_STS_3CH_OTST1 )
281
+ therm_ma = OTST1_MAX_CURRENT_MA ;
282
+ } else {
283
+ if (sts & FLASH_STS_4CH_OTST2 )
284
+ therm_ma = OTST2_MAX_CURRENT_MA ;
285
+ else if (sts & FLASH_STS_4CH_OTST1 )
286
+ therm_ma = OTST1_MAX_CURRENT_MA ;
287
+ }
288
+
289
+ /* Calculate the allowed flash current for the request */
290
+ if (therm_ma <= flash_data -> total_ma )
291
+ avail_ma = 0 ;
292
+ else
293
+ avail_ma = therm_ma - flash_data -> total_ma ;
294
+
295
+ * current_ma = min_t (u32 , * current_ma , avail_ma );
296
+ led -> current_in_use_ma = * current_ma ;
297
+ flash_data -> total_ma += led -> current_in_use_ma ;
298
+
299
+ dev_dbg (led -> flash .led_cdev .dev , "allowed flash current: %dmA, total current: %dmA\n" ,
300
+ led -> current_in_use_ma , flash_data -> total_ma );
301
+
302
+ restore :
303
+ /* Restore to default thermal threshold settings */
304
+ rc = regmap_field_write (flash_data -> r_fields [REG_THERM_THRSH1 ], thrsh [0 ]);
305
+ if (rc < 0 )
306
+ goto unlock ;
307
+
308
+ rc = regmap_field_write (flash_data -> r_fields [REG_THERM_THRSH2 ], thrsh [1 ]);
309
+ if (rc < 0 )
310
+ goto unlock ;
311
+
312
+ if (flash_data -> hw_type == QCOM_MVFLASH_3CH )
313
+ rc = regmap_field_write (flash_data -> r_fields [REG_THERM_THRSH3 ], thrsh [2 ]);
314
+
315
+ unlock :
316
+ mutex_unlock (& flash_data -> lock );
317
+ return rc ;
318
+ }
319
+
175
320
static int set_flash_current (struct qcom_flash_led * led , u32 current_ma , enum led_mode mode )
176
321
{
177
322
struct qcom_flash_data * flash_data = led -> flash_data ;
@@ -313,6 +458,10 @@ static int qcom_flash_strobe_set(struct led_classdev_flash *fled_cdev, bool stat
313
458
if (rc )
314
459
return rc ;
315
460
461
+ rc = update_allowed_flash_current (led , & led -> flash_current_ma , state );
462
+ if (rc < 0 )
463
+ return rc ;
464
+
316
465
rc = set_flash_current (led , led -> flash_current_ma , FLASH_MODE );
317
466
if (rc )
318
467
return rc ;
@@ -429,6 +578,10 @@ static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev,
429
578
if (rc )
430
579
return rc ;
431
580
581
+ rc = update_allowed_flash_current (led , & current_ma , enable );
582
+ if (rc < 0 )
583
+ return rc ;
584
+
432
585
rc = set_flash_current (led , current_ma , TORCH_MODE );
433
586
if (rc )
434
587
return rc ;
@@ -707,6 +860,14 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
707
860
flash_data -> hw_type = QCOM_MVFLASH_4CH ;
708
861
flash_data -> max_channels = 4 ;
709
862
regs = mvflash_4ch_regs ;
863
+
864
+ rc = regmap_read (regmap , reg_base + FLASH_REVISION_REG , & val );
865
+ if (rc < 0 ) {
866
+ dev_err (dev , "Failed to read flash LED module revision, rc=%d\n" , rc );
867
+ return rc ;
868
+ }
869
+
870
+ flash_data -> revision = val ;
710
871
} else {
711
872
dev_err (dev , "flash LED subtype %#x is not yet supported\n" , val );
712
873
return - ENODEV ;
0 commit comments