From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 08:20:59 +0000 Subject: [PATCH] kernel_5.10 no rt --- kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 185 ++++++++++++++++++++++++++++++++-------------- 1 files changed, 129 insertions(+), 56 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..450b162 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; @@ -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; @@ -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; @@ -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