From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2A15727F4F5 for ; Sun, 3 May 2026 16:45:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777826712; cv=none; b=gbs5cT2WGCb46L0L94Du0oMr/BpCmZz5HXYtUpklJaxPuOmqZRH1M8Jin2dCUtLRCS8zdXM/GuMCe3sqgDSYKZTOnEC7iRAxbajvpyFK/0Ury84iyyhqioNG2cgOxBeXC5v0QTaVJfuelT7UrI6vdcDDHw7I6oFf0KbbrsBlQhM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777826712; c=relaxed/simple; bh=7Op9ubqBC6Ql1b7wKXH5NzggGBRcOSoMZ1O9wP90KmY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GUsIIqPgEgsIQVIlOWm+wT+QGn3z1jZ81UNIcY/rZ/qqo/DCQOHcttVF0K4rzCVVWAunl5iEeQx4+TC4Sb6/9RdH85IHwVEcc3xyqpYr3DNq9Cczlj0LP6+six/V14Bn3/aKFu5VARyy1Pmk6GkfhB+gecppjeXJaPJ8kNIZbA4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=o+R3qjJG; arc=none smtp.client-ip=209.85.218.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="o+R3qjJG" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-ba545100a13so612599266b.2 for ; Sun, 03 May 2026 09:45:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777826705; x=1778431505; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gOh4PG7yMJifApqzJycmTrJ4xR4vGrLLw/m7gNops7A=; b=o+R3qjJGuoQWAtn6yS3YP66NuwSZrk8yIFbEPaAr6WmEbDyU3KK4I9LRtQOE5vwOgg vMBzVu1G4eE5dWS3J1wh4IzK7bsX4XY456BfuX+IA/lU+w8fvEALMTDHJmdZO0/vunc/ 6VQ5ZWg2WXVwJi1vwn50iB48HNZyGCB4Jm+yXzM0EelkrXudgMK9vFQBR3UKFgxanM2n fryE8yA05i3CnNBDoXWMaO92KNQfbjiWeOulXE6ZDR+nXmiYFwy0jtzNkFArvtjgvKi+ 3vWU09WcAy5bgbZmO4LUDDKmV95nPdY5nmQaw/Nu9eO66htro4cCGY9CH1pTOtsaUYEa 0Lpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777826705; x=1778431505; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=gOh4PG7yMJifApqzJycmTrJ4xR4vGrLLw/m7gNops7A=; b=q5VLgswk7n6sS0mu2H/DAfFuxDd46dqV1P1euW2wbmKb5NGqHfR5WK48wp9dd++O9m KTrRtcJgw0Rn9zUWpECSnBMzIP6U1RMUC3MYhYbhq/QNY+p/vdlzFVq1oDi6iLtbxZ98 mR+SWOqrzSt2+EDT5LQbXqfaB9JThFb5r3wg5vZYE98YjwSA9GY5AxbmlN/+ryGzpJzD WgY5yUv+FJLlM3VqcxExyppgJbG7iORGKu0SykSJo7Nf7NsQbn2BxtFndIMw/s1br9zi iJn1+JSbOJEtCNyaX+10s+9p+zexk1AGEUBgzZuO8cBbMg6Sb2dAt+UJcxYpllwH2tmo s1YQ== X-Forwarded-Encrypted: i=1; AFNElJ8vf4ab1gPqqjiSCiE76wqqAUmGWeUDURBbfIvEmP4Aut7GUEaJsieGb7JFzge/6v1/6rXsG8e1Vd1p/1g=@vger.kernel.org X-Gm-Message-State: AOJu0Yxx26byKK4yGGIYEEhnFeJ52TSF+HgaWW9VBCfQxiMbIIi8WNAM gxN8d8+EUbAMhe8cdEd5dgT4LYyWe2fUr8mpnVr5eRZ8yaF5FABnR1BF X-Gm-Gg: AeBDiet+Muo3pJHQeguTP7fwKnbMynQtNLPcLXVR28xdkbB4ZgkcUXAPIHkOcORQ0Cr Ets+ry8X+nLL9BfY9TxmEykHOzT7XUtfqPI3l9Q12whwnQwB357dyXAwaSyoHSD3AYRnqL+nu7C mJ5lKRLLIxujHkyVg8MIyDAQZmg4HEy8RrDcqCzwSdv/bT5u33LMb6jGN/xX4AcI2K7LeMERNQO b6KCAnqxK6Tlh6mTfGqyyz+NYoWAF8K+bkQqw+VzBybAuvHwZzQm2Y37XDVHRKl0GfU55TztcbT 2TXHe8DM3Aa/3VYn1VyEbLBMPS4tVsKmiP+F/7lvj0BMkVPs01VzcDjOy/RBHijg5NO0Q0z3K9c Tr537tliTn1TUGF+JgrVb/9c1PZIv06qj1xv38m4Qf+S+T52ILllpybYQi7TDAmitNefSTmR9XI QOcL2QsnYkZd3YM7CeIdpbNGqxUM14OPrNsg== X-Received: by 2002:a17:907:805:b0:bc1:6ec9:453b with SMTP id a640c23a62f3a-bc16ec95285mr139456566b.42.1777826705359; Sun, 03 May 2026 09:45:05 -0700 (PDT) Received: from xeon ([188.163.112.56]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-bc237ef8297sm27430566b.57.2026.05.03.09.45.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 03 May 2026 09:45:04 -0700 (PDT) From: Svyatoslav Ryhel To: Lee Jones , Pavel Machek , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Sakari Ailus , Mauro Carvalho Chehab , Svyatoslav Ryhel Cc: linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org Subject: [PATCH v5 6/6] media: i2c: lm3560: Add proper support for LM3559 Date: Sun, 3 May 2026 19:44:45 +0300 Message-ID: <20260503164445.215540-7-clamor95@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260503164445.215540-1-clamor95@gmail.com> References: <20260503164445.215540-1-clamor95@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The LM3559 is very similar to the LM3560, but it operates at much lower currents. This may result in incorrect current selection if LM3560 ranges are applied to the LM3559. Implement driver data matching to use device-specific current configurations. Since the driver no longer supports platform data and device configuration is performed more granularly, move the remaining enums from the header into the driver file and remove the header. Signed-off-by: Svyatoslav Ryhel --- drivers/media/i2c/lm3560.c | 120 ++++++++++++++++++++++++++++++------- include/media/i2c/lm3560.h | 69 --------------------- 2 files changed, 100 insertions(+), 89 deletions(-) delete mode 100644 include/media/i2c/lm3560.h diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index 15741ea5684f..da12fbd7dc59 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -23,9 +23,9 @@ #include #include #include -#include #include #include +#include /* registers definitions */ #define REG_ENABLE 0x10 @@ -40,12 +40,44 @@ #define FAULT_OVERTEMP (1<<1) #define FAULT_SHORT_CIRCUIT (1<<2) +#define LM3560_FLASH_TOUT_MIN 32 +#define LM3560_FLASH_TOUT_STEP 32 +#define LM3560_FLASH_TOUT_MAX 1024 +#define LM3560_FLASH_TOUT_ms_TO_REG(a) \ + ((a) < LM3560_FLASH_TOUT_MIN ? 0 : \ + (((a) - LM3560_FLASH_TOUT_MIN) / LM3560_FLASH_TOUT_STEP)) +#define LM3560_FLASH_TOUT_REG_TO_ms(a) \ + ((a) * LM3560_FLASH_TOUT_STEP + LM3560_FLASH_TOUT_MIN) + +enum lm3560_led_id { + LM3560_LED0 = 0, + LM3560_LED1, + LM3560_LED_MAX +}; + +enum lm3560_peak_current { + LM3560_PEAK_1600mA = 0x00, + LM3560_PEAK_2300mA = 0x20, + LM3560_PEAK_3000mA = 0x40, + LM3560_PEAK_3600mA = 0x60 +}; + enum led_enable { MODE_SHDN = 0x0, MODE_TORCH = 0x2, MODE_FLASH = 0x3, }; +struct lm3560_flash_config { + u32 flash_brt_min_ua; + u32 flash_brt_max_ua; + u32 flash_brt_step_ua; + + u32 torch_brt_min_ua; + u32 torch_brt_max_ua; + u32 torch_brt_step_ua; +}; + /** * struct lm3560_flash * @@ -62,6 +94,7 @@ enum led_enable { * @max_flash_timeout: flash timeout * @max_flash_brt: flash mode led brightness * @max_torch_brt: torch mode led brightness + * @config: device specific current configuration */ struct lm3560_flash { struct device *dev; @@ -82,6 +115,8 @@ struct lm3560_flash { u32 max_flash_brt[LM3560_LED_MAX]; u32 max_torch_brt[LM3560_LED_MAX]; + + const struct lm3560_flash_config *config; }; #define to_lm3560_flash(_ctrl, _no) \ @@ -137,15 +172,20 @@ static int lm3560_enable_ctrl(struct lm3560_flash *flash, static int lm3560_torch_brt_ctrl(struct lm3560_flash *flash, enum lm3560_led_id led_no, unsigned int brt) { + const struct lm3560_flash_config *config = flash->config; int rval; - u8 br_bits; + u32 br_bits; - if (brt < LM3560_TORCH_BRT_MIN) + if (brt < config->torch_brt_min_ua) return lm3560_enable_ctrl(flash, led_no, false); else rval = lm3560_enable_ctrl(flash, led_no, true); - br_bits = LM3560_TORCH_BRT_uA_TO_REG(brt); + br_bits = clamp(brt, config->torch_brt_min_ua, + config->torch_brt_max_ua); + br_bits = (br_bits - config->torch_brt_min_ua) / + config->torch_brt_step_ua; + if (led_no == LM3560_LED0) rval = regmap_update_bits(flash->regmap, REG_TORCH_BR, 0x07, br_bits); @@ -160,15 +200,20 @@ static int lm3560_torch_brt_ctrl(struct lm3560_flash *flash, static int lm3560_flash_brt_ctrl(struct lm3560_flash *flash, enum lm3560_led_id led_no, unsigned int brt) { + const struct lm3560_flash_config *config = flash->config; int rval; - u8 br_bits; + u32 br_bits; - if (brt < LM3560_FLASH_BRT_MIN) + if (brt < config->flash_brt_min_ua) return lm3560_enable_ctrl(flash, led_no, false); else rval = lm3560_enable_ctrl(flash, led_no, true); - br_bits = LM3560_FLASH_BRT_uA_TO_REG(brt); + br_bits = clamp(brt, config->flash_brt_min_ua, + config->flash_brt_max_ua); + br_bits = (br_bits - config->flash_brt_min_ua) / + config->flash_brt_step_ua; + if (led_no == LM3560_LED0) rval = regmap_update_bits(flash->regmap, REG_FLASH_BR, 0x0f, br_bits); @@ -308,6 +353,7 @@ static int lm3560_init_controls(struct lm3560_flash *flash, u32 max_torch_brt = flash->max_torch_brt[led_no]; struct v4l2_ctrl_handler *hdl = &flash->ctrls_led[led_no]; const struct v4l2_ctrl_ops *ops = &lm3560_led_ctrl_ops[led_no]; + const struct lm3560_flash_config *config = flash->config; v4l2_ctrl_handler_init(hdl, 8); @@ -336,13 +382,13 @@ static int lm3560_init_controls(struct lm3560_flash *flash, /* flash brt */ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_INTENSITY, - LM3560_FLASH_BRT_MIN, max_flash_brt, - LM3560_FLASH_BRT_STEP, max_flash_brt); + config->flash_brt_min_ua, max_flash_brt, + config->flash_brt_step_ua, max_flash_brt); /* torch brt */ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_TORCH_INTENSITY, - LM3560_TORCH_BRT_MIN, max_torch_brt, - LM3560_TORCH_BRT_STEP, max_torch_brt); + config->torch_brt_min_ua, max_torch_brt, + config->torch_brt_step_ua, max_torch_brt); /* fault */ fault = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FLASH_FAULT, 0, @@ -483,6 +529,10 @@ static int lm3560_probe(struct i2c_client *client) if (flash == NULL) return -ENOMEM; + flash->config = device_get_match_data(&client->dev); + if (!flash->config) + return -ENODEV; + flash->regmap = devm_regmap_init_i2c(client, &lm3560_regmap); if (IS_ERR(flash->regmap)) { rval = PTR_ERR(flash->regmap); @@ -509,16 +559,26 @@ static int lm3560_probe(struct i2c_client *client) rval = device_property_read_u32(flash->dev, "ti,peak-current-microamp", &peak_ua); if (!rval) { + /* + * LM3559 has lower peak current limit, but + * bit configuration matches LM3560. + * Correct current restrictions are enforced + * by the LM3560 schema. + */ switch (peak_ua) { + case 1400000: case 1600000: flash->peak = LM3560_PEAK_1600mA; break; + case 2100000: case 2300000: flash->peak = LM3560_PEAK_2300mA; break; + case 2700000: case 3000000: flash->peak = LM3560_PEAK_3000mA; break; + case 3200000: case 3600000: flash->peak = LM3560_PEAK_3600mA; break; @@ -547,6 +607,7 @@ static int lm3560_probe(struct i2c_client *client) pm_runtime_enable(flash->dev); for_each_available_child_of_node(dev_of_node(flash->dev), node) { + const struct lm3560_flash_config *config = flash->config; u32 reg; rval = of_property_read_u32(node, "reg", ®); @@ -555,11 +616,11 @@ static int lm3560_probe(struct i2c_client *client) continue; if (reg == LM3560_LED0 || reg == LM3560_LED1) { - flash->max_flash_brt[reg] = LM3560_FLASH_BRT_MIN; + flash->max_flash_brt[reg] = config->flash_brt_min_ua; of_property_read_u32(node, "flash-max-microamp", &flash->max_flash_brt[reg]); - flash->max_torch_brt[reg] = LM3560_TORCH_BRT_MIN; + flash->max_torch_brt[reg] = config->torch_brt_min_ua; of_property_read_u32(node, "led-max-microamp", &flash->max_torch_brt[reg]); @@ -617,24 +678,43 @@ static const struct dev_pm_ops lm3560_pm_ops = { SET_RUNTIME_PM_OPS(lm3560_power_off, lm3560_power_on, NULL) }; +static const struct lm3560_flash_config lm3559_config = { + .flash_brt_min_ua = 56250, + .flash_brt_max_ua = 900000, + .flash_brt_step_ua = 56250, + + .torch_brt_min_ua = 28125, + .torch_brt_max_ua = 225000, + .torch_brt_step_ua = 28125, +}; + +static const struct lm3560_flash_config lm3560_config = { + .flash_brt_min_ua = 62500, + .flash_brt_max_ua = 1000000, + .flash_brt_step_ua = 62500, + + .torch_brt_min_ua = 31250, + .torch_brt_max_ua = 250000, + .torch_brt_step_ua = 31250, +}; + static const struct of_device_id lm3560_of_match[] = { - { .compatible = "ti,lm3559" }, - { .compatible = "ti,lm3560" }, + { .compatible = "ti,lm3559", .data = &lm3559_config }, + { .compatible = "ti,lm3560", .data = &lm3560_config }, { } }; MODULE_DEVICE_TABLE(of, lm3560_of_match); static const struct i2c_device_id lm3560_id_table[] = { - { LM3559_NAME }, - { LM3560_NAME }, - {} + { "lm3559", (kernel_ulong_t)&lm3559_config }, + { "lm3560", (kernel_ulong_t)&lm3560_config }, + { } }; - MODULE_DEVICE_TABLE(i2c, lm3560_id_table); static struct i2c_driver lm3560_i2c_driver = { .driver = { - .name = LM3560_NAME, + .name = "lm3560", .pm = pm_ptr(&lm3560_pm_ops), .of_match_table = lm3560_of_match, }, diff --git a/include/media/i2c/lm3560.h b/include/media/i2c/lm3560.h deleted file mode 100644 index b56c1ff8fd49..000000000000 --- a/include/media/i2c/lm3560.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * include/media/i2c/lm3560.h - * - * Copyright (C) 2013 Texas Instruments - * - * Contact: Daniel Jeong - * Ldd-Mlp - */ - -#ifndef __LM3560_H__ -#define __LM3560_H__ - -#include - -#define LM3559_NAME "lm3559" -#define LM3560_NAME "lm3560" -#define LM3560_I2C_ADDR (0x53) - -/* FLASH Brightness - * min 62500uA, step 62500uA, max 1000000uA - */ -#define LM3560_FLASH_BRT_MIN 62500 -#define LM3560_FLASH_BRT_STEP 62500 -#define LM3560_FLASH_BRT_MAX 1000000 -#define LM3560_FLASH_BRT_uA_TO_REG(a) \ - ((a) < LM3560_FLASH_BRT_MIN ? 0 : \ - (((a) - LM3560_FLASH_BRT_MIN) / LM3560_FLASH_BRT_STEP)) -#define LM3560_FLASH_BRT_REG_TO_uA(a) \ - ((a) * LM3560_FLASH_BRT_STEP + LM3560_FLASH_BRT_MIN) - -/* FLASH TIMEOUT DURATION - * min 32ms, step 32ms, max 1024ms - */ -#define LM3560_FLASH_TOUT_MIN 32 -#define LM3560_FLASH_TOUT_STEP 32 -#define LM3560_FLASH_TOUT_MAX 1024 -#define LM3560_FLASH_TOUT_ms_TO_REG(a) \ - ((a) < LM3560_FLASH_TOUT_MIN ? 0 : \ - (((a) - LM3560_FLASH_TOUT_MIN) / LM3560_FLASH_TOUT_STEP)) -#define LM3560_FLASH_TOUT_REG_TO_ms(a) \ - ((a) * LM3560_FLASH_TOUT_STEP + LM3560_FLASH_TOUT_MIN) - -/* TORCH BRT - * min 31250uA, step 31250uA, max 250000uA - */ -#define LM3560_TORCH_BRT_MIN 31250 -#define LM3560_TORCH_BRT_STEP 31250 -#define LM3560_TORCH_BRT_MAX 250000 -#define LM3560_TORCH_BRT_uA_TO_REG(a) \ - ((a) < LM3560_TORCH_BRT_MIN ? 0 : \ - (((a) - LM3560_TORCH_BRT_MIN) / LM3560_TORCH_BRT_STEP)) -#define LM3560_TORCH_BRT_REG_TO_uA(a) \ - ((a) * LM3560_TORCH_BRT_STEP + LM3560_TORCH_BRT_MIN) - -enum lm3560_led_id { - LM3560_LED0 = 0, - LM3560_LED1, - LM3560_LED_MAX -}; - -enum lm3560_peak_current { - LM3560_PEAK_1600mA = 0x00, - LM3560_PEAK_2300mA = 0x20, - LM3560_PEAK_3000mA = 0x40, - LM3560_PEAK_3600mA = 0x60 -}; - -#endif /* __LM3560_H__ */ -- 2.51.0