From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 191 +++++++++++++++++++++++++++++++++--------------
1 files changed, 132 insertions(+), 59 deletions(-)
diff --git a/kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 463dcb5..3253cf2 100644
--- a/kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -17,6 +17,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_dsc.h>
#include <drm/drm_edid.h>
+#include <drm/drm_hdcp.h>
#include <drm/bridge/dw_hdmi.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
@@ -105,6 +106,8 @@
#define RK3588_HDMI1_LEVEL_INT BIT(24)
#define RK3588_HDMI1_INTR_CHANGE_CNT (0x7 << 21)
+#define RK3588_GRF_VO1_CON1 0x0004
+#define HDCP1_P1_GPIO_IN BIT(9)
#define RK3588_GRF_VO1_CON3 0x000c
#define RK3588_COLOR_FORMAT_MASK 0xf
#define RK3588_RGB 0
@@ -129,6 +132,8 @@
#define RK3588_HDMI0_GRANT_SW BIT(11)
#define RK3588_HDMI1_GRANT_SEL BIT(12)
#define RK3588_HDMI1_GRANT_SW BIT(13)
+#define RK3588_GRF_VO1_CON4 0x0010
+#define RK3588_HDMI_HDCP14_MEM_EN BIT(15)
#define RK3588_GRF_VO1_CON6 0x0018
#define RK3588_GRF_VO1_CON7 0x001c
@@ -197,7 +202,6 @@
u8 id;
bool hpd_stat;
bool is_hdmi_qp;
- bool user_split_mode;
unsigned long bus_format;
unsigned long output_bus_format;
@@ -215,9 +219,9 @@
struct drm_property *next_hdr_sink_data_property;
struct drm_property *output_hdmi_dvi;
struct drm_property *output_type_capacity;
- struct drm_property *user_split_mode_prop;
struct drm_property *allm_capacity;
struct drm_property *allm_enable;
+ struct drm_property *hdcp_state_property;
struct drm_property_blob *hdr_panel_blob_ptr;
struct drm_property_blob *next_hdr_data_ptr;
@@ -234,6 +238,7 @@
u8 max_lanes;
u8 add_func;
u8 edid_colorimetry;
+ u8 hdcp_status;
struct rockchip_drm_dsc_cap dsc_cap;
struct next_hdr_sink_data next_hdr_data;
struct dw_hdmi_link_config link_cfg;
@@ -851,7 +856,7 @@
struct drm_crtc_state *crtc_state,
unsigned int tmdsclk)
{
- struct drm_display_mode mode;
+ struct drm_display_mode mode = {};
int max_lanes, max_rate_per_lane;
int max_dsc_lanes, max_dsc_rate_per_lane;
unsigned long max_frl_rate;
@@ -1592,14 +1597,6 @@
struct drm_crtc *crtc;
struct rockchip_hdmi *hdmi;
- /*
- * Pixel clocks we support are always < 2GHz and so fit in an
- * int. We should make sure source rate does too so we don't get
- * overflow when we multiply by 1000.
- */
- if (mode->clock > INT_MAX / 1000)
- return MODE_BAD;
-
if (!encoder) {
const struct drm_connector_helper_funcs *funcs;
@@ -1615,6 +1612,21 @@
return MODE_BAD;
hdmi = to_rockchip_hdmi(encoder);
+
+ if (hdmi->is_hdmi_qp) {
+ if (!hdmi->enable_gpio && mode->clock > 600000)
+ return MODE_BAD;
+
+ return MODE_OK;
+ }
+
+ /*
+ * Pixel clocks we support are always < 2GHz and so fit in an
+ * int. We should make sure source rate does too so we don't get
+ * overflow when we multiply by 1000.
+ */
+ if (mode->clock > INT_MAX / 1000)
+ return MODE_BAD;
/*
* If sink max TMDS clock < 340MHz, we should check the mode pixel
@@ -1668,10 +1680,14 @@
{
struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
struct drm_crtc *crtc = encoder->crtc;
- struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
+ struct rockchip_crtc_state *s;
- if (WARN_ON(!crtc || !crtc->state))
+ if (!crtc || !crtc->state) {
+ dev_info(hdmi->dev, "%s old crtc state is null\n", __func__);
return;
+ }
+
+ s = to_rockchip_crtc_state(crtc->state);
if (crtc->state->active_changed) {
if (hdmi->plat_data->split_mode) {
@@ -1699,8 +1715,10 @@
int mux;
int ret;
- if (WARN_ON(!crtc || !crtc->state))
+ if (!crtc || !crtc->state) {
+ dev_info(hdmi->dev, "%s old crtc state is null\n", __func__);
return;
+ }
if (hdmi->phy)
phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width);
@@ -1878,6 +1896,26 @@
regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
}
+static void rk3588_set_hdcp_status(void *data, u8 status)
+{
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
+
+ hdmi->hdcp_status = status;
+}
+
+static void rk3588_set_hdcp2_enable(void *data, bool enable)
+{
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
+ u32 val;
+
+ if (enable)
+ val = HIWORD_UPDATE(HDCP1_P1_GPIO_IN, HDCP1_P1_GPIO_IN);
+ else
+ val = HIWORD_UPDATE(0, HDCP1_P1_GPIO_IN);
+
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON1, val);
+}
+
static void rk3588_set_grf_cfg(void *data)
{
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
@@ -1944,7 +1982,7 @@
unsigned int *eotf)
{
struct drm_display_info *info = &conn_state->connector->display_info;
- struct drm_display_mode mode;
+ struct drm_display_mode mode = {};
struct hdr_output_metadata *hdr_metadata;
u32 vic;
unsigned long tmdsclock, pixclock;
@@ -2027,11 +2065,6 @@
else
color_depth = 8;
- if (!sink_is_hdmi) {
- *color_format = RK_IF_FORMAT_RGB;
- color_depth = 8;
- }
-
*eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
if (conn_state->hdr_output_metadata) {
hdr_metadata = (struct hdr_output_metadata *)
@@ -2080,6 +2113,11 @@
if (hdmi->is_hdmi_qp && mode.clock >= 600000)
*color_format = RK_IF_FORMAT_YCBCR420;
+
+ if (!sink_is_hdmi) {
+ *color_format = RK_IF_FORMAT_RGB;
+ color_depth = 8;
+ }
if (*color_format == RK_IF_FORMAT_YCBCR422 || color_depth == 8)
tmdsclock = pixclock;
@@ -2199,7 +2237,7 @@
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
unsigned int colorformat, bus_width, tmdsclk;
- struct drm_display_mode mode;
+ struct drm_display_mode mode = {};
unsigned int output_mode;
unsigned long bus_format;
int color_depth;
@@ -2551,6 +2589,18 @@
}
}
+static void dw_hdmi_rockchip_set_hdcp14_mem(void *data, bool enable)
+{
+ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
+ u32 val;
+
+ val = HIWORD_UPDATE(enable << 15, RK3588_HDMI_HDCP14_MEM_EN);
+ if (!hdmi->id)
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val);
+ else
+ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val);
+}
+
static const struct drm_prop_enum_list color_depth_enum_list[] = {
{ 0, "Automatic" }, /* Prefer highest color depth */
{ 8, "24bit" },
@@ -2597,6 +2647,7 @@
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
struct drm_property *prop;
struct rockchip_drm_private *private = connector->dev->dev_private;
+ int ret;
switch (color) {
case MEDIA_BUS_FMT_RGB101010_1X30:
@@ -2711,30 +2762,24 @@
drm_object_attach_property(&connector->base, prop, 0);
}
- prop = drm_property_create_bool(connector->dev, DRM_MODE_PROP_IMMUTABLE,
- "USER_SPLIT_MODE");
- if (prop) {
- hdmi->user_split_mode_prop = prop;
- drm_object_attach_property(&connector->base, prop,
- hdmi->user_split_mode ? 1 : 0);
- }
+ if (hdmi->is_hdmi_qp) {
+ prop = drm_property_create_bool(connector->dev, 0, "allm_capacity");
+ if (prop) {
+ hdmi->allm_capacity = prop;
+ drm_object_attach_property(&connector->base, prop,
+ !!(hdmi->add_func & SUPPORT_HDMI_ALLM));
+ }
- prop = drm_property_create_bool(connector->dev, 0, "allm_capacity");
- if (prop) {
- hdmi->allm_capacity = prop;
- drm_object_attach_property(&connector->base, prop,
- !!(hdmi->add_func & SUPPORT_HDMI_ALLM));
+ prop = drm_property_create_enum(connector->dev, 0,
+ "allm_enable",
+ allm_enable_list,
+ ARRAY_SIZE(allm_enable_list));
+ if (prop) {
+ hdmi->allm_enable = prop;
+ drm_object_attach_property(&connector->base, prop, 0);
+ }
+ hdmi->enable_allm = allm_en;
}
-
- prop = drm_property_create_enum(connector->dev, 0,
- "allm_enable",
- allm_enable_list,
- ARRAY_SIZE(allm_enable_list));
- if (prop) {
- hdmi->allm_enable = prop;
- drm_object_attach_property(&connector->base, prop, 0);
- }
- hdmi->enable_allm = allm_en;
prop = drm_property_create_enum(connector->dev, 0,
"output_hdmi_dvi",
@@ -2773,6 +2818,21 @@
drm_object_attach_property(&connector->base,
connector->colorspace_property, 0);
drm_object_attach_property(&connector->base, private->connector_id_prop, hdmi->id);
+
+ ret = drm_connector_attach_content_protection_property(connector, true);
+ if (ret) {
+ dev_err(hdmi->dev, "failed to attach content protection: %d\n", ret);
+ return;
+ }
+
+ prop = drm_property_create_range(connector->dev, 0, RK_IF_PROP_ENCRYPTED,
+ RK_IF_HDCP_ENCRYPTED_NONE, RK_IF_HDCP_ENCRYPTED_LEVEL2);
+ if (!prop) {
+ dev_err(hdmi->dev, "create hdcp encrypted prop for hdmi%d failed\n", hdmi->id);
+ return;
+ }
+ hdmi->hdcp_state_property = prop;
+ drm_object_attach_property(&connector->base, prop, RK_IF_HDCP_ENCRYPTED_NONE);
}
static void
@@ -2833,12 +2893,6 @@
drm_property_destroy(connector->dev,
hdmi->output_type_capacity);
hdmi->output_type_capacity = NULL;
- }
-
- if (hdmi->user_split_mode_prop) {
- drm_property_destroy(connector->dev,
- hdmi->user_split_mode_prop);
- hdmi->user_split_mode_prop = NULL;
}
if (hdmi->allm_capacity) {
@@ -2913,6 +2967,8 @@
if (allm_enable != hdmi->enable_allm)
dw_hdmi_qp_set_allm_enable(hdmi->hdmi_qp, hdmi->enable_allm);
return 0;
+ } else if (property == hdmi->hdcp_state_property) {
+ return 0;
}
DRM_ERROR("Unknown property [PROP:%d:%s]\n",
@@ -2982,14 +3038,19 @@
else
*val = dw_hdmi_qp_get_output_type_cap(hdmi->hdmi_qp);
return 0;
- } else if (property == hdmi->user_split_mode_prop) {
- *val = hdmi->user_split_mode;
- return 0;
} else if (property == hdmi->allm_capacity) {
*val = !!(hdmi->add_func & SUPPORT_HDMI_ALLM);
return 0;
} else if (property == hdmi->allm_enable) {
*val = hdmi->enable_allm;
+ return 0;
+ } else if (property == hdmi->hdcp_state_property) {
+ if (hdmi->hdcp_status & BIT(1))
+ *val = RK_IF_HDCP_ENCRYPTED_LEVEL2;
+ else if (hdmi->hdcp_status & BIT(0))
+ *val = RK_IF_HDCP_ENCRYPTED_LEVEL1;
+ else
+ *val = RK_IF_HDCP_ENCRYPTED_NONE;
return 0;
}
@@ -3376,6 +3437,7 @@
};
static const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = {
+ .mode_valid = dw_hdmi_rockchip_mode_valid,
.phy_data = &rk3588_hdmi_chip_data,
.qp_phy_ops = &rk3588_hdmi_phy_ops,
.phy_name = "samsung_hdptx_phy",
@@ -3463,6 +3525,8 @@
plat_data->get_colorimetry =
dw_hdmi_rockchip_get_colorimetry;
plat_data->get_link_cfg = dw_hdmi_rockchip_get_link_cfg;
+ plat_data->set_hdcp2_enable = rk3588_set_hdcp2_enable;
+ plat_data->set_hdcp_status = rk3588_set_hdcp_status;
plat_data->set_grf_cfg = rk3588_set_grf_cfg;
plat_data->get_grf_color_fmt = rk3588_get_grf_color_fmt;
plat_data->convert_to_split_mode = drm_mode_convert_to_split_mode;
@@ -3478,6 +3542,8 @@
dw_hdmi_rockchip_set_prev_bus_format;
plat_data->set_ddc_io =
dw_hdmi_rockchip_set_ddc_io;
+ plat_data->set_hdcp14_mem =
+ dw_hdmi_rockchip_set_hdcp14_mem;
plat_data->property_ops = &dw_hdmi_rockchip_property_ops;
secondary = rockchip_hdmi_find_by_id(dev->driver, !hdmi->id);
@@ -3496,12 +3562,6 @@
secondary->plat_data->split_mode = true;
if (!secondary->plat_data->first_screen)
plat_data->first_screen = true;
- }
-
- if (device_property_read_bool(dev, "user-split-mode") ||
- device_property_read_bool(secondary->dev, "user-split-mode")) {
- hdmi->user_split_mode = true;
- secondary->user_split_mode = true;
}
}
@@ -3675,7 +3735,20 @@
drm_encoder_cleanup(&hdmi->encoder);
}
- if (plat_data->connector) {
+ if (plat_data->bridge) {
+ struct drm_connector *connector = NULL;
+ struct list_head *connector_list =
+ &plat_data->bridge->dev->mode_config.connector_list;
+
+ list_for_each_entry(connector, connector_list, head)
+ if (drm_connector_has_possible_encoder(connector,
+ &hdmi->encoder))
+ break;
+
+ hdmi->sub_dev.connector = connector;
+ hdmi->sub_dev.of_node = dev->of_node;
+ rockchip_drm_register_sub_dev(&hdmi->sub_dev);
+ } else if (plat_data->connector) {
hdmi->sub_dev.connector = plat_data->connector;
hdmi->sub_dev.loader_protect = dw_hdmi_rockchip_encoder_loader_protect;
if (secondary && device_property_read_bool(secondary->dev, "split-mode"))
--
Gitblit v1.6.2