From 23fa18eaa71266feff7ba8d83022d9e1cc83c65a Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:42:03 +0000
Subject: [PATCH] disable pwm7
---
kernel/drivers/gpu/drm/panel/panel-simple.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 203 insertions(+), 28 deletions(-)
diff --git a/kernel/drivers/gpu/drm/panel/panel-simple.c b/kernel/drivers/gpu/drm/panel/panel-simple.c
index 5f4ce17..422c096 100644
--- a/kernel/drivers/gpu/drm/panel/panel-simple.c
+++ b/kernel/drivers/gpu/drm/panel/panel-simple.c
@@ -28,6 +28,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
#include <video/display_timing.h>
#include <video/mipi_display.h>
@@ -41,6 +42,11 @@
#include <drm/drm_dsc.h>
#include "panel-simple.h"
+
+enum panel_simple_cmd_type {
+ CMD_TYPE_DEFAULT,
+ CMD_TYPE_SPI
+};
struct panel_cmd_header {
u8 data_type;
@@ -124,6 +130,11 @@
struct panel_cmd_seq *init_seq;
struct panel_cmd_seq *exit_seq;
+
+ enum panel_simple_cmd_type cmd_type;
+
+ int (*spi_read)(struct device *dev, const u8 cmd, u8 *val);
+ int (*spi_write)(struct device *dev, const u8 *data, size_t len, u8 type);
};
struct panel_simple {
@@ -148,6 +159,11 @@
struct drm_dsc_picture_parameter_set *pps;
enum drm_panel_orientation orientation;
};
+
+static inline void panel_simple_msleep(unsigned int msecs)
+{
+ usleep_range(msecs * 1000, msecs * 1000 + 100);
+}
static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
{
@@ -266,7 +282,30 @@
dev_err(dev, "failed to write dcs cmd: %d\n", err);
if (cmd->header.delay)
- msleep(cmd->header.delay);
+ panel_simple_msleep(cmd->header.delay);
+ }
+
+ return 0;
+}
+
+static int panel_simple_xfer_spi_cmd_seq(struct panel_simple *panel, struct panel_cmd_seq *cmds)
+{
+ int i;
+ int ret;
+
+ if (!cmds)
+ return -EINVAL;
+
+ for (i = 0; i < cmds->cmd_cnt; i++) {
+ struct panel_cmd_desc *cmd = &cmds->cmds[i];
+
+ ret = panel->desc->spi_write(panel->base.dev, cmd->payload,
+ cmd->header.payload_length, cmd->header.data_type);
+ if (ret)
+ return ret;
+
+ if (cmd->header.delay)
+ panel_simple_msleep(cmd->header.delay);
}
return 0;
@@ -444,7 +483,7 @@
return 0;
if (p->desc->delay.disable)
- msleep(p->desc->delay.disable);
+ panel_simple_msleep(p->desc->delay.disable);
p->enabled = false;
@@ -458,9 +497,17 @@
if (!p->prepared)
return 0;
- if (p->desc->exit_seq)
- if (p->dsi)
- panel_simple_xfer_dsi_cmd_seq(p, p->desc->exit_seq);
+ if (p->desc->exit_seq) {
+ if (p->desc->cmd_type == CMD_TYPE_SPI) {
+ if (panel_simple_xfer_spi_cmd_seq(p, p->desc->exit_seq)) {
+ dev_err(panel->dev, "failed to send exit spi cmds seq\n");
+ return -EINVAL;
+ }
+ } else {
+ if (p->dsi)
+ panel_simple_xfer_dsi_cmd_seq(p, p->desc->exit_seq);
+ }
+ }
gpiod_direction_output(p->reset_gpio, 1);
gpiod_direction_output(p->enable_gpio, 0);
@@ -468,7 +515,7 @@
panel_simple_regulator_disable(p);
if (p->desc->delay.unprepare)
- msleep(p->desc->delay.unprepare);
+ panel_simple_msleep(p->desc->delay.unprepare);
p->prepared = false;
@@ -522,7 +569,7 @@
if (p->no_hpd)
delay += p->desc->delay.hpd_absent_delay;
if (delay)
- msleep(delay);
+ panel_simple_msleep(delay);
if (p->hpd_gpio) {
if (IS_ERR(p->hpd_gpio)) {
@@ -547,16 +594,24 @@
gpiod_direction_output(p->reset_gpio, 1);
if (p->desc->delay.reset)
- msleep(p->desc->delay.reset);
+ panel_simple_msleep(p->desc->delay.reset);
gpiod_direction_output(p->reset_gpio, 0);
if (p->desc->delay.init)
- msleep(p->desc->delay.init);
+ panel_simple_msleep(p->desc->delay.init);
- if (p->desc->init_seq)
- if (p->dsi)
- panel_simple_xfer_dsi_cmd_seq(p, p->desc->init_seq);
+ if (p->desc->init_seq) {
+ if (p->desc->cmd_type == CMD_TYPE_SPI) {
+ if (panel_simple_xfer_spi_cmd_seq(p, p->desc->init_seq)) {
+ dev_err(panel->dev, "failed to send init spi cmds seq\n");
+ return -EINVAL;
+ }
+ } else {
+ if (p->dsi)
+ panel_simple_xfer_dsi_cmd_seq(p, p->desc->init_seq);
+ }
+ }
p->prepared = true;
@@ -571,7 +626,7 @@
return 0;
if (p->desc->delay.enable)
- msleep(p->desc->delay.enable);
+ panel_simple_msleep(p->desc->delay.enable);
p->enabled = true;
@@ -992,8 +1047,8 @@
.num_modes = 1,
.bpc = 8,
.size = {
- .width = 105,
- .height = 67,
+ .width = 99,
+ .height = 58,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
};
@@ -1298,21 +1353,21 @@
},
};
-static const struct drm_display_mode auo_g121ean01_mode = {
- .clock = 66700,
- .hdisplay = 1280,
- .hsync_start = 1280 + 58,
- .hsync_end = 1280 + 58 + 8,
- .htotal = 1280 + 58 + 8 + 70,
- .vdisplay = 800,
- .vsync_start = 800 + 6,
- .vsync_end = 800 + 6 + 4,
- .vtotal = 800 + 6 + 4 + 10,
+static const struct display_timing auo_g121ean01_timing = {
+ .pixelclock = { 60000000, 74400000, 90000000 },
+ .hactive = { 1280, 1280, 1280 },
+ .hfront_porch = { 20, 50, 100 },
+ .hback_porch = { 20, 50, 100 },
+ .hsync_len = { 30, 100, 200 },
+ .vactive = { 800, 800, 800 },
+ .vfront_porch = { 2, 10, 25 },
+ .vback_porch = { 2, 10, 25 },
+ .vsync_len = { 4, 18, 50 },
};
static const struct panel_desc auo_g121ean01 = {
- .modes = &auo_g121ean01_mode,
- .num_modes = 1,
+ .timings = &auo_g121ean01_timing,
+ .num_timings = 1,
.bpc = 8,
.size = {
.width = 261,
@@ -1488,7 +1543,9 @@
.delay = {
.disable = 5,
.unprepare = 1000,
- }
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
};
static const struct drm_display_mode avic_tm070ddh03_mode = {
@@ -2379,6 +2436,7 @@
.height = 54,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .connector_type = DRM_MODE_CONNECTOR_DPI,
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
};
@@ -3440,6 +3498,7 @@
.vsync_start = 480 + 49,
.vsync_end = 480 + 49 + 2,
.vtotal = 480 + 49 + 2 + 22,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
};
static const struct panel_desc powertip_ph800480t013_idf02 = {
@@ -5109,6 +5168,113 @@
.shutdown = panel_simple_dsi_shutdown,
};
+static int panel_simple_spi_read(struct device *dev, const u8 cmd, u8 *data)
+{
+ return 0;
+}
+
+static int panel_simple_spi_write_word(struct device *dev, u16 data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer = {
+ .len = 2,
+ .tx_buf = &data,
+ };
+ struct spi_message msg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ return spi_sync(spi, &msg);
+}
+
+static int panel_simple_spi_write(struct device *dev, const u8 *data, size_t len, u8 type)
+{
+ int ret = 0;
+ int i;
+ u16 mask = type ? 0x100 : 0;
+
+ for (i = 0; i < len; i++) {
+ ret = panel_simple_spi_write_word(dev, *data | mask);
+ if (ret) {
+ dev_err(dev, "failed to write spi seq: %*ph\n", (int)len, data);
+ return ret;
+ }
+ data++;
+ }
+
+ return ret;
+}
+
+static const struct of_device_id panel_simple_spi_of_match[] = {
+ { .compatible = "simple-panel-spi", .data = NULL },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, panel_simple_spi_of_match);
+
+static int panel_simple_spi_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ const struct of_device_id *id;
+ const struct panel_desc *desc;
+ struct panel_desc *d;
+ int ret;
+
+ id = of_match_node(panel_simple_spi_of_match, dev->of_node);
+ if (!id)
+ return -ENODEV;
+
+ if (!id->data) {
+ d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
+ if (!d)
+ return -ENOMEM;
+
+ ret = panel_simple_of_get_desc_data(dev, d);
+ if (ret) {
+ dev_err(dev, "failed to get desc data: %d\n", ret);
+ return ret;
+ }
+
+ d->spi_write = panel_simple_spi_write;
+ d->spi_read = panel_simple_spi_read;
+ d->cmd_type = CMD_TYPE_SPI;
+ }
+ desc = id->data ? id->data : d;
+
+ /*
+ * Set spi to 3 lines and 9bits/word mode.
+ */
+ spi->bits_per_word = 9;
+ spi->mode = SPI_MODE_3;
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ dev_err(dev, "spi setup failed.\n");
+ return ret;
+ }
+
+ return panel_simple_probe(dev, desc);
+}
+
+static int panel_simple_spi_remove(struct spi_device *spi)
+{
+ return panel_simple_remove(&spi->dev);
+}
+
+static void panel_simple_spi_shutdown(struct spi_device *spi)
+{
+ panel_simple_shutdown(&spi->dev);
+}
+
+static struct spi_driver panel_simple_spi_driver = {
+ .driver = {
+ .name = "panel-simple-spi",
+ .of_match_table = panel_simple_spi_of_match,
+ },
+ .probe = panel_simple_spi_probe,
+ .remove = panel_simple_spi_remove,
+ .shutdown = panel_simple_spi_shutdown,
+};
+
static int __init panel_simple_init(void)
{
int err;
@@ -5116,6 +5282,12 @@
err = platform_driver_register(&panel_simple_platform_driver);
if (err < 0)
return err;
+
+ if (IS_ENABLED(CONFIG_SPI_MASTER)) {
+ err = spi_register_driver(&panel_simple_spi_driver);
+ if (err < 0)
+ return err;
+ }
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
err = mipi_dsi_driver_register(&panel_simple_dsi_driver);
@@ -5132,6 +5304,9 @@
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
mipi_dsi_driver_unregister(&panel_simple_dsi_driver);
+ if (IS_ENABLED(CONFIG_SPI_MASTER))
+ spi_unregister_driver(&panel_simple_spi_driver);
+
platform_driver_unregister(&panel_simple_platform_driver);
}
module_exit(panel_simple_exit);
--
Gitblit v1.6.2