brintos

brintos / linux-shallow public Read only

0
0
Text · 26.1 KiB · 41ce034 Raw
952 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.4 */5 6#include <linux/bitfield.h>7#include <linux/bits.h>8#include <linux/leds.h>9#include <linux/led-class-flash.h>10#include <linux/module.h>11#include <linux/platform_device.h>12#include <linux/property.h>13#include <linux/regmap.h>14#include <media/v4l2-flash-led-class.h>15 16/* registers definitions */17#define FLASH_REVISION_REG		0x0018#define FLASH_4CH_REVISION_V0P1		0x0119 20#define FLASH_TYPE_REG			0x0421#define FLASH_TYPE_VAL			0x1822 23#define FLASH_SUBTYPE_REG		0x0524#define FLASH_SUBTYPE_3CH_PM8150_VAL	0x0425#define FLASH_SUBTYPE_3CH_PMI8998_VAL	0x0326#define FLASH_SUBTYPE_4CH_VAL		0x0727 28#define FLASH_STS_3CH_OTST1		BIT(0)29#define FLASH_STS_3CH_OTST2		BIT(1)30#define FLASH_STS_3CH_OTST3		BIT(2)31#define FLASH_STS_3CH_BOB_THM_OVERLOAD	BIT(3)32#define FLASH_STS_3CH_VPH_DROOP		BIT(4)33#define FLASH_STS_3CH_BOB_ILIM_S1	BIT(5)34#define FLASH_STS_3CH_BOB_ILIM_S2	BIT(6)35#define FLASH_STS_3CH_BCL_IBAT		BIT(7)36 37#define FLASH_STS_4CH_VPH_LOW		BIT(0)38#define FLASH_STS_4CH_BCL_IBAT		BIT(1)39#define FLASH_STS_4CH_BOB_ILIM_S1	BIT(2)40#define FLASH_STS_4CH_BOB_ILIM_S2	BIT(3)41#define FLASH_STS_4CH_OTST2		BIT(4)42#define FLASH_STS_4CH_OTST1		BIT(5)43#define FLASH_STS_4CHG_BOB_THM_OVERLOAD	BIT(6)44 45#define FLASH_TIMER_EN_BIT		BIT(7)46#define FLASH_TIMER_VAL_MASK		GENMASK(6, 0)47#define FLASH_TIMER_STEP_MS		1048 49#define FLASH_STROBE_HW_SW_SEL_BIT	BIT(2)50#define SW_STROBE_VAL			051#define HW_STROBE_VAL			152#define FLASH_HW_STROBE_TRIGGER_SEL_BIT	BIT(1)53#define STROBE_LEVEL_TRIGGER_VAL	054#define STROBE_EDGE_TRIGGER_VAL		155#define FLASH_STROBE_POLARITY_BIT	BIT(0)56#define STROBE_ACTIVE_HIGH_VAL		157 58#define FLASH_IRES_MASK_4CH		BIT(0)59#define FLASH_IRES_MASK_3CH		GENMASK(1, 0)60#define FLASH_IRES_12P5MA_VAL		061#define FLASH_IRES_5MA_VAL_4CH		162#define FLASH_IRES_5MA_VAL_3CH		363 64/* constants */65#define FLASH_CURRENT_MAX_UA		150000066#define TORCH_CURRENT_MAX_UA		50000067#define FLASH_TOTAL_CURRENT_MAX_UA	200000068#define FLASH_CURRENT_DEFAULT_UA	100000069#define TORCH_CURRENT_DEFAULT_UA	20000070 71#define TORCH_IRES_UA			500072#define FLASH_IRES_UA			1250073 74#define FLASH_TIMEOUT_MAX_US		128000075#define FLASH_TIMEOUT_STEP_US		1000076 77#define UA_PER_MA			100078 79/* thermal threshold constants */80#define OTST_3CH_MIN_VAL		381#define OTST1_4CH_MIN_VAL		082#define OTST1_4CH_V0P1_MIN_VAL		383#define OTST2_4CH_MIN_VAL		084 85#define OTST1_MAX_CURRENT_MA		100086#define OTST2_MAX_CURRENT_MA		50087#define OTST3_MAX_CURRENT_MA		20088 89enum hw_type {90	QCOM_MVFLASH_3CH,91	QCOM_MVFLASH_4CH,92};93 94enum led_mode {95	FLASH_MODE,96	TORCH_MODE,97};98 99enum led_strobe {100	SW_STROBE,101	HW_STROBE,102};103 104enum {105	REG_STATUS1,106	REG_STATUS2,107	REG_STATUS3,108	REG_CHAN_TIMER,109	REG_ITARGET,110	REG_MODULE_EN,111	REG_IRESOLUTION,112	REG_CHAN_STROBE,113	REG_CHAN_EN,114	REG_THERM_THRSH1,115	REG_THERM_THRSH2,116	REG_THERM_THRSH3,117	REG_MAX_COUNT,118};119 120static 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 */133};134 135static 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 */147};148 149struct qcom_flash_data {150	struct v4l2_flash	**v4l2_flash;151	struct regmap_field     *r_fields[REG_MAX_COUNT];152	struct mutex		lock;153	enum hw_type		hw_type;154	u32			total_ma;155	u8			leds_count;156	u8			max_channels;157	u8			chan_en_bits;158	u8			revision;159};160 161struct qcom_flash_led {162	struct qcom_flash_data		*flash_data;163	struct led_classdev_flash	flash;164	u32				max_flash_current_ma;165	u32				max_torch_current_ma;166	u32				max_timeout_ms;167	u32				flash_current_ma;168	u32				flash_timeout_ms;169	u32				current_in_use_ma;170	u8				*chan_id;171	u8				chan_count;172	bool				enabled;173};174 175static int set_flash_module_en(struct qcom_flash_led *led, bool en)176{177	struct qcom_flash_data *flash_data = led->flash_data;178	u8 led_mask = 0, enable;179	int i, rc;180 181	for (i = 0; i < led->chan_count; i++)182		led_mask |= BIT(led->chan_id[i]);183 184	mutex_lock(&flash_data->lock);185	if (en)186		flash_data->chan_en_bits |= led_mask;187	else188		flash_data->chan_en_bits &= ~led_mask;189 190	enable = !!flash_data->chan_en_bits;191	rc = regmap_field_write(flash_data->r_fields[REG_MODULE_EN], enable);192	if (rc)193		dev_err(led->flash.led_cdev.dev, "write module_en failed, rc=%d\n", rc);194	mutex_unlock(&flash_data->lock);195 196	return rc;197}198 199static 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 repeatedly210	 */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		else215			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 before224	 * reading over-temp real time status. If over-temp has been triggered at the lowest225	 * threshold, it's very likely that it would be triggered at a higher (default) threshold226	 * when more flash current is requested. Prevent device from triggering over-temp condition227	 * 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 hence257	 * 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	else293		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 302restore: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 315unlock:316	mutex_unlock(&flash_data->lock);317	return rc;318}319 320static int set_flash_current(struct qcom_flash_led *led, u32 current_ma, enum led_mode mode)321{322	struct qcom_flash_data *flash_data = led->flash_data;323	u32 itarg_ua, ires_ua;324	u8 shift, ires_mask = 0, ires_val = 0, chan_id;325	int i, rc;326 327	/*328	 * Split the current across the channels and set the329	 * IRESOLUTION and ITARGET registers accordingly.330	 */331	itarg_ua = (current_ma * UA_PER_MA) / led->chan_count + 1;332	ires_ua = (mode == FLASH_MODE) ? FLASH_IRES_UA : TORCH_IRES_UA;333 334	for (i = 0; i < led->chan_count; i++) {335		u8 itarget = 0;336 337		if (itarg_ua > ires_ua)338			itarget = itarg_ua / ires_ua - 1;339 340		chan_id = led->chan_id[i];341 342		rc = regmap_fields_write(flash_data->r_fields[REG_ITARGET], chan_id, itarget);343		if (rc)344			return rc;345 346		if (flash_data->hw_type == QCOM_MVFLASH_3CH) {347			shift = chan_id * 2;348			ires_mask |= FLASH_IRES_MASK_3CH << shift;349			ires_val |= ((mode == FLASH_MODE) ?350				(FLASH_IRES_12P5MA_VAL << shift) :351				(FLASH_IRES_5MA_VAL_3CH << shift));352		} else if (flash_data->hw_type == QCOM_MVFLASH_4CH) {353			shift = chan_id;354			ires_mask |= FLASH_IRES_MASK_4CH << shift;355			ires_val |= ((mode == FLASH_MODE) ?356				(FLASH_IRES_12P5MA_VAL << shift) :357				(FLASH_IRES_5MA_VAL_4CH << shift));358		} else {359			dev_err(led->flash.led_cdev.dev,360					"HW type %d is not supported\n", flash_data->hw_type);361			return -EOPNOTSUPP;362		}363	}364 365	return regmap_field_update_bits(flash_data->r_fields[REG_IRESOLUTION], ires_mask, ires_val);366}367 368static int set_flash_timeout(struct qcom_flash_led *led, u32 timeout_ms)369{370	struct qcom_flash_data *flash_data = led->flash_data;371	u8 timer, chan_id;372	int rc, i;373 374	/* set SAFETY_TIMER for all the channels connected to the same LED */375	timeout_ms = min_t(u32, timeout_ms, led->max_timeout_ms);376 377	for (i = 0; i < led->chan_count; i++) {378		chan_id = led->chan_id[i];379 380		timer = timeout_ms / FLASH_TIMER_STEP_MS;381		timer = clamp_t(u8, timer, 0, FLASH_TIMER_VAL_MASK);382 383		if (timeout_ms)384			timer |= FLASH_TIMER_EN_BIT;385 386		rc = regmap_fields_write(flash_data->r_fields[REG_CHAN_TIMER], chan_id, timer);387		if (rc)388			return rc;389	}390 391	return 0;392}393 394static int set_flash_strobe(struct qcom_flash_led *led, enum led_strobe strobe, bool state)395{396	struct qcom_flash_data *flash_data = led->flash_data;397	u8 strobe_sel, chan_en, chan_id, chan_mask = 0;398	int rc, i;399 400	/* Set SW strobe config for all channels connected to the LED */401	for (i = 0; i < led->chan_count; i++) {402		chan_id = led->chan_id[i];403 404		if (strobe == SW_STROBE)405			strobe_sel = FIELD_PREP(FLASH_STROBE_HW_SW_SEL_BIT, SW_STROBE_VAL);406		else407			strobe_sel = FIELD_PREP(FLASH_STROBE_HW_SW_SEL_BIT, HW_STROBE_VAL);408 409		strobe_sel |=410			FIELD_PREP(FLASH_HW_STROBE_TRIGGER_SEL_BIT, STROBE_LEVEL_TRIGGER_VAL) |411			FIELD_PREP(FLASH_STROBE_POLARITY_BIT, STROBE_ACTIVE_HIGH_VAL);412 413		rc = regmap_fields_write(414				flash_data->r_fields[REG_CHAN_STROBE], chan_id, strobe_sel);415		if (rc)416			return rc;417 418		chan_mask |= BIT(chan_id);419	}420 421	/* Enable/disable flash channels */422	chan_en = state ? chan_mask : 0;423	rc = regmap_field_update_bits(flash_data->r_fields[REG_CHAN_EN], chan_mask, chan_en);424	if (rc)425		return rc;426 427	led->enabled = state;428	return 0;429}430 431static inline struct qcom_flash_led *flcdev_to_qcom_fled(struct led_classdev_flash *flcdev)432{433	return container_of(flcdev, struct qcom_flash_led, flash);434}435 436static int qcom_flash_brightness_set(struct led_classdev_flash *fled_cdev, u32 brightness)437{438	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);439 440	led->flash_current_ma = min_t(u32, led->max_flash_current_ma, brightness / UA_PER_MA);441	return 0;442}443 444static int qcom_flash_timeout_set(struct led_classdev_flash *fled_cdev, u32 timeout)445{446	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);447 448	led->flash_timeout_ms = timeout / USEC_PER_MSEC;449	return 0;450}451 452static int qcom_flash_strobe_set(struct led_classdev_flash *fled_cdev, bool state)453{454	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);455	int rc;456 457	rc = set_flash_strobe(led, SW_STROBE, false);458	if (rc)459		return rc;460 461	rc = update_allowed_flash_current(led, &led->flash_current_ma, state);462	if (rc < 0)463		return rc;464 465	rc = set_flash_current(led, led->flash_current_ma, FLASH_MODE);466	if (rc)467		return rc;468 469	rc = set_flash_timeout(led, led->flash_timeout_ms);470	if (rc)471		return rc;472 473	rc = set_flash_module_en(led, state);474	if (rc)475		return rc;476 477	return set_flash_strobe(led, SW_STROBE, state);478}479 480static int qcom_flash_strobe_get(struct led_classdev_flash *fled_cdev, bool *state)481{482	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);483 484	*state = led->enabled;485	return 0;486}487 488static int qcom_flash_fault_get(struct led_classdev_flash *fled_cdev, u32 *fault)489{490	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);491	struct qcom_flash_data *flash_data = led->flash_data;492	u8 shift, chan_id, chan_mask = 0;493	u8 ot_mask = 0, oc_mask = 0, uv_mask = 0;494	u32 val, fault_sts = 0;495	int i, rc;496 497	rc = regmap_field_read(flash_data->r_fields[REG_STATUS1], &val);498	if (rc)499		return rc;500 501	for (i = 0; i < led->chan_count; i++) {502		chan_id = led->chan_id[i];503		shift = chan_id * 2;504 505		if (val & BIT(shift))506			fault_sts |= LED_FAULT_SHORT_CIRCUIT;507 508		chan_mask |= BIT(chan_id);509	}510 511	rc = regmap_field_read(flash_data->r_fields[REG_STATUS2], &val);512	if (rc)513		return rc;514 515	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {516		ot_mask = FLASH_STS_3CH_OTST1 |517			  FLASH_STS_3CH_OTST2 |518			  FLASH_STS_3CH_OTST3 |519			  FLASH_STS_3CH_BOB_THM_OVERLOAD;520		oc_mask = FLASH_STS_3CH_BOB_ILIM_S1 |521			  FLASH_STS_3CH_BOB_ILIM_S2 |522			  FLASH_STS_3CH_BCL_IBAT;523		uv_mask = FLASH_STS_3CH_VPH_DROOP;524	} else if (flash_data->hw_type == QCOM_MVFLASH_4CH) {525		ot_mask = FLASH_STS_4CH_OTST2 |526			  FLASH_STS_4CH_OTST1 |527			  FLASH_STS_4CHG_BOB_THM_OVERLOAD;528		oc_mask = FLASH_STS_4CH_BCL_IBAT |529			  FLASH_STS_4CH_BOB_ILIM_S1 |530			  FLASH_STS_4CH_BOB_ILIM_S2;531		uv_mask = FLASH_STS_4CH_VPH_LOW;532	}533 534	if (val & ot_mask)535		fault_sts |= LED_FAULT_OVER_TEMPERATURE;536 537	if (val & oc_mask)538		fault_sts |= LED_FAULT_OVER_CURRENT;539 540	if (val & uv_mask)541		fault_sts |= LED_FAULT_INPUT_VOLTAGE;542 543	rc = regmap_field_read(flash_data->r_fields[REG_STATUS3], &val);544	if (rc)545		return rc;546 547	if (flash_data->hw_type == QCOM_MVFLASH_3CH) {548		if (val & chan_mask)549			fault_sts |= LED_FAULT_TIMEOUT;550	} else if (flash_data->hw_type == QCOM_MVFLASH_4CH) {551		for (i = 0; i < led->chan_count; i++) {552			chan_id = led->chan_id[i];553			shift = chan_id * 2;554 555			if (val & BIT(shift))556				fault_sts |= LED_FAULT_TIMEOUT;557		}558	}559 560	*fault = fault_sts;561	return 0;562}563 564static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev,565					enum led_brightness brightness)566{567	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);568	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);569	u32 current_ma = brightness * led->max_torch_current_ma / LED_FULL;570	bool enable = !!brightness;571	int rc;572 573	rc = set_flash_strobe(led, SW_STROBE, false);574	if (rc)575		return rc;576 577	rc = set_flash_module_en(led, false);578	if (rc)579		return rc;580 581	rc = update_allowed_flash_current(led, &current_ma, enable);582	if (rc < 0)583		return rc;584 585	rc = set_flash_current(led, current_ma, TORCH_MODE);586	if (rc)587		return rc;588 589	/* Disable flash timeout for torch LED */590	rc = set_flash_timeout(led, 0);591	if (rc)592		return rc;593 594	rc = set_flash_module_en(led, enable);595	if (rc)596		return rc;597 598	return set_flash_strobe(led, SW_STROBE, enable);599}600 601static const struct led_flash_ops qcom_flash_ops = {602	.flash_brightness_set = qcom_flash_brightness_set,603	.strobe_set = qcom_flash_strobe_set,604	.strobe_get = qcom_flash_strobe_get,605	.timeout_set = qcom_flash_timeout_set,606	.fault_get = qcom_flash_fault_get,607};608 609#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)610static int qcom_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, bool enable)611{612	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;613	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);614	int rc;615 616	rc = set_flash_module_en(led, enable);617	if (rc)618		return rc;619 620	if (enable)621		return set_flash_strobe(led, HW_STROBE, true);622	else623		return set_flash_strobe(led, SW_STROBE, false);624}625 626static enum led_brightness627qcom_flash_intensity_to_led_brightness(struct v4l2_flash *v4l2_flash, s32 intensity)628{629	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;630	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);631	u32 current_ma = intensity / UA_PER_MA;632 633	current_ma = min_t(u32, current_ma, led->max_torch_current_ma);634	if (!current_ma)635		return LED_OFF;636 637	return (current_ma * LED_FULL) / led->max_torch_current_ma;638}639 640static s32 qcom_flash_brightness_to_led_intensity(struct v4l2_flash *v4l2_flash,641					enum led_brightness brightness)642{643	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;644	struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);645 646	return (brightness * led->max_torch_current_ma * UA_PER_MA) / LED_FULL;647}648 649static const struct v4l2_flash_ops qcom_v4l2_flash_ops = {650	.external_strobe_set = qcom_flash_external_strobe_set,651	.intensity_to_led_brightness = qcom_flash_intensity_to_led_brightness,652	.led_brightness_to_intensity = qcom_flash_brightness_to_led_intensity,653};654 655static int656qcom_flash_v4l2_init(struct device *dev, struct qcom_flash_led *led, struct fwnode_handle *fwnode)657{658	struct qcom_flash_data *flash_data = led->flash_data;659	struct v4l2_flash_config v4l2_cfg = { 0 };660	struct led_flash_setting *intensity = &v4l2_cfg.intensity;661	struct v4l2_flash *v4l2_flash;662 663	if (!(led->flash.led_cdev.flags & LED_DEV_CAP_FLASH))664		return 0;665 666	intensity->min = intensity->step = TORCH_IRES_UA * led->chan_count;667	intensity->max = led->max_torch_current_ma * UA_PER_MA;668	intensity->val = min_t(u32, intensity->max, TORCH_CURRENT_DEFAULT_UA);669 670	strscpy(v4l2_cfg.dev_name, led->flash.led_cdev.dev->kobj.name,671					sizeof(v4l2_cfg.dev_name));672 673	v4l2_cfg.has_external_strobe = true;674	v4l2_cfg.flash_faults = LED_FAULT_INPUT_VOLTAGE |675				LED_FAULT_OVER_CURRENT |676				LED_FAULT_SHORT_CIRCUIT |677				LED_FAULT_OVER_TEMPERATURE |678				LED_FAULT_TIMEOUT;679 680	v4l2_flash = v4l2_flash_init(dev, fwnode, &led->flash, &qcom_v4l2_flash_ops, &v4l2_cfg);681	if (IS_ERR(v4l2_flash))682		return PTR_ERR(v4l2_flash);683 684	flash_data->v4l2_flash[flash_data->leds_count] = v4l2_flash;685	return 0;686}687# else688static int689qcom_flash_v4l2_init(struct device *dev, struct qcom_flash_led *led, struct fwnode_handle *fwnode)690{691	return 0;692}693#endif694 695static int qcom_flash_register_led_device(struct device *dev,696		struct fwnode_handle *node, struct qcom_flash_led *led)697{698	struct qcom_flash_data *flash_data = led->flash_data;699	struct led_init_data init_data;700	struct led_classdev_flash *flash = &led->flash;701	struct led_flash_setting *brightness, *timeout;702	u32 current_ua, timeout_us;703	u32 channels[4];704	int i, rc, count;705 706	count = fwnode_property_count_u32(node, "led-sources");707	if (count <= 0) {708		dev_err(dev, "No led-sources specified\n");709		return -ENODEV;710	}711 712	if (count > flash_data->max_channels) {713		dev_err(dev, "led-sources count %u exceeds maximum channel count %u\n",714				count, flash_data->max_channels);715		return -EINVAL;716	}717 718	rc = fwnode_property_read_u32_array(node, "led-sources", channels, count);719	if (rc < 0) {720		dev_err(dev, "Failed to read led-sources property, rc=%d\n", rc);721		return rc;722	}723 724	led->chan_count = count;725	led->chan_id = devm_kcalloc(dev, count, sizeof(u8), GFP_KERNEL);726	if (!led->chan_id)727		return -ENOMEM;728 729	for (i = 0; i < count; i++) {730		if ((channels[i] == 0) || (channels[i] > flash_data->max_channels)) {731			dev_err(dev, "led-source out of HW support range [1-%u]\n",732					flash_data->max_channels);733			return -EINVAL;734		}735 736		/* Make chan_id indexing from 0 */737		led->chan_id[i] = channels[i] - 1;738	}739 740	rc = fwnode_property_read_u32(node, "led-max-microamp", &current_ua);741	if (rc < 0) {742		dev_err(dev, "Failed to read led-max-microamp property, rc=%d\n", rc);743		return rc;744	}745 746	if (current_ua == 0) {747		dev_err(dev, "led-max-microamp shouldn't be 0\n");748		return -EINVAL;749	}750 751	current_ua = min_t(u32, current_ua, TORCH_CURRENT_MAX_UA * led->chan_count);752	led->max_torch_current_ma = current_ua / UA_PER_MA;753 754	if (fwnode_property_present(node, "flash-max-microamp")) {755		flash->led_cdev.flags |= LED_DEV_CAP_FLASH;756 757		rc = fwnode_property_read_u32(node, "flash-max-microamp", &current_ua);758		if (rc < 0) {759			dev_err(dev, "Failed to read flash-max-microamp property, rc=%d\n",760					rc);761			return rc;762		}763 764		current_ua = min_t(u32, current_ua, FLASH_CURRENT_MAX_UA * led->chan_count);765		current_ua = min_t(u32, current_ua, FLASH_TOTAL_CURRENT_MAX_UA);766 767		/* Initialize flash class LED device brightness settings */768		brightness = &flash->brightness;769		brightness->min = brightness->step = FLASH_IRES_UA * led->chan_count;770		brightness->max = current_ua;771		brightness->val = min_t(u32, current_ua, FLASH_CURRENT_DEFAULT_UA);772 773		led->max_flash_current_ma = current_ua / UA_PER_MA;774		led->flash_current_ma = brightness->val / UA_PER_MA;775 776		rc = fwnode_property_read_u32(node, "flash-max-timeout-us", &timeout_us);777		if (rc < 0) {778			dev_err(dev, "Failed to read flash-max-timeout-us property, rc=%d\n",779					rc);780			return rc;781		}782 783		timeout_us = min_t(u32, timeout_us, FLASH_TIMEOUT_MAX_US);784 785		/* Initialize flash class LED device timeout settings */786		timeout = &flash->timeout;787		timeout->min = timeout->step = FLASH_TIMEOUT_STEP_US;788		timeout->val = timeout->max = timeout_us;789 790		led->max_timeout_ms = led->flash_timeout_ms = timeout_us / USEC_PER_MSEC;791 792		flash->ops = &qcom_flash_ops;793	}794 795	flash->led_cdev.brightness_set_blocking = qcom_flash_led_brightness_set;796 797	init_data.fwnode = node;798	init_data.devicename = NULL;799	init_data.default_label = NULL;800	init_data.devname_mandatory = false;801 802	rc = devm_led_classdev_flash_register_ext(dev, flash, &init_data);803	if (rc < 0) {804		dev_err(dev, "Register flash LED classdev failed, rc=%d\n", rc);805		return rc;806	}807 808	return qcom_flash_v4l2_init(dev, led, node);809}810 811static int qcom_flash_led_probe(struct platform_device *pdev)812{813	struct qcom_flash_data *flash_data;814	struct qcom_flash_led *led;815	struct fwnode_handle *child;816	struct device *dev = &pdev->dev;817	struct regmap *regmap;818	struct reg_field *regs;819	int count, i, rc;820	u32 val, reg_base;821 822	flash_data = devm_kzalloc(dev, sizeof(*flash_data), GFP_KERNEL);823	if (!flash_data)824		return -ENOMEM;825 826	regmap = dev_get_regmap(dev->parent, NULL);827	if (!regmap) {828		dev_err(dev, "Failed to get parent regmap\n");829		return -EINVAL;830	}831 832	rc = fwnode_property_read_u32(dev->fwnode, "reg", &reg_base);833	if (rc < 0) {834		dev_err(dev, "Failed to get register base address, rc=%d\n", rc);835		return rc;836	}837 838	rc = regmap_read(regmap, reg_base + FLASH_TYPE_REG, &val);839	if (rc < 0) {840		dev_err(dev, "Read flash LED module type failed, rc=%d\n", rc);841		return rc;842	}843 844	if (val != FLASH_TYPE_VAL) {845		dev_err(dev, "type %#x is not a flash LED module\n", val);846		return -ENODEV;847	}848 849	rc = regmap_read(regmap, reg_base + FLASH_SUBTYPE_REG, &val);850	if (rc < 0) {851		dev_err(dev, "Read flash LED module subtype failed, rc=%d\n", rc);852		return rc;853	}854 855	if (val == FLASH_SUBTYPE_3CH_PM8150_VAL || val == FLASH_SUBTYPE_3CH_PMI8998_VAL) {856		flash_data->hw_type = QCOM_MVFLASH_3CH;857		flash_data->max_channels = 3;858		regs = mvflash_3ch_regs;859	} else if (val == FLASH_SUBTYPE_4CH_VAL) {860		flash_data->hw_type = QCOM_MVFLASH_4CH;861		flash_data->max_channels = 4;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;871	} else {872		dev_err(dev, "flash LED subtype %#x is not yet supported\n", val);873		return -ENODEV;874	}875 876	for (i = 0; i < REG_MAX_COUNT; i++)877		regs[i].reg += reg_base;878 879	rc = devm_regmap_field_bulk_alloc(dev, regmap, flash_data->r_fields, regs, REG_MAX_COUNT);880	if (rc < 0) {881		dev_err(dev, "Failed to allocate regmap field, rc=%d\n", rc);882		return rc;883	}884 885	platform_set_drvdata(pdev, flash_data);886	mutex_init(&flash_data->lock);887 888	count = device_get_child_node_count(dev);889	if (count == 0 || count > flash_data->max_channels) {890		dev_err(dev, "No child or child count exceeds %d\n", flash_data->max_channels);891		return -EINVAL;892	}893 894	flash_data->v4l2_flash = devm_kcalloc(dev, count,895			sizeof(*flash_data->v4l2_flash), GFP_KERNEL);896	if (!flash_data->v4l2_flash)897		return -ENOMEM;898 899	device_for_each_child_node(dev, child) {900		led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);901		if (!led) {902			rc = -ENOMEM;903			goto release;904		}905 906		led->flash_data = flash_data;907		rc = qcom_flash_register_led_device(dev, child, led);908		if (rc < 0)909			goto release;910 911		flash_data->leds_count++;912	}913 914	return 0;915 916release:917	fwnode_handle_put(child);918	while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count)919		v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]);920	return rc;921}922 923static void qcom_flash_led_remove(struct platform_device *pdev)924{925	struct qcom_flash_data *flash_data = platform_get_drvdata(pdev);926 927	while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count)928		v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]);929 930	mutex_destroy(&flash_data->lock);931}932 933static const struct of_device_id qcom_flash_led_match_table[] = {934	{ .compatible = "qcom,spmi-flash-led" },935	{ }936};937 938MODULE_DEVICE_TABLE(of, qcom_flash_led_match_table);939static struct platform_driver qcom_flash_led_driver = {940	.driver = {941		.name = "leds-qcom-flash",942		.of_match_table = qcom_flash_led_match_table,943	},944	.probe = qcom_flash_led_probe,945	.remove_new = qcom_flash_led_remove,946};947 948module_platform_driver(qcom_flash_led_driver);949 950MODULE_DESCRIPTION("QCOM Flash LED driver");951MODULE_LICENSE("GPL");952