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.

Merge tag 'backlight-next-6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight

Pull backlight updates from Lee Jones:
"New Support & Features:

- Add a new driver for the Congatec Board Controller (CGBC)
backlight, providing brightness control via the board controller's
PWM interface

Improvements & Fixes:

- Resolve build failures in the Awinic AW99706 driver by switching to
the correct GPIO consumer header

- Extend the Qualcomm WLED driver to support the specific
over-voltage protection (OVP) values required for the PMI8994 and
PMI8950 variants

Device Tree Bindings Updates:

- Document the device-specific over-voltage protection (OVP)
millivolt ranges and default values for Qualcomm PMI8994 and
PMI8950 WLED controllers"

* tag 'backlight-next-6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight:
backlight: qcom-wled: Change PM8950 WLED configurations
dt-bindings: backlight: qcom-wled: Document ovp values for PMI8950
backlight: qcom-wled: Support ovp values for PMI8994
dt-bindings: backlight: qcom-wled: Document ovp values for PMI8994
backlight: aw99706: Fix build errors caused by wrong gpio header
backlight: Add Congatec Board Controller (CGBC) backlight support

+255 -5
+22 -2
Documentation/devicetree/bindings/leds/backlight/qcom-wled.yaml
··· 98 98 description: | 99 99 Over-voltage protection limit. This property is for WLED4 only. 100 100 $ref: /schemas/types.yaml#/definitions/uint32 101 - enum: [ 18100, 19600, 29600, 31100 ] 102 - default: 29600 101 + minimum: 17800 102 + maximum: 31100 103 103 104 104 qcom,num-strings: 105 105 description: | ··· 238 238 max-brightness: 239 239 minimum: 0 240 240 maximum: 4095 241 + 242 + - if: 243 + properties: 244 + compatible: 245 + contains: 246 + enum: 247 + - qcom,pmi8950-wled 248 + - qcom,pmi8994-wled 249 + 250 + then: 251 + properties: 252 + qcom,ovp-millivolt: 253 + enum: [ 17800, 19400, 29500, 31000 ] 254 + default: 29500 255 + 256 + else: 257 + properties: 258 + qcom,ovp-millivolt: 259 + enum: [ 18100, 19600, 29600, 31100 ] 260 + default: 29600 241 261 242 262 required: 243 263 - compatible
+11
drivers/video/backlight/Kconfig
··· 258 258 If you have a LCD backlight adjustable by PWM, say Y to enable 259 259 this driver. 260 260 261 + config BACKLIGHT_CGBC 262 + tristate "Congatec Board Controller (CGBC) backlight support" 263 + depends on MFD_CGBC && X86 264 + help 265 + Say Y here to enable support for LCD backlight control on Congatec 266 + x86-based boards via the CGBC (Congatec Board Controller). 267 + 268 + This driver provides backlight brightness control through the Linux 269 + backlight subsystem. It communicates with the board controller to 270 + adjust LCD backlight using PWM signals. 271 + 261 272 config BACKLIGHT_DA903X 262 273 tristate "Backlight Driver for DA9030/DA9034 using WLED" 263 274 depends on PMIC_DA903X
+1
drivers/video/backlight/Makefile
··· 27 27 obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o 28 28 obj-$(CONFIG_BACKLIGHT_AW99706) += aw99706.o 29 29 obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o 30 + obj-$(CONFIG_BACKLIGHT_CGBC) += cgbc_bl.o 30 31 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 31 32 obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o 32 33 obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o
+1 -1
drivers/video/backlight/aw99706.c
··· 12 12 #include <linux/backlight.h> 13 13 #include <linux/bitfield.h> 14 14 #include <linux/delay.h> 15 - #include <linux/gpio.h> 15 + #include <linux/gpio/consumer.h> 16 16 #include <linux/i2c.h> 17 17 #include <linux/kernel.h> 18 18 #include <linux/module.h>
+180
drivers/video/backlight/cgbc_bl.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Congatec Board Controller (CGBC) Backlight Driver 4 + * 5 + * This driver provides backlight control for LCD displays connected to 6 + * Congatec boards via the CGBC (Congatec Board Controller). It integrates 7 + * with the Linux backlight subsystem and communicates with hardware through 8 + * the cgbc-core module. 9 + * 10 + * Copyright (C) 2025 Novatron Oy 11 + * 12 + * Author: Petri Karhula <petri.karhula@novatron.fi> 13 + */ 14 + 15 + #include <linux/backlight.h> 16 + #include <linux/bitfield.h> 17 + #include <linux/bits.h> 18 + #include <linux/mfd/cgbc.h> 19 + #include <linux/module.h> 20 + #include <linux/platform_device.h> 21 + 22 + #define BLT_PWM_DUTY_MASK GENMASK(6, 0) 23 + 24 + /* CGBC command for PWM brightness control*/ 25 + #define CGBC_CMD_BLT0_PWM 0x75 26 + 27 + #define CGBC_BL_MAX_BRIGHTNESS 100 28 + 29 + /** 30 + * CGBC backlight driver data 31 + * @dev: Pointer to the platform device 32 + * @cgbc: Pointer to the parent CGBC device data 33 + * @current_brightness: Current brightness level (0-100) 34 + */ 35 + struct cgbc_bl_data { 36 + struct device *dev; 37 + struct cgbc_device_data *cgbc; 38 + unsigned int current_brightness; 39 + }; 40 + 41 + static int cgbc_bl_read_brightness(struct cgbc_bl_data *bl_data) 42 + { 43 + u8 cmd_buf[4] = { CGBC_CMD_BLT0_PWM }; 44 + u8 reply_buf[3]; 45 + int ret; 46 + 47 + ret = cgbc_command(bl_data->cgbc, cmd_buf, sizeof(cmd_buf), 48 + reply_buf, sizeof(reply_buf), NULL); 49 + if (ret < 0) 50 + return ret; 51 + 52 + /* 53 + * Get only PWM duty factor percentage, 54 + * ignore polarity inversion bit (bit 7) 55 + */ 56 + bl_data->current_brightness = FIELD_GET(BLT_PWM_DUTY_MASK, reply_buf[0]); 57 + 58 + return 0; 59 + } 60 + 61 + static int cgbc_bl_update_status(struct backlight_device *bl) 62 + { 63 + struct cgbc_bl_data *bl_data = bl_get_data(bl); 64 + u8 cmd_buf[4] = { CGBC_CMD_BLT0_PWM }; 65 + u8 reply_buf[3]; 66 + u8 brightness; 67 + int ret; 68 + 69 + brightness = backlight_get_brightness(bl); 70 + 71 + if (brightness != bl_data->current_brightness) { 72 + /* Read the current values */ 73 + ret = cgbc_command(bl_data->cgbc, cmd_buf, sizeof(cmd_buf), reply_buf, 74 + sizeof(reply_buf), NULL); 75 + if (ret < 0) { 76 + dev_err(bl_data->dev, "Failed to read PWM settings: %d\n", ret); 77 + return ret; 78 + } 79 + 80 + /* 81 + * Prepare command buffer for writing new settings. Only 2nd byte is changed 82 + * to set new brightness (PWM duty cycle %). Other values (polarity, frequency) 83 + * are preserved from the read values. 84 + */ 85 + cmd_buf[1] = (reply_buf[0] & ~BLT_PWM_DUTY_MASK) | 86 + FIELD_PREP(BLT_PWM_DUTY_MASK, brightness); 87 + cmd_buf[2] = reply_buf[1]; 88 + cmd_buf[3] = reply_buf[2]; 89 + 90 + ret = cgbc_command(bl_data->cgbc, cmd_buf, sizeof(cmd_buf), reply_buf, 91 + sizeof(reply_buf), NULL); 92 + if (ret < 0) { 93 + dev_err(bl_data->dev, "Failed to set brightness: %d\n", ret); 94 + return ret; 95 + } 96 + 97 + bl_data->current_brightness = reply_buf[0] & BLT_PWM_DUTY_MASK; 98 + 99 + /* Verify the setting was applied correctly */ 100 + if (bl_data->current_brightness != brightness) { 101 + dev_err(bl_data->dev, 102 + "Brightness setting verification failed (got %u, expected %u)\n", 103 + bl_data->current_brightness, (unsigned int)brightness); 104 + return -EIO; 105 + } 106 + } 107 + 108 + return 0; 109 + } 110 + 111 + static int cgbc_bl_get_brightness(struct backlight_device *bl) 112 + { 113 + struct cgbc_bl_data *bl_data = bl_get_data(bl); 114 + int ret; 115 + 116 + ret = cgbc_bl_read_brightness(bl_data); 117 + if (ret < 0) { 118 + dev_err(bl_data->dev, "Failed to read brightness: %d\n", ret); 119 + return ret; 120 + } 121 + 122 + return bl_data->current_brightness; 123 + } 124 + 125 + static const struct backlight_ops cgbc_bl_ops = { 126 + .options = BL_CORE_SUSPENDRESUME, 127 + .update_status = cgbc_bl_update_status, 128 + .get_brightness = cgbc_bl_get_brightness, 129 + }; 130 + 131 + static int cgbc_bl_probe(struct platform_device *pdev) 132 + { 133 + struct cgbc_device_data *cgbc = dev_get_drvdata(pdev->dev.parent); 134 + struct backlight_properties props = { }; 135 + struct backlight_device *bl_dev; 136 + struct cgbc_bl_data *bl_data; 137 + int ret; 138 + 139 + bl_data = devm_kzalloc(&pdev->dev, sizeof(*bl_data), GFP_KERNEL); 140 + if (!bl_data) 141 + return -ENOMEM; 142 + 143 + bl_data->dev = &pdev->dev; 144 + bl_data->cgbc = cgbc; 145 + 146 + ret = cgbc_bl_read_brightness(bl_data); 147 + if (ret < 0) 148 + return dev_err_probe(&pdev->dev, ret, 149 + "Failed to read initial brightness\n"); 150 + 151 + props.type = BACKLIGHT_PLATFORM; 152 + props.max_brightness = CGBC_BL_MAX_BRIGHTNESS; 153 + props.brightness = bl_data->current_brightness; 154 + props.scale = BACKLIGHT_SCALE_LINEAR; 155 + 156 + bl_dev = devm_backlight_device_register(&pdev->dev, "cgbc-backlight", 157 + &pdev->dev, bl_data, 158 + &cgbc_bl_ops, &props); 159 + if (IS_ERR(bl_dev)) 160 + return dev_err_probe(&pdev->dev, PTR_ERR(bl_dev), 161 + "Failed to register backlight device\n"); 162 + 163 + platform_set_drvdata(pdev, bl_data); 164 + 165 + return 0; 166 + } 167 + 168 + static struct platform_driver cgbc_bl_driver = { 169 + .driver = { 170 + .name = "cgbc-backlight", 171 + }, 172 + .probe = cgbc_bl_probe, 173 + }; 174 + 175 + module_platform_driver(cgbc_bl_driver); 176 + 177 + MODULE_AUTHOR("Petri Karhula <petri.karhula@novatron.fi>"); 178 + MODULE_DESCRIPTION("Congatec Board Controller (CGBC) Backlight Driver"); 179 + MODULE_LICENSE("GPL"); 180 + MODULE_ALIAS("platform:cgbc-backlight");
+40 -2
drivers/video/backlight/qcom-wled.c
··· 1244 1244 .size = ARRAY_SIZE(wled4_ovp_values), 1245 1245 }; 1246 1246 1247 + static const u32 pmi8994_wled_ovp_values[] = { 1248 + 31000, 29500, 19400, 17800, 1249 + }; 1250 + 1251 + static const struct wled_var_cfg pmi8994_wled_ovp_cfg = { 1252 + .values = pmi8994_wled_ovp_values, 1253 + .size = ARRAY_SIZE(pmi8994_wled_ovp_values), 1254 + }; 1255 + 1247 1256 static inline u32 wled5_ovp_values_fn(u32 idx) 1248 1257 { 1249 1258 /* ··· 1366 1357 }, 1367 1358 }; 1368 1359 1360 + const struct wled_u32_opts pmi8994_wled_opts[] = { 1361 + { 1362 + .name = "qcom,current-boost-limit", 1363 + .val_ptr = &cfg->boost_i_limit, 1364 + .cfg = &wled4_boost_i_limit_cfg, 1365 + }, 1366 + { 1367 + .name = "qcom,current-limit-microamp", 1368 + .val_ptr = &cfg->string_i_limit, 1369 + .cfg = &wled4_string_i_limit_cfg, 1370 + }, 1371 + { 1372 + .name = "qcom,ovp-millivolt", 1373 + .val_ptr = &cfg->ovp, 1374 + .cfg = &pmi8994_wled_ovp_cfg, 1375 + }, 1376 + { 1377 + .name = "qcom,switching-freq", 1378 + .val_ptr = &cfg->switch_freq, 1379 + .cfg = &wled3_switch_freq_cfg, 1380 + }, 1381 + }; 1382 + 1369 1383 const struct wled_u32_opts wled5_opts[] = { 1370 1384 { 1371 1385 .name = "qcom,current-boost-limit", ··· 1455 1423 break; 1456 1424 1457 1425 case 4: 1458 - u32_opts = wled4_opts; 1459 - size = ARRAY_SIZE(wled4_opts); 1426 + if (of_device_is_compatible(dev->of_node, "qcom,pmi8950-wled") || 1427 + of_device_is_compatible(dev->of_node, "qcom,pmi8994-wled")) { 1428 + u32_opts = pmi8994_wled_opts; 1429 + size = ARRAY_SIZE(pmi8994_wled_opts); 1430 + } else { 1431 + u32_opts = wled4_opts; 1432 + size = ARRAY_SIZE(wled4_opts); 1433 + } 1460 1434 *cfg = wled4_config_defaults; 1461 1435 wled->wled_set_brightness = wled4_set_brightness; 1462 1436 wled->wled_sync_toggle = wled3_sync_toggle;