build/patch/kernel/archive/sunxi-6.2/patches.megous/drm-panel-hx8394-Add-mode-init-sequence-update-via-firmware-loa.patch

142 lines
3.7 KiB
Diff

From fcba4cb8ef30d0cc16108357ccd02a14659cf020 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Wed, 19 Oct 2022 02:54:20 +0200
Subject: [PATCH 303/391] drm: panel: hx8394: Add mode/init sequence update via
firmware load
This is useful for trying various modes/init sequences quickly from
userspace.
Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
drivers/gpu/drm/panel/panel-himax-hx8394.c | 78 +++++++++++++++++++++-
1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
index fc04e50dd..f99dbe012 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx8394.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -13,6 +13,7 @@
#include <linux/media-bus-format.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/firmware.h>
#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
@@ -35,6 +36,9 @@ struct hx8394 {
struct dentry *debugfs;
const struct hx8394_panel_desc *desc;
+
+ u8* init_seq;
+ int init_seq_size;
};
struct hx8394_panel_desc {
@@ -70,6 +74,21 @@ static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ u8* s = ctx->init_seq;
+ u8* e = ctx->init_seq + ctx->init_seq_size;
+ int ret;
+
+ if (s) {
+ while (s < e) {
+ ret = mipi_dsi_dcs_write(dsi, s[0], s + 2, s[1]);
+ if (ret < 0)
+ return ret;
+
+ s += s[1] + 2;
+ }
+
+ return 0;
+ }
dsi_dcs_write_seq(dsi, 0xb9, 0xff, 0x83, 0x94);
dsi_dcs_write_seq(dsi, 0xb1, 0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
@@ -92,7 +111,7 @@ static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
return 0;
}
-static const struct drm_display_mode hsd060bhw4_mode = {
+static struct drm_display_mode hsd060bhw4_mode = {
.hdisplay = 720,
.hsync_start = 720 + 40,
.hsync_end = 720 + 40 + 46,
@@ -302,6 +321,61 @@ static void hx8394_debugfs_remove(struct hx8394 *ctx)
ctx->debugfs = NULL;
}
+struct drm_display_mode_head {
+ int clock; /* in kHz */
+ u16 hdisplay;
+ u16 hsync_start;
+ u16 hsync_end;
+ u16 htotal;
+ u16 hskew;
+ u16 vdisplay;
+ u16 vsync_start;
+ u16 vsync_end;
+ u16 vtotal;
+ u16 vscan;
+};
+
+static void hx8394_load_mode(struct hx8394 *ctx)
+{
+ const char* fw_name = "hx8394-mode.bin";
+ const struct firmware *fw;
+ struct drm_display_mode_head h;
+ int ret;
+
+ ret = request_firmware(&fw, fw_name, ctx->dev);
+ if (ret < 0)
+ return;
+
+ if (fw->size < sizeof(h))
+ goto out_free;
+
+ memcpy(&h, fw->data, sizeof(h));
+
+ hsd060bhw4_mode.hdisplay = h.hdisplay;
+ hsd060bhw4_mode.hsync_start = h.hsync_start;
+ hsd060bhw4_mode.hsync_end = h.hsync_end;
+ hsd060bhw4_mode.htotal = h.htotal;
+ hsd060bhw4_mode.vdisplay = h.vdisplay;
+ hsd060bhw4_mode.vsync_start = h.vsync_start;
+ hsd060bhw4_mode.vsync_end = h.vsync_end;
+ hsd060bhw4_mode.vtotal = h.vtotal;
+ hsd060bhw4_mode.clock = h.clock;
+ //hsd060bhw4_mode.flags = h.flags;
+
+ if (fw->size <= sizeof(h))
+ goto out_free;
+
+ ctx->init_seq_size = fw->size - sizeof(h);
+ ctx->init_seq = devm_kzalloc(ctx->dev, ctx->init_seq_size, GFP_KERNEL);
+ if (ctx->init_seq == NULL)
+ goto out_free;
+
+ memcpy(ctx->init_seq, fw->data + sizeof(h), ctx->init_seq_size);
+
+out_free:
+ release_firmware(fw);
+}
+
static int hx8394_probe(struct mipi_dsi_device *dsi)
{
struct device *dev = &dsi->dev;
@@ -322,6 +396,8 @@ static int hx8394_probe(struct mipi_dsi_device *dsi)
ctx->dev = dev;
ctx->desc = of_device_get_match_data(dev);
+ hx8394_load_mode(ctx);
+
dsi->mode_flags = ctx->desc->mode_flags;
dsi->format = ctx->desc->format;
dsi->lanes = ctx->desc->lanes;
--
2.35.3