Re: [PATCH 1/2] platform/x86: Add new Dell UART backlight driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, May 12, 2024 at 7:24 PM Hans de Goede <hdegoede@xxxxxxxxxx> wrote:
>
> Dell All In One (AIO) models released after 2017 use a backlight controller
> board connected to an UART.
>
> In DSDT this uart port will be defined as:
>
>    Name (_HID, "DELL0501")
>    Name (_CID, EisaId ("PNP0501")
>
> Instead of having a separate ACPI device with an UartSerialBusV2() resource
> to model the backlight-controller, which would be the standard way to do
> this.
>
> The acpi_quirk_skip_serdev_enumeration() has special handling for this
> and it will make the serial port code create a serdev controller device
> for the UART instead of a /dev/ttyS0 char-dev. It will also create
> a dell-uart-backlight driver platform device for this driver to bind too.
>
> This new kernel module contains 2 drivers for this:
>
> 1. A simple platform driver which creates the actual serdev device
>    (with the serdev controller device as parent)
>
> 2. A serdev driver for the created serdev device which exports
>    the backlight functionality uses a standard backlight class device.

...

> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

How is this being used?

...

> +#include <linux/acpi.h>

+ array_size.h

> +#include <linux/backlight.h>
> +#include <linux/delay.h>

+ device.h // devm_kzalloc(), dev_err() et al.

+ err.h

> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_device.h>
> +#include <linux/serdev.h>

+ string.h
+ types.h

> +#include <linux/wait.h>

> +/* The backlight controller must respond within 1 second */
> +#define DELL_BL_TIMEOUT                msecs_to_jiffies(1000)

...

> +static int dell_uart_get_brightness(struct dell_uart_backlight *dell_bl)
> +{
> +       /*
> +        * Get Brightness level: Application uses this command to get brightness.
> +        * Command: 0x6A 0x0C 0x89 (Length:3 Type:0x0A Cmd:0x0C Checksum:0x89)
> +        * Return data: 0x04 0x0C Data Checksum
> +        *              (Length:4 Cmd:0x0C Data:<brightness level>
> +        *               Checksum: SUM(Length and Cmd and Data) xor 0xFF)
> +        *              <brightness level> ranges from 0~100.
> +        */
> +       const u8 get_brightness[] = { 0x6A, 0x0C, 0x89 };
> +       u8 resp[4];
> +       int ret;
> +
> +       ret = dell_uart_bl_command(dell_bl, get_brightness, ARRAY_SIZE(get_brightness),
> +                                  resp, ARRAY_SIZE(resp));
> +       if (ret)
> +               return ret;
> +
> +       if (resp[0] != 4) {

ARRAY_SIZE() as you used it in many other similar places.

> +               dev_err(dell_bl->dev, "Unexpected get brightness response length: %d\n", resp[0]);
> +               return -EIO;
> +       }

> +       if (resp[2] > 100) {

(see also below about this number)

> +               dev_err(dell_bl->dev, "Unexpected get brightness response: %d\n", resp[2]);
> +               return -EIO;
> +       }
> +
> +       return resp[2];
> +}
> +
> +static int dell_uart_set_bl_power(struct dell_uart_backlight *dell_bl, int power)
> +{
> +       /*
> +        * Screen ON/OFF Control: Application uses this command to control screen ON or OFF.
> +        * Command: 0x8A 0x0E Data Checksum (Length:4 Type:0x0A Cmd:0x0E) where
> +        *          Data=0 to turn OFF the screen.
> +        *          Data=1 to turn ON the screen.
> +        *          Other value of Data is reserved and invalid.

values
are reserved

> +        * Return data: 0x03 0x0E 0xEE (Length:3 Cmd:0x0E Checksum:0xEE)
> +        */
> +       u8 set_power[] = { 0x8A, 0x0E, 0x00, 0x00 };
> +       u8 resp[3];
> +       int ret;
> +
> +       set_power[2] = (power == FB_BLANK_UNBLANK) ? 1 : 0;
> +       set_power[3] = dell_uart_checksum(set_power, 3);
> +
> +       ret = dell_uart_bl_command(dell_bl, set_power, ARRAY_SIZE(set_power),
> +                                  resp, ARRAY_SIZE(resp));
> +       if (ret)
> +               return ret;
> +
> +       dell_bl->power = power;
> +       return 0;
> +}

...

> +static int dell_uart_update_status(struct backlight_device *bd)
> +{
> +       struct dell_uart_backlight *dell_bl = bl_get_data(bd);
> +       int ret;
> +
> +       ret = dell_uart_set_brightness(dell_bl, bd->props.brightness);
> +       if (ret)
> +               return ret;
> +
> +       if (bd->props.power != dell_uart_get_bl_power(dell_bl))
> +               ret = dell_uart_set_bl_power(dell_bl, bd->props.power);

    return ...;

> +       return ret;

  return 0;

?

> +}

...

> +       props.max_brightness = 100;

Isn't it the same number (semantically) that is used in one of the
above functions? Perhaps define it?

...

> +       if (IS_ERR(dell_bl->bl))
> +               return PTR_ERR(dell_bl->bl);
> +
> +       return 0;

  return PTR_ERR_OR_ZERO(...);

...

Haven't noticed MODULE_DEVICE_TABLE(). Is it supposed to be
autoloaded? If so, how would it happen? Ah, okay, you are using
MODULE_ALIAS().

--
With Best Regards,
Andy Shevchenko





[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux