From 04dd17822334871b23ea2862f7798fb0e0007777 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 11 May 2024 08:53:19 +0000
Subject: [PATCH] change otg to host mode
---
u-boot/drivers/video/drm/rockchip_rgb.c | 362 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 362 insertions(+), 0 deletions(-)
diff --git a/u-boot/drivers/video/drm/rockchip_rgb.c b/u-boot/drivers/video/drm/rockchip_rgb.c
index 53fb862..2b3b85c 100644
--- a/u-boot/drivers/video/drm/rockchip_rgb.c
+++ b/u-boot/drivers/video/drm/rockchip_rgb.c
@@ -13,11 +13,14 @@
#include <dm/read.h>
#include <dm/pinctrl.h>
#include <linux/media-bus-format.h>
+#include <asm/gpio.h>
+#include <backlight.h>
#include "rockchip_display.h"
#include "rockchip_crtc.h"
#include "rockchip_connector.h"
#include "rockchip_phy.h"
+#include "rockchip_panel.h"
#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16))
@@ -48,6 +51,9 @@
#define RK3368_GRF_SOC_CON15 0x043c
#define RK3368_FORCE_JETAG(v) HIWORD_UPDATE(v, 13, 13)
+#define RK3562_GRF_IOC_VO_IO_CON 0x10500
+#define RK3562_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6)
+
#define RK3568_GRF_VO_CON1 0X0364
#define RK3568_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6)
@@ -67,6 +73,64 @@
struct rockchip_phy *phy;
const struct rockchip_rgb_funcs *funcs;
};
+
+struct mcu_cmd_header {
+ u8 data_type;
+ u8 delay;
+ u8 payload_length;
+} __packed;
+
+struct mcu_cmd_desc {
+ struct mcu_cmd_header header;
+ const u8 *payload;
+};
+
+struct mcu_cmd_seq {
+ struct mcu_cmd_desc *cmds;
+ unsigned int cmd_cnt;
+};
+
+struct rockchip_mcu_panel_desc {
+ struct mcu_cmd_seq *init_seq;
+ struct mcu_cmd_seq *exit_seq;
+
+ struct {
+ unsigned int width;
+ unsigned int height;
+ } size;
+
+ struct {
+ unsigned int prepare;
+ unsigned int enable;
+ unsigned int disable;
+ unsigned int unprepare;
+ unsigned int reset;
+ unsigned int init;
+ } delay;
+
+ unsigned int bpc;
+ u32 bus_format;
+ u32 bus_flags;
+ bool power_invert;
+};
+
+struct rockchip_mcu_panel {
+ struct rockchip_panel base;
+ struct rockchip_mcu_panel_desc *desc;
+ struct udevice *power_supply;
+ struct udevice *backlight;
+
+ struct gpio_desc enable_gpio;
+ struct gpio_desc reset_gpio;
+
+ bool prepared;
+ bool enabled;
+};
+
+static inline struct rockchip_mcu_panel *to_rockchip_mcu_panel(struct rockchip_panel *panel)
+{
+ return container_of(panel, struct rockchip_mcu_panel, base);
+}
static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn,
struct display_state *state)
@@ -170,9 +234,254 @@
.unprepare = rockchip_rgb_connector_unprepare,
};
+static int rockchip_mcu_panel_send_cmds(struct display_state *state,
+ struct mcu_cmd_seq *cmds)
+{
+ int i;
+
+ if (!cmds)
+ return -EINVAL;
+
+ display_send_mcu_cmd(state, MCU_SETBYPASS, 1);
+ for (i = 0; i < cmds->cmd_cnt; i++) {
+ struct mcu_cmd_desc *desc = &cmds->cmds[i];
+ int value = 0;
+
+ value = desc->payload[0];
+ display_send_mcu_cmd(state, desc->header.data_type, value);
+
+ if (desc->header.delay)
+ mdelay(desc->header.delay);
+ }
+ display_send_mcu_cmd(state, MCU_SETBYPASS, 0);
+
+ return 0;
+}
+
+static void rockchip_mcu_panel_prepare(struct rockchip_panel *panel)
+{
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
+ int ret;
+
+ if (mcu_panel->prepared)
+ return;
+
+ if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
+ dm_gpio_set_value(&mcu_panel->enable_gpio, 1);
+
+ if (mcu_panel->desc->delay.prepare)
+ mdelay(mcu_panel->desc->delay.prepare);
+
+ if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
+ dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
+
+ if (mcu_panel->desc->delay.reset)
+ mdelay(mcu_panel->desc->delay.reset);
+
+ if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
+ dm_gpio_set_value(&mcu_panel->reset_gpio, 0);
+
+ if (mcu_panel->desc->delay.init)
+ mdelay(mcu_panel->desc->delay.init);
+
+ if (mcu_panel->desc->init_seq) {
+ ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->init_seq);
+ if (ret)
+ printf("failed to send mcu panel init cmds: %d\n", ret);
+ }
+
+ mcu_panel->prepared = true;
+}
+
+static void rockchip_mcu_panel_unprepare(struct rockchip_panel *panel)
+{
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
+ int ret;
+
+ if (!mcu_panel->prepared)
+ return;
+
+ if (mcu_panel->desc->exit_seq) {
+ ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->exit_seq);
+ if (ret)
+ printf("failed to send mcu panel exit cmds: %d\n", ret);
+ }
+
+ if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
+ dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
+
+ if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
+ dm_gpio_set_value(&mcu_panel->enable_gpio, 0);
+
+ if (mcu_panel->desc->delay.unprepare)
+ mdelay(mcu_panel->desc->delay.unprepare);
+
+ mcu_panel->prepared = false;
+}
+
+static void rockchip_mcu_panel_enable(struct rockchip_panel *panel)
+{
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
+
+ if (mcu_panel->enabled)
+ return;
+
+ if (mcu_panel->desc->delay.enable)
+ mdelay(mcu_panel->desc->delay.enable);
+
+ if (mcu_panel->backlight)
+ backlight_enable(mcu_panel->backlight);
+
+ mcu_panel->enabled = true;
+}
+
+static void rockchip_mcu_panel_disable(struct rockchip_panel *panel)
+{
+ struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
+
+ if (!mcu_panel->enabled)
+ return;
+
+ if (mcu_panel->backlight)
+ backlight_disable(mcu_panel->backlight);
+
+ if (mcu_panel->desc->delay.disable)
+ mdelay(mcu_panel->desc->delay.disable);
+
+ mcu_panel->enabled = false;
+}
+
+static const struct rockchip_panel_funcs rockchip_mcu_panel_funcs = {
+ .prepare = rockchip_mcu_panel_prepare,
+ .unprepare = rockchip_mcu_panel_unprepare,
+ .enable = rockchip_mcu_panel_enable,
+ .disable = rockchip_mcu_panel_disable,
+};
+
+static int rockchip_mcu_panel_parse_cmds(const u8 *data, int length,
+ struct mcu_cmd_seq *pcmds)
+{
+ int len;
+ const u8 *buf;
+ const struct mcu_cmd_header *header;
+ int i, cnt = 0;
+
+ /* scan commands */
+ cnt = 0;
+ buf = data;
+ len = length;
+ while (len > sizeof(*header)) {
+ header = (const struct mcu_cmd_header *)buf;
+ buf += sizeof(*header) + header->payload_length;
+ len -= sizeof(*header) + header->payload_length;
+ cnt++;
+ }
+
+ pcmds->cmds = calloc(cnt, sizeof(struct mcu_cmd_desc));
+ if (!pcmds->cmds)
+ return -ENOMEM;
+
+ pcmds->cmd_cnt = cnt;
+
+ buf = data;
+ len = length;
+ for (i = 0; i < cnt; i++) {
+ struct mcu_cmd_desc *desc = &pcmds->cmds[i];
+
+ header = (const struct mcu_cmd_header *)buf;
+ length -= sizeof(*header);
+ buf += sizeof(*header);
+ desc->header.data_type = header->data_type;
+ desc->header.delay = header->delay;
+ desc->header.payload_length = header->payload_length;
+ desc->payload = buf;
+ buf += header->payload_length;
+ length -= header->payload_length;
+ }
+
+ return 0;
+}
+
+static int rockchip_mcu_panel_init(struct rockchip_mcu_panel *mcu_panel, ofnode mcu_panel_node)
+{
+ const void *data;
+ int len;
+ int ret;
+
+ ret = gpio_request_by_name_nodev(mcu_panel_node, "enable-gpios", 0,
+ &mcu_panel->enable_gpio, GPIOD_IS_OUT);
+ if (ret && ret != -ENOENT) {
+ printf("%s: Cannot get mcu panel enable GPIO: %d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name_nodev(mcu_panel_node, "reset-gpios", 0,
+ &mcu_panel->reset_gpio, GPIOD_IS_OUT);
+ if (ret && ret != -ENOENT) {
+ printf("%s: Cannot get mcu panel reset GPIO: %d\n", __func__, ret);
+ return ret;
+ }
+
+ mcu_panel->desc = malloc(sizeof(struct rockchip_mcu_panel_desc));
+ if (!mcu_panel->desc)
+ return -ENOMEM;
+
+ mcu_panel->desc->power_invert = ofnode_read_bool(mcu_panel_node, "power-invert");
+
+ mcu_panel->desc->delay.prepare = ofnode_read_u32_default(mcu_panel_node, "prepare-delay-ms", 0);
+ mcu_panel->desc->delay.unprepare = ofnode_read_u32_default(mcu_panel_node, "unprepare-delay-ms", 0);
+ mcu_panel->desc->delay.enable = ofnode_read_u32_default(mcu_panel_node, "enable-delay-ms", 0);
+ mcu_panel->desc->delay.disable = ofnode_read_u32_default(mcu_panel_node, "disable-delay-ms", 0);
+ mcu_panel->desc->delay.init = ofnode_read_u32_default(mcu_panel_node, "init-delay-ms", 0);
+ mcu_panel->desc->delay.reset = ofnode_read_u32_default(mcu_panel_node, "reset-delay-ms", 0);
+
+ mcu_panel->desc->bus_format = ofnode_read_u32_default(mcu_panel_node, "bus-format",
+ MEDIA_BUS_FMT_RBG888_1X24);
+ mcu_panel->desc->bpc = ofnode_read_u32_default(mcu_panel_node, "bpc", 8);
+
+ data = ofnode_get_property(mcu_panel_node, "panel-init-sequence", &len);
+ if (data) {
+ mcu_panel->desc->init_seq = calloc(1, sizeof(*mcu_panel->desc->init_seq));
+ if (!mcu_panel->desc->init_seq)
+ return -ENOMEM;
+
+ ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->init_seq);
+ if (ret) {
+ printf("failed to parse panel init sequence\n");
+ goto free_on_cmds;
+ }
+ }
+
+ data = ofnode_get_property(mcu_panel_node, "panel-exit-sequence", &len);
+ if (data) {
+ mcu_panel->desc->exit_seq = calloc(1, sizeof(*mcu_panel->desc->exit_seq));
+ if (!mcu_panel->desc->exit_seq) {
+ ret = -ENOMEM;
+ goto free_on_cmds;
+ }
+
+ ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->exit_seq);
+ if (ret) {
+ printf("failed to parse panel exit sequence\n");
+ goto free_cmds;
+ }
+ }
+
+ return 0;
+
+free_cmds:
+ free(mcu_panel->desc->exit_seq);
+free_on_cmds:
+ free(mcu_panel->desc->init_seq);
+ return ret;
+}
+
static int rockchip_rgb_probe(struct udevice *dev)
{
struct rockchip_rgb *rgb = dev_get_priv(dev);
+ ofnode mcu_panel_node;
+ int phandle;
+ int ret;
rgb->dev = dev;
rgb->funcs = (const struct rockchip_rgb_funcs *)dev_get_driver_data(dev);
@@ -181,6 +490,45 @@
rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb");
if (rgb->id < 0)
rgb->id = 0;
+
+ mcu_panel_node = dev_read_subnode(dev, "mcu-panel");
+ if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) {
+ struct rockchip_mcu_panel *mcu_panel;
+
+ mcu_panel = malloc(sizeof(struct rockchip_mcu_panel));
+ if (!mcu_panel) {
+ printf("failed to alloc mcu_panel data\n");
+ return -ENOMEM;
+ }
+
+ ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node);
+ if (ret < 0) {
+ printf("failed to init mcu_panel: %d\n", ret);
+ return ret;
+ }
+
+ phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1);
+ if (phandle < 0) {
+ printf("failed to find backlight phandle\n");
+ return -EINVAL;
+ }
+
+ ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle,
+ &mcu_panel->backlight);
+ if (ret && ret != -ENOENT) {
+ printf("%s: failed to get backlight device: %d\n", __func__, ret);
+ return ret;
+ }
+
+ mcu_panel->base.dev = dev;
+ mcu_panel->base.bus_format = mcu_panel->desc->bus_format;
+ mcu_panel->base.bpc = mcu_panel->desc->bpc;
+ mcu_panel->base.funcs = &rockchip_mcu_panel_funcs;
+ mcu_panel->enabled = false;
+ mcu_panel->prepared = false;
+
+ rgb->connector.panel = &mcu_panel->base;
+ }
rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs,
NULL, DRM_MODE_CONNECTOR_LVDS);
@@ -260,6 +608,16 @@
.prepare = rk3368_rgb_prepare,
};
+static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
+{
+ regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON,
+ RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass));
+}
+
+static const struct rockchip_rgb_funcs rk3562_rgb_funcs = {
+ .prepare = rk3562_rgb_prepare,
+};
+
static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
{
regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass));
@@ -296,6 +654,10 @@
.data = (ulong)&rk3368_rgb_funcs,
},
{
+ .compatible = "rockchip,rk3562-rgb",
+ .data = (ulong)&rk3562_rgb_funcs,
+ },
+ {
.compatible = "rockchip,rk3568-rgb",
.data = (ulong)&rk3568_rgb_funcs,
},
--
Gitblit v1.6.2