All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09  9:03 ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, linux-pwm, David Airlie, Daniel Vetter, dri-devel,
	Thierry Reding, Lee Jones, Sam Ravnborg,
	Javier Martinez Canillas, Noralf Trønnes,
	Geert Uytterhoeven, Uwe Kleine-König, devicetree,
	Thomas Zimmermann, Mark Brown, Maxime Ripard, Andy Shevchenko,
	Liam Girdwood, Rob Herring

This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.

Using the DRM fb emulation, all the tests from Geert Uytterhoeven's fbtest
(https://git.kernel.org/pub/scm/linux/kernel/git/geert/fbtest.git) passes.

I've also tested it using the display as a VT output and even though fbcon
seems to work, it is mostly unusable on a 128x64 SSD1306 display.

This is a v3 that addresses all the issues pointed in v2. Thanks a lot
to everyone that gave me feedback and reviews.

Patch #1 splits per-line conversion logic in drm_fb_xrgb8888_to_gray8() to
a separate drm_fb_xrgb8888_to_gray8_line() helper function.

Patch #2 adds two new helpers, drm_fb_gray8_to_mono_reversed() to convert
from grayscale to monochrome and a drm_fb_xrgb8888_to_mono_reversed() to
convert from XR24 to monochrome. The latter internally converts each line
first to gray8 and then to reversed monochrome.

Patch #3 adds the driver. This only has the core support but doesn't have
any bus specific code, separate drivers are needed for the transport used.

Patch #4 adds a driver to use the I2C bus to communicate with the device
and patch #5 adds a similar driver for SPI. This one is a WIP and wasn't
tested. I'm including for people to test and modify for their displays.

Patch #6 just adds a MAINTAINERS entry for the DRM driver and patch #7
adds myself as a co-maintainer of the existing Device Tree binding for
ssd1307fb, since the same is shared between the fbdev and DRM drivers.

Best regards,
Javier

Changes in v3:
- Add a drm_fb_xrgb8888_to_gray8_line() helper function (Thomas Zimmermann)
- Also add a drm_fb_xrgb8888_to_mono_reversed() helper (Thomas Zimmermann)
- Split lines copy to drm_fb_gray8_to_mono_reversed_line() (Thomas Zimmermann)
- Handle case where the source buffer is not aligned to 8 (Thomas Zimmermann)
- Move driver from tiny sub-dir to drivers/gpu/drm/solomon (Sam Ravnborg)
- Split driver in a bus agnostic core and bus specific (Andy Shevchenko)
- Use regmap to access the chip registers (Andy Shevchenko)
- Remove unnecessary blank lines (Andy Shevchenko)
- Remove unneeded inline specifier in functions (Andy Shevchenko)
- Add a comment about always returning a single mode (Andy Shevchenko)
- Change write command logic to use do while loop (Andy Shevchenko)
- Use "firmware description" instead of "device tree" (Andy Shevchenko)
- Use return foo() instead of returning the return value (Andy Shevchenko)
- Don't split lines longer than 80 chars if makes less readable (Andy Shevchenko)
- Remove redundant else statements in .mode_valid callback (Andy Shevchenko)
- Rename powero{n,ff}() functions to power_o{n,ff)() (Andy Shevchenko)
- Use dev_err_probe() to prevent spam logs on probe deferral (Andy Shevchenko)
- Remove ',' after sentinel terminator in array (Andy Shevchenko)
- Fix a bug when doing partial updates (Geert Uytterhoeven)
- Add a separate driver for SSD130X chips I2C support (Andy Shevchenko)
- Add a separate driver for SSD130X chips SPI support (Andy Shevchenko)
- Adapt MAINTAINERS entry to point to the new drivers/gpu/drm/solomon directory.

Changes in v2:
- Drop patch that was adding a DRM_MODE_CONNECTOR_I2C type.
- Invert order of backlight {en,dis}able and display {on,off} (Sam Ravnborg)
- Don't clear the screen and turn on display on probe (Sam Ravnborg)
- Use backlight_get_brightness() macro to get BL brightness (Sam Ravnborg)
- Use dev managed version of devm_backlight_device_register() (Sam Ravnborg)
- Use dev_name(dev) for backlight name instead of an array (Sam Ravnborg)
- Drop the .get_brightness callback since isn't needed  (Sam Ravnborg)
- Rename driver to ssd130x since supports a display family (Thomas Zimmermann)
- Drop the TINY prefix from the Kconfig symbol (Thomas Zimmermann)
- Sort the Kconfig symbol dependencies alphabetically (Thomas Zimmermann)
- Rename struct ssd130x_array to struct ssd130x_i2c_msg (Thomas Zimmermann)
- Rename struct ssd130x_i2c_msg .type member to .cmd (Thomas Zimmermann)
- Use sizeof(*foo) instead of sizeof(struct foo) (Thomas Zimmermann)
- Use struct_size() macro to calculate sizeof(*foo) + len (Thomas Zimmermann)
- Use kcalloc() instead of kmalloc_array() + memset() (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Reorganize code in probe to make it more legible (Thomas Zimmermann)
- ssd130x_write_cmd() uses varargs to simplify I2C code (Thomas Zimmermann)
- Move regulator/pwm init logic to display pipe enable callback.
- Add Sam Ravnborg's acked-by to patch adding a MAINTAINERS entry (Sam Ravnborg)
- Add myself as co-maintainer of the ssd1370fb DT binding (Sam Ravnborg).

Javier Martinez Canillas (7):
  drm/format-helper: Add drm_fb_xrgb8888_to_gray8_line()
  drm/format-helper: Add drm_fb_{xrgb8888,gray8}_to_mono_reversed()
  drm: Add driver for Solomon SSD130X OLED displays
  drm/solomon: Add SSD130X OLED displays I2C support
  (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  MAINTAINERS: Add entry for Solomon SSD130X OLED displays DRM driver
  dt-bindings: display: ssd1307fb: Add myself as binding co-maintainer

 .../bindings/display/solomon,ssd1307fb.yaml   |   1 +
 MAINTAINERS                                   |   7 +
 drivers/gpu/drm/Kconfig                       |   2 +
 drivers/gpu/drm/Makefile                      |   1 +
 drivers/gpu/drm/drm_format_helper.c           | 188 +++-
 drivers/gpu/drm/solomon/Kconfig               |  30 +
 drivers/gpu/drm/solomon/Makefile              |   3 +
 drivers/gpu/drm/solomon/ssd130x-i2c.c         | 117 +++
 drivers/gpu/drm/solomon/ssd130x-spi.c         | 114 +++
 drivers/gpu/drm/solomon/ssd130x.c             | 823 ++++++++++++++++++
 drivers/gpu/drm/solomon/ssd130x.h             |  76 ++
 include/drm/drm_format_helper.h               |   8 +
 12 files changed, 1358 insertions(+), 12 deletions(-)
 create mode 100644 drivers/gpu/drm/solomon/Kconfig
 create mode 100644 drivers/gpu/drm/solomon/Makefile
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-i2c.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-spi.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09  9:03 ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Javier Martinez Canillas, Daniel Vetter,
	David Airlie, Lee Jones, Liam Girdwood, Maarten Lankhorst,
	Mark Brown, Maxime Ripard, Rob Herring, Thierry Reding,
	Uwe Kleine-König, devicetree, linux-pwm

This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.

Using the DRM fb emulation, all the tests from Geert Uytterhoeven's fbtest
(https://git.kernel.org/pub/scm/linux/kernel/git/geert/fbtest.git) passes.

I've also tested it using the display as a VT output and even though fbcon
seems to work, it is mostly unusable on a 128x64 SSD1306 display.

This is a v3 that addresses all the issues pointed in v2. Thanks a lot
to everyone that gave me feedback and reviews.

Patch #1 splits per-line conversion logic in drm_fb_xrgb8888_to_gray8() to
a separate drm_fb_xrgb8888_to_gray8_line() helper function.

Patch #2 adds two new helpers, drm_fb_gray8_to_mono_reversed() to convert
from grayscale to monochrome and a drm_fb_xrgb8888_to_mono_reversed() to
convert from XR24 to monochrome. The latter internally converts each line
first to gray8 and then to reversed monochrome.

Patch #3 adds the driver. This only has the core support but doesn't have
any bus specific code, separate drivers are needed for the transport used.

Patch #4 adds a driver to use the I2C bus to communicate with the device
and patch #5 adds a similar driver for SPI. This one is a WIP and wasn't
tested. I'm including for people to test and modify for their displays.

Patch #6 just adds a MAINTAINERS entry for the DRM driver and patch #7
adds myself as a co-maintainer of the existing Device Tree binding for
ssd1307fb, since the same is shared between the fbdev and DRM drivers.

Best regards,
Javier

Changes in v3:
- Add a drm_fb_xrgb8888_to_gray8_line() helper function (Thomas Zimmermann)
- Also add a drm_fb_xrgb8888_to_mono_reversed() helper (Thomas Zimmermann)
- Split lines copy to drm_fb_gray8_to_mono_reversed_line() (Thomas Zimmermann)
- Handle case where the source buffer is not aligned to 8 (Thomas Zimmermann)
- Move driver from tiny sub-dir to drivers/gpu/drm/solomon (Sam Ravnborg)
- Split driver in a bus agnostic core and bus specific (Andy Shevchenko)
- Use regmap to access the chip registers (Andy Shevchenko)
- Remove unnecessary blank lines (Andy Shevchenko)
- Remove unneeded inline specifier in functions (Andy Shevchenko)
- Add a comment about always returning a single mode (Andy Shevchenko)
- Change write command logic to use do while loop (Andy Shevchenko)
- Use "firmware description" instead of "device tree" (Andy Shevchenko)
- Use return foo() instead of returning the return value (Andy Shevchenko)
- Don't split lines longer than 80 chars if makes less readable (Andy Shevchenko)
- Remove redundant else statements in .mode_valid callback (Andy Shevchenko)
- Rename powero{n,ff}() functions to power_o{n,ff)() (Andy Shevchenko)
- Use dev_err_probe() to prevent spam logs on probe deferral (Andy Shevchenko)
- Remove ',' after sentinel terminator in array (Andy Shevchenko)
- Fix a bug when doing partial updates (Geert Uytterhoeven)
- Add a separate driver for SSD130X chips I2C support (Andy Shevchenko)
- Add a separate driver for SSD130X chips SPI support (Andy Shevchenko)
- Adapt MAINTAINERS entry to point to the new drivers/gpu/drm/solomon directory.

Changes in v2:
- Drop patch that was adding a DRM_MODE_CONNECTOR_I2C type.
- Invert order of backlight {en,dis}able and display {on,off} (Sam Ravnborg)
- Don't clear the screen and turn on display on probe (Sam Ravnborg)
- Use backlight_get_brightness() macro to get BL brightness (Sam Ravnborg)
- Use dev managed version of devm_backlight_device_register() (Sam Ravnborg)
- Use dev_name(dev) for backlight name instead of an array (Sam Ravnborg)
- Drop the .get_brightness callback since isn't needed  (Sam Ravnborg)
- Rename driver to ssd130x since supports a display family (Thomas Zimmermann)
- Drop the TINY prefix from the Kconfig symbol (Thomas Zimmermann)
- Sort the Kconfig symbol dependencies alphabetically (Thomas Zimmermann)
- Rename struct ssd130x_array to struct ssd130x_i2c_msg (Thomas Zimmermann)
- Rename struct ssd130x_i2c_msg .type member to .cmd (Thomas Zimmermann)
- Use sizeof(*foo) instead of sizeof(struct foo) (Thomas Zimmermann)
- Use struct_size() macro to calculate sizeof(*foo) + len (Thomas Zimmermann)
- Use kcalloc() instead of kmalloc_array() + memset() (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Reorganize code in probe to make it more legible (Thomas Zimmermann)
- ssd130x_write_cmd() uses varargs to simplify I2C code (Thomas Zimmermann)
- Move regulator/pwm init logic to display pipe enable callback.
- Add Sam Ravnborg's acked-by to patch adding a MAINTAINERS entry (Sam Ravnborg)
- Add myself as co-maintainer of the ssd1370fb DT binding (Sam Ravnborg).

Javier Martinez Canillas (7):
  drm/format-helper: Add drm_fb_xrgb8888_to_gray8_line()
  drm/format-helper: Add drm_fb_{xrgb8888,gray8}_to_mono_reversed()
  drm: Add driver for Solomon SSD130X OLED displays
  drm/solomon: Add SSD130X OLED displays I2C support
  (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  MAINTAINERS: Add entry for Solomon SSD130X OLED displays DRM driver
  dt-bindings: display: ssd1307fb: Add myself as binding co-maintainer

 .../bindings/display/solomon,ssd1307fb.yaml   |   1 +
 MAINTAINERS                                   |   7 +
 drivers/gpu/drm/Kconfig                       |   2 +
 drivers/gpu/drm/Makefile                      |   1 +
 drivers/gpu/drm/drm_format_helper.c           | 188 +++-
 drivers/gpu/drm/solomon/Kconfig               |  30 +
 drivers/gpu/drm/solomon/Makefile              |   3 +
 drivers/gpu/drm/solomon/ssd130x-i2c.c         | 117 +++
 drivers/gpu/drm/solomon/ssd130x-spi.c         | 114 +++
 drivers/gpu/drm/solomon/ssd130x.c             | 823 ++++++++++++++++++
 drivers/gpu/drm/solomon/ssd130x.h             |  76 ++
 include/drm/drm_format_helper.h               |   8 +
 12 files changed, 1358 insertions(+), 12 deletions(-)
 create mode 100644 drivers/gpu/drm/solomon/Kconfig
 create mode 100644 drivers/gpu/drm/solomon/Makefile
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-i2c.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-spi.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 1/7] drm/format-helper: Add drm_fb_xrgb8888_to_gray8_line()
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, David Airlie, Daniel Vetter,
	Javier Martinez Canillas, dri-devel, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Andy Shevchenko, Sam Ravnborg

Pull the per-line conversion logic into a separate helper function.

This will allow to do line-by-line conversion in other helpers that
convert to a gray8 format.

Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Add a drm_fb_xrgb8888_to_gray8_line() helper function (Thomas Zimmermann)

 drivers/gpu/drm/drm_format_helper.c | 31 ++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index 0f28dd2bdd72..b981712623d3 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -464,6 +464,21 @@ void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst,
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio);
 
+static void drm_fb_xrgb8888_to_gray8_line(u8 *dst, const u32 *src, unsigned int pixels)
+{
+	unsigned int x;
+
+	for (x = 0; x < pixels; x++) {
+		u8 r = (*src & 0x00ff0000) >> 16;
+		u8 g = (*src & 0x0000ff00) >> 8;
+		u8 b =  *src & 0x000000ff;
+
+		/* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
+		*dst++ = (3 * r + 6 * g + b) / 10;
+		src++;
+	}
+}
+
 /**
  * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
  * @dst: 8-bit grayscale destination buffer
@@ -484,8 +499,9 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio);
 void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr,
 			      const struct drm_framebuffer *fb, const struct drm_rect *clip)
 {
-	unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
-	unsigned int x, y;
+	unsigned int linepixels = clip->x2 - clip->x1;
+	unsigned int len = linepixels * sizeof(u32);
+	unsigned int y;
 	void *buf;
 	u8 *dst8;
 	u32 *src32;
@@ -508,16 +524,7 @@ void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vad
 	for (y = clip->y1; y < clip->y2; y++) {
 		dst8 = dst;
 		src32 = memcpy(buf, vaddr, len);
-		for (x = clip->x1; x < clip->x2; x++) {
-			u8 r = (*src32 & 0x00ff0000) >> 16;
-			u8 g = (*src32 & 0x0000ff00) >> 8;
-			u8 b =  *src32 & 0x000000ff;
-
-			/* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
-			*dst8++ = (3 * r + 6 * g + b) / 10;
-			src32++;
-		}
-
+		drm_fb_xrgb8888_to_gray8_line(dst8, src32, linepixels);
 		vaddr += fb->pitches[0];
 		dst += dst_pitch;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 1/7] drm/format-helper: Add drm_fb_xrgb8888_to_gray8_line()
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Javier Martinez Canillas, Daniel Vetter,
	David Airlie, Maarten Lankhorst, Maxime Ripard

Pull the per-line conversion logic into a separate helper function.

This will allow to do line-by-line conversion in other helpers that
convert to a gray8 format.

Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Add a drm_fb_xrgb8888_to_gray8_line() helper function (Thomas Zimmermann)

 drivers/gpu/drm/drm_format_helper.c | 31 ++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index 0f28dd2bdd72..b981712623d3 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -464,6 +464,21 @@ void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst,
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio);
 
+static void drm_fb_xrgb8888_to_gray8_line(u8 *dst, const u32 *src, unsigned int pixels)
+{
+	unsigned int x;
+
+	for (x = 0; x < pixels; x++) {
+		u8 r = (*src & 0x00ff0000) >> 16;
+		u8 g = (*src & 0x0000ff00) >> 8;
+		u8 b =  *src & 0x000000ff;
+
+		/* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
+		*dst++ = (3 * r + 6 * g + b) / 10;
+		src++;
+	}
+}
+
 /**
  * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
  * @dst: 8-bit grayscale destination buffer
@@ -484,8 +499,9 @@ EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio);
 void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr,
 			      const struct drm_framebuffer *fb, const struct drm_rect *clip)
 {
-	unsigned int len = (clip->x2 - clip->x1) * sizeof(u32);
-	unsigned int x, y;
+	unsigned int linepixels = clip->x2 - clip->x1;
+	unsigned int len = linepixels * sizeof(u32);
+	unsigned int y;
 	void *buf;
 	u8 *dst8;
 	u32 *src32;
@@ -508,16 +524,7 @@ void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vad
 	for (y = clip->y1; y < clip->y2; y++) {
 		dst8 = dst;
 		src32 = memcpy(buf, vaddr, len);
-		for (x = clip->x1; x < clip->x2; x++) {
-			u8 r = (*src32 & 0x00ff0000) >> 16;
-			u8 g = (*src32 & 0x0000ff00) >> 8;
-			u8 b =  *src32 & 0x000000ff;
-
-			/* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
-			*dst8++ = (3 * r + 6 * g + b) / 10;
-			src32++;
-		}
-
+		drm_fb_xrgb8888_to_gray8_line(dst8, src32, linepixels);
 		vaddr += fb->pitches[0];
 		dst += dst_pitch;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed()
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, David Airlie, Daniel Vetter,
	Javier Martinez Canillas, dri-devel, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Andy Shevchenko, Sam Ravnborg

Add support to convert XR24 and 8-bit grayscale to reversed monochrome for
drivers that control monochromatic panels, that only have 1 bit per pixel.

The drm_fb_gray8_to_mono_reversed() helper was based on the function that
does the same in the drivers/gpu/drm/tiny/repaper.c driver.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Also add a drm_fb_xrgb8888_to_mono_reversed() helper (Thomas Zimmermann)
- Split lines copy to drm_fb_gray8_to_mono_reversed_line() (Thomas Zimmermann)
- Handle case where the source buffer is not aligned to 8 (Thomas Zimmermann)

 drivers/gpu/drm/drm_format_helper.c | 157 ++++++++++++++++++++++++++++
 include/drm/drm_format_helper.h     |   8 ++
 2 files changed, 165 insertions(+)

diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index b981712623d3..19710342c0de 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -591,3 +591,160 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
 	return -EINVAL;
 }
 EXPORT_SYMBOL(drm_fb_blit_toio);
+
+static void drm_fb_gray8_to_mono_reversed_line(u8 *dst, const u8 *src, unsigned int pixels,
+					       unsigned int start_offset, unsigned int end_offset)
+{
+	unsigned int xb, i;
+
+	for (xb = 0; xb < pixels; xb++) {
+		unsigned int start = 0, end = 8;
+		u8 byte = 0x00;
+
+		if (xb == 0 && start_offset)
+			start = start_offset;
+
+		if (xb == pixels - 1 && end_offset)
+			end = end_offset;
+
+		for (i = start; i < end; i++) {
+			unsigned int x = xb * 8 + i;
+
+			byte >>= 1;
+			if (src[x] >> 7)
+				byte |= BIT(7);
+		}
+		*dst++ = byte;
+	}
+}
+
+/**
+ * drm_fb_gray8_to_mono_reversed - Convert grayscale to reversed monochrome
+ * @dst: reversed monochrome destination buffer
+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * @src: 8-bit grayscale source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * DRM doesn't have native monochrome or grayscale support.
+ * Such drivers can announce the commonly supported XR24 format to userspace
+ * and use drm_fb_xrgb8888_to_gray8() to convert to grayscale and then this
+ * helper function to convert to the native format.
+ */
+void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
+				   const struct drm_framebuffer *fb,
+				   const struct drm_rect *clip)
+{
+
+	unsigned int linepixels = drm_rect_width(clip);
+	unsigned int lines = drm_rect_height(clip);
+	unsigned int start_offset, end_offset;
+	unsigned int y;
+	const u8 *gray8 = vaddr;
+	u8 *mono = dst;
+
+	/*
+	 * The reversed mono destination buffer contains 1 bit per pixel
+	 * and destination scanlines have to be in multiple of 8 pixels.
+	 */
+	if (!dst_pitch)
+		dst_pitch = DIV_ROUND_UP(linepixels, 8);
+
+	/*
+	 * For damage handling, it is possible that only parts of the source
+	 * buffer is copied and this could lead to start and end pixels that
+	 * are not aligned to multiple of 8.
+	 *
+	 * Calculate if the start and end pixels are not aligned and set the
+	 * offsets for the reversed mono line conversion function to adjust.
+	 */
+	start_offset = clip->x1 % 8;
+	end_offset = clip->x2 % 8;
+
+	for (y = 0; y < lines; y++) {
+		drm_fb_gray8_to_mono_reversed_line(mono, gray8, dst_pitch,
+						   start_offset, end_offset);
+		gray8 += fb->pitches[0];
+		mono += dst_pitch;
+	}
+}
+
+/**
+ * drm_fb_xrgb8888_to_mono_reversed - Convert XRGB8888 to reversed monochrome
+ * @dst: reversed monochrome destination buffer
+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * @src: XRGB8888 source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * DRM doesn't have native monochrome support.
+ * Such drivers can announce the commonly supported XR24 format to userspace
+ * and use this function to convert to the native format.
+ *
+ * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
+ * then the result is converted from grayscale to reversed monohrome.
+ */
+void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
+				      const struct drm_framebuffer *fb, const struct drm_rect *clip)
+{
+	unsigned int linepixels = drm_rect_width(clip);
+	unsigned int lines = clip->y2 - clip->y1;
+	unsigned int cpp = fb->format->cpp[0];
+	unsigned int len_src32 = linepixels * cpp;
+	unsigned int start_offset, end_offset;
+	unsigned int y;
+	u8 *mono = dst, *gray8;
+	u32 *src32;
+
+	if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
+		return;
+
+	/*
+	 * The reversed mono destination buffer contains 1 bit per pixel
+	 * and destination scanlines have to be in multiple of 8 pixels.
+	 */
+	if (!dst_pitch)
+		dst_pitch = DIV_ROUND_UP(linepixels, 8);
+
+	/*
+	 * The cma memory is write-combined so reads are uncached.
+	 * Speed up by fetching one line at a time.
+	 */
+	src32 = kmalloc(len_src32, GFP_KERNEL);
+	if (!src32)
+		return;
+
+	/*
+	 * Copies are done line-by-line, allocate an intermediate
+	 * buffer to copy the gray8 lines and then convert to mono.
+	 */
+	gray8 = kmalloc(linepixels, GFP_KERNEL);
+	if (!gray8)
+		goto free_src32;
+
+	/*
+	 * For damage handling, it is possible that only parts of the source
+	 * buffer is copied and this could lead to start and end pixels that
+	 * are not aligned to multiple of 8.
+	 *
+	 * Calculate if the start and end pixels are not aligned and set the
+	 * offsets for the reversed mono line conversion function to adjust.
+	 */
+	start_offset = clip->x1 % 8;
+	end_offset = clip->x2 % 8;
+
+	vaddr += clip_offset(clip, fb->pitches[0], cpp);
+	for (y = 0; y < lines; y++) {
+		src32 = memcpy(src32, vaddr, len_src32);
+		drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
+		drm_fb_gray8_to_mono_reversed_line(mono, gray8, dst_pitch,
+						   start_offset, end_offset);
+		vaddr += fb->pitches[0];
+		mono += dst_pitch;
+	}
+
+	kfree(gray8);
+free_src32:
+	kfree(src32);
+}
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono_reversed);
diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
index b30ed5de0a33..6638da9e9774 100644
--- a/include/drm/drm_format_helper.h
+++ b/include/drm/drm_format_helper.h
@@ -43,4 +43,12 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
 		     const void *vmap, const struct drm_framebuffer *fb,
 		     const struct drm_rect *rect);
 
+void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *src,
+				   const struct drm_framebuffer *fb,
+				   const struct drm_rect *clip);
+
+void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *src,
+				      const struct drm_framebuffer *fb,
+				      const struct drm_rect *clip);
+
 #endif /* __LINUX_DRM_FORMAT_HELPER_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888,gray8}_to_mono_reversed()
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Javier Martinez Canillas, Daniel Vetter,
	David Airlie, Maarten Lankhorst, Maxime Ripard

Add support to convert XR24 and 8-bit grayscale to reversed monochrome for
drivers that control monochromatic panels, that only have 1 bit per pixel.

The drm_fb_gray8_to_mono_reversed() helper was based on the function that
does the same in the drivers/gpu/drm/tiny/repaper.c driver.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Also add a drm_fb_xrgb8888_to_mono_reversed() helper (Thomas Zimmermann)
- Split lines copy to drm_fb_gray8_to_mono_reversed_line() (Thomas Zimmermann)
- Handle case where the source buffer is not aligned to 8 (Thomas Zimmermann)

 drivers/gpu/drm/drm_format_helper.c | 157 ++++++++++++++++++++++++++++
 include/drm/drm_format_helper.h     |   8 ++
 2 files changed, 165 insertions(+)

diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index b981712623d3..19710342c0de 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -591,3 +591,160 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
 	return -EINVAL;
 }
 EXPORT_SYMBOL(drm_fb_blit_toio);
+
+static void drm_fb_gray8_to_mono_reversed_line(u8 *dst, const u8 *src, unsigned int pixels,
+					       unsigned int start_offset, unsigned int end_offset)
+{
+	unsigned int xb, i;
+
+	for (xb = 0; xb < pixels; xb++) {
+		unsigned int start = 0, end = 8;
+		u8 byte = 0x00;
+
+		if (xb == 0 && start_offset)
+			start = start_offset;
+
+		if (xb == pixels - 1 && end_offset)
+			end = end_offset;
+
+		for (i = start; i < end; i++) {
+			unsigned int x = xb * 8 + i;
+
+			byte >>= 1;
+			if (src[x] >> 7)
+				byte |= BIT(7);
+		}
+		*dst++ = byte;
+	}
+}
+
+/**
+ * drm_fb_gray8_to_mono_reversed - Convert grayscale to reversed monochrome
+ * @dst: reversed monochrome destination buffer
+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * @src: 8-bit grayscale source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * DRM doesn't have native monochrome or grayscale support.
+ * Such drivers can announce the commonly supported XR24 format to userspace
+ * and use drm_fb_xrgb8888_to_gray8() to convert to grayscale and then this
+ * helper function to convert to the native format.
+ */
+void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
+				   const struct drm_framebuffer *fb,
+				   const struct drm_rect *clip)
+{
+
+	unsigned int linepixels = drm_rect_width(clip);
+	unsigned int lines = drm_rect_height(clip);
+	unsigned int start_offset, end_offset;
+	unsigned int y;
+	const u8 *gray8 = vaddr;
+	u8 *mono = dst;
+
+	/*
+	 * The reversed mono destination buffer contains 1 bit per pixel
+	 * and destination scanlines have to be in multiple of 8 pixels.
+	 */
+	if (!dst_pitch)
+		dst_pitch = DIV_ROUND_UP(linepixels, 8);
+
+	/*
+	 * For damage handling, it is possible that only parts of the source
+	 * buffer is copied and this could lead to start and end pixels that
+	 * are not aligned to multiple of 8.
+	 *
+	 * Calculate if the start and end pixels are not aligned and set the
+	 * offsets for the reversed mono line conversion function to adjust.
+	 */
+	start_offset = clip->x1 % 8;
+	end_offset = clip->x2 % 8;
+
+	for (y = 0; y < lines; y++) {
+		drm_fb_gray8_to_mono_reversed_line(mono, gray8, dst_pitch,
+						   start_offset, end_offset);
+		gray8 += fb->pitches[0];
+		mono += dst_pitch;
+	}
+}
+
+/**
+ * drm_fb_xrgb8888_to_mono_reversed - Convert XRGB8888 to reversed monochrome
+ * @dst: reversed monochrome destination buffer
+ * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * @src: XRGB8888 source buffer
+ * @fb: DRM framebuffer
+ * @clip: Clip rectangle area to copy
+ *
+ * DRM doesn't have native monochrome support.
+ * Such drivers can announce the commonly supported XR24 format to userspace
+ * and use this function to convert to the native format.
+ *
+ * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
+ * then the result is converted from grayscale to reversed monohrome.
+ */
+void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
+				      const struct drm_framebuffer *fb, const struct drm_rect *clip)
+{
+	unsigned int linepixels = drm_rect_width(clip);
+	unsigned int lines = clip->y2 - clip->y1;
+	unsigned int cpp = fb->format->cpp[0];
+	unsigned int len_src32 = linepixels * cpp;
+	unsigned int start_offset, end_offset;
+	unsigned int y;
+	u8 *mono = dst, *gray8;
+	u32 *src32;
+
+	if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
+		return;
+
+	/*
+	 * The reversed mono destination buffer contains 1 bit per pixel
+	 * and destination scanlines have to be in multiple of 8 pixels.
+	 */
+	if (!dst_pitch)
+		dst_pitch = DIV_ROUND_UP(linepixels, 8);
+
+	/*
+	 * The cma memory is write-combined so reads are uncached.
+	 * Speed up by fetching one line at a time.
+	 */
+	src32 = kmalloc(len_src32, GFP_KERNEL);
+	if (!src32)
+		return;
+
+	/*
+	 * Copies are done line-by-line, allocate an intermediate
+	 * buffer to copy the gray8 lines and then convert to mono.
+	 */
+	gray8 = kmalloc(linepixels, GFP_KERNEL);
+	if (!gray8)
+		goto free_src32;
+
+	/*
+	 * For damage handling, it is possible that only parts of the source
+	 * buffer is copied and this could lead to start and end pixels that
+	 * are not aligned to multiple of 8.
+	 *
+	 * Calculate if the start and end pixels are not aligned and set the
+	 * offsets for the reversed mono line conversion function to adjust.
+	 */
+	start_offset = clip->x1 % 8;
+	end_offset = clip->x2 % 8;
+
+	vaddr += clip_offset(clip, fb->pitches[0], cpp);
+	for (y = 0; y < lines; y++) {
+		src32 = memcpy(src32, vaddr, len_src32);
+		drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
+		drm_fb_gray8_to_mono_reversed_line(mono, gray8, dst_pitch,
+						   start_offset, end_offset);
+		vaddr += fb->pitches[0];
+		mono += dst_pitch;
+	}
+
+	kfree(gray8);
+free_src32:
+	kfree(src32);
+}
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono_reversed);
diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
index b30ed5de0a33..6638da9e9774 100644
--- a/include/drm/drm_format_helper.h
+++ b/include/drm/drm_format_helper.h
@@ -43,4 +43,12 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
 		     const void *vmap, const struct drm_framebuffer *fb,
 		     const struct drm_rect *rect);
 
+void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *src,
+				   const struct drm_framebuffer *fb,
+				   const struct drm_rect *clip);
+
+void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *src,
+				      const struct drm_framebuffer *fb,
+				      const struct drm_rect *clip);
+
 #endif /* __LINUX_DRM_FORMAT_HELPER_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter, Mark Brown,
	Javier Martinez Canillas, dri-devel, Liam Girdwood,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Thomas Zimmermann, Uwe Kleine-König, Thierry Reding,
	Lee Jones, Andy Shevchenko, Sam Ravnborg

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.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Move driver from tiny sub-dir to drivers/gpu/drm/solomon (Sam Ravnborg)
- Split driver in a bus agnostic core and bus specific (Andy Shevchenko)
- Use regmap to access the chip registers (Andy Shevchenko)
- Remove unnecessary blank lines (Andy Shevchenko)
- Remove unneeded inline specifier in functions (Andy Shevchenko)
- Add a comment about always returning a single mode (Andy Shevchenko)
- Change write command logic to use do while loop (Andy Shevchenko)
- Use "firmware description" instead of "device tree" (Andy Shevchenko)
- Use return foo() instead of returning the return value (Andy Shevchenko)
- Don't split lines longer than 80 chars if makes less readable (Andy Shevchenko)
- Remove redundant else statements in .mode_valid callback (Andy Shevchenko)
- Rename powero{n,ff}() functions to power_o{n,ff)() (Andy Shevchenko)
- Use dev_err_probe() to prevent spam logs on probe deferral (Andy Shevchenko)
- Remove ',' after sentinel terminator in array (Andy Shevchenko)
- Fix a bug when doing partial updates (Geert Uytterhoeven)

Changes in v2:
- Drop patch that was adding a DRM_MODE_CONNECTOR_I2C type.
- Invert order of backlight {en,dis}able and display {on,off} (Sam Ravnborg)
- Don't clear the screen and turn on display on probe (Sam Ravnborg)
- Use backlight_get_brightness() macro to get BL brightness (Sam Ravnborg)
- Use dev managed version of devm_backlight_device_register() (Sam Ravnborg)
- Use dev_name(dev) for backlight name instead of an array (Sam Ravnborg)
- Drop the .get_brightness callback since isn't needed  (Sam Ravnborg)
- Rename driver to ssd130x since supports a display family (Thomas Zimmermann)
- Drop the TINY prefix from the Kconfig symbol (Thomas Zimmermann)
- Sort the Kconfig symbol dependencies alphabetically (Thomas Zimmermann)
- Rename struct ssd130x_array to struct ssd130x_i2c_msg (Thomas Zimmermann)
- Rename struct ssd130x_i2c_msg .type member to .cmd (Thomas Zimmermann)
- Use sizeof(*foo) instead of sizeof(struct foo) (Thomas Zimmermann)
- Use struct_size() macro to calculate sizeof(*foo) + len (Thomas Zimmermann)
- Use kcalloc() instead of kmalloc_array() + memset() (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Reorganize code in probe to make it more legible (Thomas Zimmermann)
- ssd130x_write_cmd() uses varargs to simplify I2C code (Thomas Zimmermann)
- Move regulator/pwm init logic to display pipe enable callback.

 drivers/gpu/drm/Kconfig           |   2 +
 drivers/gpu/drm/Makefile          |   1 +
 drivers/gpu/drm/solomon/Kconfig   |  12 +
 drivers/gpu/drm/solomon/Makefile  |   1 +
 drivers/gpu/drm/solomon/ssd130x.c | 823 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/solomon/ssd130x.h |  76 +++
 6 files changed, 915 insertions(+)
 create mode 100644 drivers/gpu/drm/solomon/Kconfig
 create mode 100644 drivers/gpu/drm/solomon/Makefile
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index dfdd3ec5f793..c423c920c027 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -405,6 +405,8 @@ source "drivers/gpu/drm/gud/Kconfig"
 
 source "drivers/gpu/drm/sprd/Kconfig"
 
+source "drivers/gpu/drm/solomon/Kconfig"
+
 config DRM_HYPERV
 	tristate "DRM Support for Hyper-V synthetic video device"
 	depends on DRM && PCI && MMU && HYPERV
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 8675c2af7ae1..a07b777e778a 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -133,3 +133,4 @@ obj-y			+= xlnx/
 obj-y			+= gud/
 obj-$(CONFIG_DRM_HYPERV) += hyperv/
 obj-$(CONFIG_DRM_SPRD) += sprd/
+obj-y			+= solomon/
diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
new file mode 100644
index 000000000000..c969c358a4a7
--- /dev/null
+++ b/drivers/gpu/drm/solomon/Kconfig
@@ -0,0 +1,12 @@
+config DRM_SSD130X
+	tristate "DRM support for Solomon SSD130X OLED displays"
+	depends on DRM
+	select BACKLIGHT_CLASS_DEVICE
+	select DRM_GEM_SHMEM_HELPER
+	select DRM_KMS_HELPER
+	help
+	  DRM driver for the SSD1305, SSD1306, SSD1307 and SSD1309 Solomon
+	  OLED controllers. This is only for the core driver, a driver for
+	  the appropriate bus transport in your chip also must be selected.
+
+	  If M is selected the module will be called ssd130x.
diff --git a/drivers/gpu/drm/solomon/Makefile b/drivers/gpu/drm/solomon/Makefile
new file mode 100644
index 000000000000..f685addb19fe
--- /dev/null
+++ b/drivers/gpu/drm/solomon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DRM_SSD130X)	+= ssd130x.o
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
new file mode 100644
index 000000000000..79943f2e73a2
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -0,0 +1,823 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for Solomon SSD130X OLED displays
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ *
+ * Based on drivers/video/fbdev/ssd1307fb.c
+ * Copyright 2012 Free Electrons
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/property.h>
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_probe_helper.h>
+
+#include "ssd130x.h"
+
+#define DRIVER_NAME	"ssd130x"
+#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays"
+#define DRIVER_DATE	"20220131"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+#define SSD130X_DATA				0x40
+#define SSD130X_COMMAND				0x80
+
+#define SSD130X_SET_ADDRESS_MODE		0x20
+#define SSD130X_SET_ADDRESS_MODE_HORIZONTAL	(0x00)
+#define SSD130X_SET_ADDRESS_MODE_VERTICAL	(0x01)
+#define SSD130X_SET_ADDRESS_MODE_PAGE		(0x02)
+#define SSD130X_SET_COL_RANGE			0x21
+#define SSD130X_SET_PAGE_RANGE			0x22
+#define SSD130X_CONTRAST			0x81
+#define SSD130X_SET_LOOKUP_TABLE		0x91
+#define SSD130X_CHARGE_PUMP			0x8d
+#define SSD130X_SEG_REMAP_ON			0xa1
+#define SSD130X_DISPLAY_OFF			0xae
+#define SSD130X_SET_MULTIPLEX_RATIO		0xa8
+#define SSD130X_DISPLAY_ON			0xaf
+#define SSD130X_START_PAGE_ADDRESS		0xb0
+#define SSD130X_SET_DISPLAY_OFFSET		0xd3
+#define SSD130X_SET_CLOCK_FREQ			0xd5
+#define SSD130X_SET_AREA_COLOR_MODE		0xd8
+#define SSD130X_SET_PRECHARGE_PERIOD		0xd9
+#define SSD130X_SET_COM_PINS_CONFIG		0xda
+#define SSD130X_SET_VCOMH			0xdb
+
+#define MAX_CONTRAST 255
+
+static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
+{
+	return container_of(drm, struct ssd130x_device, drm);
+}
+
+/*
+ * Helper to write data (SSD130X_DATA) to the device.
+ */
+static int ssd130x_write_data(struct ssd130x_device *ssd130x, u8 *values, int count)
+{
+	int ret;
+
+	ret = regmap_bulk_write(ssd130x->regmap, SSD130X_DATA, values, count);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Helper to write command (SSD130X_COMMAND). The fist variadic argument
+ * is the command to write and the following are the command options.
+ */
+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;
+}
+
+static int ssd130x_set_col_range(struct ssd130x_device *ssd130x,
+				 u8 col_start, u8 cols)
+{
+	u8 col_end = col_start + cols - 1;
+	int ret;
+
+	if (col_start == ssd130x->col_start && col_end == ssd130x->col_end)
+		return 0;
+
+	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_COL_RANGE, col_start, col_end);
+	if (ret < 0)
+		return ret;
+
+	ssd130x->col_start = col_start;
+	ssd130x->col_end = col_end;
+	return 0;
+}
+
+static int ssd130x_set_page_range(struct ssd130x_device *ssd130x,
+				  u8 page_start, u8 pages)
+{
+	u8 page_end = page_start + pages - 1;
+	int ret;
+
+	if (page_start == ssd130x->page_start && page_end == ssd130x->page_end)
+		return 0;
+
+	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_PAGE_RANGE, page_start, page_end);
+	if (ret < 0)
+		return ret;
+
+	ssd130x->page_start = page_start;
+	ssd130x->page_end = page_end;
+	return 0;
+}
+
+static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+	struct pwm_state pwmstate;
+
+	ssd130x->pwm = pwm_get(dev, NULL);
+	if (IS_ERR(ssd130x->pwm)) {
+		dev_err(dev, "Could not get PWM from firmware description!\n");
+		return PTR_ERR(ssd130x->pwm);
+	}
+
+	pwm_init_state(ssd130x->pwm, &pwmstate);
+	pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
+	pwm_apply_state(ssd130x->pwm, &pwmstate);
+
+	/* Enable the PWM */
+	pwm_enable(ssd130x->pwm);
+
+	dev_dbg(dev, "Using PWM%d with a %lluns period.\n",
+		ssd130x->pwm->pwm, pwm_get_period(ssd130x->pwm));
+
+	return 0;
+}
+
+static void ssd130x_reset(struct ssd130x_device *ssd130x)
+{
+	/* Reset the screen */
+	gpiod_set_value_cansleep(ssd130x->reset, 1);
+	udelay(4);
+	gpiod_set_value_cansleep(ssd130x->reset, 0);
+	udelay(4);
+}
+
+static int ssd130x_power_on(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+	int ret;
+
+	if (ssd130x->reset)
+		ssd130x_reset(ssd130x);
+
+	if (ssd130x->vbat_reg) {
+		ret = regulator_enable(ssd130x->vbat_reg);
+		if (ret) {
+			dev_err(dev, "Failed to enable VBAT: %d\n", ret);
+			return ret;
+		}
+	}
+
+	if (ssd130x->device_info->need_pwm) {
+		ret = ssd130x_pwm_enable(ssd130x);
+		if (ret) {
+			dev_err(dev, "Failed to enable PWM: %d\n", ret);
+			if (ssd130x->vbat_reg)
+				regulator_disable(ssd130x->vbat_reg);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void ssd130x_power_off(struct ssd130x_device *ssd130x)
+{
+	if (ssd130x->device_info->need_pwm) {
+		pwm_disable(ssd130x->pwm);
+		pwm_put(ssd130x->pwm);
+	}
+
+	if (ssd130x->vbat_reg)
+		regulator_disable(ssd130x->vbat_reg);
+}
+
+static int ssd130x_init(struct ssd130x_device *ssd130x)
+{
+	u32 precharge, dclk, com_invdir, compins, chargepump;
+	int ret;
+
+	/* Set initial contrast */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CONTRAST, ssd130x->contrast);
+	if (ret < 0)
+		return ret;
+
+	/* Set segment re-map */
+	if (ssd130x->seg_remap) {
+		ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | ssd130x->com_invdir << 3;
+	ret = ssd130x_write_cmd(ssd130x,  1, com_invdir);
+	if (ret < 0)
+		return ret;
+
+	/* Set multiplex ratio value */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* set display offset value */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_DISPLAY_OFFSET, ssd130x->com_offset);
+	if (ret < 0)
+		return ret;
+
+	/* Set clock frequency */
+	dclk = ((ssd130x->dclk_div - 1) & 0xf) | (ssd130x->dclk_frq & 0xf) << 4;
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_CLOCK_FREQ, dclk);
+	if (ret < 0)
+		return ret;
+
+	/* Set Area Color Mode ON/OFF & Low Power Display Mode */
+	if (ssd130x->area_color_enable || ssd130x->low_power) {
+		u32 mode = ((ssd130x->area_color_enable ? 0x30 : 0) |
+			    (ssd130x->low_power ? 5 : 0));
+
+		ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_AREA_COLOR_MODE, mode);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Set precharge period in number of ticks from the internal clock */
+	precharge = (ssd130x->prechargep1 & 0xf) | (ssd130x->prechargep2 & 0xf) << 4;
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge);
+	if (ret < 0)
+		return ret;
+
+	/* Set COM pins configuration */
+	compins = 0x02 | !ssd130x->com_seq << 4 | ssd130x->com_lrremap << 5;
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_COM_PINS_CONFIG, compins);
+	if (ret < 0)
+		return ret;
+
+
+	/* Set VCOMH */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_VCOMH, ssd130x->vcomh);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the DC-DC Charge Pump */
+	chargepump = BIT(4) | (ssd130x->device_info->need_chargepump ? BIT(2) : 0);
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CHARGE_PUMP, chargepump);
+	if (ret < 0)
+		return ret;
+
+	/* Set lookup table */
+	if (ssd130x->lookup_table_set) {
+		int i;
+
+		ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SET_LOOKUP_TABLE);
+		if (ret < 0)
+			return ret;
+
+		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); ++i) {
+			u8 val = ssd130x->lookup_table[i];
+
+			if (val < 31 || val > 63)
+				dev_warn(ssd130x->dev,
+					 "lookup table index %d value out of range 31 <= %d <= 63\n",
+					 i, val);
+			ret = ssd130x_write_cmd(ssd130x, 1, val);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	/* Switch to horizontal addressing mode */
+	return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
+				 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
+}
+
+static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
+			       struct drm_rect *rect)
+{
+	unsigned int x = rect->x1;
+	unsigned int y = rect->y1;
+	unsigned int width = drm_rect_width(rect);
+	unsigned int height = drm_rect_height(rect);
+	unsigned int line_length = DIV_ROUND_UP(width, 8);
+	unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8);
+	u32 array_idx = 0;
+	int ret, i, j, k;
+	u8 *data_array = NULL;
+
+	data_array = kcalloc(width, pages, GFP_KERNEL);
+	if (!data_array)
+		return -ENOMEM;
+
+	/*
+	 * The screen is divided in pages, each having a height of 8
+	 * pixels, and the width of the screen. When sending a byte of
+	 * data to the controller, it gives the 8 bits for the current
+	 * column. I.e, the first byte are the 8 bits of the first
+	 * column, then the 8 bits for the second column, etc.
+	 *
+	 *
+	 * Representation of the screen, assuming it is 5 bits
+	 * wide. Each letter-number combination is a bit that controls
+	 * one pixel.
+	 *
+	 * A0 A1 A2 A3 A4
+	 * B0 B1 B2 B3 B4
+	 * C0 C1 C2 C3 C4
+	 * D0 D1 D2 D3 D4
+	 * E0 E1 E2 E3 E4
+	 * F0 F1 F2 F3 F4
+	 * G0 G1 G2 G3 G4
+	 * H0 H1 H2 H3 H4
+	 *
+	 * If you want to update this screen, you need to send 5 bytes:
+	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
+	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
+	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
+	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
+	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
+	 */
+
+	ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
+	if (ret < 0)
+		goto out_free;
+
+	ret = ssd130x_set_page_range(ssd130x, ssd130x->page_offset + y / 8, pages);
+	if (ret < 0)
+		goto out_free;
+
+	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;
+		for (j = x; j < x + width; j++) {
+			u8 data = 0;
+
+			for (k = 0; k < m; k++) {
+				u8 byte = buf[(8 * i + k) * line_length + j / 8];
+				u8 bit = (byte >> (j % 8)) & 1;
+
+				data |= bit << k;
+			}
+			data_array[array_idx++] = data;
+		}
+	}
+
+	ret = ssd130x_write_data(ssd130x, data_array, width * pages);
+
+out_free:
+	kfree(data_array);
+	return ret;
+}
+
+static void ssd130x_clear_screen(struct ssd130x_device *ssd130x)
+{
+	u8 *buf = NULL;
+
+	struct drm_rect fullscreen = {
+		.x1 = 0,
+		.x2 = ssd130x->width,
+		.y1 = 0,
+		.y2 = ssd130x->height,
+	};
+
+	buf = kcalloc(ssd130x->width, ssd130x->height, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	ssd130x_update_rect(ssd130x, buf, &fullscreen);
+
+	kfree(buf);
+}
+
+static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map,
+				struct drm_rect *rect)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
+	void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
+	int ret = 0;
+	u8 *buf = NULL;
+
+	buf = kcalloc(fb->width, fb->height, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	drm_fb_xrgb8888_to_mono_reversed(buf, 0, vmap, fb, rect);
+
+	ssd130x_update_rect(ssd130x, buf, rect);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static int ssd130x_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
+					   const struct drm_display_mode *mode)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+
+	if (mode->hdisplay != ssd130x->mode.hdisplay &&
+	    mode->vdisplay != ssd130x->mode.vdisplay)
+		return MODE_ONE_SIZE;
+
+	if (mode->hdisplay != ssd130x->mode.hdisplay)
+		return MODE_ONE_WIDTH;
+
+	if (mode->vdisplay != ssd130x->mode.vdisplay)
+		return MODE_ONE_HEIGHT;
+
+	return MODE_OK;
+}
+
+static void ssd130x_display_pipe_enable(struct drm_simple_display_pipe *pipe,
+					struct drm_crtc_state *crtc_state,
+					struct drm_plane_state *plane_state)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+	struct drm_device *drm = &ssd130x->drm;
+	int idx, ret;
+
+	ret = ssd130x_power_on(ssd130x);
+	if (ret)
+		return;
+
+	ret = ssd130x_init(ssd130x);
+	if (ret)
+		goto power_off;
+
+	if (!drm_dev_enter(drm, &idx))
+		goto power_off;
+
+	ssd130x_clear_screen(ssd130x);
+
+	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON);
+
+	backlight_enable(ssd130x->bl_dev);
+
+	drm_dev_exit(idx);
+
+	return;
+power_off:
+	ssd130x_power_off(ssd130x);
+}
+
+static void ssd130x_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+	struct drm_device *drm = &ssd130x->drm;
+	int idx;
+
+	if (!drm_dev_enter(drm, &idx))
+		return;
+
+	ssd130x_clear_screen(ssd130x);
+
+	backlight_disable(ssd130x->bl_dev);
+
+	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF);
+
+	ssd130x_power_off(ssd130x);
+
+	drm_dev_exit(idx);
+}
+
+static void ssd130x_display_pipe_update(struct drm_simple_display_pipe *pipe,
+					struct drm_plane_state *old_plane_state)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+	struct drm_plane_state *plane_state = pipe->plane.state;
+	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_device *drm = &ssd130x->drm;
+	struct drm_rect src_clip, dst_clip;
+	int idx;
+
+	if (!fb)
+		return;
+
+	if (!pipe->crtc.state->active)
+		return;
+
+	if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))
+		return;
+
+	dst_clip = plane_state->dst;
+	if (!drm_rect_intersect(&dst_clip, &src_clip))
+		return;
+
+	if (!drm_dev_enter(drm, &idx))
+		return;
+
+	ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
+
+	drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs ssd130x_pipe_funcs = {
+	.mode_valid = ssd130x_display_pipe_mode_valid,
+	.enable = ssd130x_display_pipe_enable,
+	.disable = ssd130x_display_pipe_disable,
+	.update = ssd130x_display_pipe_update,
+	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+};
+
+static int ssd130x_connector_get_modes(struct drm_connector *connector)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev);
+	struct drm_display_mode *mode = &ssd130x->mode;
+	struct device *dev = ssd130x->dev;
+
+	mode = drm_mode_duplicate(connector->dev, &ssd130x->mode);
+	if (!mode) {
+		dev_err(dev, "Failed to duplicated mode\n");
+		return 0;
+	}
+
+	drm_mode_probed_add(connector, mode);
+	drm_set_preferred_mode(connector, mode->hdisplay, mode->vdisplay);
+
+	/* There is only a single mode */
+	return 1;
+}
+
+static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = {
+	.get_modes = ssd130x_connector_get_modes,
+};
+
+static const struct drm_connector_funcs ssd130x_connector_funcs = {
+	.reset = drm_atomic_helper_connector_reset,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_mode_config_funcs ssd130x_mode_config_funcs = {
+	.fb_create = drm_gem_fb_create_with_dirty,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static const uint32_t ssd130x_formats[] = {
+	DRM_FORMAT_XRGB8888,
+};
+
+DEFINE_DRM_GEM_FOPS(ssd130x_fops);
+
+static const struct drm_driver ssd130x_drm_driver = {
+	DRM_GEM_SHMEM_DRIVER_OPS,
+	.name			= DRIVER_NAME,
+	.desc			= DRIVER_DESC,
+	.date			= DRIVER_DATE,
+	.major			= DRIVER_MAJOR,
+	.minor			= DRIVER_MINOR,
+	.driver_features	= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
+	.fops			= &ssd130x_fops,
+};
+
+static int ssd130x_update_bl(struct backlight_device *bdev)
+{
+	struct ssd130x_device *ssd130x = bl_get_data(bdev);
+	int brightness = backlight_get_brightness(bdev);
+	int ret;
+
+	ssd130x->contrast = brightness;
+
+	ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_CONTRAST);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd130x_write_cmd(ssd130x, 1, ssd130x->contrast);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct backlight_ops ssd130xfb_bl_ops = {
+	.update_status	= ssd130x_update_bl,
+};
+
+static void ssd130x_parse_properties(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+
+	if (device_property_read_u32(dev, "solomon,width", &ssd130x->width))
+		ssd130x->width = 96;
+
+	if (device_property_read_u32(dev, "solomon,height", &ssd130x->height))
+		ssd130x->height = 16;
+
+	if (device_property_read_u32(dev, "solomon,page-offset", &ssd130x->page_offset))
+		ssd130x->page_offset = 1;
+
+	if (device_property_read_u32(dev, "solomon,col-offset", &ssd130x->col_offset))
+		ssd130x->col_offset = 0;
+
+	if (device_property_read_u32(dev, "solomon,com-offset", &ssd130x->com_offset))
+		ssd130x->com_offset = 0;
+
+	if (device_property_read_u32(dev, "solomon,prechargep1", &ssd130x->prechargep1))
+		ssd130x->prechargep1 = 2;
+
+	if (device_property_read_u32(dev, "solomon,prechargep2", &ssd130x->prechargep2))
+		ssd130x->prechargep2 = 2;
+
+	if (!device_property_read_u8_array(dev, "solomon,lookup-table",
+					   ssd130x->lookup_table,
+					   ARRAY_SIZE(ssd130x->lookup_table)))
+		ssd130x->lookup_table_set = 1;
+
+	ssd130x->seg_remap = !device_property_read_bool(dev, "solomon,segment-no-remap");
+	ssd130x->com_seq = device_property_read_bool(dev, "solomon,com-seq");
+	ssd130x->com_lrremap = device_property_read_bool(dev, "solomon,com-lrremap");
+	ssd130x->com_invdir = device_property_read_bool(dev, "solomon,com-invdir");
+	ssd130x->area_color_enable =
+		device_property_read_bool(dev, "solomon,area-color-enable");
+	ssd130x->low_power = device_property_read_bool(dev, "solomon,low-power");
+
+	ssd130x->contrast = 127;
+	ssd130x->vcomh = ssd130x->device_info->default_vcomh;
+
+	/* Setup display timing */
+	if (device_property_read_u32(dev, "solomon,dclk-div", &ssd130x->dclk_div))
+		ssd130x->dclk_div = ssd130x->device_info->default_dclk_div;
+	if (device_property_read_u32(dev, "solomon,dclk-frq", &ssd130x->dclk_frq))
+		ssd130x->dclk_frq = ssd130x->device_info->default_dclk_frq;
+}
+
+static int ssd130x_init_modeset(struct ssd130x_device *ssd130x)
+{
+	struct drm_display_mode *mode = &ssd130x->mode;
+	struct device *dev = ssd130x->dev;
+	struct drm_device *drm = &ssd130x->drm;
+	unsigned long max_width, max_height;
+	int ret;
+
+	ret = drmm_mode_config_init(drm);
+	if (ret) {
+		dev_err(dev, "DRM mode config init failed: %d\n", ret);
+		return ret;
+	}
+
+	mode->type = DRM_MODE_TYPE_DRIVER;
+	mode->clock = 1;
+	mode->hdisplay = mode->htotal = ssd130x->width;
+	mode->hsync_start = mode->hsync_end = ssd130x->width;
+	mode->vdisplay = mode->vtotal = ssd130x->height;
+	mode->vsync_start = mode->vsync_end = ssd130x->height;
+	mode->width_mm = 27;
+	mode->height_mm = 27;
+
+	max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
+	max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
+
+	drm->mode_config.min_width = mode->hdisplay;
+	drm->mode_config.max_width = max_width;
+	drm->mode_config.min_height = mode->vdisplay;
+	drm->mode_config.max_height = max_height;
+	drm->mode_config.preferred_depth = 32;
+	drm->mode_config.funcs = &ssd130x_mode_config_funcs;
+
+	ret = drm_connector_init(drm, &ssd130x->connector, &ssd130x_connector_funcs,
+				 DRM_MODE_CONNECTOR_Unknown);
+	if (ret) {
+		dev_err(dev, "DRM connector init failed: %d\n", ret);
+		return ret;
+	}
+
+	drm_connector_helper_add(&ssd130x->connector, &ssd130x_connector_helper_funcs);
+
+	ret = drm_simple_display_pipe_init(drm, &ssd130x->pipe, &ssd130x_pipe_funcs,
+					   ssd130x_formats, ARRAY_SIZE(ssd130x_formats),
+					   NULL, &ssd130x->connector);
+	if (ret) {
+		dev_err(dev, "DRM simple display pipeline init failed: %d\n", ret);
+		return ret;
+	}
+
+	drm_plane_enable_fb_damage_clips(&ssd130x->pipe.plane);
+
+	drm_mode_config_reset(drm);
+
+	return 0;
+}
+
+static int ssd130x_get_resources(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+	int ret;
+
+	ssd130x->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(ssd130x->reset))
+		return dev_err_probe(dev, PTR_ERR(ssd130x->reset), "Failed to get reset gpio\n");
+
+	ssd130x->vbat_reg = devm_regulator_get_optional(dev, "vbat");
+	if (IS_ERR(ssd130x->vbat_reg)) {
+		ret = PTR_ERR(ssd130x->vbat_reg);
+		if (ret == -ENODEV)
+			ssd130x->vbat_reg = NULL;
+		else
+			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");
+	}
+
+	return 0;
+}
+
+struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
+{
+	struct ssd130x_device *ssd130x;
+	struct backlight_device *bl;
+	struct drm_device *drm;
+	int ret;
+
+	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
+				     struct ssd130x_device, drm);
+	if (IS_ERR(ssd130x)) {
+		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
+		return ssd130x;
+	}
+
+	drm = &ssd130x->drm;
+
+	ssd130x->dev = dev;
+	ssd130x->regmap = regmap;
+	ssd130x->device_info = device_get_match_data(dev);
+
+	ssd130x_parse_properties(ssd130x);
+
+	ret = ssd130x_get_resources(ssd130x);
+	if (ret)
+		return ERR_PTR(ret);
+
+	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(dev, "Unable to register backlight device: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	bl->props.brightness = ssd130x->contrast;
+	bl->props.max_brightness = MAX_CONTRAST;
+	ssd130x->bl_dev = bl;
+
+	ret = ssd130x_init_modeset(ssd130x);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret) {
+		dev_err(dev, "DRM device register failed: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	drm_fbdev_generic_setup(drm, 0);
+
+	return ssd130x;
+}
+EXPORT_SYMBOL_GPL(ssd130x_probe);
+
+int ssd130x_remove(struct ssd130x_device *ssd130x)
+{
+	drm_dev_unplug(&ssd130x->drm);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ssd130x_remove);
+
+void ssd130x_shutdown(struct ssd130x_device *ssd130x)
+{
+	drm_atomic_helper_shutdown(&ssd130x->drm);
+}
+EXPORT_SYMBOL_GPL(ssd130x_shutdown);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/solomon/ssd130x.h b/drivers/gpu/drm/solomon/ssd130x.h
new file mode 100644
index 000000000000..bc760fdf0dfe
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Header file for:
+ * DRM driver for Solomon SSD130X OLED displays
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ *
+ * Based on drivers/video/fbdev/ssd1307fb.c
+ * Copyright 2012 Free Electrons
+ */
+
+#ifndef __SSD1307X_H__
+#define __SSD1307X_H__
+
+#include <drm/drm_drv.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include <linux/regmap.h>
+
+struct ssd130x_deviceinfo {
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
+	int need_pwm;
+	int need_chargepump;
+};
+
+struct ssd130x_device {
+	struct drm_device drm;
+	struct device *dev;
+	struct drm_simple_display_pipe pipe;
+	struct drm_display_mode mode;
+	struct drm_connector connector;
+	struct i2c_client *client;
+
+	struct regmap *regmap;
+
+	const struct ssd130x_deviceinfo *device_info;
+
+	unsigned area_color_enable : 1;
+	unsigned com_invdir : 1;
+	unsigned com_lrremap : 1;
+	unsigned com_seq : 1;
+	unsigned lookup_table_set : 1;
+	unsigned low_power : 1;
+	unsigned seg_remap : 1;
+	u32 com_offset;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	u32 height;
+	u8 lookup_table[4];
+	u32 page_offset;
+	u32 col_offset;
+	u32 prechargep1;
+	u32 prechargep2;
+
+	struct backlight_device *bl_dev;
+	struct pwm_device *pwm;
+	struct gpio_desc *reset;
+	struct regulator *vbat_reg;
+	u32 vcomh;
+	u32 width;
+	/* Cached address ranges */
+	u8 col_start;
+	u8 col_end;
+	u8 page_start;
+	u8 page_end;
+};
+
+struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap);
+int ssd130x_remove(struct ssd130x_device *ssd130x);
+void ssd130x_shutdown(struct ssd130x_device *ssd130x);
+
+#endif /* __SSD1307X_H__ */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Javier Martinez Canillas, Daniel Vetter,
	David Airlie, Lee Jones, Liam Girdwood, Maarten Lankhorst,
	Mark Brown, Maxime Ripard, Thierry Reding, Uwe Kleine-König,
	linux-pwm

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.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Move driver from tiny sub-dir to drivers/gpu/drm/solomon (Sam Ravnborg)
- Split driver in a bus agnostic core and bus specific (Andy Shevchenko)
- Use regmap to access the chip registers (Andy Shevchenko)
- Remove unnecessary blank lines (Andy Shevchenko)
- Remove unneeded inline specifier in functions (Andy Shevchenko)
- Add a comment about always returning a single mode (Andy Shevchenko)
- Change write command logic to use do while loop (Andy Shevchenko)
- Use "firmware description" instead of "device tree" (Andy Shevchenko)
- Use return foo() instead of returning the return value (Andy Shevchenko)
- Don't split lines longer than 80 chars if makes less readable (Andy Shevchenko)
- Remove redundant else statements in .mode_valid callback (Andy Shevchenko)
- Rename powero{n,ff}() functions to power_o{n,ff)() (Andy Shevchenko)
- Use dev_err_probe() to prevent spam logs on probe deferral (Andy Shevchenko)
- Remove ',' after sentinel terminator in array (Andy Shevchenko)
- Fix a bug when doing partial updates (Geert Uytterhoeven)

Changes in v2:
- Drop patch that was adding a DRM_MODE_CONNECTOR_I2C type.
- Invert order of backlight {en,dis}able and display {on,off} (Sam Ravnborg)
- Don't clear the screen and turn on display on probe (Sam Ravnborg)
- Use backlight_get_brightness() macro to get BL brightness (Sam Ravnborg)
- Use dev managed version of devm_backlight_device_register() (Sam Ravnborg)
- Use dev_name(dev) for backlight name instead of an array (Sam Ravnborg)
- Drop the .get_brightness callback since isn't needed  (Sam Ravnborg)
- Rename driver to ssd130x since supports a display family (Thomas Zimmermann)
- Drop the TINY prefix from the Kconfig symbol (Thomas Zimmermann)
- Sort the Kconfig symbol dependencies alphabetically (Thomas Zimmermann)
- Rename struct ssd130x_array to struct ssd130x_i2c_msg (Thomas Zimmermann)
- Rename struct ssd130x_i2c_msg .type member to .cmd (Thomas Zimmermann)
- Use sizeof(*foo) instead of sizeof(struct foo) (Thomas Zimmermann)
- Use struct_size() macro to calculate sizeof(*foo) + len (Thomas Zimmermann)
- Use kcalloc() instead of kmalloc_array() + memset() (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Use shadow plane helpers virtual screen support (Thomas Zimmermann)
- Remove unused goto label in ssd1307_fb_blit_rect() (Thomas Zimmermann)
- Use drm_set_preferred_mode() inset of manually set (Thomas Zimmermann)
- Reorganize code in probe to make it more legible (Thomas Zimmermann)
- ssd130x_write_cmd() uses varargs to simplify I2C code (Thomas Zimmermann)
- Move regulator/pwm init logic to display pipe enable callback.

 drivers/gpu/drm/Kconfig           |   2 +
 drivers/gpu/drm/Makefile          |   1 +
 drivers/gpu/drm/solomon/Kconfig   |  12 +
 drivers/gpu/drm/solomon/Makefile  |   1 +
 drivers/gpu/drm/solomon/ssd130x.c | 823 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/solomon/ssd130x.h |  76 +++
 6 files changed, 915 insertions(+)
 create mode 100644 drivers/gpu/drm/solomon/Kconfig
 create mode 100644 drivers/gpu/drm/solomon/Makefile
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.c
 create mode 100644 drivers/gpu/drm/solomon/ssd130x.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index dfdd3ec5f793..c423c920c027 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -405,6 +405,8 @@ source "drivers/gpu/drm/gud/Kconfig"
 
 source "drivers/gpu/drm/sprd/Kconfig"
 
+source "drivers/gpu/drm/solomon/Kconfig"
+
 config DRM_HYPERV
 	tristate "DRM Support for Hyper-V synthetic video device"
 	depends on DRM && PCI && MMU && HYPERV
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 8675c2af7ae1..a07b777e778a 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -133,3 +133,4 @@ obj-y			+= xlnx/
 obj-y			+= gud/
 obj-$(CONFIG_DRM_HYPERV) += hyperv/
 obj-$(CONFIG_DRM_SPRD) += sprd/
+obj-y			+= solomon/
diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
new file mode 100644
index 000000000000..c969c358a4a7
--- /dev/null
+++ b/drivers/gpu/drm/solomon/Kconfig
@@ -0,0 +1,12 @@
+config DRM_SSD130X
+	tristate "DRM support for Solomon SSD130X OLED displays"
+	depends on DRM
+	select BACKLIGHT_CLASS_DEVICE
+	select DRM_GEM_SHMEM_HELPER
+	select DRM_KMS_HELPER
+	help
+	  DRM driver for the SSD1305, SSD1306, SSD1307 and SSD1309 Solomon
+	  OLED controllers. This is only for the core driver, a driver for
+	  the appropriate bus transport in your chip also must be selected.
+
+	  If M is selected the module will be called ssd130x.
diff --git a/drivers/gpu/drm/solomon/Makefile b/drivers/gpu/drm/solomon/Makefile
new file mode 100644
index 000000000000..f685addb19fe
--- /dev/null
+++ b/drivers/gpu/drm/solomon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DRM_SSD130X)	+= ssd130x.o
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
new file mode 100644
index 000000000000..79943f2e73a2
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -0,0 +1,823 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for Solomon SSD130X OLED displays
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ *
+ * Based on drivers/video/fbdev/ssd1307fb.c
+ * Copyright 2012 Free Electrons
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/property.h>
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_probe_helper.h>
+
+#include "ssd130x.h"
+
+#define DRIVER_NAME	"ssd130x"
+#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays"
+#define DRIVER_DATE	"20220131"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+#define SSD130X_DATA				0x40
+#define SSD130X_COMMAND				0x80
+
+#define SSD130X_SET_ADDRESS_MODE		0x20
+#define SSD130X_SET_ADDRESS_MODE_HORIZONTAL	(0x00)
+#define SSD130X_SET_ADDRESS_MODE_VERTICAL	(0x01)
+#define SSD130X_SET_ADDRESS_MODE_PAGE		(0x02)
+#define SSD130X_SET_COL_RANGE			0x21
+#define SSD130X_SET_PAGE_RANGE			0x22
+#define SSD130X_CONTRAST			0x81
+#define SSD130X_SET_LOOKUP_TABLE		0x91
+#define SSD130X_CHARGE_PUMP			0x8d
+#define SSD130X_SEG_REMAP_ON			0xa1
+#define SSD130X_DISPLAY_OFF			0xae
+#define SSD130X_SET_MULTIPLEX_RATIO		0xa8
+#define SSD130X_DISPLAY_ON			0xaf
+#define SSD130X_START_PAGE_ADDRESS		0xb0
+#define SSD130X_SET_DISPLAY_OFFSET		0xd3
+#define SSD130X_SET_CLOCK_FREQ			0xd5
+#define SSD130X_SET_AREA_COLOR_MODE		0xd8
+#define SSD130X_SET_PRECHARGE_PERIOD		0xd9
+#define SSD130X_SET_COM_PINS_CONFIG		0xda
+#define SSD130X_SET_VCOMH			0xdb
+
+#define MAX_CONTRAST 255
+
+static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
+{
+	return container_of(drm, struct ssd130x_device, drm);
+}
+
+/*
+ * Helper to write data (SSD130X_DATA) to the device.
+ */
+static int ssd130x_write_data(struct ssd130x_device *ssd130x, u8 *values, int count)
+{
+	int ret;
+
+	ret = regmap_bulk_write(ssd130x->regmap, SSD130X_DATA, values, count);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Helper to write command (SSD130X_COMMAND). The fist variadic argument
+ * is the command to write and the following are the command options.
+ */
+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;
+}
+
+static int ssd130x_set_col_range(struct ssd130x_device *ssd130x,
+				 u8 col_start, u8 cols)
+{
+	u8 col_end = col_start + cols - 1;
+	int ret;
+
+	if (col_start == ssd130x->col_start && col_end == ssd130x->col_end)
+		return 0;
+
+	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_COL_RANGE, col_start, col_end);
+	if (ret < 0)
+		return ret;
+
+	ssd130x->col_start = col_start;
+	ssd130x->col_end = col_end;
+	return 0;
+}
+
+static int ssd130x_set_page_range(struct ssd130x_device *ssd130x,
+				  u8 page_start, u8 pages)
+{
+	u8 page_end = page_start + pages - 1;
+	int ret;
+
+	if (page_start == ssd130x->page_start && page_end == ssd130x->page_end)
+		return 0;
+
+	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_PAGE_RANGE, page_start, page_end);
+	if (ret < 0)
+		return ret;
+
+	ssd130x->page_start = page_start;
+	ssd130x->page_end = page_end;
+	return 0;
+}
+
+static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+	struct pwm_state pwmstate;
+
+	ssd130x->pwm = pwm_get(dev, NULL);
+	if (IS_ERR(ssd130x->pwm)) {
+		dev_err(dev, "Could not get PWM from firmware description!\n");
+		return PTR_ERR(ssd130x->pwm);
+	}
+
+	pwm_init_state(ssd130x->pwm, &pwmstate);
+	pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
+	pwm_apply_state(ssd130x->pwm, &pwmstate);
+
+	/* Enable the PWM */
+	pwm_enable(ssd130x->pwm);
+
+	dev_dbg(dev, "Using PWM%d with a %lluns period.\n",
+		ssd130x->pwm->pwm, pwm_get_period(ssd130x->pwm));
+
+	return 0;
+}
+
+static void ssd130x_reset(struct ssd130x_device *ssd130x)
+{
+	/* Reset the screen */
+	gpiod_set_value_cansleep(ssd130x->reset, 1);
+	udelay(4);
+	gpiod_set_value_cansleep(ssd130x->reset, 0);
+	udelay(4);
+}
+
+static int ssd130x_power_on(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+	int ret;
+
+	if (ssd130x->reset)
+		ssd130x_reset(ssd130x);
+
+	if (ssd130x->vbat_reg) {
+		ret = regulator_enable(ssd130x->vbat_reg);
+		if (ret) {
+			dev_err(dev, "Failed to enable VBAT: %d\n", ret);
+			return ret;
+		}
+	}
+
+	if (ssd130x->device_info->need_pwm) {
+		ret = ssd130x_pwm_enable(ssd130x);
+		if (ret) {
+			dev_err(dev, "Failed to enable PWM: %d\n", ret);
+			if (ssd130x->vbat_reg)
+				regulator_disable(ssd130x->vbat_reg);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void ssd130x_power_off(struct ssd130x_device *ssd130x)
+{
+	if (ssd130x->device_info->need_pwm) {
+		pwm_disable(ssd130x->pwm);
+		pwm_put(ssd130x->pwm);
+	}
+
+	if (ssd130x->vbat_reg)
+		regulator_disable(ssd130x->vbat_reg);
+}
+
+static int ssd130x_init(struct ssd130x_device *ssd130x)
+{
+	u32 precharge, dclk, com_invdir, compins, chargepump;
+	int ret;
+
+	/* Set initial contrast */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CONTRAST, ssd130x->contrast);
+	if (ret < 0)
+		return ret;
+
+	/* Set segment re-map */
+	if (ssd130x->seg_remap) {
+		ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | ssd130x->com_invdir << 3;
+	ret = ssd130x_write_cmd(ssd130x,  1, com_invdir);
+	if (ret < 0)
+		return ret;
+
+	/* Set multiplex ratio value */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* set display offset value */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_DISPLAY_OFFSET, ssd130x->com_offset);
+	if (ret < 0)
+		return ret;
+
+	/* Set clock frequency */
+	dclk = ((ssd130x->dclk_div - 1) & 0xf) | (ssd130x->dclk_frq & 0xf) << 4;
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_CLOCK_FREQ, dclk);
+	if (ret < 0)
+		return ret;
+
+	/* Set Area Color Mode ON/OFF & Low Power Display Mode */
+	if (ssd130x->area_color_enable || ssd130x->low_power) {
+		u32 mode = ((ssd130x->area_color_enable ? 0x30 : 0) |
+			    (ssd130x->low_power ? 5 : 0));
+
+		ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_AREA_COLOR_MODE, mode);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Set precharge period in number of ticks from the internal clock */
+	precharge = (ssd130x->prechargep1 & 0xf) | (ssd130x->prechargep2 & 0xf) << 4;
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge);
+	if (ret < 0)
+		return ret;
+
+	/* Set COM pins configuration */
+	compins = 0x02 | !ssd130x->com_seq << 4 | ssd130x->com_lrremap << 5;
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_COM_PINS_CONFIG, compins);
+	if (ret < 0)
+		return ret;
+
+
+	/* Set VCOMH */
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_VCOMH, ssd130x->vcomh);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the DC-DC Charge Pump */
+	chargepump = BIT(4) | (ssd130x->device_info->need_chargepump ? BIT(2) : 0);
+	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CHARGE_PUMP, chargepump);
+	if (ret < 0)
+		return ret;
+
+	/* Set lookup table */
+	if (ssd130x->lookup_table_set) {
+		int i;
+
+		ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SET_LOOKUP_TABLE);
+		if (ret < 0)
+			return ret;
+
+		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); ++i) {
+			u8 val = ssd130x->lookup_table[i];
+
+			if (val < 31 || val > 63)
+				dev_warn(ssd130x->dev,
+					 "lookup table index %d value out of range 31 <= %d <= 63\n",
+					 i, val);
+			ret = ssd130x_write_cmd(ssd130x, 1, val);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	/* Switch to horizontal addressing mode */
+	return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
+				 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
+}
+
+static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
+			       struct drm_rect *rect)
+{
+	unsigned int x = rect->x1;
+	unsigned int y = rect->y1;
+	unsigned int width = drm_rect_width(rect);
+	unsigned int height = drm_rect_height(rect);
+	unsigned int line_length = DIV_ROUND_UP(width, 8);
+	unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8);
+	u32 array_idx = 0;
+	int ret, i, j, k;
+	u8 *data_array = NULL;
+
+	data_array = kcalloc(width, pages, GFP_KERNEL);
+	if (!data_array)
+		return -ENOMEM;
+
+	/*
+	 * The screen is divided in pages, each having a height of 8
+	 * pixels, and the width of the screen. When sending a byte of
+	 * data to the controller, it gives the 8 bits for the current
+	 * column. I.e, the first byte are the 8 bits of the first
+	 * column, then the 8 bits for the second column, etc.
+	 *
+	 *
+	 * Representation of the screen, assuming it is 5 bits
+	 * wide. Each letter-number combination is a bit that controls
+	 * one pixel.
+	 *
+	 * A0 A1 A2 A3 A4
+	 * B0 B1 B2 B3 B4
+	 * C0 C1 C2 C3 C4
+	 * D0 D1 D2 D3 D4
+	 * E0 E1 E2 E3 E4
+	 * F0 F1 F2 F3 F4
+	 * G0 G1 G2 G3 G4
+	 * H0 H1 H2 H3 H4
+	 *
+	 * If you want to update this screen, you need to send 5 bytes:
+	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
+	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
+	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
+	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
+	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
+	 */
+
+	ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
+	if (ret < 0)
+		goto out_free;
+
+	ret = ssd130x_set_page_range(ssd130x, ssd130x->page_offset + y / 8, pages);
+	if (ret < 0)
+		goto out_free;
+
+	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;
+		for (j = x; j < x + width; j++) {
+			u8 data = 0;
+
+			for (k = 0; k < m; k++) {
+				u8 byte = buf[(8 * i + k) * line_length + j / 8];
+				u8 bit = (byte >> (j % 8)) & 1;
+
+				data |= bit << k;
+			}
+			data_array[array_idx++] = data;
+		}
+	}
+
+	ret = ssd130x_write_data(ssd130x, data_array, width * pages);
+
+out_free:
+	kfree(data_array);
+	return ret;
+}
+
+static void ssd130x_clear_screen(struct ssd130x_device *ssd130x)
+{
+	u8 *buf = NULL;
+
+	struct drm_rect fullscreen = {
+		.x1 = 0,
+		.x2 = ssd130x->width,
+		.y1 = 0,
+		.y2 = ssd130x->height,
+	};
+
+	buf = kcalloc(ssd130x->width, ssd130x->height, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	ssd130x_update_rect(ssd130x, buf, &fullscreen);
+
+	kfree(buf);
+}
+
+static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map,
+				struct drm_rect *rect)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
+	void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
+	int ret = 0;
+	u8 *buf = NULL;
+
+	buf = kcalloc(fb->width, fb->height, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	drm_fb_xrgb8888_to_mono_reversed(buf, 0, vmap, fb, rect);
+
+	ssd130x_update_rect(ssd130x, buf, rect);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static int ssd130x_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
+					   const struct drm_display_mode *mode)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+
+	if (mode->hdisplay != ssd130x->mode.hdisplay &&
+	    mode->vdisplay != ssd130x->mode.vdisplay)
+		return MODE_ONE_SIZE;
+
+	if (mode->hdisplay != ssd130x->mode.hdisplay)
+		return MODE_ONE_WIDTH;
+
+	if (mode->vdisplay != ssd130x->mode.vdisplay)
+		return MODE_ONE_HEIGHT;
+
+	return MODE_OK;
+}
+
+static void ssd130x_display_pipe_enable(struct drm_simple_display_pipe *pipe,
+					struct drm_crtc_state *crtc_state,
+					struct drm_plane_state *plane_state)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+	struct drm_device *drm = &ssd130x->drm;
+	int idx, ret;
+
+	ret = ssd130x_power_on(ssd130x);
+	if (ret)
+		return;
+
+	ret = ssd130x_init(ssd130x);
+	if (ret)
+		goto power_off;
+
+	if (!drm_dev_enter(drm, &idx))
+		goto power_off;
+
+	ssd130x_clear_screen(ssd130x);
+
+	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON);
+
+	backlight_enable(ssd130x->bl_dev);
+
+	drm_dev_exit(idx);
+
+	return;
+power_off:
+	ssd130x_power_off(ssd130x);
+}
+
+static void ssd130x_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+	struct drm_device *drm = &ssd130x->drm;
+	int idx;
+
+	if (!drm_dev_enter(drm, &idx))
+		return;
+
+	ssd130x_clear_screen(ssd130x);
+
+	backlight_disable(ssd130x->bl_dev);
+
+	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF);
+
+	ssd130x_power_off(ssd130x);
+
+	drm_dev_exit(idx);
+}
+
+static void ssd130x_display_pipe_update(struct drm_simple_display_pipe *pipe,
+					struct drm_plane_state *old_plane_state)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
+	struct drm_plane_state *plane_state = pipe->plane.state;
+	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_device *drm = &ssd130x->drm;
+	struct drm_rect src_clip, dst_clip;
+	int idx;
+
+	if (!fb)
+		return;
+
+	if (!pipe->crtc.state->active)
+		return;
+
+	if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))
+		return;
+
+	dst_clip = plane_state->dst;
+	if (!drm_rect_intersect(&dst_clip, &src_clip))
+		return;
+
+	if (!drm_dev_enter(drm, &idx))
+		return;
+
+	ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
+
+	drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs ssd130x_pipe_funcs = {
+	.mode_valid = ssd130x_display_pipe_mode_valid,
+	.enable = ssd130x_display_pipe_enable,
+	.disable = ssd130x_display_pipe_disable,
+	.update = ssd130x_display_pipe_update,
+	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+};
+
+static int ssd130x_connector_get_modes(struct drm_connector *connector)
+{
+	struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev);
+	struct drm_display_mode *mode = &ssd130x->mode;
+	struct device *dev = ssd130x->dev;
+
+	mode = drm_mode_duplicate(connector->dev, &ssd130x->mode);
+	if (!mode) {
+		dev_err(dev, "Failed to duplicated mode\n");
+		return 0;
+	}
+
+	drm_mode_probed_add(connector, mode);
+	drm_set_preferred_mode(connector, mode->hdisplay, mode->vdisplay);
+
+	/* There is only a single mode */
+	return 1;
+}
+
+static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = {
+	.get_modes = ssd130x_connector_get_modes,
+};
+
+static const struct drm_connector_funcs ssd130x_connector_funcs = {
+	.reset = drm_atomic_helper_connector_reset,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_mode_config_funcs ssd130x_mode_config_funcs = {
+	.fb_create = drm_gem_fb_create_with_dirty,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static const uint32_t ssd130x_formats[] = {
+	DRM_FORMAT_XRGB8888,
+};
+
+DEFINE_DRM_GEM_FOPS(ssd130x_fops);
+
+static const struct drm_driver ssd130x_drm_driver = {
+	DRM_GEM_SHMEM_DRIVER_OPS,
+	.name			= DRIVER_NAME,
+	.desc			= DRIVER_DESC,
+	.date			= DRIVER_DATE,
+	.major			= DRIVER_MAJOR,
+	.minor			= DRIVER_MINOR,
+	.driver_features	= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
+	.fops			= &ssd130x_fops,
+};
+
+static int ssd130x_update_bl(struct backlight_device *bdev)
+{
+	struct ssd130x_device *ssd130x = bl_get_data(bdev);
+	int brightness = backlight_get_brightness(bdev);
+	int ret;
+
+	ssd130x->contrast = brightness;
+
+	ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_CONTRAST);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd130x_write_cmd(ssd130x, 1, ssd130x->contrast);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct backlight_ops ssd130xfb_bl_ops = {
+	.update_status	= ssd130x_update_bl,
+};
+
+static void ssd130x_parse_properties(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+
+	if (device_property_read_u32(dev, "solomon,width", &ssd130x->width))
+		ssd130x->width = 96;
+
+	if (device_property_read_u32(dev, "solomon,height", &ssd130x->height))
+		ssd130x->height = 16;
+
+	if (device_property_read_u32(dev, "solomon,page-offset", &ssd130x->page_offset))
+		ssd130x->page_offset = 1;
+
+	if (device_property_read_u32(dev, "solomon,col-offset", &ssd130x->col_offset))
+		ssd130x->col_offset = 0;
+
+	if (device_property_read_u32(dev, "solomon,com-offset", &ssd130x->com_offset))
+		ssd130x->com_offset = 0;
+
+	if (device_property_read_u32(dev, "solomon,prechargep1", &ssd130x->prechargep1))
+		ssd130x->prechargep1 = 2;
+
+	if (device_property_read_u32(dev, "solomon,prechargep2", &ssd130x->prechargep2))
+		ssd130x->prechargep2 = 2;
+
+	if (!device_property_read_u8_array(dev, "solomon,lookup-table",
+					   ssd130x->lookup_table,
+					   ARRAY_SIZE(ssd130x->lookup_table)))
+		ssd130x->lookup_table_set = 1;
+
+	ssd130x->seg_remap = !device_property_read_bool(dev, "solomon,segment-no-remap");
+	ssd130x->com_seq = device_property_read_bool(dev, "solomon,com-seq");
+	ssd130x->com_lrremap = device_property_read_bool(dev, "solomon,com-lrremap");
+	ssd130x->com_invdir = device_property_read_bool(dev, "solomon,com-invdir");
+	ssd130x->area_color_enable =
+		device_property_read_bool(dev, "solomon,area-color-enable");
+	ssd130x->low_power = device_property_read_bool(dev, "solomon,low-power");
+
+	ssd130x->contrast = 127;
+	ssd130x->vcomh = ssd130x->device_info->default_vcomh;
+
+	/* Setup display timing */
+	if (device_property_read_u32(dev, "solomon,dclk-div", &ssd130x->dclk_div))
+		ssd130x->dclk_div = ssd130x->device_info->default_dclk_div;
+	if (device_property_read_u32(dev, "solomon,dclk-frq", &ssd130x->dclk_frq))
+		ssd130x->dclk_frq = ssd130x->device_info->default_dclk_frq;
+}
+
+static int ssd130x_init_modeset(struct ssd130x_device *ssd130x)
+{
+	struct drm_display_mode *mode = &ssd130x->mode;
+	struct device *dev = ssd130x->dev;
+	struct drm_device *drm = &ssd130x->drm;
+	unsigned long max_width, max_height;
+	int ret;
+
+	ret = drmm_mode_config_init(drm);
+	if (ret) {
+		dev_err(dev, "DRM mode config init failed: %d\n", ret);
+		return ret;
+	}
+
+	mode->type = DRM_MODE_TYPE_DRIVER;
+	mode->clock = 1;
+	mode->hdisplay = mode->htotal = ssd130x->width;
+	mode->hsync_start = mode->hsync_end = ssd130x->width;
+	mode->vdisplay = mode->vtotal = ssd130x->height;
+	mode->vsync_start = mode->vsync_end = ssd130x->height;
+	mode->width_mm = 27;
+	mode->height_mm = 27;
+
+	max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
+	max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
+
+	drm->mode_config.min_width = mode->hdisplay;
+	drm->mode_config.max_width = max_width;
+	drm->mode_config.min_height = mode->vdisplay;
+	drm->mode_config.max_height = max_height;
+	drm->mode_config.preferred_depth = 32;
+	drm->mode_config.funcs = &ssd130x_mode_config_funcs;
+
+	ret = drm_connector_init(drm, &ssd130x->connector, &ssd130x_connector_funcs,
+				 DRM_MODE_CONNECTOR_Unknown);
+	if (ret) {
+		dev_err(dev, "DRM connector init failed: %d\n", ret);
+		return ret;
+	}
+
+	drm_connector_helper_add(&ssd130x->connector, &ssd130x_connector_helper_funcs);
+
+	ret = drm_simple_display_pipe_init(drm, &ssd130x->pipe, &ssd130x_pipe_funcs,
+					   ssd130x_formats, ARRAY_SIZE(ssd130x_formats),
+					   NULL, &ssd130x->connector);
+	if (ret) {
+		dev_err(dev, "DRM simple display pipeline init failed: %d\n", ret);
+		return ret;
+	}
+
+	drm_plane_enable_fb_damage_clips(&ssd130x->pipe.plane);
+
+	drm_mode_config_reset(drm);
+
+	return 0;
+}
+
+static int ssd130x_get_resources(struct ssd130x_device *ssd130x)
+{
+	struct device *dev = ssd130x->dev;
+	int ret;
+
+	ssd130x->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(ssd130x->reset))
+		return dev_err_probe(dev, PTR_ERR(ssd130x->reset), "Failed to get reset gpio\n");
+
+	ssd130x->vbat_reg = devm_regulator_get_optional(dev, "vbat");
+	if (IS_ERR(ssd130x->vbat_reg)) {
+		ret = PTR_ERR(ssd130x->vbat_reg);
+		if (ret == -ENODEV)
+			ssd130x->vbat_reg = NULL;
+		else
+			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");
+	}
+
+	return 0;
+}
+
+struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
+{
+	struct ssd130x_device *ssd130x;
+	struct backlight_device *bl;
+	struct drm_device *drm;
+	int ret;
+
+	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
+				     struct ssd130x_device, drm);
+	if (IS_ERR(ssd130x)) {
+		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
+		return ssd130x;
+	}
+
+	drm = &ssd130x->drm;
+
+	ssd130x->dev = dev;
+	ssd130x->regmap = regmap;
+	ssd130x->device_info = device_get_match_data(dev);
+
+	ssd130x_parse_properties(ssd130x);
+
+	ret = ssd130x_get_resources(ssd130x);
+	if (ret)
+		return ERR_PTR(ret);
+
+	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(dev, "Unable to register backlight device: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	bl->props.brightness = ssd130x->contrast;
+	bl->props.max_brightness = MAX_CONTRAST;
+	ssd130x->bl_dev = bl;
+
+	ret = ssd130x_init_modeset(ssd130x);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret) {
+		dev_err(dev, "DRM device register failed: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	drm_fbdev_generic_setup(drm, 0);
+
+	return ssd130x;
+}
+EXPORT_SYMBOL_GPL(ssd130x_probe);
+
+int ssd130x_remove(struct ssd130x_device *ssd130x)
+{
+	drm_dev_unplug(&ssd130x->drm);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ssd130x_remove);
+
+void ssd130x_shutdown(struct ssd130x_device *ssd130x)
+{
+	drm_atomic_helper_shutdown(&ssd130x->drm);
+}
+EXPORT_SYMBOL_GPL(ssd130x_shutdown);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/solomon/ssd130x.h b/drivers/gpu/drm/solomon/ssd130x.h
new file mode 100644
index 000000000000..bc760fdf0dfe
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Header file for:
+ * DRM driver for Solomon SSD130X OLED displays
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ *
+ * Based on drivers/video/fbdev/ssd1307fb.c
+ * Copyright 2012 Free Electrons
+ */
+
+#ifndef __SSD1307X_H__
+#define __SSD1307X_H__
+
+#include <drm/drm_drv.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include <linux/regmap.h>
+
+struct ssd130x_deviceinfo {
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
+	int need_pwm;
+	int need_chargepump;
+};
+
+struct ssd130x_device {
+	struct drm_device drm;
+	struct device *dev;
+	struct drm_simple_display_pipe pipe;
+	struct drm_display_mode mode;
+	struct drm_connector connector;
+	struct i2c_client *client;
+
+	struct regmap *regmap;
+
+	const struct ssd130x_deviceinfo *device_info;
+
+	unsigned area_color_enable : 1;
+	unsigned com_invdir : 1;
+	unsigned com_lrremap : 1;
+	unsigned com_seq : 1;
+	unsigned lookup_table_set : 1;
+	unsigned low_power : 1;
+	unsigned seg_remap : 1;
+	u32 com_offset;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	u32 height;
+	u8 lookup_table[4];
+	u32 page_offset;
+	u32 col_offset;
+	u32 prechargep1;
+	u32 prechargep2;
+
+	struct backlight_device *bl_dev;
+	struct pwm_device *pwm;
+	struct gpio_desc *reset;
+	struct regulator *vbat_reg;
+	u32 vcomh;
+	u32 width;
+	/* Cached address ranges */
+	u8 col_start;
+	u8 col_end;
+	u8 page_start;
+	u8 page_end;
+};
+
+struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap);
+int ssd130x_remove(struct ssd130x_device *ssd130x);
+void ssd130x_shutdown(struct ssd130x_device *ssd130x);
+
+#endif /* __SSD1307X_H__ */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, David Airlie, Daniel Vetter,
	Javier Martinez Canillas, dri-devel, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Andy Shevchenko, Sam Ravnborg

The ssd130x driver only provides the core support for these devices but it
does not have any bus transport logic. Add a driver to interface over I2C.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Add a separate driver for SSD130X chips I2C support (Andy Shevchenko)

 drivers/gpu/drm/solomon/Kconfig       |   9 ++
 drivers/gpu/drm/solomon/Makefile      |   1 +
 drivers/gpu/drm/solomon/ssd130x-i2c.c | 117 ++++++++++++++++++++++++++
 3 files changed, 127 insertions(+)
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-i2c.c

diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
index c969c358a4a7..47e16bc20e0d 100644
--- a/drivers/gpu/drm/solomon/Kconfig
+++ b/drivers/gpu/drm/solomon/Kconfig
@@ -10,3 +10,12 @@ config DRM_SSD130X
 	  the appropriate bus transport in your chip also must be selected.
 
 	  If M is selected the module will be called ssd130x.
+
+config DRM_SSD130X_I2C
+	tristate "DRM support for Solomon SSD130X OLED displays (I2C bus)"
+	depends on DRM_SSD130X && I2C
+	select REGMAP_I2C
+	help
+	  Say Y here if the SSD130X OLED display is connected via I2C bus.
+
+	  If M is selected the module will be called ssd130x-i2c.
diff --git a/drivers/gpu/drm/solomon/Makefile b/drivers/gpu/drm/solomon/Makefile
index f685addb19fe..4bfc5acb0447 100644
--- a/drivers/gpu/drm/solomon/Makefile
+++ b/drivers/gpu/drm/solomon/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_DRM_SSD130X)	+= ssd130x.o
+obj-$(CONFIG_DRM_SSD130X_I2C)	+= ssd130x-i2c.o
diff --git a/drivers/gpu/drm/solomon/ssd130x-i2c.c b/drivers/gpu/drm/solomon/ssd130x-i2c.c
new file mode 100644
index 000000000000..ff5f8992b2ff
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for Solomon SSD130X OLED displays (I2C bus)
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ *
+ * Based on drivers/video/fbdev/ssd1307fb.c
+ * Copyright 2012 Free Electrons
+ */
+#include <linux/i2c.h>
+#include <linux/module.h>
+
+#include "ssd130x.h"
+
+#define DRIVER_NAME	"ssd130x-i2c"
+#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays (I2C)"
+
+static const struct regmap_config ssd130x_i2c_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int ssd130x_i2c_probe(struct i2c_client *client)
+{
+	struct ssd130x_device *ssd130x;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_i2c(client, &ssd130x_i2c_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ssd130x = ssd130x_probe(&client->dev, regmap);
+
+	if (IS_ERR(ssd130x))
+		return PTR_ERR(ssd130x);
+
+	i2c_set_clientdata(client, ssd130x);
+
+	return 0;
+}
+
+static int ssd130x_i2c_remove(struct i2c_client *client)
+{
+	struct ssd130x_device *ssd130x = i2c_get_clientdata(client);
+
+	return ssd130x_remove(ssd130x);
+}
+
+static void ssd130x_i2c_shutdown(struct i2c_client *client)
+{
+	struct ssd130x_device *ssd130x = i2c_get_clientdata(client);
+
+	ssd130x_shutdown(ssd130x);
+}
+
+static struct ssd130x_deviceinfo ssd130x_ssd1305_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 7,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1306_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 8,
+	.need_chargepump = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1307_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 2,
+	.default_dclk_frq = 12,
+	.need_pwm = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1309_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 10,
+};
+
+static const struct of_device_id ssd130x_of_match[] = {
+	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd130x_ssd1305_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1306fb-i2c",
+		.data = (void *)&ssd130x_ssd1306_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1307fb-i2c",
+		.data = (void *)&ssd130x_ssd1307_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1309fb-i2c",
+		.data = (void *)&ssd130x_ssd1309_deviceinfo,
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ssd130x_of_match);
+
+static struct i2c_driver ssd130x_i2c_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = ssd130x_of_match,
+	},
+	.probe_new = ssd130x_i2c_probe,
+	.remove = ssd130x_i2c_remove,
+	.shutdown = ssd130x_i2c_shutdown,
+};
+module_i2c_driver(ssd130x_i2c_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
@ 2022-02-09  9:03   ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Javier Martinez Canillas, Daniel Vetter,
	David Airlie

The ssd130x driver only provides the core support for these devices but it
does not have any bus transport logic. Add a driver to interface over I2C.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Add a separate driver for SSD130X chips I2C support (Andy Shevchenko)

 drivers/gpu/drm/solomon/Kconfig       |   9 ++
 drivers/gpu/drm/solomon/Makefile      |   1 +
 drivers/gpu/drm/solomon/ssd130x-i2c.c | 117 ++++++++++++++++++++++++++
 3 files changed, 127 insertions(+)
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-i2c.c

diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
index c969c358a4a7..47e16bc20e0d 100644
--- a/drivers/gpu/drm/solomon/Kconfig
+++ b/drivers/gpu/drm/solomon/Kconfig
@@ -10,3 +10,12 @@ config DRM_SSD130X
 	  the appropriate bus transport in your chip also must be selected.
 
 	  If M is selected the module will be called ssd130x.
+
+config DRM_SSD130X_I2C
+	tristate "DRM support for Solomon SSD130X OLED displays (I2C bus)"
+	depends on DRM_SSD130X && I2C
+	select REGMAP_I2C
+	help
+	  Say Y here if the SSD130X OLED display is connected via I2C bus.
+
+	  If M is selected the module will be called ssd130x-i2c.
diff --git a/drivers/gpu/drm/solomon/Makefile b/drivers/gpu/drm/solomon/Makefile
index f685addb19fe..4bfc5acb0447 100644
--- a/drivers/gpu/drm/solomon/Makefile
+++ b/drivers/gpu/drm/solomon/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_DRM_SSD130X)	+= ssd130x.o
+obj-$(CONFIG_DRM_SSD130X_I2C)	+= ssd130x-i2c.o
diff --git a/drivers/gpu/drm/solomon/ssd130x-i2c.c b/drivers/gpu/drm/solomon/ssd130x-i2c.c
new file mode 100644
index 000000000000..ff5f8992b2ff
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for Solomon SSD130X OLED displays (I2C bus)
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ *
+ * Based on drivers/video/fbdev/ssd1307fb.c
+ * Copyright 2012 Free Electrons
+ */
+#include <linux/i2c.h>
+#include <linux/module.h>
+
+#include "ssd130x.h"
+
+#define DRIVER_NAME	"ssd130x-i2c"
+#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays (I2C)"
+
+static const struct regmap_config ssd130x_i2c_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int ssd130x_i2c_probe(struct i2c_client *client)
+{
+	struct ssd130x_device *ssd130x;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_i2c(client, &ssd130x_i2c_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ssd130x = ssd130x_probe(&client->dev, regmap);
+
+	if (IS_ERR(ssd130x))
+		return PTR_ERR(ssd130x);
+
+	i2c_set_clientdata(client, ssd130x);
+
+	return 0;
+}
+
+static int ssd130x_i2c_remove(struct i2c_client *client)
+{
+	struct ssd130x_device *ssd130x = i2c_get_clientdata(client);
+
+	return ssd130x_remove(ssd130x);
+}
+
+static void ssd130x_i2c_shutdown(struct i2c_client *client)
+{
+	struct ssd130x_device *ssd130x = i2c_get_clientdata(client);
+
+	ssd130x_shutdown(ssd130x);
+}
+
+static struct ssd130x_deviceinfo ssd130x_ssd1305_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 7,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1306_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 8,
+	.need_chargepump = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1307_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 2,
+	.default_dclk_frq = 12,
+	.need_pwm = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1309_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 10,
+};
+
+static const struct of_device_id ssd130x_of_match[] = {
+	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd130x_ssd1305_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1306fb-i2c",
+		.data = (void *)&ssd130x_ssd1306_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1307fb-i2c",
+		.data = (void *)&ssd130x_ssd1307_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1309fb-i2c",
+		.data = (void *)&ssd130x_ssd1309_deviceinfo,
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ssd130x_of_match);
+
+static struct i2c_driver ssd130x_i2c_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = ssd130x_of_match,
+	},
+	.probe_new = ssd130x_i2c_probe,
+	.remove = ssd130x_i2c_remove,
+	.shutdown = ssd130x_i2c_shutdown,
+};
+module_i2c_driver(ssd130x_i2c_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09  9:12   ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, Daniel Vetter, Javier Martinez Canillas, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Andy Shevchenko

The ssd130x driver only provides the core support for these devices but it
does not have any bus transport logic. Add a driver to interface over SPI.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Add a separate driver for SSD130X chips SPI support (Andy Shevchenko)

 drivers/gpu/drm/solomon/Kconfig       |   9 ++
 drivers/gpu/drm/solomon/Makefile      |   1 +
 drivers/gpu/drm/solomon/ssd130x-spi.c | 114 ++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-spi.c

diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
index 47e16bc20e0d..16a2098f438c 100644
--- a/drivers/gpu/drm/solomon/Kconfig
+++ b/drivers/gpu/drm/solomon/Kconfig
@@ -19,3 +19,12 @@ config DRM_SSD130X_I2C
 	  Say Y here if the SSD130X OLED display is connected via I2C bus.
 
 	  If M is selected the module will be called ssd130x-i2c.
+
+config DRM_SSD130X_SPI
+	tristate "DRM support for Solomon SSD130X OLED displays (SPI bus)"
+	depends on DRM_SSD130X && SPI
+	select REGMAP_SPI
+	help
+	  Say Y here if the SSD130X OLED display is connected via SPI bus.
+
+	  If M is selected the module will be called ssd130x-spi.
diff --git a/drivers/gpu/drm/solomon/Makefile b/drivers/gpu/drm/solomon/Makefile
index 4bfc5acb0447..b5fc792257d7 100644
--- a/drivers/gpu/drm/solomon/Makefile
+++ b/drivers/gpu/drm/solomon/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_DRM_SSD130X)	+= ssd130x.o
 obj-$(CONFIG_DRM_SSD130X_I2C)	+= ssd130x-i2c.o
+obj-$(CONFIG_DRM_SSD130X_SPI)	+= ssd130x-spi.o
diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c
new file mode 100644
index 000000000000..ccc56d2f3026
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for Solomon SSD130X OLED displays (SPI bus)
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ */
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+
+#include "ssd130x.h"
+
+#define DRIVER_NAME	"ssd130x-spi"
+#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays (SPI)"
+
+static const struct regmap_config ssd130x_spi_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int ssd130x_spi_probe(struct spi_device *spi)
+{
+	struct ssd130x_device *ssd130x;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_spi(spi, &ssd130x_spi_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ssd130x = ssd130x_probe(&spi->dev, regmap);
+
+	if (IS_ERR(ssd130x))
+		return PTR_ERR(ssd130x);
+
+	spi_set_drvdata(spi, ssd130x);
+
+	return 0;
+}
+
+static int ssd130x_spi_remove(struct spi_device *spi)
+{
+	struct ssd130x_device *ssd130x = spi_get_drvdata(spi);
+
+	return ssd130x_remove(ssd130x);
+}
+
+static void ssd130x_spi_shutdown(struct spi_device *spi)
+{
+	struct ssd130x_device *ssd130x = spi_get_drvdata(spi);
+
+	ssd130x_shutdown(ssd130x);
+}
+
+static struct ssd130x_deviceinfo ssd130x_ssd1305_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 7,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1306_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 8,
+	.need_chargepump = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1307_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 2,
+	.default_dclk_frq = 12,
+	.need_pwm = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1309_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 10,
+};
+
+static const struct of_device_id ssd130x_of_match[] = {
+	{
+		.compatible = "solomon,ssd1305fb-spi",
+		.data = (void *)&ssd130x_ssd1305_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1306fb-spi",
+		.data = (void *)&ssd130x_ssd1306_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1307fb-spi",
+		.data = (void *)&ssd130x_ssd1307_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1309fb-spi",
+		.data = (void *)&ssd130x_ssd1309_deviceinfo,
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ssd130x_of_match);
+
+static struct spi_driver ssd130x_spi_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = ssd130x_of_match,
+	},
+	.probe = ssd130x_spi_probe,
+	.remove = ssd130x_spi_remove,
+	.shutdown = ssd130x_spi_shutdown,
+};
+module_spi_driver(ssd130x_spi_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09  9:12   ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Daniel Vetter, Geert Uytterhoeven,
	Maxime Ripard, Noralf Trønnes, dri-devel, linux-fbdev,
	Javier Martinez Canillas

The ssd130x driver only provides the core support for these devices but it
does not have any bus transport logic. Add a driver to interface over SPI.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

Changes in v3:
- Add a separate driver for SSD130X chips SPI support (Andy Shevchenko)

 drivers/gpu/drm/solomon/Kconfig       |   9 ++
 drivers/gpu/drm/solomon/Makefile      |   1 +
 drivers/gpu/drm/solomon/ssd130x-spi.c | 114 ++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 drivers/gpu/drm/solomon/ssd130x-spi.c

diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
index 47e16bc20e0d..16a2098f438c 100644
--- a/drivers/gpu/drm/solomon/Kconfig
+++ b/drivers/gpu/drm/solomon/Kconfig
@@ -19,3 +19,12 @@ config DRM_SSD130X_I2C
 	  Say Y here if the SSD130X OLED display is connected via I2C bus.
 
 	  If M is selected the module will be called ssd130x-i2c.
+
+config DRM_SSD130X_SPI
+	tristate "DRM support for Solomon SSD130X OLED displays (SPI bus)"
+	depends on DRM_SSD130X && SPI
+	select REGMAP_SPI
+	help
+	  Say Y here if the SSD130X OLED display is connected via SPI bus.
+
+	  If M is selected the module will be called ssd130x-spi.
diff --git a/drivers/gpu/drm/solomon/Makefile b/drivers/gpu/drm/solomon/Makefile
index 4bfc5acb0447..b5fc792257d7 100644
--- a/drivers/gpu/drm/solomon/Makefile
+++ b/drivers/gpu/drm/solomon/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_DRM_SSD130X)	+= ssd130x.o
 obj-$(CONFIG_DRM_SSD130X_I2C)	+= ssd130x-i2c.o
+obj-$(CONFIG_DRM_SSD130X_SPI)	+= ssd130x-spi.o
diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c
new file mode 100644
index 000000000000..ccc56d2f3026
--- /dev/null
+++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for Solomon SSD130X OLED displays (SPI bus)
+ *
+ * Copyright 2022 Red Hat Inc.
+ * Authors: Javier Martinez Canillas <javierm@redhat.com>
+ */
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+
+#include "ssd130x.h"
+
+#define DRIVER_NAME	"ssd130x-spi"
+#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays (SPI)"
+
+static const struct regmap_config ssd130x_spi_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int ssd130x_spi_probe(struct spi_device *spi)
+{
+	struct ssd130x_device *ssd130x;
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_spi(spi, &ssd130x_spi_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ssd130x = ssd130x_probe(&spi->dev, regmap);
+
+	if (IS_ERR(ssd130x))
+		return PTR_ERR(ssd130x);
+
+	spi_set_drvdata(spi, ssd130x);
+
+	return 0;
+}
+
+static int ssd130x_spi_remove(struct spi_device *spi)
+{
+	struct ssd130x_device *ssd130x = spi_get_drvdata(spi);
+
+	return ssd130x_remove(ssd130x);
+}
+
+static void ssd130x_spi_shutdown(struct spi_device *spi)
+{
+	struct ssd130x_device *ssd130x = spi_get_drvdata(spi);
+
+	ssd130x_shutdown(ssd130x);
+}
+
+static struct ssd130x_deviceinfo ssd130x_ssd1305_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 7,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1306_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 8,
+	.need_chargepump = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1307_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 2,
+	.default_dclk_frq = 12,
+	.need_pwm = 1,
+};
+
+static struct ssd130x_deviceinfo ssd130x_ssd1309_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 10,
+};
+
+static const struct of_device_id ssd130x_of_match[] = {
+	{
+		.compatible = "solomon,ssd1305fb-spi",
+		.data = (void *)&ssd130x_ssd1305_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1306fb-spi",
+		.data = (void *)&ssd130x_ssd1306_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1307fb-spi",
+		.data = (void *)&ssd130x_ssd1307_deviceinfo,
+	},
+	{
+		.compatible = "solomon,ssd1309fb-spi",
+		.data = (void *)&ssd130x_ssd1309_deviceinfo,
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ssd130x_of_match);
+
+static struct spi_driver ssd130x_spi_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = ssd130x_of_match,
+	},
+	.probe = ssd130x_spi_probe,
+	.remove = ssd130x_spi_remove,
+	.shutdown = ssd130x_spi_shutdown,
+};
+module_spi_driver(ssd130x_spi_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 6/7] MAINTAINERS: Add entry for Solomon SSD130X OLED displays DRM driver
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09  9:13   ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, Daniel Vetter, Javier Martinez Canillas, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Andy Shevchenko, Sam Ravnborg

To make sure that tools like the get_maintainer.pl script will suggest
to Cc me if patches are posted for this driver.

Also include the Device Tree binding for the old ssd1307fb fbdev driver
since the new DRM driver was made compatible with the existing binding.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
---

Changes in v3:
- Adapt MAINTAINERS entry to point to the new drivers/gpu/drm/solomon directory.

Changes in v2:
- Add Sam Ravnborg's acked-by to patch adding a MAINTAINERS entry (Sam Ravnborg)

 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e3dad0d898f5..8e6e892f99f0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6163,6 +6163,13 @@ T:	git git://anongit.freedesktop.org/drm/drm-misc
 F:	Documentation/devicetree/bindings/display/repaper.txt
 F:	drivers/gpu/drm/tiny/repaper.c
 
+DRM DRIVER FOR SOLOMON SSD130X OLED DISPLAYS
+M:	Javier Martinez Canillas <javierm@redhat.com>
+S:	Maintained
+T:	git git://anongit.freedesktop.org/drm/drm-misc
+F:	Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
+F:	drivers/gpu/drm/solomon/ssd130x*
+
 DRM DRIVER FOR QEMU'S CIRRUS DEVICE
 M:	Dave Airlie <airlied@redhat.com>
 M:	Gerd Hoffmann <kraxel@redhat.com>
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 6/7] MAINTAINERS: Add entry for Solomon SSD130X OLED displays DRM driver
@ 2022-02-09  9:13   ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Daniel Vetter, Geert Uytterhoeven,
	Maxime Ripard, Noralf Trønnes, dri-devel, linux-fbdev,
	Javier Martinez Canillas, Sam Ravnborg

To make sure that tools like the get_maintainer.pl script will suggest
to Cc me if patches are posted for this driver.

Also include the Device Tree binding for the old ssd1307fb fbdev driver
since the new DRM driver was made compatible with the existing binding.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
---

Changes in v3:
- Adapt MAINTAINERS entry to point to the new drivers/gpu/drm/solomon directory.

Changes in v2:
- Add Sam Ravnborg's acked-by to patch adding a MAINTAINERS entry (Sam Ravnborg)

 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e3dad0d898f5..8e6e892f99f0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6163,6 +6163,13 @@ T:	git git://anongit.freedesktop.org/drm/drm-misc
 F:	Documentation/devicetree/bindings/display/repaper.txt
 F:	drivers/gpu/drm/tiny/repaper.c
 
+DRM DRIVER FOR SOLOMON SSD130X OLED DISPLAYS
+M:	Javier Martinez Canillas <javierm@redhat.com>
+S:	Maintained
+T:	git git://anongit.freedesktop.org/drm/drm-misc
+F:	Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
+F:	drivers/gpu/drm/solomon/ssd130x*
+
 DRM DRIVER FOR QEMU'S CIRRUS DEVICE
 M:	Dave Airlie <airlied@redhat.com>
 M:	Gerd Hoffmann <kraxel@redhat.com>
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 7/7] dt-bindings: display: ssd1307fb: Add myself as binding co-maintainer
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09  9:13   ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fbdev, Daniel Vetter, Javier Martinez Canillas, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Andy Shevchenko, Sam Ravnborg

The ssd130x DRM driver also makes use of this Device Tree binding to allow
existing users of the fbdev driver to migrate without the need to change
their Device Trees.

Add myself as another maintainer of the binding, to make sure that I will
be on Cc when patches are proposed for it.

Suggested-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

(no changes since v2)

Changes in v2:
- Add myself as co-maintainer of the ssd1370fb DT binding (Sam Ravnborg).

 Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
index 2ed2a7d0ca2f..9baafd0c42dd 100644
--- a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
+++ b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
@@ -8,6 +8,7 @@ title: Solomon SSD1307 OLED Controller Framebuffer
 
 maintainers:
   - Maxime Ripard <mripard@kernel.org>
+  - Javier Martinez Canillas <javierm@redhat.com>
 
 properties:
   compatible:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH v3 7/7] dt-bindings: display: ssd1307fb: Add myself as binding co-maintainer
@ 2022-02-09  9:13   ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09  9:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andy Shevchenko, Daniel Vetter, Geert Uytterhoeven,
	Maxime Ripard, Noralf Trønnes, dri-devel, linux-fbdev,
	Javier Martinez Canillas, Sam Ravnborg

The ssd130x DRM driver also makes use of this Device Tree binding to allow
existing users of the fbdev driver to migrate without the need to change
their Device Trees.

Add myself as another maintainer of the binding, to make sure that I will
be on Cc when patches are proposed for it.

Suggested-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---

(no changes since v2)

Changes in v2:
- Add myself as co-maintainer of the ssd1370fb DT binding (Sam Ravnborg).

 Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
index 2ed2a7d0ca2f..9baafd0c42dd 100644
--- a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
+++ b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
@@ -8,6 +8,7 @@ title: Solomon SSD1307 OLED Controller Framebuffer
 
 maintainers:
   - Maxime Ripard <mripard@kernel.org>
+  - Javier Martinez Canillas <javierm@redhat.com>
 
 properties:
   compatible:
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09  9:03 ` Javier Martinez Canillas
@ 2022-02-09 12:19   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 12:19 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Fbdev development list, Linux PWM List, David Airlie,
	Daniel Vetter, Mark Brown, Linux Kernel Mailing List,
	DRI Development, Liam Girdwood, Rob Herring, Noralf Trønnes,
	Thierry Reding, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Lee Jones, Andy Shevchenko, Sam Ravnborg

Hi Javier,

On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
> SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.

[...]

> - Fix a bug when doing partial updates (Geert Uytterhoeven)

Thanks, the text console is now more or less working as expected.
There is still an issue with the cursor, though.
After doing "echo hello > /dev/tty0", the text appears, but the cursor
is gone. "clear > /dev/tty0" brings it back.

The execution time of "time ls" has improved. It now takes 1.21s
(0.86s with ssd1306fb).

The logo is not shown, even when I create a 16-color or 224-color
version of the small monochrome logo I'm using.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 12:19   ` Geert Uytterhoeven
  0 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 12:19 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Kernel Mailing List, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Linux Fbdev development list,
	Daniel Vetter, Sam Ravnborg, DRI Development, Daniel Vetter,
	David Airlie, Lee Jones, Liam Girdwood, Maarten Lankhorst,
	Mark Brown, Maxime Ripard, Rob Herring, Thierry Reding,
	Uwe Kleine-König,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux PWM List

Hi Javier,

On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
> SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.

[...]

> - Fix a bug when doing partial updates (Geert Uytterhoeven)

Thanks, the text console is now more or less working as expected.
There is still an issue with the cursor, though.
After doing "echo hello > /dev/tty0", the text appears, but the cursor
is gone. "clear > /dev/tty0" brings it back.

The execution time of "time ls" has improved. It now takes 1.21s
(0.86s with ssd1306fb).

The logo is not shown, even when I create a 16-color or 224-color
version of the small monochrome logo I'm using.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
  2022-02-09  9:03   ` Javier Martinez Canillas
@ 2022-02-09 12:21     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 12:21 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Fbdev development list, David Airlie, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard, Thomas Zimmermann, Andy Shevchenko, Sam Ravnborg

Hi Javier,

On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over I2C.
>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>

Thanks for your patch!

> --- /dev/null
> +++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c

> +static const struct of_device_id ssd130x_of_match[] = {
> +       {
> +               .compatible = "solomon,ssd1305fb-i2c",
> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,

The casts are not needed.

> +       },
> +       {
> +               .compatible = "solomon,ssd1306fb-i2c",
> +               .data = (void *)&ssd130x_ssd1306_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1307fb-i2c",
> +               .data = (void *)&ssd130x_ssd1307_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1309fb-i2c",
> +               .data = (void *)&ssd130x_ssd1309_deviceinfo,
> +       },
> +       { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, ssd130x_of_match);

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
@ 2022-02-09 12:21     ` Geert Uytterhoeven
  0 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 12:21 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Kernel Mailing List, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Linux Fbdev development list,
	Daniel Vetter, Sam Ravnborg, DRI Development, Daniel Vetter,
	David Airlie

Hi Javier,

On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over I2C.
>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>

Thanks for your patch!

> --- /dev/null
> +++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c

> +static const struct of_device_id ssd130x_of_match[] = {
> +       {
> +               .compatible = "solomon,ssd1305fb-i2c",
> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,

The casts are not needed.

> +       },
> +       {
> +               .compatible = "solomon,ssd1306fb-i2c",
> +               .data = (void *)&ssd130x_ssd1306_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1307fb-i2c",
> +               .data = (void *)&ssd130x_ssd1307_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1309fb-i2c",
> +               .data = (void *)&ssd130x_ssd1309_deviceinfo,
> +       },
> +       { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, ssd130x_of_match);

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09  9:12   ` Javier Martinez Canillas
@ 2022-02-09 12:25     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 12:25 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Kernel Mailing List, Andy Shevchenko, Daniel Vetter,
	Maxime Ripard, Noralf Trønnes, DRI Development,
	Linux Fbdev development list

Hi Javier,

On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over SPI.
>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>

Thanks for your patch!

> --- /dev/null
> +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c

> +static const struct of_device_id ssd130x_of_match[] = {
> +       {
> +               .compatible = "solomon,ssd1305fb-spi",

This needs an update to the DT bindings.
Hence this may be a good time to deprecate the existing
"solomon,ssd130*fb-i2c" compatible values, and switch to
"solomon,ssd130*fb" instead, for both I2C and SPI.
Of course the I2C subdriver still has to bind against the old values,
too, for backwards compatibility.

> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,

The casts are not needed.

> +       },
> +       {
> +               .compatible = "solomon,ssd1306fb-spi",
> +               .data = (void *)&ssd130x_ssd1306_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1307fb-spi",
> +               .data = (void *)&ssd130x_ssd1307_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1309fb-spi",
> +               .data = (void *)&ssd130x_ssd1309_deviceinfo,
> +       },
> +       { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, ssd130x_of_match);
> +

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 12:25     ` Geert Uytterhoeven
  0 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 12:25 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard, Andy Shevchenko

Hi Javier,

On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over SPI.
>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>

Thanks for your patch!

> --- /dev/null
> +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c

> +static const struct of_device_id ssd130x_of_match[] = {
> +       {
> +               .compatible = "solomon,ssd1305fb-spi",

This needs an update to the DT bindings.
Hence this may be a good time to deprecate the existing
"solomon,ssd130*fb-i2c" compatible values, and switch to
"solomon,ssd130*fb" instead, for both I2C and SPI.
Of course the I2C subdriver still has to bind against the old values,
too, for backwards compatibility.

> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,

The casts are not needed.

> +       },
> +       {
> +               .compatible = "solomon,ssd1306fb-spi",
> +               .data = (void *)&ssd130x_ssd1306_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1307fb-spi",
> +               .data = (void *)&ssd130x_ssd1307_deviceinfo,
> +       },
> +       {
> +               .compatible = "solomon,ssd1309fb-spi",
> +               .data = (void *)&ssd130x_ssd1309_deviceinfo,
> +       },
> +       { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, ssd130x_of_match);
> +

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 12:19   ` Geert Uytterhoeven
@ 2022-02-09 12:37     ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 12:37 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Fbdev development list, Linux PWM List, David Airlie,
	Daniel Vetter, Mark Brown, Linux Kernel Mailing List,
	DRI Development, Liam Girdwood, Rob Herring, Noralf Trønnes,
	Thierry Reding, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Lee Jones, Andy Shevchenko, Sam Ravnborg

Hello Geert,

On 2/9/22 13:19, Geert Uytterhoeven wrote:
> Hi Javier,
> 
> On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:
>> This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
>> SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.
> 
> [...]
> 
>> - Fix a bug when doing partial updates (Geert Uytterhoeven)
> 
> Thanks, the text console is now more or less working as expected.

Thanks for giving it a try to this version too! Glad to know that
is working better now.

> There is still an issue with the cursor, though.
> After doing "echo hello > /dev/tty0", the text appears, but the cursor
> is gone. "clear > /dev/tty0" brings it back.
>

Hmm, I was able to reproduce this too. Thanks for pointing it out,
I'll investigate what the problem is.
 
> The execution time of "time ls" has improved. It now takes 1.21s
> (0.86s with ssd1306fb).
>

Yes, I believe that was due the bug I mentioned that partial updates
weren't done but a full screen update instead.
 
> The logo is not shown, even when I create a 16-color or 224-color
> version of the small monochrome logo I'm using.
>

I'll also dig into this.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 12:37     ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 12:37 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Fbdev development list, Noralf Trønnes, Sam Ravnborg,
	Linux PWM List, David Airlie, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Liam Girdwood,
	Rob Herring, Mark Brown, Thierry Reding, Maxime Ripard,
	Thomas Zimmermann, Uwe Kleine-König, Andy Shevchenko,
	Lee Jones

Hello Geert,

On 2/9/22 13:19, Geert Uytterhoeven wrote:
> Hi Javier,
> 
> On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:
>> This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
>> SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.
> 
> [...]
> 
>> - Fix a bug when doing partial updates (Geert Uytterhoeven)
> 
> Thanks, the text console is now more or less working as expected.

Thanks for giving it a try to this version too! Glad to know that
is working better now.

> There is still an issue with the cursor, though.
> After doing "echo hello > /dev/tty0", the text appears, but the cursor
> is gone. "clear > /dev/tty0" brings it back.
>

Hmm, I was able to reproduce this too. Thanks for pointing it out,
I'll investigate what the problem is.
 
> The execution time of "time ls" has improved. It now takes 1.21s
> (0.86s with ssd1306fb).
>

Yes, I believe that was due the bug I mentioned that partial updates
weren't done but a full screen update instead.
 
> The logo is not shown, even when I create a 16-color or 224-color
> version of the small monochrome logo I'm using.
>

I'll also dig into this.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
  2022-02-09 12:21     ` Geert Uytterhoeven
@ 2022-02-09 12:41       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 12:41 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Kernel Mailing List, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Linux Fbdev development list,
	Daniel Vetter, Sam Ravnborg, DRI Development, Daniel Vetter,
	David Airlie

Hello Geert,

Thanks for your feedback.

On 2/9/22 13:21, Geert Uytterhoeven wrote:

[snip]

> 
>> +static const struct of_device_id ssd130x_of_match[] = {
>> +       {
>> +               .compatible = "solomon,ssd1305fb-i2c",
>> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,
> 
> The casts are not needed.
> 

Right. I copied the table from the ssd1307fb driver verbatim. I'll clean it up.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
@ 2022-02-09 12:41       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 12:41 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Fbdev development list, David Airlie, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard, Thomas Zimmermann, Andy Shevchenko, Sam Ravnborg

Hello Geert,

Thanks for your feedback.

On 2/9/22 13:21, Geert Uytterhoeven wrote:

[snip]

> 
>> +static const struct of_device_id ssd130x_of_match[] = {
>> +       {
>> +               .compatible = "solomon,ssd1305fb-i2c",
>> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,
> 
> The casts are not needed.
> 

Right. I copied the table from the ssd1307fb driver verbatim. I'll clean it up.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed()
  2022-02-09  9:03   ` [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888,gray8}_to_mono_reversed() Javier Martinez Canillas
  (?)
@ 2022-02-09 12:51   ` Thomas Zimmermann
  2022-02-09 13:26     ` Javier Martinez Canillas
  -1 siblings, 1 reply; 88+ messages in thread
From: Thomas Zimmermann @ 2022-02-09 12:51 UTC (permalink / raw)
  To: Javier Martinez Canillas, linux-kernel
  Cc: linux-fbdev, David Airlie, Daniel Vetter, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Andy Shevchenko, Sam Ravnborg


[-- Attachment #1.1: Type: text/plain, Size: 8610 bytes --]

Hi

Am 09.02.22 um 10:03 schrieb Javier Martinez Canillas:
> Add support to convert XR24 and 8-bit grayscale to reversed monochrome for
> drivers that control monochromatic panels, that only have 1 bit per pixel.
> 
> The drm_fb_gray8_to_mono_reversed() helper was based on the function that
> does the same in the drivers/gpu/drm/tiny/repaper.c driver.
> 
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> ---
> 
> Changes in v3:
> - Also add a drm_fb_xrgb8888_to_mono_reversed() helper (Thomas Zimmermann)
> - Split lines copy to drm_fb_gray8_to_mono_reversed_line() (Thomas Zimmermann)
> - Handle case where the source buffer is not aligned to 8 (Thomas Zimmermann)
> 
>   drivers/gpu/drm/drm_format_helper.c | 157 ++++++++++++++++++++++++++++
>   include/drm/drm_format_helper.h     |   8 ++
>   2 files changed, 165 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
> index b981712623d3..19710342c0de 100644
> --- a/drivers/gpu/drm/drm_format_helper.c
> +++ b/drivers/gpu/drm/drm_format_helper.c
> @@ -591,3 +591,160 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
>   	return -EINVAL;
>   }
>   EXPORT_SYMBOL(drm_fb_blit_toio);
> +
> +static void drm_fb_gray8_to_mono_reversed_line(u8 *dst, const u8 *src, unsigned int pixels,
> +					       unsigned int start_offset, unsigned int end_offset)
> +{
> +	unsigned int xb, i;
> +
> +	for (xb = 0; xb < pixels; xb++) {
> +		unsigned int start = 0, end = 8;
> +		u8 byte = 0x00;
> +
> +		if (xb == 0 && start_offset)
> +			start = start_offset;
> +
> +		if (xb == pixels - 1 && end_offset)
> +			end = end_offset;

end_offset should be called end_len, because it is the number of bits in
the final byte; but not the offset of the final bit.

> +
> +		for (i = start; i < end; i++) {
> +			unsigned int x = xb * 8 + i;
> +
> +			byte >>= 1;
> +			if (src[x] >> 7)
> +				byte |= BIT(7);
> +		}
> +		*dst++ = byte;
> +	}
> +}
> +
> +/**
> + * drm_fb_gray8_to_mono_reversed - Convert grayscale to reversed monochrome
> + * @dst: reversed monochrome destination buffer
> + * @dst_pitch: Number of bytes between two consecutive scanlines within dst
> + * @src: 8-bit grayscale source buffer
> + * @fb: DRM framebuffer
> + * @clip: Clip rectangle area to copy
> + *
> + * DRM doesn't have native monochrome or grayscale support.
> + * Such drivers can announce the commonly supported XR24 format to userspace
> + * and use drm_fb_xrgb8888_to_gray8() to convert to grayscale and then this
> + * helper function to convert to the native format.
> + */
> +void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
> +				   const struct drm_framebuffer *fb,
> +				   const struct drm_rect *clip)
> +{
> +
> +	unsigned int linepixels = drm_rect_width(clip);
> +	unsigned int lines = drm_rect_height(clip);
> +	unsigned int start_offset, end_offset;
> +	unsigned int y;
> +	const u8 *gray8 = vaddr;
> +	u8 *mono = dst;
> +
> +	/*
> +	 * The reversed mono destination buffer contains 1 bit per pixel
> +	 * and destination scanlines have to be in multiple of 8 pixels.
> +	 */
> +	if (!dst_pitch)
> +		dst_pitch = DIV_ROUND_UP(linepixels, 8);
> +
> +	/*
> +	 * For damage handling, it is possible that only parts of the source
> +	 * buffer is copied and this could lead to start and end pixels that
> +	 * are not aligned to multiple of 8.
> +	 *
> +	 * Calculate if the start and end pixels are not aligned and set the
> +	 * offsets for the reversed mono line conversion function to adjust.
> +	 */
> +	start_offset = clip->x1 % 8;
> +	end_offset = clip->x2 % 8;
> +
> +	for (y = 0; y < lines; y++) {
> +		drm_fb_gray8_to_mono_reversed_line(mono, gray8, dst_pitch,
> +						   start_offset, end_offset);
> +		gray8 += fb->pitches[0];
> +		mono += dst_pitch;
> +	}
> +}

Do you really need that function. It's not exported and if it's not 
otherwise used, I'd just remove it.  We don't keep unused interfaces around.

> +
> +/**
> + * drm_fb_xrgb8888_to_mono_reversed - Convert XRGB8888 to reversed monochrome
> + * @dst: reversed monochrome destination buffer
> + * @dst_pitch: Number of bytes between two consecutive scanlines within dst
> + * @src: XRGB8888 source buffer
> + * @fb: DRM framebuffer
> + * @clip: Clip rectangle area to copy
> + *
> + * DRM doesn't have native monochrome support.
> + * Such drivers can announce the commonly supported XR24 format to userspace
> + * and use this function to convert to the native format.
> + *
> + * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
> + * then the result is converted from grayscale to reversed monohrome.
> + */
> +void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
> +				      const struct drm_framebuffer *fb, const struct drm_rect *clip)
> +{
> +	unsigned int linepixels = drm_rect_width(clip);
> +	unsigned int lines = clip->y2 - clip->y1;
> +	unsigned int cpp = fb->format->cpp[0];
> +	unsigned int len_src32 = linepixels * cpp;
> +	unsigned int start_offset, end_offset;
> +	unsigned int y;
> +	u8 *mono = dst, *gray8;
> +	u32 *src32;
> +
> +	if (WARN_ON(fb->format->format != DRM_FORMAT_XRGB8888))
> +		return;
> +
> +	/*
> +	 * The reversed mono destination buffer contains 1 bit per pixel
> +	 * and destination scanlines have to be in multiple of 8 pixels.
> +	 */
> +	if (!dst_pitch)
> +		dst_pitch = DIV_ROUND_UP(linepixels, 8);

I'd do a warn_once if (dst_pitch % 8 != 0).


> +
> +	/*
> +	 * The cma memory is write-combined so reads are uncached.
> +	 * Speed up by fetching one line at a time.

I once had a patchset that adds caching information to struct 
dma_buf_map (soon to be named struct iosys_map).  Blitting helpers would 
be able to enable/disable this optimization as needed.

However, your driver doesn't use CMA. It's backed by SHMEM. Do you 
really want to keep that code in?


> +	 */
> +	src32 = kmalloc(len_src32, GFP_KERNEL);
> +	if (!src32)
> +		return;
> +
> +	/*
> +	 * Copies are done line-by-line, allocate an intermediate
> +	 * buffer to copy the gray8 lines and then convert to mono.
> +	 */
> +	gray8 = kmalloc(linepixels, GFP_KERNEL);
> +	if (!gray8)
> +		goto free_src32;

If might be faster to allocate both buffers in one step and set the 
pointers into the allocated buffer.

> +
> +	/*
> +	 * For damage handling, it is possible that only parts of the source
> +	 * buffer is copied and this could lead to start and end pixels that
> +	 * are not aligned to multiple of 8.
> +	 *
> +	 * Calculate if the start and end pixels are not aligned and set the
> +	 * offsets for the reversed mono line conversion function to adjust.
> +	 */
> +	start_offset = clip->x1 % 8;
> +	end_offset = clip->x2 % 8;

end_len, again. If you have 1 single bit set in the final byte, the
offset is 0, but the length is 1.

Best regards
Thomas

> +
> +	vaddr += clip_offset(clip, fb->pitches[0], cpp);
> +	for (y = 0; y < lines; y++) {
> +		src32 = memcpy(src32, vaddr, len_src32);
> +		drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
> +		drm_fb_gray8_to_mono_reversed_line(mono, gray8, dst_pitch,
> +						   start_offset, end_offset);
> +		vaddr += fb->pitches[0];
> +		mono += dst_pitch;
> +	}
> +
> +	kfree(gray8);
> +free_src32:
> +	kfree(src32);
> +}
> +EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono_reversed);
> diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h
> index b30ed5de0a33..6638da9e9774 100644
> --- a/include/drm/drm_format_helper.h
> +++ b/include/drm/drm_format_helper.h
> @@ -43,4 +43,12 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
>   		     const void *vmap, const struct drm_framebuffer *fb,
>   		     const struct drm_rect *rect);
>   
> +void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *src,
> +				   const struct drm_framebuffer *fb,
> +				   const struct drm_rect *clip);
> +
> +void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *src,
> +				      const struct drm_framebuffer *fb,
> +				      const struct drm_rect *clip);
> +
>   #endif /* __LINUX_DRM_FORMAT_HELPER_H */

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 12:25     ` Geert Uytterhoeven
@ 2022-02-09 13:04       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 13:04 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Kernel Mailing List, Andy Shevchenko, Daniel Vetter,
	Maxime Ripard, Noralf Trønnes, DRI Development,
	Linux Fbdev development list

On 2/9/22 13:25, Geert Uytterhoeven wrote:
> Hi Javier,
> 
> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:
>> The ssd130x driver only provides the core support for these devices but it
>> does not have any bus transport logic. Add a driver to interface over SPI.
>>
>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> 
> Thanks for your patch!
> 
>> --- /dev/null
>> +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
> 
>> +static const struct of_device_id ssd130x_of_match[] = {
>> +       {
>> +               .compatible = "solomon,ssd1305fb-spi",
> 
> This needs an update to the DT bindings.

Yes, I know. Didn't feel like it, because the patch is a WIP anyways
(I haven't tested it but was included just for illustration purposes).

If someone confirms that works then I will include a proper DT binding
in the next revision.

> Hence this may be a good time to deprecate the existing
> "solomon,ssd130*fb-i2c" compatible values, and switch to
> "solomon,ssd130*fb" instead, for both I2C and SPI.

Is this the preferred approach ? Asking because most of the drivers I
know use this -$bus suffix. From a device <--> driver matching point
of view, shouldn't be an issue to have two different drivers to use
the same compatible strings, as long as these are for different buses.

Since AFAIK the match only happens within the same struct bus_type. But
I wonder if this could cause issues in other places, for example the
module loading. IIRC the OF modaliases don't include the device type.

If instead the drivers were old platform drivers and have an i2c_device_id
and spi_device_id tables, then using the same device name would not be an
issue due the modalias having a i2c: and spi: prefix to make a distinction.

What I think we should do is drop the "fb" part, since that seemed to me
that was included because it was an fbdev driver. And not really hardware
description.

> Of course the I2C subdriver still has to bind against the old values,
> too, for backwards compatibility.
>

Yes, agreed.
 
>> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,
> 
> The casts are not needed.
>

Ok.

Best regards, -- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 13:04       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 13:04 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard, Andy Shevchenko

On 2/9/22 13:25, Geert Uytterhoeven wrote:
> Hi Javier,
> 
> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:
>> The ssd130x driver only provides the core support for these devices but it
>> does not have any bus transport logic. Add a driver to interface over SPI.
>>
>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> 
> Thanks for your patch!
> 
>> --- /dev/null
>> +++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
> 
>> +static const struct of_device_id ssd130x_of_match[] = {
>> +       {
>> +               .compatible = "solomon,ssd1305fb-spi",
> 
> This needs an update to the DT bindings.

Yes, I know. Didn't feel like it, because the patch is a WIP anyways
(I haven't tested it but was included just for illustration purposes).

If someone confirms that works then I will include a proper DT binding
in the next revision.

> Hence this may be a good time to deprecate the existing
> "solomon,ssd130*fb-i2c" compatible values, and switch to
> "solomon,ssd130*fb" instead, for both I2C and SPI.

Is this the preferred approach ? Asking because most of the drivers I
know use this -$bus suffix. From a device <--> driver matching point
of view, shouldn't be an issue to have two different drivers to use
the same compatible strings, as long as these are for different buses.

Since AFAIK the match only happens within the same struct bus_type. But
I wonder if this could cause issues in other places, for example the
module loading. IIRC the OF modaliases don't include the device type.

If instead the drivers were old platform drivers and have an i2c_device_id
and spi_device_id tables, then using the same device name would not be an
issue due the modalias having a i2c: and spi: prefix to make a distinction.

What I think we should do is drop the "fb" part, since that seemed to me
that was included because it was an fbdev driver. And not really hardware
description.

> Of course the I2C subdriver still has to bind against the old values,
> too, for backwards compatibility.
>

Yes, agreed.
 
>> +               .data = (void *)&ssd130x_ssd1305_deviceinfo,
> 
> The casts are not needed.
>

Ok.

Best regards, -- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed()
  2022-02-09 12:51   ` [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed() Thomas Zimmermann
@ 2022-02-09 13:26     ` Javier Martinez Canillas
  2022-02-09 15:21       ` Thomas Zimmermann
  0 siblings, 1 reply; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 13:26 UTC (permalink / raw)
  To: Thomas Zimmermann, linux-kernel
  Cc: linux-fbdev, David Airlie, Daniel Vetter, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Andy Shevchenko, Sam Ravnborg

Hello Thomas,

Thanks a lot for your feedback.

On 2/9/22 13:51, Thomas Zimmermann wrote:
> Hi
> 

[snip]

>> +
>> +		if (xb == pixels - 1 && end_offset)
>> +			end = end_offset;
> 
> end_offset should be called end_len, because it is the number of bits in
> the final byte; but not the offset of the final bit.
>

Indeed.

[snip]

>> +void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
>> +				   const struct drm_framebuffer *fb,
>> +				   const struct drm_rect *clip)

[snip]

> 
> Do you really need that function. It's not exported and if it's not 
> otherwise used, I'd just remove it.  We don't keep unused interfaces around.
>

At the end after your suggestion of doing line-per-line conversions it is not
needed, but since I already typed it and we were talking about adding other
formats besides the fake XRGB8888 as an optimization (R8 for grayscale and
Dx or something like that for reversed mono), I thought that would be useful
to have it as a helper.

Also other drivers that want to advertise a R8 format could just use it and
not having to add their own helper. But I'm happy to drop it in v4 if you
think that's better to not have unused helpers. 

It could be taken from this patch-set anyways if someone wants to wire the
needed support for R8.

[snip]

>> +
>> +	/*
>> +	 * The reversed mono destination buffer contains 1 bit per pixel
>> +	 * and destination scanlines have to be in multiple of 8 pixels.
>> +	 */
>> +	if (!dst_pitch)
>> +		dst_pitch = DIV_ROUND_UP(linepixels, 8);
> 
> I'd do a warn_once if (dst_pitch % 8 != 0).
>

Agreed. I'll add a warning an mention that will be rounded up.

> 
>> +
>> +	/*
>> +	 * The cma memory is write-combined so reads are uncached.
>> +	 * Speed up by fetching one line at a time.
> 
> I once had a patchset that adds caching information to struct 
> dma_buf_map (soon to be named struct iosys_map).  Blitting helpers would 
> be able to enable/disable this optimization as needed.
> 
> However, your driver doesn't use CMA. It's backed by SHMEM. Do you 
> really want to keep that code in?
>

It doesn't but the repaper does. And since the plan was to make that driver
to use the helper instead of having their own, I wanted to also make sure
that would work well with CMA.

> 
>> +	 */
>> +	src32 = kmalloc(len_src32, GFP_KERNEL);
>> +	if (!src32)
>> +		return;
>> +
>> +	/*
>> +	 * Copies are done line-by-line, allocate an intermediate
>> +	 * buffer to copy the gray8 lines and then convert to mono.
>> +	 */
>> +	gray8 = kmalloc(linepixels, GFP_KERNEL);
>> +	if (!gray8)
>> +		goto free_src32;
> 
> If might be faster to allocate both buffers in one step and set the 
> pointers into the allocated buffer.
>

Not sure I got this. Do you mean to have a single buffer with length
linepixels + len_src32 and point src32 and gray8 to the same buffer ?

>> +
>> +	/*
>> +	 * For damage handling, it is possible that only parts of the source
>> +	 * buffer is copied and this could lead to start and end pixels that
>> +	 * are not aligned to multiple of 8.
>> +	 *
>> +	 * Calculate if the start and end pixels are not aligned and set the
>> +	 * offsets for the reversed mono line conversion function to adjust.
>> +	 */
>> +	start_offset = clip->x1 % 8;
>> +	end_offset = clip->x2 % 8;
> 
> end_len, again. If you have 1 single bit set in the final byte, the
> offset is 0, but the length is 1.
>

Agreed, will change it too.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09  9:03   ` Javier Martinez Canillas
@ 2022-02-09 13:43     ` Mark Brown
  -1 siblings, 0 replies; 88+ messages in thread
From: Mark Brown @ 2022-02-09 13:43 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Geert Uytterhoeven,
	linux-fbdev, Daniel Vetter, Sam Ravnborg, dri-devel,
	Daniel Vetter, David Airlie, Lee Jones, Liam Girdwood,
	Maarten Lankhorst, Maxime Ripard, Thierry Reding,
	Uwe Kleine-König, linux-pwm

[-- Attachment #1: Type: text/plain, Size: 413 bytes --]

On Wed, Feb 09, 2022 at 10:03:10AM +0100, Javier Martinez Canillas wrote:

> +	if (ssd130x->vbat_reg) {
> +		ret = regulator_enable(ssd130x->vbat_reg);
> +		if (ret) {
> +			dev_err(dev, "Failed to enable VBAT: %d\n", ret);
> +			return ret;
> +		}
> +	}

Unless the device supports power being physically omitted regulator
usage should not be optional, it's just more code and a recipie for poor
error handling.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 13:43     ` Mark Brown
  0 siblings, 0 replies; 88+ messages in thread
From: Mark Brown @ 2022-02-09 13:43 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones,
	Andy Shevchenko, Sam Ravnborg

[-- Attachment #1: Type: text/plain, Size: 413 bytes --]

On Wed, Feb 09, 2022 at 10:03:10AM +0100, Javier Martinez Canillas wrote:

> +	if (ssd130x->vbat_reg) {
> +		ret = regulator_enable(ssd130x->vbat_reg);
> +		if (ret) {
> +			dev_err(dev, "Failed to enable VBAT: %d\n", ret);
> +			return ret;
> +		}
> +	}

Unless the device supports power being physically omitted regulator
usage should not be optional, it's just more code and a recipie for poor
error handling.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 13:43     ` Mark Brown
@ 2022-02-09 14:17       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 14:17 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Geert Uytterhoeven,
	linux-fbdev, Daniel Vetter, Sam Ravnborg, dri-devel,
	Daniel Vetter, David Airlie, Lee Jones, Liam Girdwood,
	Maarten Lankhorst, Maxime Ripard, Thierry Reding,
	Uwe Kleine-König, linux-pwm

Hello Mark,

Thanks for your feedback.

On 2/9/22 14:43, Mark Brown wrote:
> On Wed, Feb 09, 2022 at 10:03:10AM +0100, Javier Martinez Canillas wrote:
> 
>> +	if (ssd130x->vbat_reg) {
>> +		ret = regulator_enable(ssd130x->vbat_reg);
>> +		if (ret) {
>> +			dev_err(dev, "Failed to enable VBAT: %d\n", ret);
>> +			return ret;
>> +		}
>> +	}
> 
> Unless the device supports power being physically omitted regulator
> usage should not be optional, it's just more code and a recipie for poor
> error handling.

The device has a VCC pin but in most cases this is just connected to a
power provided by the board in its pinout header. For example, I've it
connected to a rpi4 3.3v pin.

I guess in that case what we should do then is to just have a regulator
fixed as the vbat-supply in the Device Tree, that's regulator-always-on.

The old ssd1307fb fbdev driver also had this as optional and I wanted to
keep the new driver as backward compatible. But I understand now that is
not describing the hardware properly by making this regulator optional.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 14:17       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 14:17 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones,
	Andy Shevchenko, Sam Ravnborg

Hello Mark,

Thanks for your feedback.

On 2/9/22 14:43, Mark Brown wrote:
> On Wed, Feb 09, 2022 at 10:03:10AM +0100, Javier Martinez Canillas wrote:
> 
>> +	if (ssd130x->vbat_reg) {
>> +		ret = regulator_enable(ssd130x->vbat_reg);
>> +		if (ret) {
>> +			dev_err(dev, "Failed to enable VBAT: %d\n", ret);
>> +			return ret;
>> +		}
>> +	}
> 
> Unless the device supports power being physically omitted regulator
> usage should not be optional, it's just more code and a recipie for poor
> error handling.

The device has a VCC pin but in most cases this is just connected to a
power provided by the board in its pinout header. For example, I've it
connected to a rpi4 3.3v pin.

I guess in that case what we should do then is to just have a regulator
fixed as the vbat-supply in the Device Tree, that's regulator-always-on.

The old ssd1307fb fbdev driver also had this as optional and I wanted to
keep the new driver as backward compatible. But I understand now that is
not describing the hardware properly by making this regulator optional.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 14:17       ` Javier Martinez Canillas
@ 2022-02-09 14:22         ` Mark Brown
  -1 siblings, 0 replies; 88+ messages in thread
From: Mark Brown @ 2022-02-09 14:22 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Geert Uytterhoeven,
	linux-fbdev, Daniel Vetter, Sam Ravnborg, dri-devel,
	Daniel Vetter, David Airlie, Lee Jones, Liam Girdwood,
	Maarten Lankhorst, Maxime Ripard, Thierry Reding,
	Uwe Kleine-König, linux-pwm

[-- Attachment #1: Type: text/plain, Size: 1181 bytes --]

On Wed, Feb 09, 2022 at 03:17:06PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 14:43, Mark Brown wrote:

> > Unless the device supports power being physically omitted regulator
> > usage should not be optional, it's just more code and a recipie for poor
> > error handling.

> The device has a VCC pin but in most cases this is just connected to a
> power provided by the board in its pinout header. For example, I've it
> connected to a rpi4 3.3v pin.

That sounds like a very common configuration.

> I guess in that case what we should do then is to just have a regulator
> fixed as the vbat-supply in the Device Tree, that's regulator-always-on.

Generally I'd suggest labelling things with whatever the supply is
called in the board's schematics/documentation, that tends to make
things clearer and easier to follow.

> The old ssd1307fb fbdev driver also had this as optional and I wanted to
> keep the new driver as backward compatible. But I understand now that is
> not describing the hardware properly by making this regulator optional.

It is depressingly common to see broken code here, unfortunately
graphics drivers seem like one of the most common offendors.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 14:22         ` Mark Brown
  0 siblings, 0 replies; 88+ messages in thread
From: Mark Brown @ 2022-02-09 14:22 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones,
	Andy Shevchenko, Sam Ravnborg

[-- Attachment #1: Type: text/plain, Size: 1181 bytes --]

On Wed, Feb 09, 2022 at 03:17:06PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 14:43, Mark Brown wrote:

> > Unless the device supports power being physically omitted regulator
> > usage should not be optional, it's just more code and a recipie for poor
> > error handling.

> The device has a VCC pin but in most cases this is just connected to a
> power provided by the board in its pinout header. For example, I've it
> connected to a rpi4 3.3v pin.

That sounds like a very common configuration.

> I guess in that case what we should do then is to just have a regulator
> fixed as the vbat-supply in the Device Tree, that's regulator-always-on.

Generally I'd suggest labelling things with whatever the supply is
called in the board's schematics/documentation, that tends to make
things clearer and easier to follow.

> The old ssd1307fb fbdev driver also had this as optional and I wanted to
> keep the new driver as backward compatible. But I understand now that is
> not describing the hardware properly by making this regulator optional.

It is depressingly common to see broken code here, unfortunately
graphics drivers seem like one of the most common offendors.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 14:22         ` Mark Brown
@ 2022-02-09 14:50           ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 14:50 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Geert Uytterhoeven,
	linux-fbdev, Daniel Vetter, Sam Ravnborg, dri-devel,
	Daniel Vetter, David Airlie, Lee Jones, Liam Girdwood,
	Maarten Lankhorst, Maxime Ripard, Thierry Reding,
	Uwe Kleine-König, linux-pwm

On 2/9/22 15:22, Mark Brown wrote:
> On Wed, Feb 09, 2022 at 03:17:06PM +0100, Javier Martinez Canillas wrote:
>> On 2/9/22 14:43, Mark Brown wrote:
> 
>>> Unless the device supports power being physically omitted regulator
>>> usage should not be optional, it's just more code and a recipie for poor
>>> error handling.
> 
>> The device has a VCC pin but in most cases this is just connected to a
>> power provided by the board in its pinout header. For example, I've it
>> connected to a rpi4 3.3v pin.
> 
> That sounds like a very common configuration.
>

Yep.
 
>> I guess in that case what we should do then is to just have a regulator
>> fixed as the vbat-supply in the Device Tree, that's regulator-always-on.
> 
> Generally I'd suggest labelling things with whatever the supply is
> called in the board's schematics/documentation, that tends to make
> things clearer and easier to follow.
> 

The display controller datasheet and schematics mention VBAT as the power
supply but the documentation says that it's just connected to VCC and the
label in the display says VCC.

But I understand why the Device Tree binding and fbdev driver used VBAT
since that's what the documentation mentions.

>> The old ssd1307fb fbdev driver also had this as optional and I wanted to
>> keep the new driver as backward compatible. But I understand now that is
>> not describing the hardware properly by making this regulator optional.
> 
> It is depressingly common to see broken code here, unfortunately
> graphics drivers seem like one of the most common offendors.

I'll include a patch for the existing DT binding and mark the vbat-supply
property as required. Probably we won't be able to change the fbdev driver
without causing regressions, and I'm not interested in that driver anyways.

Best regards,
--
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 14:50           ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 14:50 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones,
	Andy Shevchenko, Sam Ravnborg

On 2/9/22 15:22, Mark Brown wrote:
> On Wed, Feb 09, 2022 at 03:17:06PM +0100, Javier Martinez Canillas wrote:
>> On 2/9/22 14:43, Mark Brown wrote:
> 
>>> Unless the device supports power being physically omitted regulator
>>> usage should not be optional, it's just more code and a recipie for poor
>>> error handling.
> 
>> The device has a VCC pin but in most cases this is just connected to a
>> power provided by the board in its pinout header. For example, I've it
>> connected to a rpi4 3.3v pin.
> 
> That sounds like a very common configuration.
>

Yep.
 
>> I guess in that case what we should do then is to just have a regulator
>> fixed as the vbat-supply in the Device Tree, that's regulator-always-on.
> 
> Generally I'd suggest labelling things with whatever the supply is
> called in the board's schematics/documentation, that tends to make
> things clearer and easier to follow.
> 

The display controller datasheet and schematics mention VBAT as the power
supply but the documentation says that it's just connected to VCC and the
label in the display says VCC.

But I understand why the Device Tree binding and fbdev driver used VBAT
since that's what the documentation mentions.

>> The old ssd1307fb fbdev driver also had this as optional and I wanted to
>> keep the new driver as backward compatible. But I understand now that is
>> not describing the hardware properly by making this regulator optional.
> 
> It is depressingly common to see broken code here, unfortunately
> graphics drivers seem like one of the most common offendors.

I'll include a patch for the existing DT binding and mark the vbat-supply
property as required. Probably we won't be able to change the fbdev driver
without causing regressions, and I'm not interested in that driver anyways.

Best regards,
--
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 14:50           ` Javier Martinez Canillas
@ 2022-02-09 15:03             ` Mark Brown
  -1 siblings, 0 replies; 88+ messages in thread
From: Mark Brown @ 2022-02-09 15:03 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Geert Uytterhoeven,
	linux-fbdev, Daniel Vetter, Sam Ravnborg, dri-devel,
	Daniel Vetter, David Airlie, Lee Jones, Liam Girdwood,
	Maarten Lankhorst, Maxime Ripard, Thierry Reding,
	Uwe Kleine-König, linux-pwm

[-- Attachment #1: Type: text/plain, Size: 1642 bytes --]

On Wed, Feb 09, 2022 at 03:50:13PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 15:22, Mark Brown wrote:
> > On Wed, Feb 09, 2022 at 03:17:06PM +0100, Javier Martinez Canillas wrote:

> >> I guess in that case what we should do then is to just have a regulator
> >> fixed as the vbat-supply in the Device Tree, that's regulator-always-on.

> > Generally I'd suggest labelling things with whatever the supply is
> > called in the board's schematics/documentation, that tends to make
> > things clearer and easier to follow.

> The display controller datasheet and schematics mention VBAT as the power
> supply but the documentation says that it's just connected to VCC and the
> label in the display says VCC.

> But I understand why the Device Tree binding and fbdev driver used VBAT
> since that's what the documentation mentions.

What is "the documentation" in this context and how is that distinct
from the datasheet for the display controller?  In general the consumer
driver should be using the name from the datasheet and the regulator
itself should get a regulator-name reflecting the name in the schematic.

> > It is depressingly common to see broken code here, unfortunately
> > graphics drivers seem like one of the most common offendors.

> I'll include a patch for the existing DT binding and mark the vbat-supply
> property as required. Probably we won't be able to change the fbdev driver
> without causing regressions, and I'm not interested in that driver anyways.

There should be little danger of causing regressions given that a dummy
regualtor will be provided when one is missing.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 15:03             ` Mark Brown
  0 siblings, 0 replies; 88+ messages in thread
From: Mark Brown @ 2022-02-09 15:03 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones,
	Andy Shevchenko, Sam Ravnborg

[-- Attachment #1: Type: text/plain, Size: 1642 bytes --]

On Wed, Feb 09, 2022 at 03:50:13PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 15:22, Mark Brown wrote:
> > On Wed, Feb 09, 2022 at 03:17:06PM +0100, Javier Martinez Canillas wrote:

> >> I guess in that case what we should do then is to just have a regulator
> >> fixed as the vbat-supply in the Device Tree, that's regulator-always-on.

> > Generally I'd suggest labelling things with whatever the supply is
> > called in the board's schematics/documentation, that tends to make
> > things clearer and easier to follow.

> The display controller datasheet and schematics mention VBAT as the power
> supply but the documentation says that it's just connected to VCC and the
> label in the display says VCC.

> But I understand why the Device Tree binding and fbdev driver used VBAT
> since that's what the documentation mentions.

What is "the documentation" in this context and how is that distinct
from the datasheet for the display controller?  In general the consumer
driver should be using the name from the datasheet and the regulator
itself should get a regulator-name reflecting the name in the schematic.

> > It is depressingly common to see broken code here, unfortunately
> > graphics drivers seem like one of the most common offendors.

> I'll include a patch for the existing DT binding and mark the vbat-supply
> property as required. Probably we won't be able to change the fbdev driver
> without causing regressions, and I'm not interested in that driver anyways.

There should be little danger of causing regressions given that a dummy
regualtor will be provided when one is missing.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09  9:03   ` Javier Martinez Canillas
@ 2022-02-09 15:12     ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:12 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie, Lee Jones,
	Liam Girdwood, Maarten Lankhorst, Mark Brown, Maxime Ripard,
	Thierry Reding, Uwe Kleine-König, linux-pwm

On Wed, Feb 09, 2022 at 10:03:10AM +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.

Thank you for the update, my comments below.

...

>  source "drivers/gpu/drm/sprd/Kconfig"
>  
> +source "drivers/gpu/drm/solomon/Kconfig"

'o' before 'p' ?

...

>  obj-$(CONFIG_DRM_SPRD) += sprd/
> +obj-y			+= solomon/

Ditto ?

...

> +/*
> + * DRM driver for Solomon SSD130X OLED displays

Solomon SSD130x (with lower letter it's easy to read and realize that it's
not a model name).

> + * Copyright 2022 Red Hat Inc.
> + * Authors: Javier Martinez Canillas <javierm@redhat.com>
> + *
> + * Based on drivers/video/fbdev/ssd1307fb.c
> + * Copyright 2012 Free Electrons
> + */

> +#include <linux/backlight.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/property.h>
> +#include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>

...

> +#define DRIVER_NAME	"ssd130x"
> +#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays"
> +#define DRIVER_DATE	"20220131"
> +#define DRIVER_MAJOR	1
> +#define DRIVER_MINOR	0

Not sure it has a value when being defined. Only one string is reused and even
if hard coded twice linker will optimize it.

...

> +/*
> + * Helper to write command (SSD130X_COMMAND). The fist variadic argument
> + * is the command to write and the following are the command options.
> + */
> +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;

Can bulk operation be used in the callers instead?

I have noticed that all of the callers are using
- 1 -- makes no sense at all, can be replaced with regmap_write()
- 2
- 3

Can be helpers for two and three arguments, with use of bulk call.

What do you think?

> +}

...

> +static void ssd130x_reset(struct ssd130x_device *ssd130x)
> +{
> +	/* Reset the screen */
> +	gpiod_set_value_cansleep(ssd130x->reset, 1);
> +	udelay(4);
> +	gpiod_set_value_cansleep(ssd130x->reset, 0);
> +	udelay(4);

I don't remember if reset pin is mandatory. fbtft does

	if (!gpiod->reset)
		return;

	...do reset...

> +}

...

> +	if (ssd130x->reset)

A-ha, why not in the callee?

> +		ssd130x_reset(ssd130x);

...

> +	/* Set COM direction */
> +	com_invdir = 0xc0 | ssd130x->com_invdir << 3;

Can 0xc0 and 3 be GENMASK()'ed and defined?

...

> +	/* Set clock frequency */
> +	dclk = ((ssd130x->dclk_div - 1) & 0xf) | (ssd130x->dclk_frq & 0xf) << 4;

GENMASK() ?

...

> +		u32 mode = ((ssd130x->area_color_enable ? 0x30 : 0) |
> +			    (ssd130x->low_power ? 5 : 0));

With if's it will look better.

		u32 mode = 0;

		if (ssd130x->area_color_enable)
			mode |= 0x30;
		if (ssd130x->low_power)
			mode |= 5;

...

> +	/* Turn on the DC-DC Charge Pump */
> +	chargepump = BIT(4) | (ssd130x->device_info->need_chargepump ? BIT(2) : 0);

Ditto.

...

> +		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); ++i) {

i++ should work as well.

> +			u8 val = ssd130x->lookup_table[i];
> +
> +			if (val < 31 || val > 63)
> +				dev_warn(ssd130x->dev,
> +					 "lookup table index %d value out of range 31 <= %d <= 63\n",
> +					 i, val);
> +			ret = ssd130x_write_cmd(ssd130x, 1, val);
> +			if (ret < 0)
> +				return ret;
> +		}

...

> +	u8 *buf = NULL;

> +

Redundant blank line, not sure if checkpatch catches this.

> +	struct drm_rect fullscreen = {
> +		.x1 = 0,
> +		.x2 = ssd130x->width,
> +		.y1 = 0,
> +		.y2 = ssd130x->height,
> +	};

...

> +power_off:

out_power_off: ?

...

> +		ret = PTR_ERR(ssd130x->vbat_reg);
> +		if (ret == -ENODEV)
> +			ssd130x->vbat_reg = NULL;
> +		else
> +			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");

Can it be

		ret = PTR_ERR(ssd130x->vbat_reg);
		if (ret != -ENODEV)
			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");

		ssd130x->vbat_reg = NULL;

?

...

> +	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
> +				     struct ssd130x_device, drm);
> +	if (IS_ERR(ssd130x)) {

> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
> +		return ssd130x;

return dev_err_probe() ?

> +	}

...

> +	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(dev, "Unable to register backlight device: %d\n", ret);
> +		return ERR_PTR(ret);

Ditto.

> +	}

...

> +	ret = drm_dev_register(drm, 0);
> +	if (ret) {
> +		dev_err(dev, "DRM device register failed: %d\n", ret);
> +		return ERR_PTR(ret);

Ditto.

> +	}

...

I have feelings that half of my comments were ignored...
Maybe I missed the discussion(s).


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 15:12     ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:12 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter, Mark Brown,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones, Sam Ravnborg

On Wed, Feb 09, 2022 at 10:03:10AM +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.

Thank you for the update, my comments below.

...

>  source "drivers/gpu/drm/sprd/Kconfig"
>  
> +source "drivers/gpu/drm/solomon/Kconfig"

'o' before 'p' ?

...

>  obj-$(CONFIG_DRM_SPRD) += sprd/
> +obj-y			+= solomon/

Ditto ?

...

> +/*
> + * DRM driver for Solomon SSD130X OLED displays

Solomon SSD130x (with lower letter it's easy to read and realize that it's
not a model name).

> + * Copyright 2022 Red Hat Inc.
> + * Authors: Javier Martinez Canillas <javierm@redhat.com>
> + *
> + * Based on drivers/video/fbdev/ssd1307fb.c
> + * Copyright 2012 Free Electrons
> + */

> +#include <linux/backlight.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/property.h>
> +#include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>

...

> +#define DRIVER_NAME	"ssd130x"
> +#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays"
> +#define DRIVER_DATE	"20220131"
> +#define DRIVER_MAJOR	1
> +#define DRIVER_MINOR	0

Not sure it has a value when being defined. Only one string is reused and even
if hard coded twice linker will optimize it.

...

> +/*
> + * Helper to write command (SSD130X_COMMAND). The fist variadic argument
> + * is the command to write and the following are the command options.
> + */
> +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;

Can bulk operation be used in the callers instead?

I have noticed that all of the callers are using
- 1 -- makes no sense at all, can be replaced with regmap_write()
- 2
- 3

Can be helpers for two and three arguments, with use of bulk call.

What do you think?

> +}

...

> +static void ssd130x_reset(struct ssd130x_device *ssd130x)
> +{
> +	/* Reset the screen */
> +	gpiod_set_value_cansleep(ssd130x->reset, 1);
> +	udelay(4);
> +	gpiod_set_value_cansleep(ssd130x->reset, 0);
> +	udelay(4);

I don't remember if reset pin is mandatory. fbtft does

	if (!gpiod->reset)
		return;

	...do reset...

> +}

...

> +	if (ssd130x->reset)

A-ha, why not in the callee?

> +		ssd130x_reset(ssd130x);

...

> +	/* Set COM direction */
> +	com_invdir = 0xc0 | ssd130x->com_invdir << 3;

Can 0xc0 and 3 be GENMASK()'ed and defined?

...

> +	/* Set clock frequency */
> +	dclk = ((ssd130x->dclk_div - 1) & 0xf) | (ssd130x->dclk_frq & 0xf) << 4;

GENMASK() ?

...

> +		u32 mode = ((ssd130x->area_color_enable ? 0x30 : 0) |
> +			    (ssd130x->low_power ? 5 : 0));

With if's it will look better.

		u32 mode = 0;

		if (ssd130x->area_color_enable)
			mode |= 0x30;
		if (ssd130x->low_power)
			mode |= 5;

...

> +	/* Turn on the DC-DC Charge Pump */
> +	chargepump = BIT(4) | (ssd130x->device_info->need_chargepump ? BIT(2) : 0);

Ditto.

...

> +		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); ++i) {

i++ should work as well.

> +			u8 val = ssd130x->lookup_table[i];
> +
> +			if (val < 31 || val > 63)
> +				dev_warn(ssd130x->dev,
> +					 "lookup table index %d value out of range 31 <= %d <= 63\n",
> +					 i, val);
> +			ret = ssd130x_write_cmd(ssd130x, 1, val);
> +			if (ret < 0)
> +				return ret;
> +		}

...

> +	u8 *buf = NULL;

> +

Redundant blank line, not sure if checkpatch catches this.

> +	struct drm_rect fullscreen = {
> +		.x1 = 0,
> +		.x2 = ssd130x->width,
> +		.y1 = 0,
> +		.y2 = ssd130x->height,
> +	};

...

> +power_off:

out_power_off: ?

...

> +		ret = PTR_ERR(ssd130x->vbat_reg);
> +		if (ret == -ENODEV)
> +			ssd130x->vbat_reg = NULL;
> +		else
> +			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");

Can it be

		ret = PTR_ERR(ssd130x->vbat_reg);
		if (ret != -ENODEV)
			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");

		ssd130x->vbat_reg = NULL;

?

...

> +	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
> +				     struct ssd130x_device, drm);
> +	if (IS_ERR(ssd130x)) {

> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
> +		return ssd130x;

return dev_err_probe() ?

> +	}

...

> +	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(dev, "Unable to register backlight device: %d\n", ret);
> +		return ERR_PTR(ret);

Ditto.

> +	}

...

> +	ret = drm_dev_register(drm, 0);
> +	if (ret) {
> +		dev_err(dev, "DRM device register failed: %d\n", ret);
> +		return ERR_PTR(ret);

Ditto.

> +	}

...

I have feelings that half of my comments were ignored...
Maybe I missed the discussion(s).


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
  2022-02-09  9:03   ` Javier Martinez Canillas
@ 2022-02-09 15:15     ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:15 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie

On Wed, Feb 09, 2022 at 10:03:11AM +0100, Javier Martinez Canillas wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over I2C.

Thanks!

...

> + * Authors: Javier Martinez Canillas <javierm@redhat.com>

s?!

...

> +#include <linux/i2c.h>
> +#include <linux/module.h>

regmap.h ?
err.h?

...

> +	ssd130x = ssd130x_probe(&client->dev, regmap);

> +

Redundant blank line.

> +	if (IS_ERR(ssd130x))
> +		return PTR_ERR(ssd130x);

...

> +	{ /* sentinel */ },

No comma for terminator entry.


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
@ 2022-02-09 15:15     ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:15 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-fbdev, David Airlie, Daniel Vetter, linux-kernel,
	dri-devel, Noralf Trønnes, Geert Uytterhoeven,
	Maxime Ripard, Thomas Zimmermann, Sam Ravnborg

On Wed, Feb 09, 2022 at 10:03:11AM +0100, Javier Martinez Canillas wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over I2C.

Thanks!

...

> + * Authors: Javier Martinez Canillas <javierm@redhat.com>

s?!

...

> +#include <linux/i2c.h>
> +#include <linux/module.h>

regmap.h ?
err.h?

...

> +	ssd130x = ssd130x_probe(&client->dev, regmap);

> +

Redundant blank line.

> +	if (IS_ERR(ssd130x))
> +		return PTR_ERR(ssd130x);

...

> +	{ /* sentinel */ },

No comma for terminator entry.


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09  9:12   ` Javier Martinez Canillas
@ 2022-02-09 15:16     ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:16 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Daniel Vetter, Geert Uytterhoeven, Maxime Ripard,
	Noralf Trønnes, dri-devel, linux-fbdev

On Wed, Feb 09, 2022 at 10:12:04AM +0100, Javier Martinez Canillas wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over SPI.

Thanks!

Same set of comments as per I²C patch.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 15:16     ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:16 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-fbdev, Daniel Vetter, linux-kernel, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard

On Wed, Feb 09, 2022 at 10:12:04AM +0100, Javier Martinez Canillas wrote:
> The ssd130x driver only provides the core support for these devices but it
> does not have any bus transport logic. Add a driver to interface over SPI.

Thanks!

Same set of comments as per I²C patch.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 15:03             ` Mark Brown
@ 2022-02-09 15:17               ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 15:17 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones,
	Andy Shevchenko, Sam Ravnborg

On 2/9/22 16:03, Mark Brown wrote:
> On Wed, Feb 09, 2022 at 03:50:13PM +0100, Javier Martinez Canillas wrote:

[snip]

> 
>> But I understand why the Device Tree binding and fbdev driver used VBAT
>> since that's what the documentation mentions.
> 
> What is "the documentation" in this context and how is that distinct
> from the datasheet for the display controller?  In general the consumer
> driver should be using the name from the datasheet and the regulator
> itself should get a regulator-name reflecting the name in the schematic.
>

For "documentation" I meant the datasheet that mentions VBAT but I got
what you mean and will also propose a change to the binding to rename
the property to vcc-supply instead to match the pin name in the device.

>>> It is depressingly common to see broken code here, unfortunately
>>> graphics drivers seem like one of the most common offendors.
> 
>> I'll include a patch for the existing DT binding and mark the vbat-supply
>> property as required. Probably we won't be able to change the fbdev driver
>> without causing regressions, and I'm not interested in that driver anyways.
> 
> There should be little danger of causing regressions given that a dummy
> regualtor will be provided when one is missing.

Right, I forgot that a dummy regulator is provided in that case. Perfect.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 15:17               ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 15:17 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-pwm, linux-fbdev, Sam Ravnborg, David Airlie,
	Daniel Vetter, linux-kernel, dri-devel, Liam Girdwood,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Thomas Zimmermann, Uwe Kleine-König, Thierry Reding,
	Andy Shevchenko, Lee Jones

On 2/9/22 16:03, Mark Brown wrote:
> On Wed, Feb 09, 2022 at 03:50:13PM +0100, Javier Martinez Canillas wrote:

[snip]

> 
>> But I understand why the Device Tree binding and fbdev driver used VBAT
>> since that's what the documentation mentions.
> 
> What is "the documentation" in this context and how is that distinct
> from the datasheet for the display controller?  In general the consumer
> driver should be using the name from the datasheet and the regulator
> itself should get a regulator-name reflecting the name in the schematic.
>

For "documentation" I meant the datasheet that mentions VBAT but I got
what you mean and will also propose a change to the binding to rename
the property to vcc-supply instead to match the pin name in the device.

>>> It is depressingly common to see broken code here, unfortunately
>>> graphics drivers seem like one of the most common offendors.
> 
>> I'll include a patch for the existing DT binding and mark the vbat-supply
>> property as required. Probably we won't be able to change the fbdev driver
>> without causing regressions, and I'm not interested in that driver anyways.
> 
> There should be little danger of causing regressions given that a dummy
> regualtor will be provided when one is missing.

Right, I forgot that a dummy regulator is provided in that case. Perfect.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 12:25     ` Geert Uytterhoeven
@ 2022-02-09 15:17       ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:17 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Javier Martinez Canillas, Linux Kernel Mailing List,
	Daniel Vetter, Maxime Ripard, Noralf Trønnes,
	DRI Development, Linux Fbdev development list

On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:

...

> > +               .compatible = "solomon,ssd1305fb-spi",
> 
> This needs an update to the DT bindings.
> Hence this may be a good time to deprecate the existing
> "solomon,ssd130*fb-i2c" compatible values, and switch to
> "solomon,ssd130*fb" instead, for both I2C and SPI.

Agree!

> Of course the I2C subdriver still has to bind against the old values,
> too, for backwards compatibility.


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 15:17       ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:17 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Fbdev development list, Daniel Vetter,
	Javier Martinez Canillas, DRI Development,
	Linux Kernel Mailing List, Noralf Trønnes, Maxime Ripard

On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:

...

> > +               .compatible = "solomon,ssd1305fb-spi",
> 
> This needs an update to the DT bindings.
> Hence this may be a good time to deprecate the existing
> "solomon,ssd130*fb-i2c" compatible values, and switch to
> "solomon,ssd130*fb" instead, for both I2C and SPI.

Agree!

> Of course the I2C subdriver still has to bind against the old values,
> too, for backwards compatibility.


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 13:04       ` Javier Martinez Canillas
@ 2022-02-09 15:19         ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:19 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Geert Uytterhoeven, Linux Kernel Mailing List, Daniel Vetter,
	Maxime Ripard, Noralf Trønnes, DRI Development,
	Linux Fbdev development list

On Wed, Feb 09, 2022 at 02:04:17PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 13:25, Geert Uytterhoeven wrote:
> > On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> > <javierm@redhat.com> wrote:

> Yes, I know. Didn't feel like it, because the patch is a WIP anyways
> (I haven't tested it but was included just for illustration purposes).
> 
> If someone confirms that works then I will include a proper DT binding
> in the next revision.

In a few weeks I hope I can do this.

But you know Linux is almost always broken (*) on the certain embedded device
if nobody keep an eye each rc cycle. It might take time to return it in shape
first.

*) Speaking out of my own experience with device(s) that I possess.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 15:19         ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 15:19 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard

On Wed, Feb 09, 2022 at 02:04:17PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 13:25, Geert Uytterhoeven wrote:
> > On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> > <javierm@redhat.com> wrote:

> Yes, I know. Didn't feel like it, because the patch is a WIP anyways
> (I haven't tested it but was included just for illustration purposes).
> 
> If someone confirms that works then I will include a proper DT binding
> in the next revision.

In a few weeks I hope I can do this.

But you know Linux is almost always broken (*) on the certain embedded device
if nobody keep an eye each rc cycle. It might take time to return it in shape
first.

*) Speaking out of my own experience with device(s) that I possess.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed()
  2022-02-09 13:26     ` Javier Martinez Canillas
@ 2022-02-09 15:21       ` Thomas Zimmermann
  2022-02-09 15:30         ` Javier Martinez Canillas
  0 siblings, 1 reply; 88+ messages in thread
From: Thomas Zimmermann @ 2022-02-09 15:21 UTC (permalink / raw)
  To: Javier Martinez Canillas, linux-kernel
  Cc: linux-fbdev, David Airlie, Daniel Vetter, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Andy Shevchenko, Sam Ravnborg


[-- Attachment #1.1: Type: text/plain, Size: 4500 bytes --]

Hi

Am 09.02.22 um 14:26 schrieb Javier Martinez Canillas:
> Hello Thomas,
> 
> Thanks a lot for your feedback.
> 
> On 2/9/22 13:51, Thomas Zimmermann wrote:
>> Hi
>>
> 
> [snip]
> 
>>> +
>>> +		if (xb == pixels - 1 && end_offset)
>>> +			end = end_offset;
>>
>> end_offset should be called end_len, because it is the number of bits in
>> the final byte; but not the offset of the final bit.
>>
> 
> Indeed.
> 
> [snip]
> 
>>> +void drm_fb_gray8_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr,
>>> +				   const struct drm_framebuffer *fb,
>>> +				   const struct drm_rect *clip)
> 
> [snip]
> 
>>
>> Do you really need that function. It's not exported and if it's not
>> otherwise used, I'd just remove it.  We don't keep unused interfaces around.
>>
> 
> At the end after your suggestion of doing line-per-line conversions it is not
> needed, but since I already typed it and we were talking about adding other
> formats besides the fake XRGB8888 as an optimization (R8 for grayscale and
> Dx or something like that for reversed mono), I thought that would be useful
> to have it as a helper.
> 
> Also other drivers that want to advertise a R8 format could just use it and
> not having to add their own helper. But I'm happy to drop it in v4 if you
> think that's better to not have unused helpers.
> 
> It could be taken from this patch-set anyways if someone wants to wire the
> needed support for R8.

I think, policy is to not keep unused code around.

> 
> [snip]
> 
>>> +
>>> +	/*
>>> +	 * The reversed mono destination buffer contains 1 bit per pixel
>>> +	 * and destination scanlines have to be in multiple of 8 pixels.
>>> +	 */
>>> +	if (!dst_pitch)
>>> +		dst_pitch = DIV_ROUND_UP(linepixels, 8);
>>
>> I'd do a warn_once if (dst_pitch % 8 != 0).
>>
> 
> Agreed. I'll add a warning an mention that will be rounded up.
> 
>>
>>> +
>>> +	/*
>>> +	 * The cma memory is write-combined so reads are uncached.
>>> +	 * Speed up by fetching one line at a time.
>>
>> I once had a patchset that adds caching information to struct
>> dma_buf_map (soon to be named struct iosys_map).  Blitting helpers would
>> be able to enable/disable this optimization as needed.
>>
>> However, your driver doesn't use CMA. It's backed by SHMEM. Do you
>> really want to keep that code in?
>>
> 
> It doesn't but the repaper does. And since the plan was to make that driver
> to use the helper instead of having their own, I wanted to also make sure
> that would work well with CMA.

That makes sense then.

> 
>>
>>> +	 */
>>> +	src32 = kmalloc(len_src32, GFP_KERNEL);
>>> +	if (!src32)
>>> +		return;
>>> +
>>> +	/*
>>> +	 * Copies are done line-by-line, allocate an intermediate
>>> +	 * buffer to copy the gray8 lines and then convert to mono.
>>> +	 */
>>> +	gray8 = kmalloc(linepixels, GFP_KERNEL);
>>> +	if (!gray8)
>>> +		goto free_src32;
>>
>> If might be faster to allocate both buffers in one step and set the
>> pointers into the allocated buffer.
>>
> 
> Not sure I got this. Do you mean to have a single buffer with length
> linepixels + len_src32 and point src32 and gray8 to the same buffer ?

That's the idea. I don't know the exact overhead for kalloc(), but at 
least the in userspace, malloc() in hot code paths is not a good idea. 
There's usually some searching for free space involved.

In the long term, we could add a field in struct drm_framebuffer to keep 
such buffers around for reuse.

> 
>>> +
>>> +	/*
>>> +	 * For damage handling, it is possible that only parts of the source
>>> +	 * buffer is copied and this could lead to start and end pixels that
>>> +	 * are not aligned to multiple of 8.
>>> +	 *
>>> +	 * Calculate if the start and end pixels are not aligned and set the
>>> +	 * offsets for the reversed mono line conversion function to adjust.
>>> +	 */
>>> +	start_offset = clip->x1 % 8;
>>> +	end_offset = clip->x2 % 8;
>>
>> end_len, again. If you have 1 single bit set in the final byte, the
>> offset is 0, but the length is 1.
>>
> 
> Agreed, will change it too.

Feel free to add my

Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>

to the next version.

Best regards
Thomas

> 
> Best regards,

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed()
  2022-02-09 15:21       ` Thomas Zimmermann
@ 2022-02-09 15:30         ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 15:30 UTC (permalink / raw)
  To: Thomas Zimmermann, linux-kernel
  Cc: linux-fbdev, David Airlie, Daniel Vetter, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard,
	Andy Shevchenko, Sam Ravnborg

On 2/9/22 16:21, Thomas Zimmermann wrote:

[snip]

>>
>> It could be taken from this patch-set anyways if someone wants to wire the
>> needed support for R8.
> 
> I think, policy is to not keep unused code around.
>

Ok, I'll drop it then. We can include it again when adding R8 formats.
 
[snip]

>>> If might be faster to allocate both buffers in one step and set the
>>> pointers into the allocated buffer.
>>>
>>
>> Not sure I got this. Do you mean to have a single buffer with length
>> linepixels + len_src32 and point src32 and gray8 to the same buffer ?
> 
> That's the idea. I don't know the exact overhead for kalloc(), but at 
> least the in userspace, malloc() in hot code paths is not a good idea. 
> There's usually some searching for free space involved.
>

Sure, let's do it in one allocation then and I'll add some comments to
make easier for people to follow the code.
 
> In the long term, we could add a field in struct drm_framebuffer to keep 
> such buffers around for reuse.
> 
>>
>>>> +
>>>> +	/*
>>>> +	 * For damage handling, it is possible that only parts of the source
>>>> +	 * buffer is copied and this could lead to start and end pixels that
>>>> +	 * are not aligned to multiple of 8.
>>>> +	 *
>>>> +	 * Calculate if the start and end pixels are not aligned and set the
>>>> +	 * offsets for the reversed mono line conversion function to adjust.
>>>> +	 */
>>>> +	start_offset = clip->x1 % 8;
>>>> +	end_offset = clip->x2 % 8;
>>>
>>> end_len, again. If you have 1 single bit set in the final byte, the
>>> offset is 0, but the length is 1.
>>>
>>
>> Agreed, will change it too.
> 
> Feel free to add my
> 
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
>

Thanks!

Best regards, -- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 15:12     ` Andy Shevchenko
@ 2022-02-09 15:54       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 15:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie, Lee Jones,
	Liam Girdwood, Maarten Lankhorst, Mark Brown, Maxime Ripard,
	Thierry Reding, Uwe Kleine-König, linux-pwm

Hello Andy,

Thanks for your feedback.

On 2/9/22 16:12, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 10:03:10AM +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.
> 
> Thank you for the update, my comments below.
> 
> ...
> 
>>  source "drivers/gpu/drm/sprd/Kconfig"
>>  
>> +source "drivers/gpu/drm/solomon/Kconfig"
>
> 'o' before 'p' ?
>

The Kconfig was not sorted alphabetically so I just added it at
the end. Same for the Makefile. But I will change it in v4 just
to not keep adding unsorted entries.

[snip]

>> +/*
>> + * DRM driver for Solomon SSD130X OLED displays
> 
> Solomon SSD130x (with lower letter it's easy to read and realize that it's
> not a model name).
>

Ok.
 
>> + * Copyright 2022 Red Hat Inc.
>> + * Authors: Javier Martinez Canillas <javierm@redhat.com>
>> + *
>> + * Based on drivers/video/fbdev/ssd1307fb.c
>> + * Copyright 2012 Free Electrons
>> + */
> 
>> +#include <linux/backlight.h>
>> +#include <linux/delay.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/property.h>
>> +#include <linux/pwm.h>
>> +#include <linux/regulator/consumer.h>
> 
> ...
> 
>> +#define DRIVER_NAME	"ssd130x"
>> +#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays"
>> +#define DRIVER_DATE	"20220131"
>> +#define DRIVER_MAJOR	1
>> +#define DRIVER_MINOR	0
> 
> Not sure it has a value when being defined. Only one string is reused and even
> if hard coded twice linker will optimize it.
>

I like to have all this at the beginning, it makes easier to read IMO.

[snip]

>> +
>> +	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;
> 
> Can bulk operation be used in the callers instead?
>

I'm using bulk writes for the data but not for the commands. Because I
tried to do that before and didn't work. But I'll give it a try again
now that I switched to regmap. Maybe it was some mistake on my end.
 
> I have noticed that all of the callers are using
> - 1 -- makes no sense at all, can be replaced with regmap_write()

Yes, I just used for consistency. That way all the places sending a
command would use the same function call.

> - 2
> - 3
> 
> Can be helpers for two and three arguments, with use of bulk call.
> 
> What do you think?
> 

Agreed, as mentioned I'll give it a try to sending all the data as a
bulk write with regmap.

>> +}
> 
> ...
> 
>> +static void ssd130x_reset(struct ssd130x_device *ssd130x)
>> +{
>> +	/* Reset the screen */
>> +	gpiod_set_value_cansleep(ssd130x->reset, 1);
>> +	udelay(4);
>> +	gpiod_set_value_cansleep(ssd130x->reset, 0);
>> +	udelay(4);
> 
> I don't remember if reset pin is mandatory. fbtft does
> 
> 	if (!gpiod->reset)
> 		return;
> 
> 	...do reset...
> 
>> +}
> 
> ...
> 
>> +	if (ssd130x->reset)
> 
> A-ha, why not in the callee?
>

I think is easier to read when doing it in the caller, specially since there
is only a single call. Than calling it unconditionally and making it a no-op
if there isn't a reset GPIO.

>> +		ssd130x_reset(ssd130x);
> 
> ...
> 
>> +	/* Set COM direction */
>> +	com_invdir = 0xc0 | ssd130x->com_invdir << 3;
> 
> Can 0xc0 and 3 be GENMASK()'ed and defined?
>

Ok.
 
> ...
> 
>> +	/* Set clock frequency */
>> +	dclk = ((ssd130x->dclk_div - 1) & 0xf) | (ssd130x->dclk_frq & 0xf) << 4;
> 
> GENMASK() ?
>

Ok.
 
> ...
> 
>> +		u32 mode = ((ssd130x->area_color_enable ? 0x30 : 0) |
>> +			    (ssd130x->low_power ? 5 : 0));
> 
> With if's it will look better.
> 
> 		u32 mode = 0;
> 
> 		if (ssd130x->area_color_enable)
> 			mode |= 0x30;
> 		if (ssd130x->low_power)
> 			mode |= 5;
>

Sure.
 
> ...
> 
>> +	/* Turn on the DC-DC Charge Pump */
>> +	chargepump = BIT(4) | (ssd130x->device_info->need_chargepump ? BIT(2) : 0);
> 
> Ditto.
>

Ok.
 
> ...
> 
>> +		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); ++i) {
> 
> i++ should work as well.
>

Yeah.
 
>> +			u8 val = ssd130x->lookup_table[i];
>> +
>> +			if (val < 31 || val > 63)
>> +				dev_warn(ssd130x->dev,
>> +					 "lookup table index %d value out of range 31 <= %d <= 63\n",
>> +					 i, val);
>> +			ret = ssd130x_write_cmd(ssd130x, 1, val);
>> +			if (ret < 0)
>> +				return ret;
>> +		}
> 
> ...
> 
>> +	u8 *buf = NULL;
>
>> +
>
> Redundant blank line, not sure if checkpatch catches this.
>

Agreed.
 
>> +	struct drm_rect fullscreen = {
>> +		.x1 = 0,
>> +		.x2 = ssd130x->width,
>> +		.y1 = 0,
>> +		.y2 = ssd130x->height,
>> +	};
> 
> ...
> 
>> +power_off:
> 
> out_power_off: ?
>

Ok.
 
> ...
> 
>> +		ret = PTR_ERR(ssd130x->vbat_reg);
>> +		if (ret == -ENODEV)
>> +			ssd130x->vbat_reg = NULL;
>> +		else
>> +			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");
> 
> Can it be
> 
> 		ret = PTR_ERR(ssd130x->vbat_reg);
> 		if (ret != -ENODEV)
> 			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");
> 
> 		ssd130x->vbat_reg = NULL;
>
> ?
> 

Mark mentioned that the regulator shouldn't really be optional.
So half of this part is going away.

> ...
> 
>> +	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
>> +				     struct ssd130x_device, drm);
>> +	if (IS_ERR(ssd130x)) {
> 
>> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
>> +		return ssd130x;
> 
> return dev_err_probe() ?
>

No, because this isn't a resource provided by other driver. If this
failed is mostly due a memory allocation error.
 
>> +	}
> 
> ...
> 
>> +	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(dev, "Unable to register backlight device: %d\n", ret);
>> +		return ERR_PTR(ret);
> 
> Ditto.
>

Same. This is an error and not a reason to defer the probe.

>> +	}
> 
> ...
> 
>> +	ret = drm_dev_register(drm, 0);
>> +	if (ret) {
>> +		dev_err(dev, "DRM device register failed: %d\n", ret);
>> +		return ERR_PTR(ret);
> 
> Ditto.
>

And same.
 
>> +	}
> 
> ...
> 
> I have feelings that half of my comments were ignored...
> Maybe I missed the discussion(s).
> 

I assure you that no comments from you or anyone were ignored.

I may had missed something but if if I did was a mistake and
not intentionally. I keep a changelog for each revision in
the patches with the name of the reviewer so people can check
and compare.

If something that you mentioned is not there, I apologize and
please point me out so I can address it in v4.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 15:54       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 15:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter, Mark Brown,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones, Sam Ravnborg

Hello Andy,

Thanks for your feedback.

On 2/9/22 16:12, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 10:03:10AM +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.
> 
> Thank you for the update, my comments below.
> 
> ...
> 
>>  source "drivers/gpu/drm/sprd/Kconfig"
>>  
>> +source "drivers/gpu/drm/solomon/Kconfig"
>
> 'o' before 'p' ?
>

The Kconfig was not sorted alphabetically so I just added it at
the end. Same for the Makefile. But I will change it in v4 just
to not keep adding unsorted entries.

[snip]

>> +/*
>> + * DRM driver for Solomon SSD130X OLED displays
> 
> Solomon SSD130x (with lower letter it's easy to read and realize that it's
> not a model name).
>

Ok.
 
>> + * Copyright 2022 Red Hat Inc.
>> + * Authors: Javier Martinez Canillas <javierm@redhat.com>
>> + *
>> + * Based on drivers/video/fbdev/ssd1307fb.c
>> + * Copyright 2012 Free Electrons
>> + */
> 
>> +#include <linux/backlight.h>
>> +#include <linux/delay.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/property.h>
>> +#include <linux/pwm.h>
>> +#include <linux/regulator/consumer.h>
> 
> ...
> 
>> +#define DRIVER_NAME	"ssd130x"
>> +#define DRIVER_DESC	"DRM driver for Solomon SSD130X OLED displays"
>> +#define DRIVER_DATE	"20220131"
>> +#define DRIVER_MAJOR	1
>> +#define DRIVER_MINOR	0
> 
> Not sure it has a value when being defined. Only one string is reused and even
> if hard coded twice linker will optimize it.
>

I like to have all this at the beginning, it makes easier to read IMO.

[snip]

>> +
>> +	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;
> 
> Can bulk operation be used in the callers instead?
>

I'm using bulk writes for the data but not for the commands. Because I
tried to do that before and didn't work. But I'll give it a try again
now that I switched to regmap. Maybe it was some mistake on my end.
 
> I have noticed that all of the callers are using
> - 1 -- makes no sense at all, can be replaced with regmap_write()

Yes, I just used for consistency. That way all the places sending a
command would use the same function call.

> - 2
> - 3
> 
> Can be helpers for two and three arguments, with use of bulk call.
> 
> What do you think?
> 

Agreed, as mentioned I'll give it a try to sending all the data as a
bulk write with regmap.

>> +}
> 
> ...
> 
>> +static void ssd130x_reset(struct ssd130x_device *ssd130x)
>> +{
>> +	/* Reset the screen */
>> +	gpiod_set_value_cansleep(ssd130x->reset, 1);
>> +	udelay(4);
>> +	gpiod_set_value_cansleep(ssd130x->reset, 0);
>> +	udelay(4);
> 
> I don't remember if reset pin is mandatory. fbtft does
> 
> 	if (!gpiod->reset)
> 		return;
> 
> 	...do reset...
> 
>> +}
> 
> ...
> 
>> +	if (ssd130x->reset)
> 
> A-ha, why not in the callee?
>

I think is easier to read when doing it in the caller, specially since there
is only a single call. Than calling it unconditionally and making it a no-op
if there isn't a reset GPIO.

>> +		ssd130x_reset(ssd130x);
> 
> ...
> 
>> +	/* Set COM direction */
>> +	com_invdir = 0xc0 | ssd130x->com_invdir << 3;
> 
> Can 0xc0 and 3 be GENMASK()'ed and defined?
>

Ok.
 
> ...
> 
>> +	/* Set clock frequency */
>> +	dclk = ((ssd130x->dclk_div - 1) & 0xf) | (ssd130x->dclk_frq & 0xf) << 4;
> 
> GENMASK() ?
>

Ok.
 
> ...
> 
>> +		u32 mode = ((ssd130x->area_color_enable ? 0x30 : 0) |
>> +			    (ssd130x->low_power ? 5 : 0));
> 
> With if's it will look better.
> 
> 		u32 mode = 0;
> 
> 		if (ssd130x->area_color_enable)
> 			mode |= 0x30;
> 		if (ssd130x->low_power)
> 			mode |= 5;
>

Sure.
 
> ...
> 
>> +	/* Turn on the DC-DC Charge Pump */
>> +	chargepump = BIT(4) | (ssd130x->device_info->need_chargepump ? BIT(2) : 0);
> 
> Ditto.
>

Ok.
 
> ...
> 
>> +		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); ++i) {
> 
> i++ should work as well.
>

Yeah.
 
>> +			u8 val = ssd130x->lookup_table[i];
>> +
>> +			if (val < 31 || val > 63)
>> +				dev_warn(ssd130x->dev,
>> +					 "lookup table index %d value out of range 31 <= %d <= 63\n",
>> +					 i, val);
>> +			ret = ssd130x_write_cmd(ssd130x, 1, val);
>> +			if (ret < 0)
>> +				return ret;
>> +		}
> 
> ...
> 
>> +	u8 *buf = NULL;
>
>> +
>
> Redundant blank line, not sure if checkpatch catches this.
>

Agreed.
 
>> +	struct drm_rect fullscreen = {
>> +		.x1 = 0,
>> +		.x2 = ssd130x->width,
>> +		.y1 = 0,
>> +		.y2 = ssd130x->height,
>> +	};
> 
> ...
> 
>> +power_off:
> 
> out_power_off: ?
>

Ok.
 
> ...
> 
>> +		ret = PTR_ERR(ssd130x->vbat_reg);
>> +		if (ret == -ENODEV)
>> +			ssd130x->vbat_reg = NULL;
>> +		else
>> +			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");
> 
> Can it be
> 
> 		ret = PTR_ERR(ssd130x->vbat_reg);
> 		if (ret != -ENODEV)
> 			return dev_err_probe(dev, ret, "Failed to get VBAT regulator\n");
> 
> 		ssd130x->vbat_reg = NULL;
>
> ?
> 

Mark mentioned that the regulator shouldn't really be optional.
So half of this part is going away.

> ...
> 
>> +	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
>> +				     struct ssd130x_device, drm);
>> +	if (IS_ERR(ssd130x)) {
> 
>> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
>> +		return ssd130x;
> 
> return dev_err_probe() ?
>

No, because this isn't a resource provided by other driver. If this
failed is mostly due a memory allocation error.
 
>> +	}
> 
> ...
> 
>> +	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(dev, "Unable to register backlight device: %d\n", ret);
>> +		return ERR_PTR(ret);
> 
> Ditto.
>

Same. This is an error and not a reason to defer the probe.

>> +	}
> 
> ...
> 
>> +	ret = drm_dev_register(drm, 0);
>> +	if (ret) {
>> +		dev_err(dev, "DRM device register failed: %d\n", ret);
>> +		return ERR_PTR(ret);
> 
> Ditto.
>

And same.
 
>> +	}
> 
> ...
> 
> I have feelings that half of my comments were ignored...
> Maybe I missed the discussion(s).
> 

I assure you that no comments from you or anyone were ignored.

I may had missed something but if if I did was a mistake and
not intentionally. I keep a changelog for each revision in
the patches with the name of the reviewer so people can check
and compare.

If something that you mentioned is not there, I apologize and
please point me out so I can address it in v4.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
  2022-02-09 15:15     ` Andy Shevchenko
@ 2022-02-09 16:05       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:05 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie

On 2/9/22 16:15, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 10:03:11AM +0100, Javier Martinez Canillas wrote:
>> The ssd130x driver only provides the core support for these devices but it
>> does not have any bus transport logic. Add a driver to interface over I2C.
> 
> Thanks!
> 
> ...
> 
>> + * Authors: Javier Martinez Canillas <javierm@redhat.com>
> 
> s?!
>

Right.
 
> ...
> 
>> +#include <linux/i2c.h>
>> +#include <linux/module.h>
> 
> regmap.h ?
> err.h?
>

The regmap.h header is included in ssd130x.h and err.h in regmap.h.

> ...
> 
>> +	ssd130x = ssd130x_probe(&client->dev, regmap);
> 
>> +
> 
> Redundant blank line.
> 

Ok.

>> +	if (IS_ERR(ssd130x))
>> +		return PTR_ERR(ssd130x);
> 
> ...
> 
>> +	{ /* sentinel */ },
>
> No comma for terminator entry.
> 
> 

Right. I removed in one place bug forgot here.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support
@ 2022-02-09 16:05       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:05 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-fbdev, David Airlie, Daniel Vetter, linux-kernel,
	dri-devel, Noralf Trønnes, Geert Uytterhoeven,
	Maxime Ripard, Thomas Zimmermann, Sam Ravnborg

On 2/9/22 16:15, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 10:03:11AM +0100, Javier Martinez Canillas wrote:
>> The ssd130x driver only provides the core support for these devices but it
>> does not have any bus transport logic. Add a driver to interface over I2C.
> 
> Thanks!
> 
> ...
> 
>> + * Authors: Javier Martinez Canillas <javierm@redhat.com>
> 
> s?!
>

Right.
 
> ...
> 
>> +#include <linux/i2c.h>
>> +#include <linux/module.h>
> 
> regmap.h ?
> err.h?
>

The regmap.h header is included in ssd130x.h and err.h in regmap.h.

> ...
> 
>> +	ssd130x = ssd130x_probe(&client->dev, regmap);
> 
>> +
> 
> Redundant blank line.
> 

Ok.

>> +	if (IS_ERR(ssd130x))
>> +		return PTR_ERR(ssd130x);
> 
> ...
> 
>> +	{ /* sentinel */ },
>
> No comma for terminator entry.
> 
> 

Right. I removed in one place bug forgot here.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 15:16     ` Andy Shevchenko
@ 2022-02-09 16:05       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:05 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, Daniel Vetter, Geert Uytterhoeven, Maxime Ripard,
	Noralf Trønnes, dri-devel, linux-fbdev

On 2/9/22 16:16, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 10:12:04AM +0100, Javier Martinez Canillas wrote:
>> The ssd130x driver only provides the core support for these devices but it
>> does not have any bus transport logic. Add a driver to interface over SPI.
> 
> Thanks!
> 
> Same set of comments as per I²C patch.
> 

Sure, thanks for your feedback!

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 16:05       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:05 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-fbdev, Daniel Vetter, linux-kernel, dri-devel,
	Noralf Trønnes, Geert Uytterhoeven, Maxime Ripard

On 2/9/22 16:16, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 10:12:04AM +0100, Javier Martinez Canillas wrote:
>> The ssd130x driver only provides the core support for these devices but it
>> does not have any bus transport logic. Add a driver to interface over SPI.
> 
> Thanks!
> 
> Same set of comments as per I²C patch.
> 

Sure, thanks for your feedback!

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 15:17       ` Andy Shevchenko
@ 2022-02-09 16:07         ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:07 UTC (permalink / raw)
  To: Andy Shevchenko, Geert Uytterhoeven
  Cc: Linux Kernel Mailing List, Daniel Vetter, Maxime Ripard,
	Noralf Trønnes, DRI Development,
	Linux Fbdev development list

On 2/9/22 16:17, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
>> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
>> <javierm@redhat.com> wrote:
> 
> ...
> 
>>> +               .compatible = "solomon,ssd1305fb-spi",
>>
>> This needs an update to the DT bindings.
>> Hence this may be a good time to deprecate the existing
>> "solomon,ssd130*fb-i2c" compatible values, and switch to
>> "solomon,ssd130*fb" instead, for both I2C and SPI.
> 
> Agree!
> 

Did you see my comment about automatic module loading ? I think
that would be an issue if we use the same compatible for both
I2C and SPI drivers.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 16:07         ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:07 UTC (permalink / raw)
  To: Andy Shevchenko, Geert Uytterhoeven
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard

On 2/9/22 16:17, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
>> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
>> <javierm@redhat.com> wrote:
> 
> ...
> 
>>> +               .compatible = "solomon,ssd1305fb-spi",
>>
>> This needs an update to the DT bindings.
>> Hence this may be a good time to deprecate the existing
>> "solomon,ssd130*fb-i2c" compatible values, and switch to
>> "solomon,ssd130*fb" instead, for both I2C and SPI.
> 
> Agree!
> 

Did you see my comment about automatic module loading ? I think
that would be an issue if we use the same compatible for both
I2C and SPI drivers.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 15:54       ` Javier Martinez Canillas
@ 2022-02-09 16:08         ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:08 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie, Lee Jones,
	Liam Girdwood, Maarten Lankhorst, Mark Brown, Maxime Ripard,
	Thierry Reding, Uwe Kleine-König, linux-pwm

On Wed, Feb 09, 2022 at 04:54:01PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 16:12, Andy Shevchenko wrote:
> > On Wed, Feb 09, 2022 at 10:03:10AM +0100, Javier Martinez Canillas wrote:

...

> >> +	do {
> >> +		value = va_arg(ap, int);
> >> +		ret = regmap_write(ssd130x->regmap, SSD130X_COMMAND, (u8)value);
> >> +		if (ret)
> >> +			goto out_end;
> >> +	} while (--count);

> > 
> > Can bulk operation be used in the callers instead?
> >
> 
> I'm using bulk writes for the data but not for the commands. Because I
> tried to do that before and didn't work. But I'll give it a try again
> now that I switched to regmap. Maybe it was some mistake on my end.
>  
> > I have noticed that all of the callers are using
> > - 1 -- makes no sense at all, can be replaced with regmap_write()
> 
> Yes, I just used for consistency. That way all the places sending a
> command would use the same function call.
> 
> > - 2
> > - 3
> > 
> > Can be helpers for two and three arguments, with use of bulk call.
> > 
> > What do you think?
> > 
> 
> Agreed, as mentioned I'll give it a try to sending all the data as a
> bulk write with regmap.

Ah, it might be that it should be noinc bulk op. Need to be checked anyway.

...

> >> +static void ssd130x_reset(struct ssd130x_device *ssd130x)
> >> +{
> >> +	/* Reset the screen */
> >> +	gpiod_set_value_cansleep(ssd130x->reset, 1);
> >> +	udelay(4);
> >> +	gpiod_set_value_cansleep(ssd130x->reset, 0);
> >> +	udelay(4);
> > 
> > I don't remember if reset pin is mandatory. fbtft does
> > 
> > 	if (!gpiod->reset)
> > 		return;
> > 
> > 	...do reset...
> > 
> >> +}
> > 
> > ...
> > 
> >> +	if (ssd130x->reset)
> > 
> > A-ha, why not in the callee?
> >
> 
> I think is easier to read when doing it in the caller, specially since there
> is only a single call. Than calling it unconditionally and making it a no-op
> if there isn't a reset GPIO.

It doesn't matter where the check is and checking that in the callee seems
better as it relies on the reset functionality. Caller in such case shouldn't
even think if it's supported or not, not their business.

Last, but not least, if you think of power management, you probably want to
assert reset there as well, means additional checks?

> >> +		ssd130x_reset(ssd130x);

...

> >> +	if (IS_ERR(ssd130x)) {
> > 
> >> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
> >> +		return ssd130x;
> > 
> > return dev_err_probe() ?
> >
> 
> No, because this isn't a resource provided by other driver. If this
> failed is mostly due a memory allocation error.

Is it a problem? dev_err_probe() got update in the documentation explaining
that's fine to call even in such cases. The outcome is less amount of LOCs.

> >> +	}

...

> >> +	if (IS_ERR(bl)) {
> >> +		ret = PTR_ERR(bl);
> >> +		dev_err(dev, "Unable to register backlight device: %d\n", ret);
> >> +		return ERR_PTR(ret);
> > 
> > Ditto.
> 
> Same. This is an error and not a reason to defer the probe.

Ditto.

> >> +	}

...

> >> +	ret = drm_dev_register(drm, 0);
> >> +	if (ret) {
> >> +		dev_err(dev, "DRM device register failed: %d\n", ret);
> >> +		return ERR_PTR(ret);
> > 
> > Ditto.
> 
> And same.

Ditto.

> >> +	}

...

> > I have feelings that half of my comments were ignored...
> > Maybe I missed the discussion(s).
> 
> I assure you that no comments from you or anyone were ignored.
> 
> I may had missed something but if if I did was a mistake and
> not intentionally. I keep a changelog for each revision in
> the patches with the name of the reviewer so people can check
> and compare.
> 
> If something that you mentioned is not there, I apologize and
> please point me out so I can address it in v4.

It's just a feeling, because I repeating that dev_err_probe() a lot :-)
Nevertheless, now I see at least your point why you went that way.
But see my comments on it.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 16:08         ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:08 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter, Mark Brown,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones, Sam Ravnborg

On Wed, Feb 09, 2022 at 04:54:01PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 16:12, Andy Shevchenko wrote:
> > On Wed, Feb 09, 2022 at 10:03:10AM +0100, Javier Martinez Canillas wrote:

...

> >> +	do {
> >> +		value = va_arg(ap, int);
> >> +		ret = regmap_write(ssd130x->regmap, SSD130X_COMMAND, (u8)value);
> >> +		if (ret)
> >> +			goto out_end;
> >> +	} while (--count);

> > 
> > Can bulk operation be used in the callers instead?
> >
> 
> I'm using bulk writes for the data but not for the commands. Because I
> tried to do that before and didn't work. But I'll give it a try again
> now that I switched to regmap. Maybe it was some mistake on my end.
>  
> > I have noticed that all of the callers are using
> > - 1 -- makes no sense at all, can be replaced with regmap_write()
> 
> Yes, I just used for consistency. That way all the places sending a
> command would use the same function call.
> 
> > - 2
> > - 3
> > 
> > Can be helpers for two and three arguments, with use of bulk call.
> > 
> > What do you think?
> > 
> 
> Agreed, as mentioned I'll give it a try to sending all the data as a
> bulk write with regmap.

Ah, it might be that it should be noinc bulk op. Need to be checked anyway.

...

> >> +static void ssd130x_reset(struct ssd130x_device *ssd130x)
> >> +{
> >> +	/* Reset the screen */
> >> +	gpiod_set_value_cansleep(ssd130x->reset, 1);
> >> +	udelay(4);
> >> +	gpiod_set_value_cansleep(ssd130x->reset, 0);
> >> +	udelay(4);
> > 
> > I don't remember if reset pin is mandatory. fbtft does
> > 
> > 	if (!gpiod->reset)
> > 		return;
> > 
> > 	...do reset...
> > 
> >> +}
> > 
> > ...
> > 
> >> +	if (ssd130x->reset)
> > 
> > A-ha, why not in the callee?
> >
> 
> I think is easier to read when doing it in the caller, specially since there
> is only a single call. Than calling it unconditionally and making it a no-op
> if there isn't a reset GPIO.

It doesn't matter where the check is and checking that in the callee seems
better as it relies on the reset functionality. Caller in such case shouldn't
even think if it's supported or not, not their business.

Last, but not least, if you think of power management, you probably want to
assert reset there as well, means additional checks?

> >> +		ssd130x_reset(ssd130x);

...

> >> +	if (IS_ERR(ssd130x)) {
> > 
> >> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
> >> +		return ssd130x;
> > 
> > return dev_err_probe() ?
> >
> 
> No, because this isn't a resource provided by other driver. If this
> failed is mostly due a memory allocation error.

Is it a problem? dev_err_probe() got update in the documentation explaining
that's fine to call even in such cases. The outcome is less amount of LOCs.

> >> +	}

...

> >> +	if (IS_ERR(bl)) {
> >> +		ret = PTR_ERR(bl);
> >> +		dev_err(dev, "Unable to register backlight device: %d\n", ret);
> >> +		return ERR_PTR(ret);
> > 
> > Ditto.
> 
> Same. This is an error and not a reason to defer the probe.

Ditto.

> >> +	}

...

> >> +	ret = drm_dev_register(drm, 0);
> >> +	if (ret) {
> >> +		dev_err(dev, "DRM device register failed: %d\n", ret);
> >> +		return ERR_PTR(ret);
> > 
> > Ditto.
> 
> And same.

Ditto.

> >> +	}

...

> > I have feelings that half of my comments were ignored...
> > Maybe I missed the discussion(s).
> 
> I assure you that no comments from you or anyone were ignored.
> 
> I may had missed something but if if I did was a mistake and
> not intentionally. I keep a changelog for each revision in
> the patches with the name of the reviewer so people can check
> and compare.
> 
> If something that you mentioned is not there, I apologize and
> please point me out so I can address it in v4.

It's just a feeling, because I repeating that dev_err_probe() a lot :-)
Nevertheless, now I see at least your point why you went that way.
But see my comments on it.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 15:19         ` Andy Shevchenko
@ 2022-02-09 16:10           ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:10 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Geert Uytterhoeven, Linux Kernel Mailing List, Daniel Vetter,
	Maxime Ripard, Noralf Trønnes, DRI Development,
	Linux Fbdev development list

On 2/9/22 16:19, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 02:04:17PM +0100, Javier Martinez Canillas wrote:
>> On 2/9/22 13:25, Geert Uytterhoeven wrote:
>>> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
>>> <javierm@redhat.com> wrote:
> 
>> Yes, I know. Didn't feel like it, because the patch is a WIP anyways
>> (I haven't tested it but was included just for illustration purposes).
>>
>> If someone confirms that works then I will include a proper DT binding
>> in the next revision.
> 
> In a few weeks I hope I can do this.
>

Thanks, there's no rush. I just included this for your convenience because you
mentioned that have an display with a SPI interface.
 
> But you know Linux is almost always broken (*) on the certain embedded device
> if nobody keep an eye each rc cycle. It might take time to return it in shape
> first.
> 
> *) Speaking out of my own experience with device(s) that I possess.
> 

Unfortunately that's my experience too. I'll keep this patch in the series and
marked as RFC. But in v4 will extend the DT binding to mention the SPI devices.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 16:10           ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:10 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard

On 2/9/22 16:19, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 02:04:17PM +0100, Javier Martinez Canillas wrote:
>> On 2/9/22 13:25, Geert Uytterhoeven wrote:
>>> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
>>> <javierm@redhat.com> wrote:
> 
>> Yes, I know. Didn't feel like it, because the patch is a WIP anyways
>> (I haven't tested it but was included just for illustration purposes).
>>
>> If someone confirms that works then I will include a proper DT binding
>> in the next revision.
> 
> In a few weeks I hope I can do this.
>

Thanks, there's no rush. I just included this for your convenience because you
mentioned that have an display with a SPI interface.
 
> But you know Linux is almost always broken (*) on the certain embedded device
> if nobody keep an eye each rc cycle. It might take time to return it in shape
> first.
> 
> *) Speaking out of my own experience with device(s) that I possess.
> 

Unfortunately that's my experience too. I'll keep this patch in the series and
marked as RFC. But in v4 will extend the DT binding to mention the SPI devices.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 16:07         ` Javier Martinez Canillas
@ 2022-02-09 16:25           ` Geert Uytterhoeven
  -1 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 16:25 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Andy Shevchenko, Linux Kernel Mailing List, Daniel Vetter,
	Maxime Ripard, Noralf Trønnes, DRI Development,
	Linux Fbdev development list

Hi Javier,

On Wed, Feb 9, 2022 at 5:07 PM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> On 2/9/22 16:17, Andy Shevchenko wrote:
> > On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
> >> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> >> <javierm@redhat.com> wrote:
> >
> > ...
> >
> >>> +               .compatible = "solomon,ssd1305fb-spi",
> >>
> >> This needs an update to the DT bindings.
> >> Hence this may be a good time to deprecate the existing
> >> "solomon,ssd130*fb-i2c" compatible values, and switch to
> >> "solomon,ssd130*fb" instead, for both I2C and SPI.
> >
> > Agree!
> >
>
> Did you see my comment about automatic module loading ? I think
> that would be an issue if we use the same compatible for both
> I2C and SPI drivers.

We have several drivers that have a core and separate i2c and spi
wrappers, see e.g.

$ git grep -w ltc2947_of_match
drivers/hwmon/ltc2947-core.c:const struct of_device_id ltc2947_of_match[] = {
drivers/hwmon/ltc2947-core.c:EXPORT_SYMBOL_GPL(ltc2947_of_match);
drivers/hwmon/ltc2947-core.c:MODULE_DEVICE_TABLE(of, ltc2947_of_match);
drivers/hwmon/ltc2947-i2c.c:            .of_match_table = ltc2947_of_match,
drivers/hwmon/ltc2947-spi.c:            .of_match_table = ltc2947_of_match,
drivers/hwmon/ltc2947.h:extern const struct of_device_id ltc2947_of_match[];

Are they all broken?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 16:25           ` Geert Uytterhoeven
  0 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-09 16:25 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard, Andy Shevchenko

Hi Javier,

On Wed, Feb 9, 2022 at 5:07 PM Javier Martinez Canillas
<javierm@redhat.com> wrote:
> On 2/9/22 16:17, Andy Shevchenko wrote:
> > On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
> >> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> >> <javierm@redhat.com> wrote:
> >
> > ...
> >
> >>> +               .compatible = "solomon,ssd1305fb-spi",
> >>
> >> This needs an update to the DT bindings.
> >> Hence this may be a good time to deprecate the existing
> >> "solomon,ssd130*fb-i2c" compatible values, and switch to
> >> "solomon,ssd130*fb" instead, for both I2C and SPI.
> >
> > Agree!
> >
>
> Did you see my comment about automatic module loading ? I think
> that would be an issue if we use the same compatible for both
> I2C and SPI drivers.

We have several drivers that have a core and separate i2c and spi
wrappers, see e.g.

$ git grep -w ltc2947_of_match
drivers/hwmon/ltc2947-core.c:const struct of_device_id ltc2947_of_match[] = {
drivers/hwmon/ltc2947-core.c:EXPORT_SYMBOL_GPL(ltc2947_of_match);
drivers/hwmon/ltc2947-core.c:MODULE_DEVICE_TABLE(of, ltc2947_of_match);
drivers/hwmon/ltc2947-i2c.c:            .of_match_table = ltc2947_of_match,
drivers/hwmon/ltc2947-spi.c:            .of_match_table = ltc2947_of_match,
drivers/hwmon/ltc2947.h:extern const struct of_device_id ltc2947_of_match[];

Are they all broken?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 16:08         ` Andy Shevchenko
@ 2022-02-09 16:26           ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:26 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie, Lee Jones,
	Liam Girdwood, Maarten Lankhorst, Mark Brown, Maxime Ripard,
	Thierry Reding, Uwe Kleine-König, linux-pwm

On 2/9/22 17:08, Andy Shevchenko wrote:

[snip]

>> Agreed, as mentioned I'll give it a try to sending all the data as a
>> bulk write with regmap.
> 
> Ah, it might be that it should be noinc bulk op. Need to be checked anyway.
>

Yeah, I'll give it a try for v4. Let's see how it goes.

[snip]

>>>
>>> A-ha, why not in the callee?
>>>
>>
>> I think is easier to read when doing it in the caller, specially since there
>> is only a single call. Than calling it unconditionally and making it a no-op
>> if there isn't a reset GPIO.
> 
> It doesn't matter where the check is and checking that in the callee seems
> better as it relies on the reset functionality. Caller in such case shouldn't
> even think if it's supported or not, not their business.
>

Ok, no strong opinions really so I will change it.
 
> Last, but not least, if you think of power management, you probably want to
> assert reset there as well, means additional checks?
> 
>>>> +		ssd130x_reset(ssd130x);
> 
> ...
> 
>>>> +	if (IS_ERR(ssd130x)) {
>>>
>>>> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
>>>> +		return ssd130x;
>>>
>>> return dev_err_probe() ?
>>>
>>
>> No, because this isn't a resource provided by other driver. If this
>> failed is mostly due a memory allocation error.
> 
> Is it a problem? dev_err_probe() got update in the documentation explaining
> that's fine to call even in such cases. The outcome is less amount of LOCs.
>

Thanks for pointing out. In my mind that was a way to denote in the code that
a probe deferral was possible and that the message should be debug but now I
went and read the comment as you suggested:

 * Note that it is deemed acceptable to use this function for error
 * prints during probe even if the @err is known to never be -EPROBE_DEFER.
 * The benefit compared to a normal dev_err() is the standardized format
 * of the error code and the fact that the error code is returned

So you are correct and using it is preferred even when no probe defer error
will be returned. I'll do that here and in the other places you mentioned.

[snip] 

>>> I have feelings that half of my comments were ignored...
>>> Maybe I missed the discussion(s).
>>
>> I assure you that no comments from you or anyone were ignored.
>>
>> I may had missed something but if if I did was a mistake and
>> not intentionally. I keep a changelog for each revision in
>> the patches with the name of the reviewer so people can check
>> and compare.
>>
>> If something that you mentioned is not there, I apologize and
>> please point me out so I can address it in v4.
> 
> It's just a feeling, because I repeating that dev_err_probe() a lot :-)
> Nevertheless, now I see at least your point why you went that way.
> But see my comments on it.

And I did use dev_err_probe() in the places that could cause a probe
deferral so it wasn't (completely) ignored.

On that topic, I even typed a SPI driver because of your feedback :)

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 16:26           ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:26 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter, Mark Brown,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones, Sam Ravnborg

On 2/9/22 17:08, Andy Shevchenko wrote:

[snip]

>> Agreed, as mentioned I'll give it a try to sending all the data as a
>> bulk write with regmap.
> 
> Ah, it might be that it should be noinc bulk op. Need to be checked anyway.
>

Yeah, I'll give it a try for v4. Let's see how it goes.

[snip]

>>>
>>> A-ha, why not in the callee?
>>>
>>
>> I think is easier to read when doing it in the caller, specially since there
>> is only a single call. Than calling it unconditionally and making it a no-op
>> if there isn't a reset GPIO.
> 
> It doesn't matter where the check is and checking that in the callee seems
> better as it relies on the reset functionality. Caller in such case shouldn't
> even think if it's supported or not, not their business.
>

Ok, no strong opinions really so I will change it.
 
> Last, but not least, if you think of power management, you probably want to
> assert reset there as well, means additional checks?
> 
>>>> +		ssd130x_reset(ssd130x);
> 
> ...
> 
>>>> +	if (IS_ERR(ssd130x)) {
>>>
>>>> +		dev_err(dev, "Failed to allocate DRM device: %d\n", ret);
>>>> +		return ssd130x;
>>>
>>> return dev_err_probe() ?
>>>
>>
>> No, because this isn't a resource provided by other driver. If this
>> failed is mostly due a memory allocation error.
> 
> Is it a problem? dev_err_probe() got update in the documentation explaining
> that's fine to call even in such cases. The outcome is less amount of LOCs.
>

Thanks for pointing out. In my mind that was a way to denote in the code that
a probe deferral was possible and that the message should be debug but now I
went and read the comment as you suggested:

 * Note that it is deemed acceptable to use this function for error
 * prints during probe even if the @err is known to never be -EPROBE_DEFER.
 * The benefit compared to a normal dev_err() is the standardized format
 * of the error code and the fact that the error code is returned

So you are correct and using it is preferred even when no probe defer error
will be returned. I'll do that here and in the other places you mentioned.

[snip] 

>>> I have feelings that half of my comments were ignored...
>>> Maybe I missed the discussion(s).
>>
>> I assure you that no comments from you or anyone were ignored.
>>
>> I may had missed something but if if I did was a mistake and
>> not intentionally. I keep a changelog for each revision in
>> the patches with the name of the reviewer so people can check
>> and compare.
>>
>> If something that you mentioned is not there, I apologize and
>> please point me out so I can address it in v4.
> 
> It's just a feeling, because I repeating that dev_err_probe() a lot :-)
> Nevertheless, now I see at least your point why you went that way.
> But see my comments on it.

And I did use dev_err_probe() in the places that could cause a probe
deferral so it wasn't (completely) ignored.

On that topic, I even typed a SPI driver because of your feedback :)

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 16:07         ` Javier Martinez Canillas
@ 2022-02-09 16:40           ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:40 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Geert Uytterhoeven, Linux Kernel Mailing List, Daniel Vetter,
	Maxime Ripard, Noralf Trønnes, DRI Development,
	Linux Fbdev development list

On Wed, Feb 09, 2022 at 05:07:03PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 16:17, Andy Shevchenko wrote:
> > On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
> >> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> >> <javierm@redhat.com> wrote:
> > 
> > ...
> > 
> >>> +               .compatible = "solomon,ssd1305fb-spi",
> >>
> >> This needs an update to the DT bindings.
> >> Hence this may be a good time to deprecate the existing
> >> "solomon,ssd130*fb-i2c" compatible values, and switch to
> >> "solomon,ssd130*fb" instead, for both I2C and SPI.
> > 
> > Agree!
> > 
> 
> Did you see my comment about automatic module loading ? I think
> that would be an issue if we use the same compatible for both
> I2C and SPI drivers.

Bug in OF code? This is not a problem in ACPI AFAICT.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 16:40           ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:40 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard

On Wed, Feb 09, 2022 at 05:07:03PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 16:17, Andy Shevchenko wrote:
> > On Wed, Feb 09, 2022 at 01:25:46PM +0100, Geert Uytterhoeven wrote:
> >> On Wed, Feb 9, 2022 at 10:12 AM Javier Martinez Canillas
> >> <javierm@redhat.com> wrote:
> > 
> > ...
> > 
> >>> +               .compatible = "solomon,ssd1305fb-spi",
> >>
> >> This needs an update to the DT bindings.
> >> Hence this may be a good time to deprecate the existing
> >> "solomon,ssd130*fb-i2c" compatible values, and switch to
> >> "solomon,ssd130*fb" instead, for both I2C and SPI.
> > 
> > Agree!
> > 
> 
> Did you see my comment about automatic module loading ? I think
> that would be an issue if we use the same compatible for both
> I2C and SPI drivers.

Bug in OF code? This is not a problem in ACPI AFAICT.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 16:25           ` Geert Uytterhoeven
@ 2022-02-09 16:41             ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:41 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Javier Martinez Canillas, Linux Kernel Mailing List,
	Daniel Vetter, Maxime Ripard, Noralf Trønnes,
	DRI Development, Linux Fbdev development list

On Wed, Feb 09, 2022 at 05:25:03PM +0100, Geert Uytterhoeven wrote:
> On Wed, Feb 9, 2022 at 5:07 PM Javier Martinez Canillas
> <javierm@redhat.com> wrote:

...

> Are they all broken?

I guess it's incorrect question. The one we need to ask is is OF code broken?
B/c ACPI can easily cope with this (they are different buses, can't clash).

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 16:41             ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:41 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Fbdev development list, Daniel Vetter,
	Javier Martinez Canillas, DRI Development,
	Linux Kernel Mailing List, Noralf Trønnes, Maxime Ripard

On Wed, Feb 09, 2022 at 05:25:03PM +0100, Geert Uytterhoeven wrote:
> On Wed, Feb 9, 2022 at 5:07 PM Javier Martinez Canillas
> <javierm@redhat.com> wrote:

...

> Are they all broken?

I guess it's incorrect question. The one we need to ask is is OF code broken?
B/c ACPI can easily cope with this (they are different buses, can't clash).

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 16:26           ` Javier Martinez Canillas
@ 2022-02-09 16:44             ` Andy Shevchenko
  -1 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:44 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie, Lee Jones,
	Liam Girdwood, Maarten Lankhorst, Mark Brown, Maxime Ripard,
	Thierry Reding, Uwe Kleine-König, linux-pwm

On Wed, Feb 09, 2022 at 05:26:00PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 17:08, Andy Shevchenko wrote:

...

> On that topic, I even typed a SPI driver because of your feedback :)

Much appreciated, makes me much easier to test.

Thank you for doing all this!

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-09 16:44             ` Andy Shevchenko
  0 siblings, 0 replies; 88+ messages in thread
From: Andy Shevchenko @ 2022-02-09 16:44 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter, Mark Brown,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones, Sam Ravnborg

On Wed, Feb 09, 2022 at 05:26:00PM +0100, Javier Martinez Canillas wrote:
> On 2/9/22 17:08, Andy Shevchenko wrote:

...

> On that topic, I even typed a SPI driver because of your feedback :)

Much appreciated, makes me much easier to test.

Thank you for doing all this!

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 16:25           ` Geert Uytterhoeven
@ 2022-02-09 16:56             ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:56 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andy Shevchenko, Linux Kernel Mailing List, Daniel Vetter,
	Maxime Ripard, Noralf Trønnes, DRI Development,
	Linux Fbdev development list

Sorry for the long reply but I don't really know how to make it shorter.

On 2/9/22 17:25, Geert Uytterhoeven wrote:
> Hi Javier,

[snip]

>> Did you see my comment about automatic module loading ? I think
>> that would be an issue if we use the same compatible for both
>> I2C and SPI drivers.
> 
> We have several drivers that have a core and separate i2c and spi
> wrappers, see e.g.
> 
> $ git grep -w ltc2947_of_match
> drivers/hwmon/ltc2947-core.c:const struct of_device_id ltc2947_of_match[] = {
> drivers/hwmon/ltc2947-core.c:EXPORT_SYMBOL_GPL(ltc2947_of_match);
> drivers/hwmon/ltc2947-core.c:MODULE_DEVICE_TABLE(of, ltc2947_of_match);
> drivers/hwmon/ltc2947-i2c.c:            .of_match_table = ltc2947_of_match,
> drivers/hwmon/ltc2947-spi.c:            .of_match_table = ltc2947_of_match,
> drivers/hwmon/ltc2947.h:extern const struct of_device_id ltc2947_of_match[];
> 
> Are they all broken?
>

It doesn't have an easy answer. It depends on what device ID tables have to
match, what modalias are present in the kernel modules and for what buses
are since not all subsystem reports the modalias uevent in the same manner.

Let's take this particular driver for example, the module aliases are the
following for each kernel module:

$ modinfo drivers/hwmon/ltc2947-core.ko | grep alias
alias:          of:N*T*Cadi,ltc2947C*
alias:          of:N*T*Cadi,ltc2947

$ modinfo drivers/hwmon/ltc2947-i2c.ko | grep alias
alias:          i2c:ltc2947

$ modinfo drivers/hwmon/ltc2947-spi.ko | grep alias
alias:          spi:ltc2947

The DT node will just contain a node with compatible = "adi,ltc2947", and
depending if the device is on a I2C or SPI bus, the OF subsystem will do
a device registration with the proper bus_type.

If is SPI, the subsystem always report a modalias uevent of the type
"spi:ltc2947", even if the device was registered by OF. So for SPI the
proper module will be loaded since it contains an alias "spi:ltc2947".

But I2C does report a proper OF modalias, so it will report instead
"of:N*T*Cadi,ltc2947" which will match the core module but not the I2C.

The I2C ltc2947-i2c.ko module is missing a "of:N*T*Cadi,ltc2947" alias
and the module loading likely isn't working and needs to be done manually.

Conversely, if ltc2947-spi.ko only add "of:N*T*Cadi,ltc2947", then the
automatic module loading wouldn't work because the modalias uevent will
be "spi:ltc2947" which won't match "of:N*T*Cadi,ltc2947". So everything
is really fragile.

Note also that the "T*" in the alias, that's to denote the device type
according to the ePAPR spec but that's only filled in the DT node has a
device_type DT property, and most DT nodes don't fill this.

So the driver module is greedy and will match any device type. And also
the modalias reported by the kernel won't set this, i.e:

$ cat /sys/bus/i2c/drivers/ssd130x-i2c/1-003c/modalias 
of:NoledT(null)Csolomon,ssd1306fb-i2c

The only way I found to make this robust and always working is with each
driver to define its own tables depending on what is used to match and
report the modalias to user-space. That means having an of_device_id and
spi_device_id (just for modalias reporting and alias table in module) for
SPI and a of_device_id table for I2C and platform devices.

And also having different compatible strings with a "-i2c" and "-spi" as
suffixes to allow kmod / udev to differentiate and match the modules.

Otherwise you will get "of:N(null)T(null)Cadi,ltc2947" in both cases and
user-space won't be able to figure out which module to match AFAICT.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 16:56             ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 16:56 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard, Andy Shevchenko

Sorry for the long reply but I don't really know how to make it shorter.

On 2/9/22 17:25, Geert Uytterhoeven wrote:
> Hi Javier,

[snip]

>> Did you see my comment about automatic module loading ? I think
>> that would be an issue if we use the same compatible for both
>> I2C and SPI drivers.
> 
> We have several drivers that have a core and separate i2c and spi
> wrappers, see e.g.
> 
> $ git grep -w ltc2947_of_match
> drivers/hwmon/ltc2947-core.c:const struct of_device_id ltc2947_of_match[] = {
> drivers/hwmon/ltc2947-core.c:EXPORT_SYMBOL_GPL(ltc2947_of_match);
> drivers/hwmon/ltc2947-core.c:MODULE_DEVICE_TABLE(of, ltc2947_of_match);
> drivers/hwmon/ltc2947-i2c.c:            .of_match_table = ltc2947_of_match,
> drivers/hwmon/ltc2947-spi.c:            .of_match_table = ltc2947_of_match,
> drivers/hwmon/ltc2947.h:extern const struct of_device_id ltc2947_of_match[];
> 
> Are they all broken?
>

It doesn't have an easy answer. It depends on what device ID tables have to
match, what modalias are present in the kernel modules and for what buses
are since not all subsystem reports the modalias uevent in the same manner.

Let's take this particular driver for example, the module aliases are the
following for each kernel module:

$ modinfo drivers/hwmon/ltc2947-core.ko | grep alias
alias:          of:N*T*Cadi,ltc2947C*
alias:          of:N*T*Cadi,ltc2947

$ modinfo drivers/hwmon/ltc2947-i2c.ko | grep alias
alias:          i2c:ltc2947

$ modinfo drivers/hwmon/ltc2947-spi.ko | grep alias
alias:          spi:ltc2947

The DT node will just contain a node with compatible = "adi,ltc2947", and
depending if the device is on a I2C or SPI bus, the OF subsystem will do
a device registration with the proper bus_type.

If is SPI, the subsystem always report a modalias uevent of the type
"spi:ltc2947", even if the device was registered by OF. So for SPI the
proper module will be loaded since it contains an alias "spi:ltc2947".

But I2C does report a proper OF modalias, so it will report instead
"of:N*T*Cadi,ltc2947" which will match the core module but not the I2C.

The I2C ltc2947-i2c.ko module is missing a "of:N*T*Cadi,ltc2947" alias
and the module loading likely isn't working and needs to be done manually.

Conversely, if ltc2947-spi.ko only add "of:N*T*Cadi,ltc2947", then the
automatic module loading wouldn't work because the modalias uevent will
be "spi:ltc2947" which won't match "of:N*T*Cadi,ltc2947". So everything
is really fragile.

Note also that the "T*" in the alias, that's to denote the device type
according to the ePAPR spec but that's only filled in the DT node has a
device_type DT property, and most DT nodes don't fill this.

So the driver module is greedy and will match any device type. And also
the modalias reported by the kernel won't set this, i.e:

$ cat /sys/bus/i2c/drivers/ssd130x-i2c/1-003c/modalias 
of:NoledT(null)Csolomon,ssd1306fb-i2c

The only way I found to make this robust and always working is with each
driver to define its own tables depending on what is used to match and
report the modalias to user-space. That means having an of_device_id and
spi_device_id (just for modalias reporting and alias table in module) for
SPI and a of_device_id table for I2C and platform devices.

And also having different compatible strings with a "-i2c" and "-spi" as
suffixes to allow kmod / udev to differentiate and match the modules.

Otherwise you will get "of:N(null)T(null)Cadi,ltc2947" in both cases and
user-space won't be able to figure out which module to match AFAICT.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
  2022-02-09 16:41             ` Andy Shevchenko
@ 2022-02-09 17:04               ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 17:04 UTC (permalink / raw)
  To: Andy Shevchenko, Geert Uytterhoeven
  Cc: Linux Kernel Mailing List, Daniel Vetter, Maxime Ripard,
	Noralf Trønnes, DRI Development,
	Linux Fbdev development list

On 2/9/22 17:41, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 05:25:03PM +0100, Geert Uytterhoeven wrote:
>> On Wed, Feb 9, 2022 at 5:07 PM Javier Martinez Canillas
>> <javierm@redhat.com> wrote:
> 
> ...
> 
>> Are they all broken?
> 
> I guess it's incorrect question. The one we need to ask is is OF code broken?
> B/c ACPI can easily cope with this (they are different buses, can't clash).
> 

Yes, it's a problem specific to OF. It works correctly with both ACPI
and legacy platform code.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support
@ 2022-02-09 17:04               ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-09 17:04 UTC (permalink / raw)
  To: Andy Shevchenko, Geert Uytterhoeven
  Cc: Linux Fbdev development list, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Noralf Trønnes,
	Maxime Ripard

On 2/9/22 17:41, Andy Shevchenko wrote:
> On Wed, Feb 09, 2022 at 05:25:03PM +0100, Geert Uytterhoeven wrote:
>> On Wed, Feb 9, 2022 at 5:07 PM Javier Martinez Canillas
>> <javierm@redhat.com> wrote:
> 
> ...
> 
>> Are they all broken?
> 
> I guess it's incorrect question. The one we need to ask is is OF code broken?
> B/c ACPI can easily cope with this (they are different buses, can't clash).
> 

Yes, it's a problem specific to OF. It works correctly with both ACPI
and legacy platform code.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 12:19   ` Geert Uytterhoeven
@ 2022-02-10 17:06     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-10 17:06 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Linux Kernel Mailing List, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Linux Fbdev development list,
	Daniel Vetter, Sam Ravnborg, DRI Development, Daniel Vetter,
	David Airlie, Lee Jones, Liam Girdwood, Maarten Lankhorst,
	Mark Brown, Maxime Ripard, Rob Herring, Thierry Reding,
	Uwe Kleine-König,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux PWM List

On Wed, Feb 9, 2022 at 1:19 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:
> > This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
> > SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.
>
> [...]

> The logo is not shown, even when I create a 16-color or 224-color
> version of the small monochrome logo I'm using.

My mistake, I messed up the hook-up, causing it to pick a different
logo that was too large to be displayed.

Of course it's using the 224-color logo reduced to monochrome instead
of the real monochrome logo, as fbcon thinks it's running on XRGB8888.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-10 17:06     ` Geert Uytterhoeven
  0 siblings, 0 replies; 88+ messages in thread
From: Geert Uytterhoeven @ 2022-02-10 17:06 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Fbdev development list, Linux PWM List, David Airlie,
	Daniel Vetter, Mark Brown, Linux Kernel Mailing List,
	DRI Development, Liam Girdwood, Rob Herring, Noralf Trønnes,
	Thierry Reding, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Lee Jones, Andy Shevchenko, Sam Ravnborg

On Wed, Feb 9, 2022 at 1:19 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
> <javierm@redhat.com> wrote:
> > This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
> > SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.
>
> [...]

> The logo is not shown, even when I create a 16-color or 224-color
> version of the small monochrome logo I'm using.

My mistake, I messed up the hook-up, causing it to pick a different
logo that was too large to be displayed.

Of course it's using the 224-color logo reduced to monochrome instead
of the real monochrome logo, as fbcon thinks it's running on XRGB8888.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-10 17:06     ` Geert Uytterhoeven
@ 2022-02-10 17:55       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-10 17:55 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Kernel Mailing List, Andy Shevchenko, Thomas Zimmermann,
	Noralf Trønnes, Maxime Ripard, Linux Fbdev development list,
	Daniel Vetter, Sam Ravnborg, DRI Development, Daniel Vetter,
	David Airlie, Lee Jones, Liam Girdwood, Maarten Lankhorst,
	Mark Brown, Maxime Ripard, Rob Herring, Thierry Reding,
	Uwe Kleine-König,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux PWM List

Hello Geert,

On 2/10/22 18:06, Geert Uytterhoeven wrote:
> On Wed, Feb 9, 2022 at 1:19 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>> On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
>> <javierm@redhat.com> wrote:
>>> This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
>>> SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.
>>
>> [...]
> 
>> The logo is not shown, even when I create a 16-color or 224-color
>> version of the small monochrome logo I'm using.
> 
> My mistake, I messed up the hook-up, causing it to pick a different
> logo that was too large to be displayed.
>

Great, thanks for all the testing.
 
> Of course it's using the 224-color logo reduced to monochrome instead
> of the real monochrome logo, as fbcon thinks it's running on XRGB8888.
>

Right. Once the patch lands, I'll look at wiring up the needed support in
DRM for the drivers to be able to advertise 8-bit grayscale and monochrome
to avoid the unnecessary conversions and to have feature parity with fbdev.

But I just wanted to do it incrementally and first port to DRM as first step.
 
Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-10 17:55       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-10 17:55 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Fbdev development list, Linux PWM List, David Airlie,
	Daniel Vetter, Mark Brown, Linux Kernel Mailing List,
	DRI Development, Liam Girdwood, Rob Herring, Noralf Trønnes,
	Thierry Reding, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Lee Jones, Andy Shevchenko, Sam Ravnborg

Hello Geert,

On 2/10/22 18:06, Geert Uytterhoeven wrote:
> On Wed, Feb 9, 2022 at 1:19 PM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>> On Wed, Feb 9, 2022 at 10:03 AM Javier Martinez Canillas
>> <javierm@redhat.com> wrote:
>>> This patch series adds a DRM driver for the Solomon OLED SSD1305, SSD1306,
>>> SSD1307 and SSD1309 displays. It is a port of the ssd1307fb fbdev driver.
>>
>> [...]
> 
>> The logo is not shown, even when I create a 16-color or 224-color
>> version of the small monochrome logo I'm using.
> 
> My mistake, I messed up the hook-up, causing it to pick a different
> logo that was too large to be displayed.
>

Great, thanks for all the testing.
 
> Of course it's using the 224-color logo reduced to monochrome instead
> of the real monochrome logo, as fbcon thinks it's running on XRGB8888.
>

Right. Once the patch lands, I'll look at wiring up the needed support in
DRM for the drivers to be able to advertise 8-bit grayscale and monochrome
to avoid the unnecessary conversions and to have feature parity with fbdev.

But I just wanted to do it incrementally and first port to DRM as first step.
 
Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 12:37     ` Javier Martinez Canillas
@ 2022-02-11  8:45       ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-11  8:45 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Fbdev development list, Linux PWM List, David Airlie,
	Daniel Vetter, Mark Brown, Linux Kernel Mailing List,
	DRI Development, Liam Girdwood, Rob Herring, Noralf Trønnes,
	Thierry Reding, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Lee Jones, Andy Shevchenko, Sam Ravnborg

On 2/9/22 13:37, Javier Martinez Canillas wrote:

[snip]

> 
>> There is still an issue with the cursor, though.
>> After doing "echo hello > /dev/tty0", the text appears, but the cursor
>> is gone. "clear > /dev/tty0" brings it back.
>>
> 
> Hmm, I was able to reproduce this too. Thanks for pointing it out,
> I'll investigate what the problem is.
>

I still didn't have time to dig on this for v4. But I think that the
driver works well enough to be merged and we can then fix the issues
that are still present in the fbdev emulation and fbcon interaction
as a follow-up.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-11  8:45       ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-11  8:45 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Fbdev development list, Noralf Trønnes, Sam Ravnborg,
	Linux PWM List, David Airlie, Daniel Vetter,
	Linux Kernel Mailing List, DRI Development, Liam Girdwood,
	Rob Herring, Mark Brown, Thierry Reding, Maxime Ripard,
	Thomas Zimmermann, Uwe Kleine-König, Andy Shevchenko,
	Lee Jones

On 2/9/22 13:37, Javier Martinez Canillas wrote:

[snip]

> 
>> There is still an issue with the cursor, though.
>> After doing "echo hello > /dev/tty0", the text appears, but the cursor
>> is gone. "clear > /dev/tty0" brings it back.
>>
> 
> Hmm, I was able to reproduce this too. Thanks for pointing it out,
> I'll investigate what the problem is.
>

I still didn't have time to dig on this for v4. But I think that the
driver works well enough to be merged and we can then fix the issues
that are still present in the fbdev emulation and fbcon interaction
as a follow-up.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
  2022-02-09 16:26           ` Javier Martinez Canillas
@ 2022-02-11  8:54             ` Javier Martinez Canillas
  -1 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-11  8:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, Thomas Zimmermann, Noralf Trønnes,
	Maxime Ripard, Geert Uytterhoeven, linux-fbdev, Daniel Vetter,
	Sam Ravnborg, dri-devel, Daniel Vetter, David Airlie, Lee Jones,
	Liam Girdwood, Maarten Lankhorst, Mark Brown, Maxime Ripard,
	Thierry Reding, Uwe Kleine-König, linux-pwm

On 2/9/22 17:26, Javier Martinez Canillas wrote:
> On 2/9/22 17:08, Andy Shevchenko wrote:
> 
> [snip]
> 
>>> Agreed, as mentioned I'll give it a try to sending all the data as a
>>> bulk write with regmap.
>>
>> Ah, it might be that it should be noinc bulk op. Need to be checked anyway.
>>
> 
> Yeah, I'll give it a try for v4. Let's see how it goes.
> 

I tried to do bulk writes for the command, but the problem is that the
command stream has to be as follow (i.e: SSD130X_SET_COL_RANGE command):

SSD130X_COMMAND
SSD130X_SET_COL_RANGE
SSD130X_COMMAND
col_start
SSD130X_COMMAND
col_end

That is, a SSD130X_COMMAND has to be writtn for each command and command
option. This means that you need to either construct a command stream in
the ssd130x_write_cmd() function or pass multiple SSD130X_COMMAND as
variadic arguments.

Both cases lead to a less elegant implementation than just having a count
parameter in ssd130x_write_cmd() and doing multiple writes as it is done
in the current implementation.

After all, these are only for commands that are done once to setup the
device. The SSD130X_DATA writes that are to update the display pixels are
already done in bulk, which are more important to do it efficiently.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays
@ 2022-02-11  8:54             ` Javier Martinez Canillas
  0 siblings, 0 replies; 88+ messages in thread
From: Javier Martinez Canillas @ 2022-02-11  8:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-pwm, linux-fbdev, David Airlie, Daniel Vetter, Mark Brown,
	linux-kernel, dri-devel, Liam Girdwood, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Thomas Zimmermann,
	Uwe Kleine-König, Thierry Reding, Lee Jones, Sam Ravnborg

On 2/9/22 17:26, Javier Martinez Canillas wrote:
> On 2/9/22 17:08, Andy Shevchenko wrote:
> 
> [snip]
> 
>>> Agreed, as mentioned I'll give it a try to sending all the data as a
>>> bulk write with regmap.
>>
>> Ah, it might be that it should be noinc bulk op. Need to be checked anyway.
>>
> 
> Yeah, I'll give it a try for v4. Let's see how it goes.
> 

I tried to do bulk writes for the command, but the problem is that the
command stream has to be as follow (i.e: SSD130X_SET_COL_RANGE command):

SSD130X_COMMAND
SSD130X_SET_COL_RANGE
SSD130X_COMMAND
col_start
SSD130X_COMMAND
col_end

That is, a SSD130X_COMMAND has to be writtn for each command and command
option. This means that you need to either construct a command stream in
the ssd130x_write_cmd() function or pass multiple SSD130X_COMMAND as
variadic arguments.

Both cases lead to a less elegant implementation than just having a count
parameter in ssd130x_write_cmd() and doing multiple writes as it is done
in the current implementation.

After all, these are only for commands that are done once to setup the
device. The SSD130X_DATA writes that are to update the display pixels are
already done in bulk, which are more important to do it efficiently.

Best regards,
-- 
Javier Martinez Canillas
Linux Engineering
Red Hat


^ permalink raw reply	[flat|nested] 88+ messages in thread

end of thread, other threads:[~2022-02-11  8:55 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-09  9:03 [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays Javier Martinez Canillas
2022-02-09  9:03 ` Javier Martinez Canillas
2022-02-09  9:03 ` [PATCH v3 1/7] drm/format-helper: Add drm_fb_xrgb8888_to_gray8_line() Javier Martinez Canillas
2022-02-09  9:03   ` Javier Martinez Canillas
2022-02-09  9:03 ` [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed() Javier Martinez Canillas
2022-02-09  9:03   ` [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888,gray8}_to_mono_reversed() Javier Martinez Canillas
2022-02-09 12:51   ` [PATCH v3 2/7] drm/format-helper: Add drm_fb_{xrgb8888, gray8}_to_mono_reversed() Thomas Zimmermann
2022-02-09 13:26     ` Javier Martinez Canillas
2022-02-09 15:21       ` Thomas Zimmermann
2022-02-09 15:30         ` Javier Martinez Canillas
2022-02-09  9:03 ` [PATCH v3 3/7] drm: Add driver for Solomon SSD130X OLED displays Javier Martinez Canillas
2022-02-09  9:03   ` Javier Martinez Canillas
2022-02-09 13:43   ` Mark Brown
2022-02-09 13:43     ` Mark Brown
2022-02-09 14:17     ` Javier Martinez Canillas
2022-02-09 14:17       ` Javier Martinez Canillas
2022-02-09 14:22       ` Mark Brown
2022-02-09 14:22         ` Mark Brown
2022-02-09 14:50         ` Javier Martinez Canillas
2022-02-09 14:50           ` Javier Martinez Canillas
2022-02-09 15:03           ` Mark Brown
2022-02-09 15:03             ` Mark Brown
2022-02-09 15:17             ` Javier Martinez Canillas
2022-02-09 15:17               ` Javier Martinez Canillas
2022-02-09 15:12   ` Andy Shevchenko
2022-02-09 15:12     ` Andy Shevchenko
2022-02-09 15:54     ` Javier Martinez Canillas
2022-02-09 15:54       ` Javier Martinez Canillas
2022-02-09 16:08       ` Andy Shevchenko
2022-02-09 16:08         ` Andy Shevchenko
2022-02-09 16:26         ` Javier Martinez Canillas
2022-02-09 16:26           ` Javier Martinez Canillas
2022-02-09 16:44           ` Andy Shevchenko
2022-02-09 16:44             ` Andy Shevchenko
2022-02-11  8:54           ` Javier Martinez Canillas
2022-02-11  8:54             ` Javier Martinez Canillas
2022-02-09  9:03 ` [PATCH v3 4/7] drm/solomon: Add SSD130X OLED displays I2C support Javier Martinez Canillas
2022-02-09  9:03   ` Javier Martinez Canillas
2022-02-09 12:21   ` Geert Uytterhoeven
2022-02-09 12:21     ` Geert Uytterhoeven
2022-02-09 12:41     ` Javier Martinez Canillas
2022-02-09 12:41       ` Javier Martinez Canillas
2022-02-09 15:15   ` Andy Shevchenko
2022-02-09 15:15     ` Andy Shevchenko
2022-02-09 16:05     ` Javier Martinez Canillas
2022-02-09 16:05       ` Javier Martinez Canillas
2022-02-09  9:12 ` [PATCH v3 5/7] (WIP) drm/solomon: Add SSD130X OLED displays SPI support Javier Martinez Canillas
2022-02-09  9:12   ` Javier Martinez Canillas
2022-02-09 12:25   ` Geert Uytterhoeven
2022-02-09 12:25     ` Geert Uytterhoeven
2022-02-09 13:04     ` Javier Martinez Canillas
2022-02-09 13:04       ` Javier Martinez Canillas
2022-02-09 15:19       ` Andy Shevchenko
2022-02-09 15:19         ` Andy Shevchenko
2022-02-09 16:10         ` Javier Martinez Canillas
2022-02-09 16:10           ` Javier Martinez Canillas
2022-02-09 15:17     ` Andy Shevchenko
2022-02-09 15:17       ` Andy Shevchenko
2022-02-09 16:07       ` Javier Martinez Canillas
2022-02-09 16:07         ` Javier Martinez Canillas
2022-02-09 16:25         ` Geert Uytterhoeven
2022-02-09 16:25           ` Geert Uytterhoeven
2022-02-09 16:41           ` Andy Shevchenko
2022-02-09 16:41             ` Andy Shevchenko
2022-02-09 17:04             ` Javier Martinez Canillas
2022-02-09 17:04               ` Javier Martinez Canillas
2022-02-09 16:56           ` Javier Martinez Canillas
2022-02-09 16:56             ` Javier Martinez Canillas
2022-02-09 16:40         ` Andy Shevchenko
2022-02-09 16:40           ` Andy Shevchenko
2022-02-09 15:16   ` Andy Shevchenko
2022-02-09 15:16     ` Andy Shevchenko
2022-02-09 16:05     ` Javier Martinez Canillas
2022-02-09 16:05       ` Javier Martinez Canillas
2022-02-09  9:13 ` [PATCH v3 6/7] MAINTAINERS: Add entry for Solomon SSD130X OLED displays DRM driver Javier Martinez Canillas
2022-02-09  9:13   ` Javier Martinez Canillas
2022-02-09  9:13 ` [PATCH v3 7/7] dt-bindings: display: ssd1307fb: Add myself as binding co-maintainer Javier Martinez Canillas
2022-02-09  9:13   ` Javier Martinez Canillas
2022-02-09 12:19 ` [PATCH v3 0/7] drm: Add driver for Solomon SSD130X OLED displays Geert Uytterhoeven
2022-02-09 12:19   ` Geert Uytterhoeven
2022-02-09 12:37   ` Javier Martinez Canillas
2022-02-09 12:37     ` Javier Martinez Canillas
2022-02-11  8:45     ` Javier Martinez Canillas
2022-02-11  8:45       ` Javier Martinez Canillas
2022-02-10 17:06   ` Geert Uytterhoeven
2022-02-10 17:06     ` Geert Uytterhoeven
2022-02-10 17:55     ` Javier Martinez Canillas
2022-02-10 17:55       ` Javier Martinez Canillas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.