From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 13 May 2024 10:30:14 +0000 Subject: [PATCH] modify sin led gpio --- 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