All of lore.kernel.org
 help / color / mirror / Atom feed
From: Javier Martinez Canillas <javierm@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: Thomas Zimmermann <tzimmermann@suse.de>,
	Javier Martinez Canillas <javierm@redhat.com>,
	Maxime Ripard <mripard@kernel.org>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	dri-devel@lists.freedesktop.org
Subject: [PATCH 5/8] drm/ssd13xx: Add a per controller family functions table
Date: Mon,  9 Oct 2023 20:34:19 +0200	[thread overview]
Message-ID: <20231009183522.543918-6-javierm@redhat.com> (raw)
In-Reply-To: <20231009183522.543918-1-javierm@redhat.com>

To allow the driver to decouple the common logic in the function callbacks
from the behaviour that is specific of a given Solomon controller family.

For this, include a chip family to the device info and add fields to the
driver-private device struct, to store the hardware buffer maximum size,
the intermediate buffer maximum size and pixel format, and a set of per
chip family function handlers.

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

 drivers/gpu/drm/solomon/ssd13xx.c | 88 ++++++++++++++++++++++---------
 drivers/gpu/drm/solomon/ssd13xx.h | 27 ++++++++++
 2 files changed, 90 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/solomon/ssd13xx.c b/drivers/gpu/drm/solomon/ssd13xx.c
index 9747f8656636..5a426ac10c58 100644
--- a/drivers/gpu/drm/solomon/ssd13xx.c
+++ b/drivers/gpu/drm/solomon/ssd13xx.c
@@ -104,6 +104,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.default_width = 132,
 		.default_height = 64,
 		.page_mode_only = 1,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1305_ID] = {
 		.default_vcomh = 0x34,
@@ -111,6 +112,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.default_dclk_frq = 7,
 		.default_width = 132,
 		.default_height = 64,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1306_ID] = {
 		.default_vcomh = 0x20,
@@ -119,6 +121,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.need_chargepump = 1,
 		.default_width = 128,
 		.default_height = 64,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1307_ID] = {
 		.default_vcomh = 0x20,
@@ -127,6 +130,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.need_pwm = 1,
 		.default_width = 128,
 		.default_height = 39,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1309_ID] = {
 		.default_vcomh = 0x34,
@@ -134,6 +138,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.default_dclk_frq = 10,
 		.default_width = 128,
 		.default_height = 64,
+		.family_id = SSD130X_FAMILY,
 	}
 };
 EXPORT_SYMBOL_NS_GPL(ssd13xx_variants, DRM_SSD13XX);
@@ -148,8 +153,6 @@ struct ssd13xx_plane_state {
 	struct drm_shadow_plane_state base;
 	/* Intermediate buffer to convert pixels from XRGB8888 to HW format */
 	u8 *buffer;
-	/* Pixel format info for the intermediate buffer */
-	const struct drm_format_info *fi;
 };
 
 static inline struct ssd13xx_crtc_state *to_ssd13xx_crtc_state(struct drm_crtc_state *state)
@@ -331,7 +334,7 @@ static void ssd13xx_power_off(struct ssd13xx_device *ssd13xx)
 	regulator_disable(ssd13xx->vcc_reg);
 }
 
-static int ssd13xx_init(struct ssd13xx_device *ssd13xx)
+static int ssd130x_init(struct ssd13xx_device *ssd13xx)
 {
 	u32 precharge, dclk, com_invdir, compins, chargepump, seg_remap;
 	bool scan_mode;
@@ -455,7 +458,7 @@ static int ssd13xx_init(struct ssd13xx_device *ssd13xx)
 				 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
 }
 
-static int ssd13xx_update_rect(struct ssd13xx_device *ssd13xx,
+static int ssd130x_update_rect(struct ssd13xx_device *ssd13xx,
 			       struct drm_rect *rect, u8 *buf,
 			       u8 *data_array)
 {
@@ -561,7 +564,7 @@ static int ssd13xx_update_rect(struct ssd13xx_device *ssd13xx,
 	return ret;
 }
 
-static void ssd13xx_clear_screen(struct ssd13xx_device *ssd13xx, u8 *data_array)
+static void ssd130x_clear_screen(struct ssd13xx_device *ssd13xx, u8 *data_array)
 {
 	unsigned int pages = DIV_ROUND_UP(ssd13xx->height, SSD130X_PAGE_HEIGHT);
 	unsigned int width = ssd13xx->width;
@@ -602,6 +605,15 @@ static void ssd13xx_clear_screen(struct ssd13xx_device *ssd13xx, u8 *data_array)
 	}
 }
 
+static const struct ssd13xx_funcs ssd13xx_family_funcs[] = {
+	[SSD130X_FAMILY] = {
+		.init = ssd130x_init,
+		.update_rect = ssd130x_update_rect,
+		.clear_screen = ssd130x_clear_screen,
+		.fmt_convert = drm_fb_xrgb8888_to_mono,
+	},
+};
+
 static int ssd13xx_fb_blit_rect(struct drm_framebuffer *fb,
 				const struct iosys_map *vmap,
 				struct drm_rect *rect, u8 *buf,
@@ -609,6 +621,7 @@ static int ssd13xx_fb_blit_rect(struct drm_framebuffer *fb,
 				u8 *data_array)
 {
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(fb->dev);
+	const struct ssd13xx_funcs *ssd13xx_funcs = ssd13xx->funcs;
 	struct iosys_map dst;
 	unsigned int dst_pitch;
 	int ret = 0;
@@ -624,13 +637,11 @@ static int ssd13xx_fb_blit_rect(struct drm_framebuffer *fb,
 		return ret;
 
 	iosys_map_set_vaddr(&dst, buf);
-	drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect);
+	ssd13xx_funcs->fmt_convert(&dst, &dst_pitch, vmap, fb, rect);
 
 	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
 
-	ssd13xx_update_rect(ssd13xx, rect, buf, data_array);
-
-	return ret;
+	return ssd13xx_funcs->update_rect(ssd13xx, rect, buf, data_array);
 }
 
 static int ssd13xx_primary_plane_atomic_check(struct drm_plane *plane,
@@ -642,8 +653,6 @@ static int ssd13xx_primary_plane_atomic_check(struct drm_plane *plane,
 	struct ssd13xx_plane_state *ssd13xx_state = to_ssd13xx_plane_state(plane_state);
 	struct drm_crtc *crtc = plane_state->crtc;
 	struct drm_crtc_state *crtc_state;
-	const struct drm_format_info *fi;
-	unsigned int pitch;
 	int ret;
 
 	if (!crtc)
@@ -657,18 +666,10 @@ static int ssd13xx_primary_plane_atomic_check(struct drm_plane *plane,
 	if (ret)
 		return ret;
 
-	fi = drm_format_info(DRM_FORMAT_R1);
-	if (!fi)
-		return -EINVAL;
-
-	pitch = drm_format_info_min_pitch(fi, 0, ssd13xx->width);
-
-	ssd13xx_state->buffer = kcalloc(pitch, ssd13xx->height, GFP_KERNEL);
+	ssd13xx_state->buffer = kzalloc(ssd13xx->buffer_size, GFP_KERNEL);
 	if (!ssd13xx_state->buffer)
 		return -ENOMEM;
 
-	ssd13xx_state->fi = fi;
-
 	return 0;
 }
 
@@ -684,6 +685,7 @@ static void ssd13xx_primary_plane_atomic_update(struct drm_plane *plane,
 	struct drm_framebuffer *fb = plane_state->fb;
 	struct drm_atomic_helper_damage_iter iter;
 	struct drm_device *drm = plane->dev;
+	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
 	struct drm_rect dst_clip;
 	struct drm_rect damage;
 	int idx;
@@ -700,7 +702,7 @@ static void ssd13xx_primary_plane_atomic_update(struct drm_plane *plane,
 
 		ssd13xx_fb_blit_rect(fb, &shadow_plane_state->data[0], &dst_clip,
 				     ssd13xx_plane_state->buffer,
-				     ssd13xx_plane_state->fi,
+				     ssd13xx->buffer_fi,
 				     ssd13xx_crtc_state->data_array);
 	}
 
@@ -712,6 +714,7 @@ static void ssd13xx_primary_plane_atomic_disable(struct drm_plane *plane,
 {
 	struct drm_device *drm = plane->dev;
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
+	const struct ssd13xx_funcs *ssd13xx_funcs = ssd13xx->funcs;
 	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
 	struct drm_crtc_state *crtc_state;
 	struct ssd13xx_crtc_state *ssd13xx_crtc_state;
@@ -726,7 +729,7 @@ static void ssd13xx_primary_plane_atomic_disable(struct drm_plane *plane,
 	if (!drm_dev_enter(drm, &idx))
 		return;
 
-	ssd13xx_clear_screen(ssd13xx, ssd13xx_crtc_state->data_array);
+	ssd13xx_funcs->clear_screen(ssd13xx, ssd13xx_crtc_state->data_array);
 
 	drm_dev_exit(idx);
 }
@@ -820,14 +823,13 @@ static int ssd13xx_crtc_atomic_check(struct drm_crtc *crtc,
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
 	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 	struct ssd13xx_crtc_state *ssd13xx_state = to_ssd13xx_crtc_state(crtc_state);
-	unsigned int pages = DIV_ROUND_UP(ssd13xx->height, SSD130X_PAGE_HEIGHT);
 	int ret;
 
 	ret = drm_crtc_helper_atomic_check(crtc, state);
 	if (ret)
 		return ret;
 
-	ssd13xx_state->data_array = kmalloc(ssd13xx->width * pages, GFP_KERNEL);
+	ssd13xx_state->data_array = kmalloc(ssd13xx->data_array_size, GFP_KERNEL);
 	if (!ssd13xx_state->data_array)
 		return -ENOMEM;
 
@@ -905,13 +907,14 @@ static void ssd13xx_encoder_atomic_enable(struct drm_encoder *encoder,
 {
 	struct drm_device *drm = encoder->dev;
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
+	const struct ssd13xx_funcs *ssd13xx_funcs = ssd13xx->funcs;
 	int ret;
 
 	ret = ssd13xx_power_on(ssd13xx);
 	if (ret)
 		return;
 
-	ret = ssd13xx_init(ssd13xx);
+	ret = ssd13xx_funcs->init(ssd13xx);
 	if (ret)
 		goto power_off;
 
@@ -1195,11 +1198,38 @@ static int ssd13xx_get_resources(struct ssd13xx_device *ssd13xx)
 	return 0;
 }
 
+static int ssd13xx_set_buffer_sizes(struct ssd13xx_device *ssd13xx,
+				    enum ssd13xx_family_ids family_id)
+{
+	const struct drm_format_info *fi;
+	unsigned int buffer_pitch;
+
+	switch (family_id) {
+	case SSD130X_FAMILY:
+		unsigned int pages = DIV_ROUND_UP(ssd13xx->height, SSD130X_PAGE_HEIGHT);
+
+		ssd13xx->data_array_size = ssd13xx->width * pages;
+
+		fi = drm_format_info(DRM_FORMAT_R1);
+		break;
+	}
+
+	if (!fi)
+		return -EINVAL;
+
+	buffer_pitch = drm_format_info_min_pitch(fi, 0, ssd13xx->width);
+	ssd13xx->buffer_size = buffer_pitch * ssd13xx->height;
+	ssd13xx->buffer_fi = fi;
+
+	return 0;
+}
+
 struct ssd13xx_device *ssd13xx_probe(struct device *dev, struct regmap *regmap)
 {
 	struct ssd13xx_device *ssd13xx;
 	struct backlight_device *bl;
 	struct drm_device *drm;
+	enum ssd13xx_family_ids family_id;
 	int ret;
 
 	ssd13xx = devm_drm_dev_alloc(dev, &ssd13xx_drm_driver,
@@ -1214,11 +1244,19 @@ struct ssd13xx_device *ssd13xx_probe(struct device *dev, struct regmap *regmap)
 	ssd13xx->regmap = regmap;
 	ssd13xx->device_info = device_get_match_data(dev);
 
+	family_id = ssd13xx->device_info->family_id;
+
+	ssd13xx->funcs = &ssd13xx_family_funcs[family_id];
+
 	if (ssd13xx->device_info->page_mode_only)
 		ssd13xx->page_address_mode = 1;
 
 	ssd13xx_parse_properties(ssd13xx);
 
+	ret = ssd13xx_set_buffer_sizes(ssd13xx, family_id);
+	if (ret)
+		return ERR_PTR(ret);
+
 	ret = ssd13xx_get_resources(ssd13xx);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/solomon/ssd13xx.h b/drivers/gpu/drm/solomon/ssd13xx.h
index 64283935fbc1..e78d5ab87474 100644
--- a/drivers/gpu/drm/solomon/ssd13xx.h
+++ b/drivers/gpu/drm/solomon/ssd13xx.h
@@ -20,11 +20,17 @@
 #include <drm/drm_plane_helper.h>
 
 #include <linux/regmap.h>
+#include <linux/iosys-map.h>
 
 #define SSD130X_DATA				0x40
 #define SSD130X_COMMAND				0x80
 
+enum ssd13xx_family_ids {
+	SSD130X_FAMILY,
+};
+
 enum ssd13xx_variants {
+	/* ssd130x family */
 	SH1106_ID,
 	SSD1305_ID,
 	SSD1306_ID,
@@ -39,6 +45,7 @@ struct ssd13xx_deviceinfo {
 	u32 default_dclk_frq;
 	u32 default_width;
 	u32 default_height;
+	enum ssd13xx_family_ids family_id;
 	bool need_pwm;
 	bool need_chargepump;
 	bool page_mode_only;
@@ -76,6 +83,12 @@ struct ssd13xx_device {
 	u32 col_offset;
 	u32 prechargep1;
 	u32 prechargep2;
+	/* HW format buffer size */
+	u32 data_array_size;
+	/* Intermediate buffer size */
+	u32 buffer_size;
+	/* Pixel format info for the intermediate buffer */
+	const struct drm_format_info *buffer_fi;
 
 	struct backlight_device *bl_dev;
 	struct pwm_device *pwm;
@@ -88,6 +101,20 @@ struct ssd13xx_device {
 	u8 col_end;
 	u8 page_start;
 	u8 page_end;
+
+	/* Chip family specific operations */
+	const struct ssd13xx_funcs *funcs;
+};
+
+struct ssd13xx_funcs {
+	int (*init)(struct ssd13xx_device *ssd130x);
+	int (*update_rect)(struct ssd13xx_device *ssd13xx, struct drm_rect *rect,
+			   u8 *buf, u8 *data_array);
+	void (*clear_screen)(struct ssd13xx_device *ssd13xx,
+			     u8 *data_array);
+	void (*fmt_convert)(struct iosys_map *dst, const unsigned int *dst_pitch,
+			    const struct iosys_map *src, const struct drm_framebuffer *fb,
+			    const struct drm_rect *clip);
 };
 
 extern const struct ssd13xx_deviceinfo ssd13xx_variants[];
-- 
2.41.0


WARNING: multiple messages have this Message-ID (diff)
From: Javier Martinez Canillas <javierm@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: Maxime Ripard <mripard@kernel.org>,
	Thomas Zimmermann <tzimmermann@suse.de>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Javier Martinez Canillas <javierm@redhat.com>,
	Daniel Vetter <daniel@ffwll.ch>, David Airlie <airlied@gmail.com>,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	dri-devel@lists.freedesktop.org
Subject: [PATCH 5/8] drm/ssd13xx: Add a per controller family functions table
Date: Mon,  9 Oct 2023 20:34:19 +0200	[thread overview]
Message-ID: <20231009183522.543918-6-javierm@redhat.com> (raw)
In-Reply-To: <20231009183522.543918-1-javierm@redhat.com>

To allow the driver to decouple the common logic in the function callbacks
from the behaviour that is specific of a given Solomon controller family.

For this, include a chip family to the device info and add fields to the
driver-private device struct, to store the hardware buffer maximum size,
the intermediate buffer maximum size and pixel format, and a set of per
chip family function handlers.

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

 drivers/gpu/drm/solomon/ssd13xx.c | 88 ++++++++++++++++++++++---------
 drivers/gpu/drm/solomon/ssd13xx.h | 27 ++++++++++
 2 files changed, 90 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/solomon/ssd13xx.c b/drivers/gpu/drm/solomon/ssd13xx.c
index 9747f8656636..5a426ac10c58 100644
--- a/drivers/gpu/drm/solomon/ssd13xx.c
+++ b/drivers/gpu/drm/solomon/ssd13xx.c
@@ -104,6 +104,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.default_width = 132,
 		.default_height = 64,
 		.page_mode_only = 1,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1305_ID] = {
 		.default_vcomh = 0x34,
@@ -111,6 +112,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.default_dclk_frq = 7,
 		.default_width = 132,
 		.default_height = 64,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1306_ID] = {
 		.default_vcomh = 0x20,
@@ -119,6 +121,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.need_chargepump = 1,
 		.default_width = 128,
 		.default_height = 64,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1307_ID] = {
 		.default_vcomh = 0x20,
@@ -127,6 +130,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.need_pwm = 1,
 		.default_width = 128,
 		.default_height = 39,
+		.family_id = SSD130X_FAMILY,
 	},
 	[SSD1309_ID] = {
 		.default_vcomh = 0x34,
@@ -134,6 +138,7 @@ const struct ssd13xx_deviceinfo ssd13xx_variants[] = {
 		.default_dclk_frq = 10,
 		.default_width = 128,
 		.default_height = 64,
+		.family_id = SSD130X_FAMILY,
 	}
 };
 EXPORT_SYMBOL_NS_GPL(ssd13xx_variants, DRM_SSD13XX);
@@ -148,8 +153,6 @@ struct ssd13xx_plane_state {
 	struct drm_shadow_plane_state base;
 	/* Intermediate buffer to convert pixels from XRGB8888 to HW format */
 	u8 *buffer;
-	/* Pixel format info for the intermediate buffer */
-	const struct drm_format_info *fi;
 };
 
 static inline struct ssd13xx_crtc_state *to_ssd13xx_crtc_state(struct drm_crtc_state *state)
@@ -331,7 +334,7 @@ static void ssd13xx_power_off(struct ssd13xx_device *ssd13xx)
 	regulator_disable(ssd13xx->vcc_reg);
 }
 
-static int ssd13xx_init(struct ssd13xx_device *ssd13xx)
+static int ssd130x_init(struct ssd13xx_device *ssd13xx)
 {
 	u32 precharge, dclk, com_invdir, compins, chargepump, seg_remap;
 	bool scan_mode;
@@ -455,7 +458,7 @@ static int ssd13xx_init(struct ssd13xx_device *ssd13xx)
 				 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
 }
 
-static int ssd13xx_update_rect(struct ssd13xx_device *ssd13xx,
+static int ssd130x_update_rect(struct ssd13xx_device *ssd13xx,
 			       struct drm_rect *rect, u8 *buf,
 			       u8 *data_array)
 {
@@ -561,7 +564,7 @@ static int ssd13xx_update_rect(struct ssd13xx_device *ssd13xx,
 	return ret;
 }
 
-static void ssd13xx_clear_screen(struct ssd13xx_device *ssd13xx, u8 *data_array)
+static void ssd130x_clear_screen(struct ssd13xx_device *ssd13xx, u8 *data_array)
 {
 	unsigned int pages = DIV_ROUND_UP(ssd13xx->height, SSD130X_PAGE_HEIGHT);
 	unsigned int width = ssd13xx->width;
@@ -602,6 +605,15 @@ static void ssd13xx_clear_screen(struct ssd13xx_device *ssd13xx, u8 *data_array)
 	}
 }
 
+static const struct ssd13xx_funcs ssd13xx_family_funcs[] = {
+	[SSD130X_FAMILY] = {
+		.init = ssd130x_init,
+		.update_rect = ssd130x_update_rect,
+		.clear_screen = ssd130x_clear_screen,
+		.fmt_convert = drm_fb_xrgb8888_to_mono,
+	},
+};
+
 static int ssd13xx_fb_blit_rect(struct drm_framebuffer *fb,
 				const struct iosys_map *vmap,
 				struct drm_rect *rect, u8 *buf,
@@ -609,6 +621,7 @@ static int ssd13xx_fb_blit_rect(struct drm_framebuffer *fb,
 				u8 *data_array)
 {
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(fb->dev);
+	const struct ssd13xx_funcs *ssd13xx_funcs = ssd13xx->funcs;
 	struct iosys_map dst;
 	unsigned int dst_pitch;
 	int ret = 0;
@@ -624,13 +637,11 @@ static int ssd13xx_fb_blit_rect(struct drm_framebuffer *fb,
 		return ret;
 
 	iosys_map_set_vaddr(&dst, buf);
-	drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect);
+	ssd13xx_funcs->fmt_convert(&dst, &dst_pitch, vmap, fb, rect);
 
 	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
 
-	ssd13xx_update_rect(ssd13xx, rect, buf, data_array);
-
-	return ret;
+	return ssd13xx_funcs->update_rect(ssd13xx, rect, buf, data_array);
 }
 
 static int ssd13xx_primary_plane_atomic_check(struct drm_plane *plane,
@@ -642,8 +653,6 @@ static int ssd13xx_primary_plane_atomic_check(struct drm_plane *plane,
 	struct ssd13xx_plane_state *ssd13xx_state = to_ssd13xx_plane_state(plane_state);
 	struct drm_crtc *crtc = plane_state->crtc;
 	struct drm_crtc_state *crtc_state;
-	const struct drm_format_info *fi;
-	unsigned int pitch;
 	int ret;
 
 	if (!crtc)
@@ -657,18 +666,10 @@ static int ssd13xx_primary_plane_atomic_check(struct drm_plane *plane,
 	if (ret)
 		return ret;
 
-	fi = drm_format_info(DRM_FORMAT_R1);
-	if (!fi)
-		return -EINVAL;
-
-	pitch = drm_format_info_min_pitch(fi, 0, ssd13xx->width);
-
-	ssd13xx_state->buffer = kcalloc(pitch, ssd13xx->height, GFP_KERNEL);
+	ssd13xx_state->buffer = kzalloc(ssd13xx->buffer_size, GFP_KERNEL);
 	if (!ssd13xx_state->buffer)
 		return -ENOMEM;
 
-	ssd13xx_state->fi = fi;
-
 	return 0;
 }
 
@@ -684,6 +685,7 @@ static void ssd13xx_primary_plane_atomic_update(struct drm_plane *plane,
 	struct drm_framebuffer *fb = plane_state->fb;
 	struct drm_atomic_helper_damage_iter iter;
 	struct drm_device *drm = plane->dev;
+	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
 	struct drm_rect dst_clip;
 	struct drm_rect damage;
 	int idx;
@@ -700,7 +702,7 @@ static void ssd13xx_primary_plane_atomic_update(struct drm_plane *plane,
 
 		ssd13xx_fb_blit_rect(fb, &shadow_plane_state->data[0], &dst_clip,
 				     ssd13xx_plane_state->buffer,
-				     ssd13xx_plane_state->fi,
+				     ssd13xx->buffer_fi,
 				     ssd13xx_crtc_state->data_array);
 	}
 
@@ -712,6 +714,7 @@ static void ssd13xx_primary_plane_atomic_disable(struct drm_plane *plane,
 {
 	struct drm_device *drm = plane->dev;
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
+	const struct ssd13xx_funcs *ssd13xx_funcs = ssd13xx->funcs;
 	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
 	struct drm_crtc_state *crtc_state;
 	struct ssd13xx_crtc_state *ssd13xx_crtc_state;
@@ -726,7 +729,7 @@ static void ssd13xx_primary_plane_atomic_disable(struct drm_plane *plane,
 	if (!drm_dev_enter(drm, &idx))
 		return;
 
-	ssd13xx_clear_screen(ssd13xx, ssd13xx_crtc_state->data_array);
+	ssd13xx_funcs->clear_screen(ssd13xx, ssd13xx_crtc_state->data_array);
 
 	drm_dev_exit(idx);
 }
@@ -820,14 +823,13 @@ static int ssd13xx_crtc_atomic_check(struct drm_crtc *crtc,
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
 	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 	struct ssd13xx_crtc_state *ssd13xx_state = to_ssd13xx_crtc_state(crtc_state);
-	unsigned int pages = DIV_ROUND_UP(ssd13xx->height, SSD130X_PAGE_HEIGHT);
 	int ret;
 
 	ret = drm_crtc_helper_atomic_check(crtc, state);
 	if (ret)
 		return ret;
 
-	ssd13xx_state->data_array = kmalloc(ssd13xx->width * pages, GFP_KERNEL);
+	ssd13xx_state->data_array = kmalloc(ssd13xx->data_array_size, GFP_KERNEL);
 	if (!ssd13xx_state->data_array)
 		return -ENOMEM;
 
@@ -905,13 +907,14 @@ static void ssd13xx_encoder_atomic_enable(struct drm_encoder *encoder,
 {
 	struct drm_device *drm = encoder->dev;
 	struct ssd13xx_device *ssd13xx = drm_to_ssd13xx(drm);
+	const struct ssd13xx_funcs *ssd13xx_funcs = ssd13xx->funcs;
 	int ret;
 
 	ret = ssd13xx_power_on(ssd13xx);
 	if (ret)
 		return;
 
-	ret = ssd13xx_init(ssd13xx);
+	ret = ssd13xx_funcs->init(ssd13xx);
 	if (ret)
 		goto power_off;
 
@@ -1195,11 +1198,38 @@ static int ssd13xx_get_resources(struct ssd13xx_device *ssd13xx)
 	return 0;
 }
 
+static int ssd13xx_set_buffer_sizes(struct ssd13xx_device *ssd13xx,
+				    enum ssd13xx_family_ids family_id)
+{
+	const struct drm_format_info *fi;
+	unsigned int buffer_pitch;
+
+	switch (family_id) {
+	case SSD130X_FAMILY:
+		unsigned int pages = DIV_ROUND_UP(ssd13xx->height, SSD130X_PAGE_HEIGHT);
+
+		ssd13xx->data_array_size = ssd13xx->width * pages;
+
+		fi = drm_format_info(DRM_FORMAT_R1);
+		break;
+	}
+
+	if (!fi)
+		return -EINVAL;
+
+	buffer_pitch = drm_format_info_min_pitch(fi, 0, ssd13xx->width);
+	ssd13xx->buffer_size = buffer_pitch * ssd13xx->height;
+	ssd13xx->buffer_fi = fi;
+
+	return 0;
+}
+
 struct ssd13xx_device *ssd13xx_probe(struct device *dev, struct regmap *regmap)
 {
 	struct ssd13xx_device *ssd13xx;
 	struct backlight_device *bl;
 	struct drm_device *drm;
+	enum ssd13xx_family_ids family_id;
 	int ret;
 
 	ssd13xx = devm_drm_dev_alloc(dev, &ssd13xx_drm_driver,
@@ -1214,11 +1244,19 @@ struct ssd13xx_device *ssd13xx_probe(struct device *dev, struct regmap *regmap)
 	ssd13xx->regmap = regmap;
 	ssd13xx->device_info = device_get_match_data(dev);
 
+	family_id = ssd13xx->device_info->family_id;
+
+	ssd13xx->funcs = &ssd13xx_family_funcs[family_id];
+
 	if (ssd13xx->device_info->page_mode_only)
 		ssd13xx->page_address_mode = 1;
 
 	ssd13xx_parse_properties(ssd13xx);
 
+	ret = ssd13xx_set_buffer_sizes(ssd13xx, family_id);
+	if (ret)
+		return ERR_PTR(ret);
+
 	ret = ssd13xx_get_resources(ssd13xx);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/solomon/ssd13xx.h b/drivers/gpu/drm/solomon/ssd13xx.h
index 64283935fbc1..e78d5ab87474 100644
--- a/drivers/gpu/drm/solomon/ssd13xx.h
+++ b/drivers/gpu/drm/solomon/ssd13xx.h
@@ -20,11 +20,17 @@
 #include <drm/drm_plane_helper.h>
 
 #include <linux/regmap.h>
+#include <linux/iosys-map.h>
 
 #define SSD130X_DATA				0x40
 #define SSD130X_COMMAND				0x80
 
+enum ssd13xx_family_ids {
+	SSD130X_FAMILY,
+};
+
 enum ssd13xx_variants {
+	/* ssd130x family */
 	SH1106_ID,
 	SSD1305_ID,
 	SSD1306_ID,
@@ -39,6 +45,7 @@ struct ssd13xx_deviceinfo {
 	u32 default_dclk_frq;
 	u32 default_width;
 	u32 default_height;
+	enum ssd13xx_family_ids family_id;
 	bool need_pwm;
 	bool need_chargepump;
 	bool page_mode_only;
@@ -76,6 +83,12 @@ struct ssd13xx_device {
 	u32 col_offset;
 	u32 prechargep1;
 	u32 prechargep2;
+	/* HW format buffer size */
+	u32 data_array_size;
+	/* Intermediate buffer size */
+	u32 buffer_size;
+	/* Pixel format info for the intermediate buffer */
+	const struct drm_format_info *buffer_fi;
 
 	struct backlight_device *bl_dev;
 	struct pwm_device *pwm;
@@ -88,6 +101,20 @@ struct ssd13xx_device {
 	u8 col_end;
 	u8 page_start;
 	u8 page_end;
+
+	/* Chip family specific operations */
+	const struct ssd13xx_funcs *funcs;
+};
+
+struct ssd13xx_funcs {
+	int (*init)(struct ssd13xx_device *ssd130x);
+	int (*update_rect)(struct ssd13xx_device *ssd13xx, struct drm_rect *rect,
+			   u8 *buf, u8 *data_array);
+	void (*clear_screen)(struct ssd13xx_device *ssd13xx,
+			     u8 *data_array);
+	void (*fmt_convert)(struct iosys_map *dst, const unsigned int *dst_pitch,
+			    const struct iosys_map *src, const struct drm_framebuffer *fb,
+			    const struct drm_rect *clip);
 };
 
 extern const struct ssd13xx_deviceinfo ssd13xx_variants[];
-- 
2.41.0


  parent reply	other threads:[~2023-10-09 18:36 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-09 18:34 [PATCH 0/8] drm/solomon: Add support for the SSD132x controller family Javier Martinez Canillas
2023-10-09 18:34 ` Javier Martinez Canillas
2023-10-09 18:34 ` [PATCH 1/8] drm/solomon: Rename ssd130x driver to ssd13xx Javier Martinez Canillas
2023-10-09 18:34   ` Javier Martinez Canillas
2023-10-10  8:09   ` Maxime Ripard
2023-10-10  8:09     ` Maxime Ripard
2023-10-10  8:38     ` Javier Martinez Canillas
2023-10-10  8:38       ` Javier Martinez Canillas
2023-10-09 18:34 ` [PATCH 2/8] drm/ssd13xx: Rename data structures and functions prefixes Javier Martinez Canillas
2023-10-09 18:34   ` Javier Martinez Canillas
2023-10-09 18:34 ` [PATCH 3/8] drm/ssd13xx: Replace .page_height field in device info with a constant Javier Martinez Canillas
2023-10-09 18:34   ` Javier Martinez Canillas
2023-10-11  7:39   ` Geert Uytterhoeven
2023-10-11  7:39     ` Geert Uytterhoeven
2023-10-11  8:33     ` Javier Martinez Canillas
2023-10-11  8:33       ` Javier Martinez Canillas
2023-10-09 18:34 ` [PATCH 4/8] drm/ssd13xx: Use drm_format_info_min_pitch() to calculate the dest_pitch Javier Martinez Canillas
2023-10-09 18:34   ` Javier Martinez Canillas
2023-10-11  7:59   ` Geert Uytterhoeven
2023-10-11  7:59     ` Geert Uytterhoeven
2023-10-11  8:37     ` Javier Martinez Canillas
2023-10-11  8:37       ` Javier Martinez Canillas
2023-10-09 18:34 ` Javier Martinez Canillas [this message]
2023-10-09 18:34   ` [PATCH 5/8] drm/ssd13xx: Add a per controller family functions table Javier Martinez Canillas
2023-10-11  8:09   ` Geert Uytterhoeven
2023-10-11  8:09     ` Geert Uytterhoeven
2023-10-11  8:48     ` Javier Martinez Canillas
2023-10-11  8:48       ` Javier Martinez Canillas
2023-10-09 18:34 ` [PATCH 6/8] drm/ssd13xx: Rename commands that are shared across chip families Javier Martinez Canillas
2023-10-09 18:34   ` Javier Martinez Canillas
2023-10-09 18:34 ` [PATCH 7/8] drm/ssd13xx: Add support for the SSD132x OLED controller family Javier Martinez Canillas
2023-10-09 18:34   ` Javier Martinez Canillas
2023-10-11  8:13   ` Geert Uytterhoeven
2023-10-11  8:13     ` Geert Uytterhoeven
2023-10-11  8:49     ` Javier Martinez Canillas
2023-10-11  8:49       ` Javier Martinez Canillas
2023-10-09 18:34 ` [PATCH 8/8] dt-bindings: display: Add SSD132x OLED controllers Javier Martinez Canillas
2023-10-09 18:34   ` Javier Martinez Canillas
2023-10-10 16:31   ` Conor Dooley
2023-10-10 16:31     ` Conor Dooley
2023-10-11  6:34     ` Javier Martinez Canillas
2023-10-11  6:34       ` Javier Martinez Canillas
2023-10-11 15:50       ` Conor Dooley
2023-10-11 15:50         ` Conor Dooley
2023-10-10 16:58   ` Rob Herring
2023-10-10 16:58     ` Rob Herring
2023-10-11  6:39     ` Javier Martinez Canillas
2023-10-11  6:39       ` Javier Martinez Canillas
2023-10-11  7:34       ` Javier Martinez Canillas
2023-10-11  7:34         ` Javier Martinez Canillas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231009183522.543918-6-javierm@redhat.com \
    --to=javierm@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=geert@linux-m68k.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mripard@kernel.org \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.