On 2/11/22 12:33, Andy Shevchenko wrote: > On Fri, Feb 11, 2022 at 10:19:24AM +0100, Javier Martinez Canillas wrote: >> This adds a DRM driver for SSD1305, SSD1306, SSD1307 and SSD1309 Solomon >> OLED display controllers. >> >> It's only the core part of the driver and a bus specific driver is needed >> for each transport interface supported by the display controllers. > > ... > >> +#include <linux/backlight.h> >> +#include <linux/bitfield.h> > > bits.h Ok, missed that both weren't in the same macro. > (FYI, specifically sent a patch few days ago to add explicitly the inclusions > that needed for bitfield operations in the example inside bitfield.h). > >> +#include <linux/delay.h> >> +#include <linux/gpio/consumer.h> >> +#include <linux/property.h> >> +#include <linux/pwm.h> >> +#include <linux/regulator/consumer.h> > > ... > >> +#define SSD130X_SET_ADDRESS_MODE_HORIZONTAL (0x00) >> +#define SSD130X_SET_ADDRESS_MODE_VERTICAL (0x01) >> +#define SSD130X_SET_ADDRESS_MODE_PAGE (0x02) >> + >> +#define SSD130X_SET_AREA_COLOR_MODE_ENABLE (0x1e) >> +#define SSD130X_SET_AREA_COLOR_MODE_LOW_POWER (0x05) > > Do the parentheses add anything here? > Not really, the fbdev driver used it and I understood that was a convention to denote that these are command options and not a command or register. I'll drop them. > ... > >> +/* >> + * Helper to write command (SSD130X_COMMAND). The fist variadic argument >> + * is the command to write and the following are the command options. > > This is not correct explanation. Please, rephrase to show that _each_ of the > options is sent with a preceding command. > It's a correct explanation IMO from the caller point of view. The first argument is the command sent (i.e: SSD130X_SET_ADDRESS_MODE) and the next ones are the the command options (i.e: SSD130X_SET_ADDRESS_MODE_HORIZONTAL). The fact that each command and options are preceding with a SSD130X_COMMAND value is part of the protocol of the device and a detail that's abstracted away by this helper function to the callers. >> + */ >> +static int ssd130x_write_cmd(struct ssd130x_device *ssd130x, int count, >> + /* u8 cmd, u8 option, ... */...) >> +{ >> + va_list ap; >> + u8 value; >> + int ret; >> + >> + va_start(ap, count); >> + >> + do { >> + value = va_arg(ap, int); >> + ret = regmap_write(ssd130x->regmap, SSD130X_COMMAND, (u8)value); >> + if (ret) >> + goto out_end; >> + } while (--count); >> + >> +out_end: >> + va_end(ap); >> + >> + return ret; >> +} > > ... > >> + if (ssd130x->device_info->need_pwm) { > > Yeah, unfortunately we still don't have pwm_get_optional()... > >> + ret = ssd130x_pwm_enable(ssd130x); >> + if (ret) { >> + dev_err(dev, "Failed to enable PWM: %d\n", ret); >> + regulator_disable(ssd130x->vcc_reg); >> + return ret; >> + } >> + } > > ... > >> +static void ssd130x_power_off(struct ssd130x_device *ssd130x) >> +{ > >> + if (ssd130x->device_info->need_pwm) { > > Redundant check. The two below are NULL-aware. > Ok, I'll drop it. >> + pwm_disable(ssd130x->pwm); >> + pwm_put(ssd130x->pwm); >> + } >> + >> + regulator_disable(ssd130x->vcc_reg); >> +} > > ... > >> + ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_COM_PINS_CONFIG, compins); >> + if (ret < 0) >> + return ret; > >> + >> + > > One blank line is enough. > Indeed, that was a left over when changing this to use the macros. > ... > >> + for (i = y / 8; i < y / 8 + pages; i++) { >> + int m = 8; >> + >> + /* Last page may be partial */ >> + if (8 * (i + 1) > ssd130x->height) >> + m = ssd130x->height % 8; > > Perhaps it can be moved out of the loop with refactored piece below. > Not sure I'm following since it depends on the for loop iterator value. [snip] >> + bl = devm_backlight_device_register(dev, dev_name(dev), dev, ssd130x, >> + &ssd130xfb_bl_ops, NULL); >> + if (IS_ERR(bl)) { > >> + ret = PTR_ERR(bl); >> + dev_err_probe(dev, ret, "Unable to register backlight device\n"); >> + return ERR_PTR(ret); > > dev_err_probe(dev, PTR_ERR(bl), "Unable to register backlight device\n"); > return bl; > > ? No, because this function's return value is a struct ssd130x_device pointer, not a struct backlight_device pointer. Best regards, -- Javier Martinez Canillas Linux Engineering Red Hat