11// SPDX-License-Identifier: GPL-2.0-only
22/*
3- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
3+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
44 */
55
66#include <linux/bitfield.h>
1414#include <media/v4l2-flash-led-class.h>
1515
1616/* registers definitions */
17+ #define FLASH_REVISION_REG 0x00
18+ #define FLASH_4CH_REVISION_V0P1 0x01
19+
1720#define FLASH_TYPE_REG 0x04
1821#define FLASH_TYPE_VAL 0x18
1922
7376
7477#define UA_PER_MA 1000
7578
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+
7689enum hw_type {
7790 QCOM_MVFLASH_3CH ,
7891 QCOM_MVFLASH_4CH ,
@@ -98,6 +111,9 @@ enum {
98111 REG_IRESOLUTION ,
99112 REG_CHAN_STROBE ,
100113 REG_CHAN_EN ,
114+ REG_THERM_THRSH1 ,
115+ REG_THERM_THRSH2 ,
116+ REG_THERM_THRSH3 ,
101117 REG_MAX_COUNT ,
102118};
103119
@@ -111,6 +127,9 @@ static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
111127 REG_FIELD (0x47 , 0 , 5 ), /* iresolution */
112128 REG_FIELD_ID (0x49 , 0 , 2 , 3 , 1 ), /* chan_strobe */
113129 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 */
114133};
115134
116135static struct reg_field mvflash_4ch_regs [REG_MAX_COUNT ] = {
@@ -123,16 +142,20 @@ static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
123142 REG_FIELD (0x49 , 0 , 3 ), /* iresolution */
124143 REG_FIELD_ID (0x4a , 0 , 6 , 4 , 1 ), /* chan_strobe */
125144 REG_FIELD (0x4e , 0 , 3 ), /* chan_en */
145+ REG_FIELD (0x7a , 0 , 2 ), /* therm_thrsh1 */
146+ REG_FIELD (0x78 , 0 , 2 ), /* therm_thrsh2 */
126147};
127148
128149struct qcom_flash_data {
129150 struct v4l2_flash * * v4l2_flash ;
130151 struct regmap_field * r_fields [REG_MAX_COUNT ];
131152 struct mutex lock ;
132153 enum hw_type hw_type ;
154+ u32 total_ma ;
133155 u8 leds_count ;
134156 u8 max_channels ;
135157 u8 chan_en_bits ;
158+ u8 revision ;
136159};
137160
138161struct qcom_flash_led {
@@ -143,6 +166,7 @@ struct qcom_flash_led {
143166 u32 max_timeout_ms ;
144167 u32 flash_current_ma ;
145168 u32 flash_timeout_ms ;
169+ u32 current_in_use_ma ;
146170 u8 * chan_id ;
147171 u8 chan_count ;
148172 bool enabled ;
@@ -172,6 +196,127 @@ static int set_flash_module_en(struct qcom_flash_led *led, bool en)
172196 return rc ;
173197}
174198
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+
175320static int set_flash_current (struct qcom_flash_led * led , u32 current_ma , enum led_mode mode )
176321{
177322 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
313458 if (rc )
314459 return rc ;
315460
461+ rc = update_allowed_flash_current (led , & led -> flash_current_ma , state );
462+ if (rc < 0 )
463+ return rc ;
464+
316465 rc = set_flash_current (led , led -> flash_current_ma , FLASH_MODE );
317466 if (rc )
318467 return rc ;
@@ -429,6 +578,10 @@ static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev,
429578 if (rc )
430579 return rc ;
431580
581+ rc = update_allowed_flash_current (led , & current_ma , enable );
582+ if (rc < 0 )
583+ return rc ;
584+
432585 rc = set_flash_current (led , current_ma , TORCH_MODE );
433586 if (rc )
434587 return rc ;
@@ -707,6 +860,14 @@ static int qcom_flash_led_probe(struct platform_device *pdev)
707860 flash_data -> hw_type = QCOM_MVFLASH_4CH ;
708861 flash_data -> max_channels = 4 ;
709862 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 ;
710871 } else {
711872 dev_err (dev , "flash LED subtype %#x is not yet supported\n" , val );
712873 return - ENODEV ;
0 commit comments