Loading drivers/gpu/drm/msm/dp/dp_catalog.c +96 −98 Original line number Diff line number Diff line Loading @@ -338,6 +338,7 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) struct drm_msm_ext_hdr_metadata *hdr; void __iomem *base; u32 header, parity, data; u8 buf[SZ_128], off = 0; if (!panel) { pr_err("invalid input\n"); Loading @@ -354,8 +355,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); dp_write(base + MMSS_DP_VSCEXT_0, data); pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_VSCEXT_0: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); /* HEADER BYTE 2 */ header = panel->hdr_data.vscext_header_byte2; Loading @@ -363,8 +364,6 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); dp_write(base + MMSS_DP_VSCEXT_1, data); pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_VSCEXT_1: 0x%x\n", data); /* HEADER BYTE 3 */ header = panel->hdr_data.vscext_header_byte3; Loading @@ -373,101 +372,71 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) | (parity << PARITY_BYTE_3_BIT)); data |= dp_read(base + MMSS_DP_VSCEXT_1); dp_write(base + MMSS_DP_VSCEXT_1, data); pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_VSCEXT_1: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = panel->hdr_data.version; data |= panel->hdr_data.length << 8; data |= hdr->eotf << 16; pr_debug("DP_VSCEXT_2: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_2, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->display_primaries_x[0]) | (DP_GET_MSB(hdr->display_primaries_x[0]) << 8) | (DP_GET_LSB(hdr->display_primaries_y[0]) << 16) | (DP_GET_MSB(hdr->display_primaries_y[0]) << 24)); pr_debug("DP_VSCEXT_3: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_3, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->display_primaries_x[1]) | (DP_GET_MSB(hdr->display_primaries_x[1]) << 8) | (DP_GET_LSB(hdr->display_primaries_y[1]) << 16) | (DP_GET_MSB(hdr->display_primaries_y[1]) << 24)); pr_debug("DP_VSCEXT_4: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_4, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->display_primaries_x[2]) | (DP_GET_MSB(hdr->display_primaries_x[2]) << 8) | (DP_GET_LSB(hdr->display_primaries_y[2]) << 16) | (DP_GET_MSB(hdr->display_primaries_y[2]) << 24)); pr_debug("DP_VSCEXT_5: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_5, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->white_point_x) | (DP_GET_MSB(hdr->white_point_x) << 8) | (DP_GET_LSB(hdr->white_point_y) << 16) | (DP_GET_MSB(hdr->white_point_y) << 24)); pr_debug("DP_VSCEXT_6: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_6, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->max_luminance) | (DP_GET_MSB(hdr->max_luminance) << 8) | (DP_GET_LSB(hdr->min_luminance) << 16) | (DP_GET_MSB(hdr->min_luminance) << 24)); pr_debug("DP_VSCEXT_7: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_7, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->max_content_light_level) | (DP_GET_MSB(hdr->max_content_light_level) << 8) | (DP_GET_LSB(hdr->max_average_light_level) << 16) | (DP_GET_MSB(hdr->max_average_light_level) << 24)); pr_debug("DP_VSCEXT_8: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_8, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_VSCEXT_9, 0x00); } static void dp_catalog_panel_setup_ext_sdp(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; void __iomem *base; u32 header, parity, data; data = 0; dp_write(base + MMSS_DP_VSCEXT_9, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); if (!panel) { pr_err("invalid input\n"); return; } dp_catalog_get_priv(panel); base = catalog->io->dp_link.base; /* HEADER BYTE 1 */ header = panel->hdr_data.ext_header_byte1; parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); dp_write(base + MMSS_DP_EXTENSION_0, data); pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_EXTENSION_0: 0x%x\n", data); /* HEADER BYTE 2 */ header = panel->hdr_data.ext_header_byte2; parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); dp_write(base + MMSS_DP_EXTENSION_1, data); pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_EXTENSION_1: 0x%x\n", data); dp_write(base + MMSS_DP_EXTENSION_1, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_2, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_3, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_4, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_5, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_6, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_7, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_8, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_9, 0x5AA55AA5); print_hex_dump(KERN_DEBUG, "[drm-dp] VSCEXT: ", DUMP_PREFIX_NONE, 16, 4, buf, off, false); } static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) Loading @@ -475,7 +444,8 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) struct dp_catalog_private *catalog; void __iomem *base; u32 header, parity, data; u8 bpc; u8 bpc, off = 0; u8 buf[SZ_128]; if (!panel) { pr_err("invalid input\n"); Loading @@ -483,7 +453,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) } dp_catalog_get_priv(panel); base = catalog->io->ctrl_io.base; base = catalog->io->dp_link.base; /* HEADER BYTE 1 */ header = panel->hdr_data.vsc_header_byte1; Loading @@ -491,8 +461,8 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); dp_write(base + MMSS_DP_GENERIC0_0, data); pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_GENERIC0_0: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); /* HEADER BYTE 2 */ header = panel->hdr_data.vsc_header_byte2; Loading @@ -500,8 +470,6 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); dp_write(base + MMSS_DP_GENERIC0_1, data); pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_GENERIC0_1: 0x%x\n", data); /* HEADER BYTE 3 */ header = panel->hdr_data.vsc_header_byte3; Loading @@ -510,14 +478,25 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) | (parity << PARITY_BYTE_3_BIT)); data |= dp_read(base + MMSS_DP_GENERIC0_1); dp_write(base + MMSS_DP_GENERIC0_1, data); pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_GENERIC0_1: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = 0; dp_write(base + MMSS_DP_GENERIC0_2, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_2, 0x00); dp_write(base + MMSS_DP_GENERIC0_3, 0x00); dp_write(base + MMSS_DP_GENERIC0_4, 0x00); dp_write(base + MMSS_DP_GENERIC0_5, 0x00); dp_write(base + MMSS_DP_GENERIC0_3, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_4, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_5, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); switch (panel->hdr_data.bpc) { default: Loading @@ -538,18 +517,32 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) ((panel->hdr_data.dynamic_range & 0x1) << 15) | ((panel->hdr_data.content_type & 0x7) << 16); pr_debug("DP_GENERIC0_6: 0x%x\n", data); dp_write(base + MMSS_DP_GENERIC0_6, data); dp_write(base + MMSS_DP_GENERIC0_7, 0x00); dp_write(base + MMSS_DP_GENERIC0_8, 0x00); dp_write(base + MMSS_DP_GENERIC0_9, 0x00); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = 0; dp_write(base + MMSS_DP_GENERIC0_7, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_8, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_9, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", DUMP_PREFIX_NONE, 16, 4, buf, off, false); } static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel) static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en) { struct dp_catalog_private *catalog; void __iomem *base; u32 cfg, cfg2; u32 cfg, cfg2, misc; if (!panel) { pr_err("invalid input\n"); Loading @@ -560,39 +553,44 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel) base = catalog->io->dp_link.base; cfg = dp_read(base + MMSS_DP_SDP_CFG); /* EXTENSION_SDP_EN */ cfg |= BIT(4); cfg2 = dp_read(base + MMSS_DP_SDP_CFG2); misc = dp_read(base + DP_MISC1_MISC0); /* VSCEXT_SDP_EN */ cfg |= BIT(16); if (en) { /* VSCEXT_SDP_EN, GEN0_SDP_EN */ cfg |= BIT(16) | BIT(17); dp_write(base + MMSS_DP_SDP_CFG, cfg); /* GEN0_SDP_EN */ cfg |= BIT(17); /* EXTN_SDPSIZE GENERIC0_SDPSIZE */ cfg2 |= BIT(15) | BIT(16); dp_write(base + MMSS_DP_SDP_CFG2, cfg2); /* GEN1_SDP_EN */ cfg |= BIT(18); dp_write(base + MMSS_DP_SDP_CFG, cfg); dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_setup_infoframe_sdp(panel); cfg2 = dp_read(base + MMSS_DP_SDP_CFG2); /* EXTN_SDPSIZE */ cfg2 |= BIT(15); /* indicates presence of VSC (BIT(6) of MISC1) */ misc |= BIT(14); /* GENERIC0_SDPSIZE */ cfg |= BIT(16); if (panel->hdr_data.hdr_meta.eotf) pr_debug("Enabled\n"); else pr_debug("Reset\n"); } else { /* VSCEXT_SDP_EN, GEN0_SDP_EN */ cfg &= ~BIT(16) & ~BIT(17); dp_write(base + MMSS_DP_SDP_CFG, cfg); /* GENERIC1_SDPSIZE */ cfg |= BIT(17); /* EXTN_SDPSIZE GENERIC0_SDPSIZE */ cfg2 &= ~BIT(15) & ~BIT(16); dp_write(base + MMSS_DP_SDP_CFG2, cfg2); dp_catalog_panel_setup_ext_sdp(panel); dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_setup_infoframe_sdp(panel); /* switch back to MSA */ misc &= ~BIT(14); cfg = dp_read(base + DP_MISC1_MISC0); /* Indicates presence of VSC */ cfg |= BIT(6) << 8; pr_debug("Disabled\n"); } dp_write(base + DP_MISC1_MISC0, cfg); dp_write(base + DP_MISC1_MISC0, misc); dp_write(base + MMSS_DP_SDP_CFG3, 0x01); dp_write(base + MMSS_DP_SDP_CFG3, 0x00); Loading drivers/gpu/drm/msm/dp/dp_catalog.h +1 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ struct dp_catalog_panel { u32 display_hctl; int (*timing_cfg)(struct dp_catalog_panel *panel); void (*config_hdr)(struct dp_catalog_panel *panel); void (*config_hdr)(struct dp_catalog_panel *panel, bool en); void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); void (*config_spd)(struct dp_catalog_panel *panel); }; Loading drivers/gpu/drm/msm/dp/dp_debug.c +212 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "dp_ctrl.h" #include "dp_debug.h" #include "drm_connector.h" #include "sde_connector.h" #include "dp_display.h" #define DEBUG_NAME "drm_dp" Loading Loading @@ -618,6 +619,201 @@ static ssize_t dp_debug_tpg_read(struct file *file, return len; } static ssize_t dp_debug_write_hdr(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct drm_connector *connector; struct sde_connector *c_conn; struct sde_connector_state *c_state; struct dp_debug_private *debug = file->private_data; char buf[SZ_1K]; size_t len = 0; if (!debug) return -ENODEV; if (*ppos) return 0; connector = *debug->connector; c_conn = to_sde_connector(connector); c_state = to_sde_connector_state(connector->state); /* Leave room for termination char */ len = min_t(size_t, count, SZ_1K - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", &c_state->hdr_meta.hdr_supported, &c_state->hdr_meta.hdr_state, &c_state->hdr_meta.eotf, &c_state->hdr_meta.display_primaries_x[0], &c_state->hdr_meta.display_primaries_x[1], &c_state->hdr_meta.display_primaries_x[2], &c_state->hdr_meta.display_primaries_y[0], &c_state->hdr_meta.display_primaries_y[1], &c_state->hdr_meta.display_primaries_y[2], &c_state->hdr_meta.white_point_x, &c_state->hdr_meta.white_point_y, &c_state->hdr_meta.max_luminance, &c_state->hdr_meta.min_luminance, &c_state->hdr_meta.max_content_light_level, &c_state->hdr_meta.max_average_light_level) != 15) { pr_err("invalid input\n"); len = -EINVAL; } end: return len; } static ssize_t dp_debug_read_hdr(struct file *file, char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char *buf; u32 len = 0, i; u32 max_size = SZ_4K; int rc = 0; struct drm_connector *connector; struct sde_connector *c_conn; struct sde_connector_state *c_state; struct drm_msm_ext_hdr_metadata *hdr; if (!debug) { pr_err("invalid data\n"); rc = -ENODEV; goto error; } connector = *debug->connector; if (!connector) { pr_err("connector is NULL\n"); rc = -EINVAL; goto error; } if (*ppos) goto error; buf = kzalloc(SZ_4K, GFP_KERNEL); if (!buf) { rc = -ENOMEM; goto error; } c_conn = to_sde_connector(connector); c_state = to_sde_connector_state(connector->state); hdr = &c_state->hdr_meta; rc = snprintf(buf + len, max_size, "============SINK HDR PARAMETERS===========\n"); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "eotf = %d\n", connector->hdr_eotf); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "type_one = %d\n", connector->hdr_metadata_type_one); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "max_luminance = %d\n", connector->hdr_max_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "avg_luminance = %d\n", connector->hdr_avg_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "min_luminance = %d\n", connector->hdr_min_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "============VIDEO HDR PARAMETERS===========\n"); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "hdr_state = %d\n", hdr->hdr_state); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "hdr_supported = %d\n", hdr->hdr_supported); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "eotf = %d\n", hdr->eotf); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "white_point_x = %d\n", hdr->white_point_x); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "white_point_y = %d\n", hdr->white_point_y); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "max_luminance = %d\n", hdr->max_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "min_luminance = %d\n", hdr->min_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "max_content_light_level = %d\n", hdr->max_content_light_level); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "min_content_light_level = %d\n", hdr->max_average_light_level); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; for (i = 0; i < HDR_PRIMARIES_COUNT; i++) { rc = snprintf(buf + len, max_size, "primaries_x[%d] = %d\n", i, hdr->display_primaries_x[i]); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "primaries_y[%d] = %d\n", i, hdr->display_primaries_y[i]); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; } if (copy_to_user(user_buff, buf, len)) { kfree(buf); rc = -EFAULT; goto error; } *ppos += len; kfree(buf); return len; error: return rc; } static const struct file_operations dp_debug_fops = { .open = simple_open, .read = dp_debug_read_info, Loading Loading @@ -661,6 +857,12 @@ static const struct file_operations tpg_fops = { .write = dp_debug_tpg_write, }; static const struct file_operations hdr_fops = { .open = simple_open, .write = dp_debug_write_hdr, .read = dp_debug_read_hdr, }; static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; Loading Loading @@ -753,6 +955,16 @@ static int dp_debug_init(struct dp_debug *dp_debug) goto error_remove_dir; } file = debugfs_create_file("hdr", 0644, dir, debug, &hdr_fops); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); pr_err("[%s] debugfs hdr failed, rc=%d\n", DEBUG_NAME, rc); goto error_remove_dir; } return 0; error_remove_dir: Loading drivers/gpu/drm/msm/dp/dp_display.c +5 −1 Original line number Diff line number Diff line Loading @@ -1196,6 +1196,7 @@ static int dp_display_get_modes(struct dp_display *dp, static int dp_display_pre_kickoff(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr) { int rc = 0; struct dp_display_private *dp; if (!dp_display) { Loading @@ -1205,7 +1206,10 @@ static int dp_display_pre_kickoff(struct dp_display *dp_display, dp = container_of(dp_display, struct dp_display_private, dp_display); return dp->panel->setup_hdr(dp->panel, hdr); if (hdr->hdr_supported) rc = dp->panel->setup_hdr(dp->panel, hdr); return rc; } static int dp_display_create_workqueue(struct dp_display_private *dp) Loading drivers/gpu/drm/msm/dp/dp_panel.c +68 −39 Original line number Diff line number Diff line Loading @@ -19,8 +19,41 @@ #define DP_PANEL_DEFAULT_BPP 24 #define DP_MAX_DS_PORT_COUNT 1 enum { DP_LINK_RATE_MULTIPLIER = 27000000, enum dp_panel_hdr_pixel_encoding { RGB, YCbCr444, YCbCr422, YCbCr420, YONLY, RAW, }; enum dp_panel_hdr_rgb_colorimetry { sRGB, RGB_WIDE_GAMUT_FIXED_POINT, RGB_WIDE_GAMUT_FLOATING_POINT, ADOBERGB, DCI_P3, CUSTOM_COLOR_PROFILE, ITU_R_BT_2020_RGB, }; enum dp_panel_hdr_dynamic_range { VESA, CEA, }; enum dp_panel_hdr_content_type { NOT_DEFINED, GRAPHICS, PHOTO, VIDEO, GAME, }; enum dp_panel_hdr_state { HDR_DISABLED, HDR_ENABLED, }; struct dp_panel_private { Loading @@ -32,6 +65,7 @@ struct dp_panel_private { bool custom_edid; bool custom_dpcd; bool panel_on; enum dp_panel_hdr_state hdr_state; u8 spd_vendor_name[8]; u8 spd_product_description[16]; }; Loading Loading @@ -621,37 +655,29 @@ static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel) return min_link_rate_khz; } enum dp_panel_hdr_pixel_encoding { RGB, YCbCr444, YCbCr422, YCbCr420, YONLY, RAW, }; static bool dp_panel_is_validate_hdr_state(struct dp_panel_private *panel, struct drm_msm_ext_hdr_metadata *hdr_meta) { struct drm_msm_ext_hdr_metadata *panel_hdr_meta = &panel->catalog->hdr_data.hdr_meta; enum dp_panel_hdr_rgb_colorimetry { sRGB, RGB_WIDE_GAMUT_FIXED_POINT, RGB_WIDE_GAMUT_FLOATING_POINT, ADOBERGB, DCI_P3, CUSTOM_COLOR_PROFILE, ITU_R_BT_2020_RGB, }; if (!hdr_meta) goto end; enum dp_panel_hdr_dynamic_range { VESA, CEA, }; /* bail out if HDR not active */ if (hdr_meta->hdr_state == HDR_DISABLED && panel->hdr_state == HDR_DISABLED) goto end; enum dp_panel_hdr_content_type { NOT_DEFINED, GRAPHICS, PHOTO, VIDEO, GAME, }; /* bail out if same meta data is received */ if (hdr_meta->hdr_state == HDR_ENABLED && panel_hdr_meta->eotf == hdr_meta->eotf) goto end; return true; end: return false; } static int dp_panel_setup_hdr(struct dp_panel *dp_panel, struct drm_msm_ext_hdr_metadata *hdr_meta) Loading @@ -660,9 +686,6 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, struct dp_panel_private *panel; struct dp_catalog_hdr_data *hdr; if (!hdr_meta || !hdr_meta->hdr_state) goto end; if (!dp_panel) { pr_err("invalid input\n"); rc = -EINVAL; Loading @@ -670,6 +693,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, } panel = container_of(dp_panel, struct dp_panel_private, dp_panel); if (!dp_panel_is_validate_hdr_state(panel, hdr_meta)) goto end; panel->hdr_state = hdr_meta->hdr_state; hdr = &panel->catalog->hdr_data; hdr->ext_header_byte0 = 0x00; Loading @@ -682,6 +711,11 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, hdr->vsc_header_byte2 = 0x05; hdr->vsc_header_byte3 = 0x13; hdr->vscext_header_byte0 = 0x00; hdr->vscext_header_byte1 = 0x87; hdr->vscext_header_byte2 = 0x1D; hdr->vscext_header_byte3 = 0x13 << 2; /* VSC SDP Payload for DB16 */ hdr->pixel_encoding = RGB; hdr->colorimetry = ITU_R_BT_2020_RGB; Loading @@ -694,17 +728,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, hdr->bpc = dp_panel->pinfo.bpp / 3; hdr->vscext_header_byte0 = 0x00; hdr->vscext_header_byte1 = 0x87; hdr->vscext_header_byte2 = 0x1D; hdr->vscext_header_byte3 = 0x13 << 2; hdr->version = 0x01; hdr->length = 0x1A; memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta)); panel->catalog->config_hdr(panel->catalog); panel->catalog->config_hdr(panel->catalog, panel->hdr_state); end: return rc; } Loading Loading
drivers/gpu/drm/msm/dp/dp_catalog.c +96 −98 Original line number Diff line number Diff line Loading @@ -338,6 +338,7 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) struct drm_msm_ext_hdr_metadata *hdr; void __iomem *base; u32 header, parity, data; u8 buf[SZ_128], off = 0; if (!panel) { pr_err("invalid input\n"); Loading @@ -354,8 +355,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); dp_write(base + MMSS_DP_VSCEXT_0, data); pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_VSCEXT_0: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); /* HEADER BYTE 2 */ header = panel->hdr_data.vscext_header_byte2; Loading @@ -363,8 +364,6 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); dp_write(base + MMSS_DP_VSCEXT_1, data); pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_VSCEXT_1: 0x%x\n", data); /* HEADER BYTE 3 */ header = panel->hdr_data.vscext_header_byte3; Loading @@ -373,101 +372,71 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel) | (parity << PARITY_BYTE_3_BIT)); data |= dp_read(base + MMSS_DP_VSCEXT_1); dp_write(base + MMSS_DP_VSCEXT_1, data); pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_VSCEXT_1: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = panel->hdr_data.version; data |= panel->hdr_data.length << 8; data |= hdr->eotf << 16; pr_debug("DP_VSCEXT_2: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_2, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->display_primaries_x[0]) | (DP_GET_MSB(hdr->display_primaries_x[0]) << 8) | (DP_GET_LSB(hdr->display_primaries_y[0]) << 16) | (DP_GET_MSB(hdr->display_primaries_y[0]) << 24)); pr_debug("DP_VSCEXT_3: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_3, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->display_primaries_x[1]) | (DP_GET_MSB(hdr->display_primaries_x[1]) << 8) | (DP_GET_LSB(hdr->display_primaries_y[1]) << 16) | (DP_GET_MSB(hdr->display_primaries_y[1]) << 24)); pr_debug("DP_VSCEXT_4: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_4, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->display_primaries_x[2]) | (DP_GET_MSB(hdr->display_primaries_x[2]) << 8) | (DP_GET_LSB(hdr->display_primaries_y[2]) << 16) | (DP_GET_MSB(hdr->display_primaries_y[2]) << 24)); pr_debug("DP_VSCEXT_5: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_5, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->white_point_x) | (DP_GET_MSB(hdr->white_point_x) << 8) | (DP_GET_LSB(hdr->white_point_y) << 16) | (DP_GET_MSB(hdr->white_point_y) << 24)); pr_debug("DP_VSCEXT_6: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_6, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->max_luminance) | (DP_GET_MSB(hdr->max_luminance) << 8) | (DP_GET_LSB(hdr->min_luminance) << 16) | (DP_GET_MSB(hdr->min_luminance) << 24)); pr_debug("DP_VSCEXT_7: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_7, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = (DP_GET_LSB(hdr->max_content_light_level) | (DP_GET_MSB(hdr->max_content_light_level) << 8) | (DP_GET_LSB(hdr->max_average_light_level) << 16) | (DP_GET_MSB(hdr->max_average_light_level) << 24)); pr_debug("DP_VSCEXT_8: 0x%x\n", data); dp_write(base + MMSS_DP_VSCEXT_8, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_VSCEXT_9, 0x00); } static void dp_catalog_panel_setup_ext_sdp(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; void __iomem *base; u32 header, parity, data; data = 0; dp_write(base + MMSS_DP_VSCEXT_9, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); if (!panel) { pr_err("invalid input\n"); return; } dp_catalog_get_priv(panel); base = catalog->io->dp_link.base; /* HEADER BYTE 1 */ header = panel->hdr_data.ext_header_byte1; parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); dp_write(base + MMSS_DP_EXTENSION_0, data); pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_EXTENSION_0: 0x%x\n", data); /* HEADER BYTE 2 */ header = panel->hdr_data.ext_header_byte2; parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); dp_write(base + MMSS_DP_EXTENSION_1, data); pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_EXTENSION_1: 0x%x\n", data); dp_write(base + MMSS_DP_EXTENSION_1, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_2, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_3, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_4, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_5, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_6, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_7, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_8, 0x5AA55AA5); dp_write(base + MMSS_DP_EXTENSION_9, 0x5AA55AA5); print_hex_dump(KERN_DEBUG, "[drm-dp] VSCEXT: ", DUMP_PREFIX_NONE, 16, 4, buf, off, false); } static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) Loading @@ -475,7 +444,8 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) struct dp_catalog_private *catalog; void __iomem *base; u32 header, parity, data; u8 bpc; u8 bpc, off = 0; u8 buf[SZ_128]; if (!panel) { pr_err("invalid input\n"); Loading @@ -483,7 +453,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) } dp_catalog_get_priv(panel); base = catalog->io->ctrl_io.base; base = catalog->io->dp_link.base; /* HEADER BYTE 1 */ header = panel->hdr_data.vsc_header_byte1; Loading @@ -491,8 +461,8 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); dp_write(base + MMSS_DP_GENERIC0_0, data); pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_GENERIC0_0: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); /* HEADER BYTE 2 */ header = panel->hdr_data.vsc_header_byte2; Loading @@ -500,8 +470,6 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); dp_write(base + MMSS_DP_GENERIC0_1, data); pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_GENERIC0_1: 0x%x\n", data); /* HEADER BYTE 3 */ header = panel->hdr_data.vsc_header_byte3; Loading @@ -510,14 +478,25 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) | (parity << PARITY_BYTE_3_BIT)); data |= dp_read(base + MMSS_DP_GENERIC0_1); dp_write(base + MMSS_DP_GENERIC0_1, data); pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity); pr_debug("DP_GENERIC0_1: 0x%x\n", data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = 0; dp_write(base + MMSS_DP_GENERIC0_2, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_2, 0x00); dp_write(base + MMSS_DP_GENERIC0_3, 0x00); dp_write(base + MMSS_DP_GENERIC0_4, 0x00); dp_write(base + MMSS_DP_GENERIC0_5, 0x00); dp_write(base + MMSS_DP_GENERIC0_3, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_4, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_5, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); switch (panel->hdr_data.bpc) { default: Loading @@ -538,18 +517,32 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) ((panel->hdr_data.dynamic_range & 0x1) << 15) | ((panel->hdr_data.content_type & 0x7) << 16); pr_debug("DP_GENERIC0_6: 0x%x\n", data); dp_write(base + MMSS_DP_GENERIC0_6, data); dp_write(base + MMSS_DP_GENERIC0_7, 0x00); dp_write(base + MMSS_DP_GENERIC0_8, 0x00); dp_write(base + MMSS_DP_GENERIC0_9, 0x00); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); data = 0; dp_write(base + MMSS_DP_GENERIC0_7, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_8, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); dp_write(base + MMSS_DP_GENERIC0_9, data); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", DUMP_PREFIX_NONE, 16, 4, buf, off, false); } static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel) static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en) { struct dp_catalog_private *catalog; void __iomem *base; u32 cfg, cfg2; u32 cfg, cfg2, misc; if (!panel) { pr_err("invalid input\n"); Loading @@ -560,39 +553,44 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel) base = catalog->io->dp_link.base; cfg = dp_read(base + MMSS_DP_SDP_CFG); /* EXTENSION_SDP_EN */ cfg |= BIT(4); cfg2 = dp_read(base + MMSS_DP_SDP_CFG2); misc = dp_read(base + DP_MISC1_MISC0); /* VSCEXT_SDP_EN */ cfg |= BIT(16); if (en) { /* VSCEXT_SDP_EN, GEN0_SDP_EN */ cfg |= BIT(16) | BIT(17); dp_write(base + MMSS_DP_SDP_CFG, cfg); /* GEN0_SDP_EN */ cfg |= BIT(17); /* EXTN_SDPSIZE GENERIC0_SDPSIZE */ cfg2 |= BIT(15) | BIT(16); dp_write(base + MMSS_DP_SDP_CFG2, cfg2); /* GEN1_SDP_EN */ cfg |= BIT(18); dp_write(base + MMSS_DP_SDP_CFG, cfg); dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_setup_infoframe_sdp(panel); cfg2 = dp_read(base + MMSS_DP_SDP_CFG2); /* EXTN_SDPSIZE */ cfg2 |= BIT(15); /* indicates presence of VSC (BIT(6) of MISC1) */ misc |= BIT(14); /* GENERIC0_SDPSIZE */ cfg |= BIT(16); if (panel->hdr_data.hdr_meta.eotf) pr_debug("Enabled\n"); else pr_debug("Reset\n"); } else { /* VSCEXT_SDP_EN, GEN0_SDP_EN */ cfg &= ~BIT(16) & ~BIT(17); dp_write(base + MMSS_DP_SDP_CFG, cfg); /* GENERIC1_SDPSIZE */ cfg |= BIT(17); /* EXTN_SDPSIZE GENERIC0_SDPSIZE */ cfg2 &= ~BIT(15) & ~BIT(16); dp_write(base + MMSS_DP_SDP_CFG2, cfg2); dp_catalog_panel_setup_ext_sdp(panel); dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_setup_infoframe_sdp(panel); /* switch back to MSA */ misc &= ~BIT(14); cfg = dp_read(base + DP_MISC1_MISC0); /* Indicates presence of VSC */ cfg |= BIT(6) << 8; pr_debug("Disabled\n"); } dp_write(base + DP_MISC1_MISC0, cfg); dp_write(base + DP_MISC1_MISC0, misc); dp_write(base + MMSS_DP_SDP_CFG3, 0x01); dp_write(base + MMSS_DP_SDP_CFG3, 0x00); Loading
drivers/gpu/drm/msm/dp/dp_catalog.h +1 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ struct dp_catalog_panel { u32 display_hctl; int (*timing_cfg)(struct dp_catalog_panel *panel); void (*config_hdr)(struct dp_catalog_panel *panel); void (*config_hdr)(struct dp_catalog_panel *panel, bool en); void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); void (*config_spd)(struct dp_catalog_panel *panel); }; Loading
drivers/gpu/drm/msm/dp/dp_debug.c +212 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "dp_ctrl.h" #include "dp_debug.h" #include "drm_connector.h" #include "sde_connector.h" #include "dp_display.h" #define DEBUG_NAME "drm_dp" Loading Loading @@ -618,6 +619,201 @@ static ssize_t dp_debug_tpg_read(struct file *file, return len; } static ssize_t dp_debug_write_hdr(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct drm_connector *connector; struct sde_connector *c_conn; struct sde_connector_state *c_state; struct dp_debug_private *debug = file->private_data; char buf[SZ_1K]; size_t len = 0; if (!debug) return -ENODEV; if (*ppos) return 0; connector = *debug->connector; c_conn = to_sde_connector(connector); c_state = to_sde_connector_state(connector->state); /* Leave room for termination char */ len = min_t(size_t, count, SZ_1K - 1); if (copy_from_user(buf, user_buff, len)) goto end; buf[len] = '\0'; if (sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", &c_state->hdr_meta.hdr_supported, &c_state->hdr_meta.hdr_state, &c_state->hdr_meta.eotf, &c_state->hdr_meta.display_primaries_x[0], &c_state->hdr_meta.display_primaries_x[1], &c_state->hdr_meta.display_primaries_x[2], &c_state->hdr_meta.display_primaries_y[0], &c_state->hdr_meta.display_primaries_y[1], &c_state->hdr_meta.display_primaries_y[2], &c_state->hdr_meta.white_point_x, &c_state->hdr_meta.white_point_y, &c_state->hdr_meta.max_luminance, &c_state->hdr_meta.min_luminance, &c_state->hdr_meta.max_content_light_level, &c_state->hdr_meta.max_average_light_level) != 15) { pr_err("invalid input\n"); len = -EINVAL; } end: return len; } static ssize_t dp_debug_read_hdr(struct file *file, char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; char *buf; u32 len = 0, i; u32 max_size = SZ_4K; int rc = 0; struct drm_connector *connector; struct sde_connector *c_conn; struct sde_connector_state *c_state; struct drm_msm_ext_hdr_metadata *hdr; if (!debug) { pr_err("invalid data\n"); rc = -ENODEV; goto error; } connector = *debug->connector; if (!connector) { pr_err("connector is NULL\n"); rc = -EINVAL; goto error; } if (*ppos) goto error; buf = kzalloc(SZ_4K, GFP_KERNEL); if (!buf) { rc = -ENOMEM; goto error; } c_conn = to_sde_connector(connector); c_state = to_sde_connector_state(connector->state); hdr = &c_state->hdr_meta; rc = snprintf(buf + len, max_size, "============SINK HDR PARAMETERS===========\n"); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "eotf = %d\n", connector->hdr_eotf); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "type_one = %d\n", connector->hdr_metadata_type_one); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "max_luminance = %d\n", connector->hdr_max_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "avg_luminance = %d\n", connector->hdr_avg_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "min_luminance = %d\n", connector->hdr_min_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "============VIDEO HDR PARAMETERS===========\n"); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "hdr_state = %d\n", hdr->hdr_state); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "hdr_supported = %d\n", hdr->hdr_supported); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "eotf = %d\n", hdr->eotf); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "white_point_x = %d\n", hdr->white_point_x); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "white_point_y = %d\n", hdr->white_point_y); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "max_luminance = %d\n", hdr->max_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "min_luminance = %d\n", hdr->min_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "max_content_light_level = %d\n", hdr->max_content_light_level); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "min_content_light_level = %d\n", hdr->max_average_light_level); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; for (i = 0; i < HDR_PRIMARIES_COUNT; i++) { rc = snprintf(buf + len, max_size, "primaries_x[%d] = %d\n", i, hdr->display_primaries_x[i]); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; rc = snprintf(buf + len, max_size, "primaries_y[%d] = %d\n", i, hdr->display_primaries_y[i]); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; } if (copy_to_user(user_buff, buf, len)) { kfree(buf); rc = -EFAULT; goto error; } *ppos += len; kfree(buf); return len; error: return rc; } static const struct file_operations dp_debug_fops = { .open = simple_open, .read = dp_debug_read_info, Loading Loading @@ -661,6 +857,12 @@ static const struct file_operations tpg_fops = { .write = dp_debug_tpg_write, }; static const struct file_operations hdr_fops = { .open = simple_open, .write = dp_debug_write_hdr, .read = dp_debug_read_hdr, }; static int dp_debug_init(struct dp_debug *dp_debug) { int rc = 0; Loading Loading @@ -753,6 +955,16 @@ static int dp_debug_init(struct dp_debug *dp_debug) goto error_remove_dir; } file = debugfs_create_file("hdr", 0644, dir, debug, &hdr_fops); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); pr_err("[%s] debugfs hdr failed, rc=%d\n", DEBUG_NAME, rc); goto error_remove_dir; } return 0; error_remove_dir: Loading
drivers/gpu/drm/msm/dp/dp_display.c +5 −1 Original line number Diff line number Diff line Loading @@ -1196,6 +1196,7 @@ static int dp_display_get_modes(struct dp_display *dp, static int dp_display_pre_kickoff(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr) { int rc = 0; struct dp_display_private *dp; if (!dp_display) { Loading @@ -1205,7 +1206,10 @@ static int dp_display_pre_kickoff(struct dp_display *dp_display, dp = container_of(dp_display, struct dp_display_private, dp_display); return dp->panel->setup_hdr(dp->panel, hdr); if (hdr->hdr_supported) rc = dp->panel->setup_hdr(dp->panel, hdr); return rc; } static int dp_display_create_workqueue(struct dp_display_private *dp) Loading
drivers/gpu/drm/msm/dp/dp_panel.c +68 −39 Original line number Diff line number Diff line Loading @@ -19,8 +19,41 @@ #define DP_PANEL_DEFAULT_BPP 24 #define DP_MAX_DS_PORT_COUNT 1 enum { DP_LINK_RATE_MULTIPLIER = 27000000, enum dp_panel_hdr_pixel_encoding { RGB, YCbCr444, YCbCr422, YCbCr420, YONLY, RAW, }; enum dp_panel_hdr_rgb_colorimetry { sRGB, RGB_WIDE_GAMUT_FIXED_POINT, RGB_WIDE_GAMUT_FLOATING_POINT, ADOBERGB, DCI_P3, CUSTOM_COLOR_PROFILE, ITU_R_BT_2020_RGB, }; enum dp_panel_hdr_dynamic_range { VESA, CEA, }; enum dp_panel_hdr_content_type { NOT_DEFINED, GRAPHICS, PHOTO, VIDEO, GAME, }; enum dp_panel_hdr_state { HDR_DISABLED, HDR_ENABLED, }; struct dp_panel_private { Loading @@ -32,6 +65,7 @@ struct dp_panel_private { bool custom_edid; bool custom_dpcd; bool panel_on; enum dp_panel_hdr_state hdr_state; u8 spd_vendor_name[8]; u8 spd_product_description[16]; }; Loading Loading @@ -621,37 +655,29 @@ static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel) return min_link_rate_khz; } enum dp_panel_hdr_pixel_encoding { RGB, YCbCr444, YCbCr422, YCbCr420, YONLY, RAW, }; static bool dp_panel_is_validate_hdr_state(struct dp_panel_private *panel, struct drm_msm_ext_hdr_metadata *hdr_meta) { struct drm_msm_ext_hdr_metadata *panel_hdr_meta = &panel->catalog->hdr_data.hdr_meta; enum dp_panel_hdr_rgb_colorimetry { sRGB, RGB_WIDE_GAMUT_FIXED_POINT, RGB_WIDE_GAMUT_FLOATING_POINT, ADOBERGB, DCI_P3, CUSTOM_COLOR_PROFILE, ITU_R_BT_2020_RGB, }; if (!hdr_meta) goto end; enum dp_panel_hdr_dynamic_range { VESA, CEA, }; /* bail out if HDR not active */ if (hdr_meta->hdr_state == HDR_DISABLED && panel->hdr_state == HDR_DISABLED) goto end; enum dp_panel_hdr_content_type { NOT_DEFINED, GRAPHICS, PHOTO, VIDEO, GAME, }; /* bail out if same meta data is received */ if (hdr_meta->hdr_state == HDR_ENABLED && panel_hdr_meta->eotf == hdr_meta->eotf) goto end; return true; end: return false; } static int dp_panel_setup_hdr(struct dp_panel *dp_panel, struct drm_msm_ext_hdr_metadata *hdr_meta) Loading @@ -660,9 +686,6 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, struct dp_panel_private *panel; struct dp_catalog_hdr_data *hdr; if (!hdr_meta || !hdr_meta->hdr_state) goto end; if (!dp_panel) { pr_err("invalid input\n"); rc = -EINVAL; Loading @@ -670,6 +693,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, } panel = container_of(dp_panel, struct dp_panel_private, dp_panel); if (!dp_panel_is_validate_hdr_state(panel, hdr_meta)) goto end; panel->hdr_state = hdr_meta->hdr_state; hdr = &panel->catalog->hdr_data; hdr->ext_header_byte0 = 0x00; Loading @@ -682,6 +711,11 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, hdr->vsc_header_byte2 = 0x05; hdr->vsc_header_byte3 = 0x13; hdr->vscext_header_byte0 = 0x00; hdr->vscext_header_byte1 = 0x87; hdr->vscext_header_byte2 = 0x1D; hdr->vscext_header_byte3 = 0x13 << 2; /* VSC SDP Payload for DB16 */ hdr->pixel_encoding = RGB; hdr->colorimetry = ITU_R_BT_2020_RGB; Loading @@ -694,17 +728,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, hdr->bpc = dp_panel->pinfo.bpp / 3; hdr->vscext_header_byte0 = 0x00; hdr->vscext_header_byte1 = 0x87; hdr->vscext_header_byte2 = 0x1D; hdr->vscext_header_byte3 = 0x13 << 2; hdr->version = 0x01; hdr->length = 0x1A; memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta)); panel->catalog->config_hdr(panel->catalog); panel->catalog->config_hdr(panel->catalog, panel->hdr_state); end: return rc; } Loading