Merge tag 'backlight-next-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2024 17:35:46 +0000 (10:35 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2024 17:35:46 +0000 (10:35 -0700)
Pull backlight updates from Lee Jones:
 "New Drivers:
   - Add support for Kinetic KTD2801 Backlight

  Fix-ups:
   - Fix include lists; alphabetise, remove unused, explicitly add used
   - Device Tree binding adaptions/conversions/creation
   - Use dev_err_probe() to clean-up error paths
   - Use/convert to new/better APIs/helpers/MACROs instead of hand-rolling implementations

  Bug Fixes:
   - Fix changes of NULL pointer dereference
   - Remedy a bunch of logic errors
   - Initialise (zero) Backlight properties data structures"

* tag 'backlight-next-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight: (32 commits)
  backlight: pandora_bl: Drop unneeded ENOMEM error message
  backlight: lm3630a_bl: Simplify probe return on gpio request error
  backlight: lm3630a_bl: Handle deferred probe
  backlight: as3711_bl: Handle deferred probe
  backlight: bd6107: Handle deferred probe
  backlight: l4f00242t03: Simplify with dev_err_probe()
  backlight: gpio: Simplify with dev_err_probe()
  backlight: lp8788: Fully initialize backlight_properties during probe
  backlight: lm3639: Fully initialize backlight_properties during probe
  backlight: da9052: Fully initialize backlight_properties during probe
  backlight: lm3630a: Use backlight_get_brightness helper in update_status
  backlight: lm3630a: Don't set bl->props.brightness in get_brightness
  backlight: lm3630a: Initialize backlight_properties on init
  backlight: mp3309c: Fully initialize backlight_properties during probe
  backlight: mp3309c: Utilise temporary variable for struct device
  backlight: mp3309c: Use dev_err_probe() instead of dev_err()
  backlight: mp3309c: Make use of device properties
  dt-bindings: backlight: qcom-wled: Fix bouncing email addresses
  backlight: hx8357: Utilise temporary variable for struct device
  backlight: hx8357: Make use of dev_err_probe()
  ...

24 files changed:
Documentation/devicetree/bindings/leds/backlight/kinetic,ktd2801.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/leds/backlight/qcom-wled.yaml
MAINTAINERS
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/flash/Kconfig
drivers/leds/flash/leds-ktd2692.c
drivers/leds/leds-expresswire.c [new file with mode: 0644]
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/as3711_bl.c
drivers/video/backlight/bd6107.c
drivers/video/backlight/da9052_bl.c
drivers/video/backlight/gpio_backlight.c
drivers/video/backlight/hx8357.c
drivers/video/backlight/ktd2801-backlight.c [new file with mode: 0644]
drivers/video/backlight/ktz8866.c
drivers/video/backlight/l4f00242t03.c
drivers/video/backlight/lm3630a_bl.c
drivers/video/backlight/lm3639_bl.c
drivers/video/backlight/lp8788_bl.c
drivers/video/backlight/mp3309c.c
drivers/video/backlight/pandora_bl.c
include/linux/leds-expresswire.h [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/leds/backlight/kinetic,ktd2801.yaml b/Documentation/devicetree/bindings/leds/backlight/kinetic,ktd2801.yaml
new file mode 100644 (file)
index 0000000..b005065
--- /dev/null
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/backlight/kinetic,ktd2801.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kinetic Technologies KTD2801 one-wire backlight
+
+maintainers:
+  - Duje Mihanović <duje.mihanovic@skole.hr>
+
+description: |
+  The Kinetic Technologies KTD2801 is a LED backlight driver controlled
+  by a single GPIO line. The driver can be controlled with a PWM signal
+  or by pulsing the GPIO line to set the backlight level. This is called
+  "ExpressWire".
+
+allOf:
+  - $ref: common.yaml#
+
+properties:
+  compatible:
+    const: kinetic,ktd2801
+
+  ctrl-gpios:
+    maxItems: 1
+
+  default-brightness: true
+  max-brightness: true
+
+required:
+  - compatible
+  - ctrl-gpios
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    backlight {
+        compatible = "kinetic,ktd2801";
+        ctrl-gpios = <&gpio 97 GPIO_ACTIVE_HIGH>;
+        max-brightness = <210>;
+        default-brightness = <100>;
+    };
index 5f1849bdabba2fad967108d62583d7fd14d6cb7b..a8490781011d1b842ff393566777d35c735ae3c0 100644 (file)
@@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Qualcomm Technologies, Inc. WLED driver
 
 maintainers:
-  - Bjorn Andersson <bjorn.andersson@linaro.org>
-  - Kiran Gunda <kgunda@codeaurora.org>
+  - Bjorn Andersson <andersson@kernel.org>
+  - Kiran Gunda <quic_kgunda@quicinc.com>
 
 description: |
   WLED (White Light Emitting Diode) driver is used for controlling display
index ba68e3bf0a0d88116cf54be5e0012d302d36a43e..5194176c7c98ad3c6038a8a212bed232b45f0588 100644 (file)
@@ -8039,6 +8039,13 @@ S:       Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat.git
 F:     fs/exfat/
 
+EXPRESSWIRE PROTOCOL LIBRARY
+M:     Duje Mihanović <duje.mihanovic@skole.hr>
+L:     linux-leds@vger.kernel.org
+S:     Maintained
+F:     drivers/leds/leds-expresswire.c
+F:     include/linux/leds-expresswire.h
+
 EXT2 FILE SYSTEM
 M:     Jan Kara <jack@suse.com>
 L:     linux-ext4@vger.kernel.org
@@ -12103,6 +12110,12 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml
 F:     drivers/video/backlight/ktd253-backlight.c
 
+KTD2801 BACKLIGHT DRIVER
+M:     Duje Mihanović <duje.mihanovic@skole.hr>
+S:     Maintained
+F:     Documentation/devicetree/bindings/leds/backlight/kinetic,ktd2801.yaml
+F:     drivers/video/backlight/ktd2801-backlight.c
+
 KTEST
 M:     Steven Rostedt <rostedt@goodmis.org>
 M:     John Hawley <warthog9@eaglescrag.net>
index d721b254e1e45072a627cbe45d3fed97ed81a5f7..64bb2de237e950ceefb63bc7dd9e3a0a963ffbe0 100644 (file)
@@ -186,6 +186,10 @@ config LEDS_EL15203000
          To compile this driver as a module, choose M here: the module
          will be called leds-el15203000.
 
+config LEDS_EXPRESSWIRE
+       bool
+       depends on GPIOLIB
+
 config LEDS_TURRIS_OMNIA
        tristate "LED support for CZ.NIC's Turris Omnia"
        depends on LEDS_CLASS_MULTICOLOR
index ce07dc295ff000082c7ca187d6594ce8175c0f6d..effdfc6f1e95105e71dda27aa04dc691575ccb7c 100644 (file)
@@ -91,6 +91,9 @@ obj-$(CONFIG_LEDS_WM831X_STATUS)      += leds-wm831x-status.o
 obj-$(CONFIG_LEDS_WM8350)              += leds-wm8350.o
 obj-$(CONFIG_LEDS_WRAP)                        += leds-wrap.o
 
+# Kinetic ExpressWire Protocol
+obj-$(CONFIG_LEDS_EXPRESSWIRE)         += leds-expresswire.o
+
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_CR0014114)           += leds-cr0014114.o
 obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o
index 4e08dbc057096f7239b5f628cf3cb6bb7407040c..24722d581369969eb96e9f354733ffa4d9d0dfbf 100644 (file)
@@ -23,7 +23,8 @@ config LEDS_AS3645A
 config LEDS_KTD2692
        tristate "LED support for Kinetic KTD2692 flash LED controller"
        depends on OF
-       depends on GPIOLIB || COMPILE_TEST
+       depends on GPIOLIB
+       select LEDS_EXPRESSWIRE
        help
          This option enables support for Kinetic KTD2692 LED flash connected
          through ExpressWire interface.
index 598eee5daa527137117cd3498c2816066987f557..7bb0aa2753e365ef386835767bfe357690631ff3 100644 (file)
@@ -6,9 +6,9 @@
  * Ingi Kim <ingi2.kim@samsung.com>
  */
 
-#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
+#include <linux/leds-expresswire.h>
 #include <linux/led-class-flash.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #define KTD2692_REG_FLASH_CURRENT_BASE         0x80
 #define KTD2692_REG_MODE_BASE                  0xA0
 
-/* Set bit coding time for expresswire interface */
-#define KTD2692_TIME_RESET_US                  700
-#define KTD2692_TIME_DATA_START_TIME_US                10
-#define KTD2692_TIME_HIGH_END_OF_DATA_US       350
-#define KTD2692_TIME_LOW_END_OF_DATA_US                10
-#define KTD2692_TIME_SHORT_BITSET_US           4
-#define KTD2692_TIME_LONG_BITSET_US            12
-
 /* KTD2692 default length of name */
 #define KTD2692_NAME_LENGTH                    20
 
-enum ktd2692_bitset {
-       KTD2692_LOW = 0,
-       KTD2692_HIGH,
-};
-
 /* Movie / Flash Mode Control */
 enum ktd2692_led_mode {
        KTD2692_MODE_DISABLE = 0,       /* default */
@@ -71,7 +58,19 @@ struct ktd2692_led_config_data {
        enum led_brightness max_brightness;
 };
 
+const struct expresswire_timing ktd2692_timing = {
+       .poweroff_us = 700,
+       .data_start_us = 10,
+       .end_of_data_low_us = 10,
+       .end_of_data_high_us = 350,
+       .short_bitset_us = 4,
+       .long_bitset_us = 12
+};
+
 struct ktd2692_context {
+       /* Common ExpressWire properties (ctrl GPIO and timing) */
+       struct expresswire_common_props props;
+
        /* Related LED Flash class device */
        struct led_classdev_flash fled_cdev;
 
@@ -80,7 +79,6 @@ struct ktd2692_context {
        struct regulator *regulator;
 
        struct gpio_desc *aux_gpio;
-       struct gpio_desc *ctrl_gpio;
 
        enum ktd2692_led_mode mode;
        enum led_brightness torch_brightness;
@@ -92,67 +90,6 @@ static struct ktd2692_context *fled_cdev_to_led(
        return container_of(fled_cdev, struct ktd2692_context, fled_cdev);
 }
 
-static void ktd2692_expresswire_start(struct ktd2692_context *led)
-{
-       gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
-       udelay(KTD2692_TIME_DATA_START_TIME_US);
-}
-
-static void ktd2692_expresswire_reset(struct ktd2692_context *led)
-{
-       gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
-       udelay(KTD2692_TIME_RESET_US);
-}
-
-static void ktd2692_expresswire_end(struct ktd2692_context *led)
-{
-       gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
-       udelay(KTD2692_TIME_LOW_END_OF_DATA_US);
-       gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
-       udelay(KTD2692_TIME_HIGH_END_OF_DATA_US);
-}
-
-static void ktd2692_expresswire_set_bit(struct ktd2692_context *led, bool bit)
-{
-       /*
-        * The Low Bit(0) and High Bit(1) is based on a time detection
-        * algorithm between time low and time high
-        * Time_(L_LB) : Low time of the Low Bit(0)
-        * Time_(H_LB) : High time of the LOW Bit(0)
-        * Time_(L_HB) : Low time of the High Bit(1)
-        * Time_(H_HB) : High time of the High Bit(1)
-        *
-        * It can be simplified to:
-        * Low Bit(0) : 2 * Time_(H_LB) < Time_(L_LB)
-        * High Bit(1) : 2 * Time_(L_HB) < Time_(H_HB)
-        * HIGH  ___           ____    _..     _________    ___
-        *          |_________|    |_..  |____|         |__|
-        * LOW        <L_LB>  <H_LB>     <L_HB>  <H_HB>
-        *          [  Low Bit (0) ]     [  High Bit(1) ]
-        */
-       if (bit) {
-               gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
-               udelay(KTD2692_TIME_SHORT_BITSET_US);
-               gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
-               udelay(KTD2692_TIME_LONG_BITSET_US);
-       } else {
-               gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
-               udelay(KTD2692_TIME_LONG_BITSET_US);
-               gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
-               udelay(KTD2692_TIME_SHORT_BITSET_US);
-       }
-}
-
-static void ktd2692_expresswire_write(struct ktd2692_context *led, u8 value)
-{
-       int i;
-
-       ktd2692_expresswire_start(led);
-       for (i = 7; i >= 0; i--)
-               ktd2692_expresswire_set_bit(led, value & BIT(i));
-       ktd2692_expresswire_end(led);
-}
-
 static int ktd2692_led_brightness_set(struct led_classdev *led_cdev,
                                       enum led_brightness brightness)
 {
@@ -163,14 +100,14 @@ static int ktd2692_led_brightness_set(struct led_classdev *led_cdev,
 
        if (brightness == LED_OFF) {
                led->mode = KTD2692_MODE_DISABLE;
-               gpiod_direction_output(led->aux_gpio, KTD2692_LOW);
+               gpiod_direction_output(led->aux_gpio, 0);
        } else {
-               ktd2692_expresswire_write(led, brightness |
+               expresswire_write_u8(&led->props, brightness |
                                        KTD2692_REG_MOVIE_CURRENT_BASE);
                led->mode = KTD2692_MODE_MOVIE;
        }
 
-       ktd2692_expresswire_write(led, led->mode | KTD2692_REG_MODE_BASE);
+       expresswire_write_u8(&led->props, led->mode | KTD2692_REG_MODE_BASE);
        mutex_unlock(&led->lock);
 
        return 0;
@@ -187,17 +124,17 @@ static int ktd2692_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
 
        if (state) {
                flash_tm_reg = GET_TIMEOUT_OFFSET(timeout->val, timeout->step);
-               ktd2692_expresswire_write(led, flash_tm_reg
+               expresswire_write_u8(&led->props, flash_tm_reg
                                | KTD2692_REG_FLASH_TIMEOUT_BASE);
 
                led->mode = KTD2692_MODE_FLASH;
-               gpiod_direction_output(led->aux_gpio, KTD2692_HIGH);
+               gpiod_direction_output(led->aux_gpio, 1);
        } else {
                led->mode = KTD2692_MODE_DISABLE;
-               gpiod_direction_output(led->aux_gpio, KTD2692_LOW);
+               gpiod_direction_output(led->aux_gpio, 0);
        }
 
-       ktd2692_expresswire_write(led, led->mode | KTD2692_REG_MODE_BASE);
+       expresswire_write_u8(&led->props, led->mode | KTD2692_REG_MODE_BASE);
 
        fled_cdev->led_cdev.brightness = LED_OFF;
        led->mode = KTD2692_MODE_DISABLE;
@@ -247,12 +184,12 @@ static void ktd2692_init_flash_timeout(struct led_classdev_flash *fled_cdev,
 static void ktd2692_setup(struct ktd2692_context *led)
 {
        led->mode = KTD2692_MODE_DISABLE;
-       ktd2692_expresswire_reset(led);
-       gpiod_direction_output(led->aux_gpio, KTD2692_LOW);
+       expresswire_power_off(&led->props);
+       gpiod_direction_output(led->aux_gpio, 0);
 
-       ktd2692_expresswire_write(led, (KTD2692_MM_MIN_CURR_THRESHOLD_SCALE - 1)
+       expresswire_write_u8(&led->props, (KTD2692_MM_MIN_CURR_THRESHOLD_SCALE - 1)
                                 | KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE);
-       ktd2692_expresswire_write(led, KTD2692_FLASH_MODE_CURR_PERCENT(45)
+       expresswire_write_u8(&led->props, KTD2692_FLASH_MODE_CURR_PERCENT(45)
                                 | KTD2692_REG_FLASH_CURRENT_BASE);
 }
 
@@ -277,8 +214,8 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev,
        if (!np)
                return -ENXIO;
 
-       led->ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS);
-       ret = PTR_ERR_OR_ZERO(led->ctrl_gpio);
+       led->props.ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS);
+       ret = PTR_ERR_OR_ZERO(led->props.ctrl_gpio);
        if (ret)
                return dev_err_probe(dev, ret, "cannot get ctrl-gpios\n");
 
@@ -412,6 +349,7 @@ static struct platform_driver ktd2692_driver = {
 
 module_platform_driver(ktd2692_driver);
 
+MODULE_IMPORT_NS(EXPRESSWIRE);
 MODULE_AUTHOR("Ingi Kim <ingi2.kim@samsung.com>");
 MODULE_DESCRIPTION("Kinetic KTD2692 LED driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-expresswire.c b/drivers/leds/leds-expresswire.c
new file mode 100644 (file)
index 0000000..e4937a8
--- /dev/null
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Shared library for Kinetic's ExpressWire protocol.
+ * This protocol works by pulsing the ExpressWire IC's control GPIO.
+ * ktd2692 and ktd2801 are known to use this protocol.
+ */
+
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/gpio/consumer.h>
+#include <linux/types.h>
+
+#include <linux/leds-expresswire.h>
+
+void expresswire_power_off(struct expresswire_common_props *props)
+{
+       gpiod_set_value_cansleep(props->ctrl_gpio, 0);
+       usleep_range(props->timing.poweroff_us, props->timing.poweroff_us * 2);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_power_off, EXPRESSWIRE);
+
+void expresswire_enable(struct expresswire_common_props *props)
+{
+       gpiod_set_value(props->ctrl_gpio, 1);
+       udelay(props->timing.detect_delay_us);
+       gpiod_set_value(props->ctrl_gpio, 0);
+       udelay(props->timing.detect_us);
+       gpiod_set_value(props->ctrl_gpio, 1);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_enable, EXPRESSWIRE);
+
+void expresswire_start(struct expresswire_common_props *props)
+{
+       gpiod_set_value(props->ctrl_gpio, 1);
+       udelay(props->timing.data_start_us);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_start, EXPRESSWIRE);
+
+void expresswire_end(struct expresswire_common_props *props)
+{
+       gpiod_set_value(props->ctrl_gpio, 0);
+       udelay(props->timing.end_of_data_low_us);
+       gpiod_set_value(props->ctrl_gpio, 1);
+       udelay(props->timing.end_of_data_high_us);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_end, EXPRESSWIRE);
+
+void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
+{
+       if (bit) {
+               gpiod_set_value(props->ctrl_gpio, 0);
+               udelay(props->timing.short_bitset_us);
+               gpiod_set_value(props->ctrl_gpio, 1);
+               udelay(props->timing.long_bitset_us);
+       } else {
+               gpiod_set_value(props->ctrl_gpio, 0);
+               udelay(props->timing.long_bitset_us);
+               gpiod_set_value(props->ctrl_gpio, 1);
+               udelay(props->timing.short_bitset_us);
+       }
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_set_bit, EXPRESSWIRE);
+
+void expresswire_write_u8(struct expresswire_common_props *props, u8 val)
+{
+       expresswire_start(props);
+       for (int i = 7; i >= 0; i--)
+               expresswire_set_bit(props, val & BIT(i));
+       expresswire_end(props);
+}
+EXPORT_SYMBOL_NS_GPL(expresswire_write_u8, EXPRESSWIRE);
index ea2d0d69bd8cc11f6393bea249b9744d57fb86a7..230bca07b09dc99cb7253ea7d46912086ce9440d 100644 (file)
@@ -183,6 +183,13 @@ config BACKLIGHT_KTD253
          which is a 1-wire GPIO-controlled backlight found in some mobile
          phones.
 
+config BACKLIGHT_KTD2801
+       tristate "Backlight Driver for Kinetic KTD2801"
+       select LEDS_EXPRESSWIRE
+       help
+         Say Y to enable the backlight driver for the Kinetic KTD2801 1-wire
+         GPIO-controlled backlight found in Samsung Galaxy Core Prime VE LTE.
+
 config BACKLIGHT_KTZ8866
        tristate "Backlight Driver for Kinetic KTZ8866"
        depends on I2C
index 06966cb204597b74afffe16ba4814357843b2d86..8d2cb252042db76f2d02a2032f832b86797bb7aa 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_BACKLIGHT_HP680)         += hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_HP700)          += jornada720_bl.o
 obj-$(CONFIG_BACKLIGHT_IPAQ_MICRO)     += ipaq_micro_bl.o
 obj-$(CONFIG_BACKLIGHT_KTD253)         += ktd253-backlight.o
+obj-$(CONFIG_BACKLIGHT_KTD2801)                += ktd2801-backlight.o
 obj-$(CONFIG_BACKLIGHT_KTZ8866)                += ktz8866.o
 obj-$(CONFIG_BACKLIGHT_LM3533)         += lm3533_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3630A)                += lm3630a_bl.o
index 28437c2da0f5894003f3fab8055322539c2688ce..e6f66bb35ef596e9b5a2959a6039e5bce731b10a 100644 (file)
@@ -383,10 +383,8 @@ static int as3711_backlight_probe(struct platform_device *pdev)
 
        if (pdev->dev.parent->of_node) {
                ret = as3711_backlight_parse_dt(&pdev->dev);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "DT parsing failed: %d\n", ret);
-                       return ret;
-               }
+               if (ret < 0)
+                       return dev_err_probe(&pdev->dev, ret, "DT parsing failed\n");
        }
 
        if (!pdata->su1_fb && !pdata->su2_fb) {
index c95a12bf0ce263e015c31a2ade139e6e228cbd1a..b1e7126380ef2745b669f8189caa1b54f5fc9244 100644 (file)
@@ -119,7 +119,6 @@ static int bd6107_probe(struct i2c_client *client)
        struct backlight_device *backlight;
        struct backlight_properties props;
        struct bd6107 *bd;
-       int ret;
 
        if (pdata == NULL) {
                dev_err(&client->dev, "No platform data\n");
@@ -147,11 +146,9 @@ static int bd6107_probe(struct i2c_client *client)
         * the reset.
         */
        bd->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(bd->reset)) {
-               dev_err(&client->dev, "unable to request reset GPIO\n");
-               ret = PTR_ERR(bd->reset);
-               return ret;
-       }
+       if (IS_ERR(bd->reset))
+               return dev_err_probe(&client->dev, PTR_ERR(bd->reset),
+                                    "unable to request reset GPIO\n");
 
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
index 1cdc8543310b4d3ac06d41702ca3220cefc654ad..b8ff7046510eb90165c126c913c5678a4dcc61c5 100644 (file)
@@ -117,6 +117,7 @@ static int da9052_backlight_probe(struct platform_device *pdev)
        wleds->led_reg = platform_get_device_id(pdev)->driver_data;
        wleds->state = DA9052_WLEDS_OFF;
 
+       memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = DA9052_MAX_BRIGHTNESS;
 
index d28c30b2a35d23b4d66cc97258f709b4f2b22aa1..e0c8c2a3f5dc2bb6b2a59d1406ae17ad0f54f2ec 100644 (file)
@@ -64,13 +64,9 @@ static int gpio_backlight_probe(struct platform_device *pdev)
        def_value = device_property_read_bool(dev, "default-on");
 
        gbl->gpiod = devm_gpiod_get(dev, NULL, GPIOD_ASIS);
-       if (IS_ERR(gbl->gpiod)) {
-               ret = PTR_ERR(gbl->gpiod);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(dev,
-                               "Error: The gpios parameter is missing or invalid.\n");
-               return ret;
-       }
+       if (IS_ERR(gbl->gpiod))
+               return dev_err_probe(dev, PTR_ERR(gbl->gpiod),
+                                    "The gpios parameter is missing or invalid\n");
 
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
index d7298376cf74ddd89c4804ab297b621538ff15e2..339d9128fbdeb1499c2d47a6e2519248aeb199ad 100644 (file)
@@ -8,9 +8,9 @@
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/lcd.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/property.h>
 #include <linux/spi/spi.h>
 
 #define HX8357_NUM_IM_PINS     3
@@ -564,41 +564,28 @@ static struct lcd_ops hx8357_ops = {
        .get_power      = hx8357_get_power,
 };
 
-static const struct of_device_id hx8357_dt_ids[] = {
-       {
-               .compatible = "himax,hx8357",
-               .data = hx8357_lcd_init,
-       },
-       {
-               .compatible = "himax,hx8369",
-               .data = hx8369_lcd_init,
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
+typedef int (*hx8357_init_fn)(struct lcd_device *);
 
 static int hx8357_probe(struct spi_device *spi)
 {
        struct device *dev = &spi->dev;
        struct lcd_device *lcdev;
        struct hx8357_data *lcd;
-       const struct of_device_id *match;
+       hx8357_init_fn init_fn;
        int i, ret;
 
-       lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
+       lcd = devm_kzalloc(dev, sizeof(*lcd), GFP_KERNEL);
        if (!lcd)
                return -ENOMEM;
 
        ret = spi_setup(spi);
-       if (ret < 0) {
-               dev_err(&spi->dev, "SPI setup failed.\n");
-               return ret;
-       }
+       if (ret < 0)
+               return dev_err_probe(dev, ret, "SPI setup failed.\n");
 
        lcd->spi = spi;
 
-       match = of_match_device(hx8357_dt_ids, &spi->dev);
-       if (!match || !match->data)
+       init_fn = device_get_match_data(dev);
+       if (!init_fn)
                return -EINVAL;
 
        lcd->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
@@ -609,14 +596,15 @@ static int hx8357_probe(struct spi_device *spi)
        lcd->im_pins = devm_gpiod_get_array_optional(dev, "im", GPIOD_OUT_LOW);
        if (IS_ERR(lcd->im_pins))
                return dev_err_probe(dev, PTR_ERR(lcd->im_pins), "failed to request im GPIOs\n");
-       if (lcd->im_pins->ndescs < HX8357_NUM_IM_PINS)
-               return dev_err_probe(dev, -EINVAL, "not enough im GPIOs\n");
+       if (lcd->im_pins) {
+               if (lcd->im_pins->ndescs < HX8357_NUM_IM_PINS)
+                       return dev_err_probe(dev, -EINVAL, "not enough im GPIOs\n");
 
-       for (i = 0; i < HX8357_NUM_IM_PINS; i++)
-               gpiod_set_consumer_name(lcd->im_pins->desc[i], "im_pins");
+               for (i = 0; i < HX8357_NUM_IM_PINS; i++)
+                       gpiod_set_consumer_name(lcd->im_pins->desc[i], "im_pins");
+       }
 
-       lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd,
-                                       &hx8357_ops);
+       lcdev = devm_lcd_device_register(dev, "mxsfb", dev, lcd, &hx8357_ops);
        if (IS_ERR(lcdev)) {
                ret = PTR_ERR(lcdev);
                return ret;
@@ -625,17 +613,28 @@ static int hx8357_probe(struct spi_device *spi)
 
        hx8357_lcd_reset(lcdev);
 
-       ret = ((int (*)(struct lcd_device *))match->data)(lcdev);
-       if (ret) {
-               dev_err(&spi->dev, "Couldn't initialize panel\n");
-               return ret;
-       }
+       ret = init_fn(lcdev);
+       if (ret)
+               return dev_err_probe(dev, ret, "Couldn't initialize panel\n");
 
-       dev_info(&spi->dev, "Panel probed\n");
+       dev_info(dev, "Panel probed\n");
 
        return 0;
 }
 
+static const struct of_device_id hx8357_dt_ids[] = {
+       {
+               .compatible = "himax,hx8357",
+               .data = hx8357_lcd_init,
+       },
+       {
+               .compatible = "himax,hx8369",
+               .data = hx8369_lcd_init,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
+
 static struct spi_driver hx8357_driver = {
        .probe  = hx8357_probe,
        .driver = {
diff --git a/drivers/video/backlight/ktd2801-backlight.c b/drivers/video/backlight/ktd2801-backlight.c
new file mode 100644 (file)
index 0000000..d295c27
--- /dev/null
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Datasheet:
+ * https://www.kinet-ic.com/uploads/web/KTD2801/KTD2801-04b.pdf
+ */
+#include <linux/backlight.h>
+#include <linux/gpio/consumer.h>
+#include <linux/leds-expresswire.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+
+#define KTD2801_DEFAULT_BRIGHTNESS     100
+#define KTD2801_MAX_BRIGHTNESS         255
+
+/* These values have been extracted from Samsung's driver. */
+static const struct expresswire_timing ktd2801_timing = {
+       .poweroff_us = 2600,
+       .detect_delay_us = 150,
+       .detect_us = 270,
+       .data_start_us = 5,
+       .short_bitset_us = 5,
+       .long_bitset_us = 15,
+       .end_of_data_low_us = 10,
+       .end_of_data_high_us = 350
+};
+
+struct ktd2801_backlight {
+       struct expresswire_common_props props;
+       struct backlight_device *bd;
+       bool was_on;
+};
+
+static int ktd2801_update_status(struct backlight_device *bd)
+{
+       struct ktd2801_backlight *ktd2801 = bl_get_data(bd);
+       u8 brightness = (u8) backlight_get_brightness(bd);
+
+       if (backlight_is_blank(bd)) {
+               expresswire_power_off(&ktd2801->props);
+               ktd2801->was_on = false;
+               return 0;
+       }
+
+       if (!ktd2801->was_on) {
+               expresswire_enable(&ktd2801->props);
+               ktd2801->was_on = true;
+       }
+
+       expresswire_write_u8(&ktd2801->props, brightness);
+
+       return 0;
+}
+
+static const struct backlight_ops ktd2801_backlight_ops = {
+       .update_status = ktd2801_update_status,
+};
+
+static int ktd2801_backlight_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct backlight_device *bd;
+       struct ktd2801_backlight *ktd2801;
+       u32 brightness, max_brightness;
+       int ret;
+
+       ktd2801 = devm_kzalloc(dev, sizeof(*ktd2801), GFP_KERNEL);
+       if (!ktd2801)
+               return -ENOMEM;
+       ktd2801->was_on = true;
+       ktd2801->props.timing = ktd2801_timing;
+
+       ret = device_property_read_u32(dev, "max-brightness", &max_brightness);
+       if (ret)
+               max_brightness = KTD2801_MAX_BRIGHTNESS;
+       if (max_brightness > KTD2801_MAX_BRIGHTNESS) {
+               dev_err(dev, "illegal max brightness specified\n");
+               max_brightness = KTD2801_MAX_BRIGHTNESS;
+       }
+
+       ret = device_property_read_u32(dev, "default-brightness", &brightness);
+       if (ret)
+               brightness = KTD2801_DEFAULT_BRIGHTNESS;
+       if (brightness > max_brightness) {
+               dev_err(dev, "default brightness exceeds max\n");
+               brightness = max_brightness;
+       }
+
+       ktd2801->props.ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_OUT_HIGH);
+       if (IS_ERR(ktd2801->props.ctrl_gpio))
+               return dev_err_probe(dev, PTR_ERR(ktd2801->props.ctrl_gpio),
+                               "failed to get backlight GPIO");
+       gpiod_set_consumer_name(ktd2801->props.ctrl_gpio, dev_name(dev));
+
+       bd = devm_backlight_device_register(dev, dev_name(dev), dev, ktd2801,
+                       &ktd2801_backlight_ops, NULL);
+       if (IS_ERR(bd))
+               return dev_err_probe(dev, PTR_ERR(bd),
+                               "failed to register backlight");
+
+       bd->props.max_brightness = max_brightness;
+       bd->props.brightness = brightness;
+
+       ktd2801->bd = bd;
+       platform_set_drvdata(pdev, bd);
+       backlight_update_status(bd);
+
+       return 0;
+}
+
+static const struct of_device_id ktd2801_of_match[] = {
+       { .compatible = "kinetic,ktd2801" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ktd2801_of_match);
+
+static struct platform_driver ktd2801_backlight_driver = {
+       .driver = {
+               .name = "ktd2801-backlight",
+               .of_match_table = ktd2801_of_match,
+       },
+       .probe = ktd2801_backlight_probe,
+};
+module_platform_driver(ktd2801_backlight_driver);
+
+MODULE_IMPORT_NS(EXPRESSWIRE);
+MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>");
+MODULE_DESCRIPTION("Kinetic KTD2801 Backlight Driver");
+MODULE_LICENSE("GPL");
index 9c980f2571ee3594cbefda4e7a13950210d8669d..014877b5a9848f27c71e5003299669d39fd6da8e 100644 (file)
@@ -97,20 +97,20 @@ static void ktz8866_init(struct ktz8866 *ktz)
 {
        unsigned int val = 0;
 
-       if (of_property_read_u32(ktz->client->dev.of_node, "current-num-sinks", &val))
+       if (!of_property_read_u32(ktz->client->dev.of_node, "current-num-sinks", &val))
                ktz8866_write(ktz, BL_EN, BIT(val) - 1);
        else
                /* Enable all 6 current sinks if the number of current sinks isn't specified. */
                ktz8866_write(ktz, BL_EN, BIT(6) - 1);
 
-       if (of_property_read_u32(ktz->client->dev.of_node, "kinetic,current-ramp-delay-ms", &val)) {
+       if (!of_property_read_u32(ktz->client->dev.of_node, "kinetic,current-ramp-delay-ms", &val)) {
                if (val <= 128)
                        ktz8866_write(ktz, BL_CFG2, BIT(7) | (ilog2(val) << 3) | PWM_HYST);
                else
                        ktz8866_write(ktz, BL_CFG2, BIT(7) | ((5 + val / 64) << 3) | PWM_HYST);
        }
 
-       if (of_property_read_u32(ktz->client->dev.of_node, "kinetic,led-enable-ramp-delay-ms", &val)) {
+       if (!of_property_read_u32(ktz->client->dev.of_node, "kinetic,led-enable-ramp-delay-ms", &val)) {
                if (val == 0)
                        ktz8866_write(ktz, BL_DIMMING, 0);
                else {
index cc763cf15f53e695c541bd28df5f4e111af627a6..bd5137ee203badab41167203828c1e7fb031e866 100644 (file)
@@ -179,34 +179,28 @@ static int l4f00242t03_probe(struct spi_device *spi)
        priv->spi = spi;
 
        priv->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
-       if (IS_ERR(priv->reset)) {
-               dev_err(&spi->dev,
-                       "Unable to get the lcd l4f00242t03 reset gpio.\n");
-               return PTR_ERR(priv->reset);
-       }
+       if (IS_ERR(priv->reset))
+               return dev_err_probe(&spi->dev, PTR_ERR(priv->reset),
+                                    "Unable to get the lcd l4f00242t03 reset gpio.\n");
        gpiod_set_consumer_name(priv->reset, "lcd l4f00242t03 reset");
 
        priv->enable = devm_gpiod_get(&spi->dev, "enable", GPIOD_OUT_LOW);
-       if (IS_ERR(priv->enable)) {
-               dev_err(&spi->dev,
-                       "Unable to get the lcd l4f00242t03 data en gpio.\n");
-               return PTR_ERR(priv->enable);
-       }
+       if (IS_ERR(priv->enable))
+               return dev_err_probe(&spi->dev, PTR_ERR(priv->enable),
+                                    "Unable to get the lcd l4f00242t03 data en gpio.\n");
        gpiod_set_consumer_name(priv->enable, "lcd l4f00242t03 data enable");
 
        priv->io_reg = devm_regulator_get(&spi->dev, "vdd");
-       if (IS_ERR(priv->io_reg)) {
-               dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
-                      __func__);
-               return PTR_ERR(priv->io_reg);
-       }
+       if (IS_ERR(priv->io_reg))
+               return dev_err_probe(&spi->dev, PTR_ERR(priv->io_reg),
+                                    "%s: Unable to get the IO regulator\n",
+                                    __func__);
 
        priv->core_reg = devm_regulator_get(&spi->dev, "vcore");
-       if (IS_ERR(priv->core_reg)) {
-               dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
-                      __func__);
-               return PTR_ERR(priv->core_reg);
-       }
+       if (IS_ERR(priv->core_reg))
+               return dev_err_probe(&spi->dev, PTR_ERR(priv->core_reg),
+                                    "%s: Unable to get the core regulator\n",
+                                    __func__);
 
        priv->ld = devm_lcd_device_register(&spi->dev, "l4f00242t03", &spi->dev,
                                        priv, &l4f_ops);
index a3412c936ca28cfb38544aa4a3c3eb7f1c0155ad..76d47e2e82427017d0cc25997245f77d720c9f71 100644 (file)
@@ -189,10 +189,11 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl)
        int ret;
        struct lm3630a_chip *pchip = bl_get_data(bl);
        enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+       int brightness = backlight_get_brightness(bl);
 
        /* pwm control */
        if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0)
-               return lm3630a_pwm_ctrl(pchip, bl->props.brightness,
+               return lm3630a_pwm_ctrl(pchip, brightness,
                                        bl->props.max_brightness);
 
        /* disable sleep */
@@ -201,9 +202,9 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl)
                goto out_i2c_err;
        usleep_range(1000, 2000);
        /* minimum brightness is 0x04 */
-       ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness);
+       ret = lm3630a_write(pchip, REG_BRT_A, brightness);
 
-       if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4))
+       if (brightness < 0x4)
                /* turn the string off  */
                ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0);
        else
@@ -233,7 +234,7 @@ static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
                if (rval < 0)
                        goto out_i2c_err;
                brightness |= rval;
-               goto out;
+               return brightness;
        }
 
        /* disable sleep */
@@ -244,11 +245,8 @@ static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
        rval = lm3630a_read(pchip, REG_BRT_A);
        if (rval < 0)
                goto out_i2c_err;
-       brightness = rval;
+       return rval;
 
-out:
-       bl->props.brightness = brightness;
-       return bl->props.brightness;
 out_i2c_err:
        dev_err(pchip->dev, "i2c failed to access register\n");
        return 0;
@@ -266,10 +264,11 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl)
        int ret;
        struct lm3630a_chip *pchip = bl_get_data(bl);
        enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+       int brightness = backlight_get_brightness(bl);
 
        /* pwm control */
        if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0)
-               return lm3630a_pwm_ctrl(pchip, bl->props.brightness,
+               return lm3630a_pwm_ctrl(pchip, brightness,
                                        bl->props.max_brightness);
 
        /* disable sleep */
@@ -278,9 +277,9 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl)
                goto out_i2c_err;
        usleep_range(1000, 2000);
        /* minimum brightness is 0x04 */
-       ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness);
+       ret = lm3630a_write(pchip, REG_BRT_B, brightness);
 
-       if (backlight_is_blank(bl) || (backlight_get_brightness(bl) < 0x4))
+       if (brightness < 0x4)
                /* turn the string off  */
                ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0);
        else
@@ -310,7 +309,7 @@ static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
                if (rval < 0)
                        goto out_i2c_err;
                brightness |= rval;
-               goto out;
+               return brightness;
        }
 
        /* disable sleep */
@@ -321,11 +320,8 @@ static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
        rval = lm3630a_read(pchip, REG_BRT_B);
        if (rval < 0)
                goto out_i2c_err;
-       brightness = rval;
+       return rval;
 
-out:
-       bl->props.brightness = brightness;
-       return bl->props.brightness;
 out_i2c_err:
        dev_err(pchip->dev, "i2c failed to access register\n");
        return 0;
@@ -343,6 +339,7 @@ static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
        struct backlight_properties props;
        const char *label;
 
+       memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
                props.brightness = pdata->leda_init_brt;
@@ -543,10 +540,8 @@ static int lm3630a_probe(struct i2c_client *client)
 
        pchip->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
                                                GPIOD_OUT_HIGH);
-       if (IS_ERR(pchip->enable_gpio)) {
-               rval = PTR_ERR(pchip->enable_gpio);
-               return rval;
-       }
+       if (IS_ERR(pchip->enable_gpio))
+               return PTR_ERR(pchip->enable_gpio);
 
        /* chip initialize */
        rval = lm3630a_chip_init(pchip);
@@ -563,10 +558,9 @@ static int lm3630a_probe(struct i2c_client *client)
        /* pwm */
        if (pdata->pwm_ctrl != LM3630A_PWM_DISABLE) {
                pchip->pwmd = devm_pwm_get(pchip->dev, "lm3630a-pwm");
-               if (IS_ERR(pchip->pwmd)) {
-                       dev_err(&client->dev, "fail : get pwm device\n");
-                       return PTR_ERR(pchip->pwmd);
-               }
+               if (IS_ERR(pchip->pwmd))
+                       return dev_err_probe(&client->dev, PTR_ERR(pchip->pwmd),
+                                            "fail : get pwm device\n");
 
                pwm_init_state(pchip->pwmd, &pchip->pwmd_state);
        }
index 5246c171497d6fa4dfb9265b333296cf087adb12..564f62acd7211ea8386a4c383a7ed6c6b6065ccc 100644 (file)
@@ -338,6 +338,7 @@ static int lm3639_probe(struct i2c_client *client)
        }
 
        /* backlight */
+       memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.brightness = pdata->init_brt_led;
        props.max_brightness = pdata->max_brt_led;
index d1a14b0db265b7ce303662b789c2f13c4f21837a..31f97230ee506a55eb1632ef34d5a17e2fc9075a 100644 (file)
@@ -191,6 +191,7 @@ static int lp8788_backlight_register(struct lp8788_bl *bl)
        int init_brt;
        char *name;
 
+       memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = MAX_BRIGHTNESS;
 
index 34d71259fac1d7da3222f02ef8bc716a8e54f25c..c80a1481e742bb77eaa061f674e5642d5100cbfe 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
 #include <linux/pwm.h>
 #include <linux/regmap.h>
 
@@ -131,7 +133,7 @@ static int mp3309c_bl_update_status(struct backlight_device *bl)
                                            chip->pdata->levels[brightness],
                                            chip->pdata->levels[chip->pdata->max_brightness]);
                pwmstate.enabled = true;
-               ret = pwm_apply_state(chip->pwmd, &pwmstate);
+               ret = pwm_apply_might_sleep(chip->pwmd, &pwmstate);
                if (ret)
                        return ret;
 
@@ -199,20 +201,15 @@ static const struct backlight_ops mp3309c_bl_ops = {
        .update_status = mp3309c_bl_update_status,
 };
 
-static int pm3309c_parse_dt_node(struct mp3309c_chip *chip,
-                                struct mp3309c_platform_data *pdata)
+static int mp3309c_parse_fwnode(struct mp3309c_chip *chip,
+                               struct mp3309c_platform_data *pdata)
 {
-       struct device_node *node = chip->dev->of_node;
-       struct property *prop_pwms;
-       struct property *prop_levels = NULL;
-       int length = 0;
        int ret, i;
        unsigned int num_levels, tmp_value;
+       struct device *dev = chip->dev;
 
-       if (!node) {
-               dev_err(chip->dev, "failed to get DT node\n");
-               return -ENODEV;
-       }
+       if (!dev_fwnode(dev))
+               return dev_err_probe(dev, -ENODEV, "failed to get firmware node\n");
 
        /*
         * Dimming mode: the MP3309C provides two dimming control mode:
@@ -224,12 +221,10 @@ static int pm3309c_parse_dt_node(struct mp3309c_chip *chip,
         * found in the backlight node, the mode switches to PWM mode.
         */
        pdata->dimming_mode = DIMMING_ANALOG_I2C;
-       prop_pwms = of_find_property(node, "pwms", &length);
-       if (prop_pwms) {
-               chip->pwmd = devm_pwm_get(chip->dev, NULL);
+       if (device_property_present(dev, "pwms")) {
+               chip->pwmd = devm_pwm_get(dev, NULL);
                if (IS_ERR(chip->pwmd))
-                       return dev_err_probe(chip->dev, PTR_ERR(chip->pwmd),
-                                            "error getting pwm data\n");
+                       return dev_err_probe(dev, PTR_ERR(chip->pwmd), "error getting pwm data\n");
                pdata->dimming_mode = DIMMING_PWM;
                pwm_apply_args(chip->pwmd);
        }
@@ -247,21 +242,17 @@ static int pm3309c_parse_dt_node(struct mp3309c_chip *chip,
                num_levels = ANALOG_I2C_NUM_LEVELS;
 
                /* Enable GPIO used in I2C dimming mode only */
-               chip->enable_gpio = devm_gpiod_get(chip->dev, "enable",
-                                                  GPIOD_OUT_HIGH);
+               chip->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
                if (IS_ERR(chip->enable_gpio))
-                       return dev_err_probe(chip->dev,
-                                            PTR_ERR(chip->enable_gpio),
+                       return dev_err_probe(dev, PTR_ERR(chip->enable_gpio),
                                             "error getting enable gpio\n");
        } else {
                /*
                 * PWM control mode: check for brightness level in DT
                 */
-               prop_levels = of_find_property(node, "brightness-levels",
-                                              &length);
-               if (prop_levels) {
+               if (device_property_present(dev, "brightness-levels")) {
                        /* Read brightness levels from DT */
-                       num_levels = length / sizeof(u32);
+                       num_levels = device_property_count_u32(dev, "brightness-levels");
                        if (num_levels < 2)
                                return -EINVAL;
                } else {
@@ -271,14 +262,12 @@ static int pm3309c_parse_dt_node(struct mp3309c_chip *chip,
        }
 
        /* Fill brightness levels array */
-       pdata->levels = devm_kcalloc(chip->dev, num_levels,
-                                    sizeof(*pdata->levels), GFP_KERNEL);
+       pdata->levels = devm_kcalloc(dev, num_levels, sizeof(*pdata->levels), GFP_KERNEL);
        if (!pdata->levels)
                return -ENOMEM;
-       if (prop_levels) {
-               ret = of_property_read_u32_array(node, "brightness-levels",
-                                                pdata->levels,
-                                                num_levels);
+       if (device_property_present(dev, "brightness-levels")) {
+               ret = device_property_read_u32_array(dev, "brightness-levels",
+                                                    pdata->levels, num_levels);
                if (ret < 0)
                        return ret;
        } else {
@@ -288,13 +277,11 @@ static int pm3309c_parse_dt_node(struct mp3309c_chip *chip,
 
        pdata->max_brightness = num_levels - 1;
 
-       ret = of_property_read_u32(node, "default-brightness",
-                                  &pdata->default_brightness);
+       ret = device_property_read_u32(dev, "default-brightness", &pdata->default_brightness);
        if (ret)
                pdata->default_brightness = pdata->max_brightness;
        if (pdata->default_brightness > pdata->max_brightness) {
-               dev_err(chip->dev,
-                       "default brightness exceeds max brightness\n");
+               dev_err_probe(dev, -ERANGE, "default brightness exceeds max brightness\n");
                pdata->default_brightness = pdata->max_brightness;
        }
 
@@ -310,8 +297,8 @@ static int pm3309c_parse_dt_node(struct mp3309c_chip *chip,
         * If missing, the default value for OVP is 35.5V
         */
        pdata->over_voltage_protection = REG_I2C_1_OVP1;
-       if (!of_property_read_u32(node, "mps,overvoltage-protection-microvolt",
-                                 &tmp_value)) {
+       ret = device_property_read_u32(dev, "mps,overvoltage-protection-microvolt", &tmp_value);
+       if (!ret) {
                switch (tmp_value) {
                case 13500000:
                        pdata->over_voltage_protection = 0x00;
@@ -328,62 +315,59 @@ static int pm3309c_parse_dt_node(struct mp3309c_chip *chip,
        }
 
        /* Synchronous (default) and non-synchronous mode */
-       pdata->sync_mode = true;
-       if (of_property_read_bool(node, "mps,no-sync-mode"))
-               pdata->sync_mode = false;
+       pdata->sync_mode = !device_property_read_bool(dev, "mps,no-sync-mode");
 
        return 0;
 }
 
 static int mp3309c_probe(struct i2c_client *client)
 {
-       struct mp3309c_platform_data *pdata = dev_get_platdata(&client->dev);
+       struct device *dev = &client->dev;
+       struct mp3309c_platform_data *pdata = dev_get_platdata(dev);
        struct mp3309c_chip *chip;
        struct backlight_properties props;
        struct pwm_state pwmstate;
        int ret;
 
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               dev_err(&client->dev, "failed to check i2c functionality\n");
-               return -EOPNOTSUPP;
-       }
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return dev_err_probe(dev, -EOPNOTSUPP, "failed to check i2c functionality\n");
 
-       chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
                return -ENOMEM;
 
-       chip->dev = &client->dev;
+       chip->dev = dev;
 
        chip->regmap = devm_regmap_init_i2c(client, &mp3309c_regmap);
        if (IS_ERR(chip->regmap))
-               return dev_err_probe(&client->dev, PTR_ERR(chip->regmap),
+               return dev_err_probe(dev, PTR_ERR(chip->regmap),
                                     "failed to allocate register map\n");
 
        i2c_set_clientdata(client, chip);
 
        if (!pdata) {
-               pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
+               pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
                if (!pdata)
                        return -ENOMEM;
 
-               ret = pm3309c_parse_dt_node(chip, pdata);
+               ret = mp3309c_parse_fwnode(chip, pdata);
                if (ret)
                        return ret;
        }
        chip->pdata = pdata;
 
        /* Backlight properties */
+       memset(&props, 0, sizeof(struct backlight_properties));
        props.brightness = pdata->default_brightness;
        props.max_brightness = pdata->max_brightness;
        props.scale = BACKLIGHT_SCALE_LINEAR;
        props.type = BACKLIGHT_RAW;
        props.power = FB_BLANK_UNBLANK;
        props.fb_blank = FB_BLANK_UNBLANK;
-       chip->bl = devm_backlight_device_register(chip->dev, "mp3309c",
-                                                 chip->dev, chip,
+       chip->bl = devm_backlight_device_register(dev, "mp3309c", dev, chip,
                                                  &mp3309c_bl_ops, &props);
        if (IS_ERR(chip->bl))
-               return dev_err_probe(chip->dev, PTR_ERR(chip->bl),
+               return dev_err_probe(dev, PTR_ERR(chip->bl),
                                     "error registering backlight device\n");
 
        /* In PWM dimming mode, enable pwm device */
@@ -393,10 +377,9 @@ static int mp3309c_probe(struct i2c_client *client)
                                            chip->pdata->default_brightness,
                                            chip->pdata->max_brightness);
                pwmstate.enabled = true;
-               ret = pwm_apply_state(chip->pwmd, &pwmstate);
+               ret = pwm_apply_might_sleep(chip->pwmd, &pwmstate);
                if (ret)
-                       return dev_err_probe(chip->dev, ret,
-                                            "error setting pwm device\n");
+                       return dev_err_probe(dev, ret, "error setting pwm device\n");
        }
 
        chip->pdata->status = FIRST_POWER_ON;
index f946470ce9f6549047ae573cc9dd8338ac046a09..51faa889e01f42e3a679fd3113261c80c8ec8691 100644 (file)
@@ -114,10 +114,8 @@ static int pandora_backlight_probe(struct platform_device *pdev)
        u8 r;
 
        priv = devm_kmalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv) {
-               dev_err(&pdev->dev, "failed to allocate driver private data\n");
+       if (!priv)
                return -ENOMEM;
-       }
 
        memset(&props, 0, sizeof(props));
        props.max_brightness = MAX_USER_VALUE;
diff --git a/include/linux/leds-expresswire.h b/include/linux/leds-expresswire.h
new file mode 100644 (file)
index 0000000..a422921
--- /dev/null
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Shared library for Kinetic's ExpressWire protocol.
+ * This protocol works by pulsing the ExpressWire IC's control GPIO.
+ * ktd2692 and ktd2801 are known to use this protocol.
+ */
+
+#ifndef _LEDS_EXPRESSWIRE_H
+#define _LEDS_EXPRESSWIRE_H
+
+#include <linux/types.h>
+
+struct gpio_desc;
+
+struct expresswire_timing {
+       unsigned long poweroff_us;
+       unsigned long detect_delay_us;
+       unsigned long detect_us;
+       unsigned long data_start_us;
+       unsigned long end_of_data_low_us;
+       unsigned long end_of_data_high_us;
+       unsigned long short_bitset_us;
+       unsigned long long_bitset_us;
+};
+
+struct expresswire_common_props {
+       struct gpio_desc *ctrl_gpio;
+       struct expresswire_timing timing;
+};
+
+void expresswire_power_off(struct expresswire_common_props *props);
+void expresswire_enable(struct expresswire_common_props *props);
+void expresswire_start(struct expresswire_common_props *props);
+void expresswire_end(struct expresswire_common_props *props);
+void expresswire_set_bit(struct expresswire_common_props *props, bool bit);
+void expresswire_write_u8(struct expresswire_common_props *props, u8 val);
+
+#endif /* _LEDS_EXPRESSWIRE_H */