From 95099d4622f8cb224d94e314c7a8e0df60b13f87 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 08:38:01 +0000
Subject: [PATCH] enable docker ppp
---
kernel/drivers/gpu/drm/bridge/lontium-lt9611.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 95 insertions(+), 14 deletions(-)
diff --git a/kernel/drivers/gpu/drm/bridge/lontium-lt9611.c b/kernel/drivers/gpu/drm/bridge/lontium-lt9611.c
index 8ae33c6..1dcc28a 100644
--- a/kernel/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/kernel/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -11,13 +11,14 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
-#include <drm/drm_crtc_helper.h>
+
#include <sound/hdmi-codec.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
#define EDID_SEG_SIZE 256
#define EDID_LEN 32
@@ -46,6 +47,7 @@
struct gpio_desc *enable_gpio;
bool power_on;
+ bool sleep;
struct regulator_bulk_data supplies[2];
@@ -437,6 +439,26 @@
regmap_write(lt9611->regmap, 0x8207, 0x3f);
}
+static void lt9611_sleep_setup(struct lt9611 *lt9611)
+{
+ const struct reg_sequence sleep_setup[] = {
+ { 0x8024, 0x76 },
+ { 0x8023, 0x01 },
+ { 0x8157, 0x03 }, /* set addr pin as output */
+ { 0x8149, 0x0b },
+ { 0x8151, 0x30 }, /* disable IRQ */
+ { 0x8102, 0x48 }, /* MIPI Rx power down */
+ { 0x8123, 0x80 },
+ { 0x8130, 0x00 },
+ { 0x8100, 0x01 }, /* bandgap power down */
+ { 0x8101, 0x00 }, /* system clk power down */
+ };
+
+ regmap_multi_reg_write(lt9611->regmap,
+ sleep_setup, ARRAY_SIZE(sleep_setup));
+ lt9611->sleep = true;
+}
+
static int lt9611_power_on(struct lt9611 *lt9611)
{
int ret;
@@ -754,7 +776,8 @@
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
- dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_VIDEO_HSE;
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
@@ -793,20 +816,28 @@
drm_connector_helper_add(<9611->connector,
<9611_bridge_connector_helper_funcs);
- drm_connector_attach_encoder(<9611->connector, bridge->encoder);
if (!bridge->encoder) {
DRM_ERROR("Parent encoder object not found");
return -ENODEV;
}
+ drm_connector_attach_encoder(<9611->connector, bridge->encoder);
+
return 0;
}
-static int lt9611_bridge_attach(struct drm_bridge *bridge)
+static int lt9611_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
{
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
int ret;
+
+ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
+ ret = lt9611_connector_init(bridge, lt9611);
+ if (ret < 0)
+ return ret;
+ }
/* Attach primary DSI */
lt9611->dsi0 = lt9611_attach_dsi(lt9611, lt9611->dsi0_node);
@@ -822,9 +853,7 @@
}
}
- ret = lt9611_connector_init(bridge, lt9611);
-
- return ret;
+ return 0;
err_unregister_dsi0:
lt9611_bridge_detach(bridge);
@@ -835,30 +864,43 @@
}
static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
const struct drm_display_mode *mode)
{
struct lt9611_mode *lt9611_mode = lt9611_find_mode(mode);
+ struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
- return lt9611_mode ? MODE_OK : MODE_BAD;
+ if (!lt9611_mode)
+ return MODE_BAD;
+ else if (lt9611_mode->intfs > 1 && !lt9611->dsi1)
+ return MODE_PANEL;
+ else
+ return MODE_OK;
}
static void lt9611_bridge_pre_enable(struct drm_bridge *bridge)
{
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
+ if (!lt9611->sleep)
+ return;
+
lt9611_reset(lt9611);
regmap_write(lt9611->regmap, 0x80ee, 0x01);
- lt9611_enable_hpd_interrupts(lt9611);
+ lt9611->sleep = false;
}
static void lt9611_bridge_post_disable(struct drm_bridge *bridge)
{
+ struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
+
+ lt9611_sleep_setup(lt9611);
}
static void lt9611_bridge_mode_set(struct drm_bridge *bridge,
- struct drm_display_mode *mode,
- struct drm_display_mode *adj_mode)
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adj_mode)
{
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
struct hdmi_avi_infoframe avi_frame;
@@ -871,9 +913,42 @@
lt9611_mipi_video_setup(lt9611, mode);
lt9611_pcr_setup(lt9611, mode);
- ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame, mode, false);
+ ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame,
+ <9611->connector,
+ mode);
if (!ret)
lt9611->vic = avi_frame.video_code;
+}
+
+static enum drm_connector_status lt9611_bridge_detect(struct drm_bridge *bridge)
+{
+ struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
+ unsigned int reg_val = 0;
+ int connected;
+
+ regmap_read(lt9611->regmap, 0x825e, ®_val);
+ connected = reg_val & BIT(2);
+
+ lt9611->status = connected ? connector_status_connected :
+ connector_status_disconnected;
+
+ return lt9611->status;
+}
+
+static struct edid *lt9611_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
+
+ lt9611_power_on(lt9611);
+ return drm_do_get_edid(connector, lt9611_get_edid_block, lt9611);
+}
+
+static void lt9611_bridge_hpd_enable(struct drm_bridge *bridge)
+{
+ struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
+
+ lt9611_enable_hpd_interrupts(lt9611);
}
static const struct drm_bridge_funcs lt9611_bridge_funcs = {
@@ -884,6 +959,9 @@
.disable = lt9611_bridge_disable,
.post_disable = lt9611_bridge_post_disable,
.mode_set = lt9611_bridge_mode_set,
+ .detect = lt9611_bridge_detect,
+ .get_edid = lt9611_bridge_get_edid,
+ .hpd_enable = lt9611_bridge_hpd_enable,
};
static int lt9611_parse_dt(struct device *dev,
@@ -1050,6 +1128,7 @@
lt9611->dev = &client->dev;
lt9611->client = client;
+ lt9611->sleep = false;
lt9611->regmap = devm_regmap_init_i2c(client, <9611_regmap_config);
if (IS_ERR(lt9611->regmap)) {
@@ -1087,8 +1166,7 @@
ret = devm_request_threaded_irq(dev, client->irq, NULL,
lt9611_irq_thread_handler,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "lt9611", lt9611);
+ IRQF_ONESHOT, "lt9611", lt9611);
if (ret) {
dev_err(dev, "failed to request irq\n");
goto err_disable_regulators;
@@ -1098,6 +1176,9 @@
lt9611->bridge.funcs = <9611_bridge_funcs;
lt9611->bridge.of_node = client->dev.of_node;
+ lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
+ DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES;
+ lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
drm_bridge_add(<9611->bridge);
--
Gitblit v1.6.2