Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

leds: flash: leds-qcom-flash: Update torch current clamp setting

There is a register to clamp the flash current per LED channel when
safety timer is disabled. It needs to be updated according to the
maximum torch LED current setting to ensure the torch current won't
be clamped unexpectedly.

Fixes: 96a2e242a5dc ("leds: flash: Add driver to support flash LED module in QCOM PMICs")
Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250729-fix-torch-clamp-issue-v2-1-9b83816437a3@oss.qualcomm.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Fenglin Wu and committed by
Lee Jones
5974e8f6 6e3779e3

+36 -26
+36 -26
drivers/leds/flash/leds-qcom-flash.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved. 3 + * Copyright (c) 2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. 4 4 */ 5 5 6 6 #include <linux/bitfield.h> ··· 114 114 REG_THERM_THRSH1, 115 115 REG_THERM_THRSH2, 116 116 REG_THERM_THRSH3, 117 + REG_TORCH_CLAMP, 117 118 REG_MAX_COUNT, 118 119 }; 119 120 120 121 static const struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = { 121 - REG_FIELD(0x08, 0, 7), /* status1 */ 122 - REG_FIELD(0x09, 0, 7), /* status2 */ 123 - REG_FIELD(0x0a, 0, 7), /* status3 */ 124 - REG_FIELD_ID(0x40, 0, 7, 3, 1), /* chan_timer */ 125 - REG_FIELD_ID(0x43, 0, 6, 3, 1), /* itarget */ 126 - REG_FIELD(0x46, 7, 7), /* module_en */ 127 - REG_FIELD(0x47, 0, 5), /* iresolution */ 128 - REG_FIELD_ID(0x49, 0, 2, 3, 1), /* chan_strobe */ 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 */ 122 + [REG_STATUS1] = REG_FIELD(0x08, 0, 7), 123 + [REG_STATUS2] = REG_FIELD(0x09, 0, 7), 124 + [REG_STATUS3] = REG_FIELD(0x0a, 0, 7), 125 + [REG_CHAN_TIMER] = REG_FIELD_ID(0x40, 0, 7, 3, 1), 126 + [REG_ITARGET] = REG_FIELD_ID(0x43, 0, 6, 3, 1), 127 + [REG_MODULE_EN] = REG_FIELD(0x46, 7, 7), 128 + [REG_IRESOLUTION] = REG_FIELD(0x47, 0, 5), 129 + [REG_CHAN_STROBE] = REG_FIELD_ID(0x49, 0, 2, 3, 1), 130 + [REG_CHAN_EN] = REG_FIELD(0x4c, 0, 2), 131 + [REG_THERM_THRSH1] = REG_FIELD(0x56, 0, 2), 132 + [REG_THERM_THRSH2] = REG_FIELD(0x57, 0, 2), 133 + [REG_THERM_THRSH3] = REG_FIELD(0x58, 0, 2), 134 + [REG_TORCH_CLAMP] = REG_FIELD(0xec, 0, 6), 133 135 }; 134 136 135 137 static const struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = { 136 - REG_FIELD(0x06, 0, 7), /* status1 */ 137 - REG_FIELD(0x07, 0, 6), /* status2 */ 138 - REG_FIELD(0x09, 0, 7), /* status3 */ 139 - REG_FIELD_ID(0x3e, 0, 7, 4, 1), /* chan_timer */ 140 - REG_FIELD_ID(0x42, 0, 6, 4, 1), /* itarget */ 141 - REG_FIELD(0x46, 7, 7), /* module_en */ 142 - REG_FIELD(0x49, 0, 3), /* iresolution */ 143 - REG_FIELD_ID(0x4a, 0, 6, 4, 1), /* chan_strobe */ 144 - REG_FIELD(0x4e, 0, 3), /* chan_en */ 145 - REG_FIELD(0x7a, 0, 2), /* therm_thrsh1 */ 146 - REG_FIELD(0x78, 0, 2), /* therm_thrsh2 */ 138 + [REG_STATUS1] = REG_FIELD(0x06, 0, 7), 139 + [REG_STATUS2] = REG_FIELD(0x07, 0, 6), 140 + [REG_STATUS3] = REG_FIELD(0x09, 0, 7), 141 + [REG_CHAN_TIMER] = REG_FIELD_ID(0x3e, 0, 7, 4, 1), 142 + [REG_ITARGET] = REG_FIELD_ID(0x42, 0, 6, 4, 1), 143 + [REG_MODULE_EN] = REG_FIELD(0x46, 7, 7), 144 + [REG_IRESOLUTION] = REG_FIELD(0x49, 0, 3), 145 + [REG_CHAN_STROBE] = REG_FIELD_ID(0x4a, 0, 6, 4, 1), 146 + [REG_CHAN_EN] = REG_FIELD(0x4e, 0, 3), 147 + [REG_THERM_THRSH1] = REG_FIELD(0x7a, 0, 2), 148 + [REG_THERM_THRSH2] = REG_FIELD(0x78, 0, 2), 149 + [REG_TORCH_CLAMP] = REG_FIELD(0xed, 0, 6), 147 150 }; 148 151 149 152 struct qcom_flash_data { ··· 159 156 u8 max_channels; 160 157 u8 chan_en_bits; 161 158 u8 revision; 159 + u8 torch_clamp; 162 160 }; 163 161 164 162 struct qcom_flash_led { ··· 706 702 u32 current_ua, timeout_us; 707 703 u32 channels[4]; 708 704 int i, rc, count; 705 + u8 torch_clamp; 709 706 710 707 count = fwnode_property_count_u32(node, "led-sources"); 711 708 if (count <= 0) { ··· 755 750 756 751 current_ua = min_t(u32, current_ua, TORCH_CURRENT_MAX_UA * led->chan_count); 757 752 led->max_torch_current_ma = current_ua / UA_PER_MA; 753 + 754 + torch_clamp = (current_ua / led->chan_count) / TORCH_IRES_UA; 755 + if (torch_clamp != 0) 756 + torch_clamp--; 757 + 758 + flash_data->torch_clamp = max_t(u8, flash_data->torch_clamp, torch_clamp); 758 759 759 760 if (fwnode_property_present(node, "flash-max-microamp")) { 760 761 flash->led_cdev.flags |= LED_DEV_CAP_FLASH; ··· 928 917 flash_data->leds_count++; 929 918 } 930 919 931 - return 0; 932 - 920 + return regmap_field_write(flash_data->r_fields[REG_TORCH_CLAMP], flash_data->torch_clamp); 933 921 release: 934 922 while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count) 935 923 v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]);