Loading msm/dp/dp_catalog.c +169 −91 Original line number Original line Diff line number Diff line Loading @@ -6,7 +6,6 @@ #include <linux/delay.h> #include <linux/delay.h> #include <linux/iopoll.h> #include <linux/iopoll.h> #include <drm/drm_dp_helper.h> #include "dp_catalog.h" #include "dp_catalog.h" #include "dp_reg.h" #include "dp_reg.h" Loading Loading @@ -478,6 +477,29 @@ static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl) return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS); return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS); } } static void dp_catalog_panel_sdp_update(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 sdp_cfg3_off = 0; if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream_id:%d\n", panel->stream_id); return; } if (panel->stream_id == DP_STREAM_1) sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x01); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x00); } static void dp_catalog_panel_setup_vsif_infoframe_sdp( static void dp_catalog_panel_setup_vsif_infoframe_sdp( struct dp_catalog_panel *panel) struct dp_catalog_panel *panel) { { Loading @@ -496,11 +518,11 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp( mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0; mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0; catalog = dp_catalog_get_priv(panel); catalog = dp_catalog_get_priv(panel); hdr = &panel->hdr_data.hdr_meta; hdr = &panel->hdr_meta; io_data = catalog->io.dp_link; io_data = catalog->io.dp_link; /* HEADER BYTE 1 */ /* HEADER BYTE 1 */ header = panel->hdr_data.vscext_header_byte1; header = panel->dhdr_vsif_sdp.HB1; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); | (parity << PARITY_BYTE_1_BIT)); Loading @@ -510,7 +532,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp( off += sizeof(data); off += sizeof(data); /* HEADER BYTE 2 */ /* HEADER BYTE 2 */ header = panel->hdr_data.vscext_header_byte2; header = panel->dhdr_vsif_sdp.HB2; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); | (parity << PARITY_BYTE_2_BIT)); Loading @@ -518,7 +540,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp( data); data); /* HEADER BYTE 3 */ /* HEADER BYTE 3 */ header = panel->hdr_data.vscext_header_byte3; header = panel->dhdr_vsif_sdp.HB3; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_3_BIT) data = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT)); | (parity << PARITY_BYTE_3_BIT)); Loading @@ -541,6 +563,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( struct dp_io_data *io_data; struct dp_io_data *io_data; u32 header, parity, data, mst_offset = 0; u32 header, parity, data, mst_offset = 0; u8 buf[SZ_64], off = 0; u8 buf[SZ_64], off = 0; u32 const version = 0x01; u32 const length = 0x1a; if (panel->stream_id >= DP_STREAM_MAX) { if (panel->stream_id >= DP_STREAM_MAX) { DP_ERR("invalid stream_id:%d\n", panel->stream_id); DP_ERR("invalid stream_id:%d\n", panel->stream_id); Loading @@ -551,11 +575,11 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0; mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0; catalog = dp_catalog_get_priv(panel); catalog = dp_catalog_get_priv(panel); hdr = &panel->hdr_data.hdr_meta; hdr = &panel->hdr_meta; io_data = catalog->io.dp_link; io_data = catalog->io.dp_link; /* HEADER BYTE 1 */ /* HEADER BYTE 1 */ header = panel->hdr_data.shdr_header_byte1; header = panel->shdr_if_sdp.HB1; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); | (parity << PARITY_BYTE_1_BIT)); Loading @@ -565,7 +589,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( off += sizeof(data); off += sizeof(data); /* HEADER BYTE 2 */ /* HEADER BYTE 2 */ header = panel->hdr_data.shdr_header_byte2; header = panel->shdr_if_sdp.HB2; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); | (parity << PARITY_BYTE_2_BIT)); Loading @@ -573,7 +597,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( data); data); /* HEADER BYTE 3 */ /* HEADER BYTE 3 */ header = panel->hdr_data.shdr_header_byte3; header = panel->shdr_if_sdp.HB3; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_3_BIT) data = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT)); | (parity << PARITY_BYTE_3_BIT)); Loading @@ -584,8 +608,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( memcpy(buf + off, &data, sizeof(data)); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); off += sizeof(data); data = panel->hdr_data.version; data = version; data |= panel->hdr_data.length << 8; data |= length << 8; data |= hdr->eotf << 16; data |= hdr->eotf << 16; dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset, dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset, data); data); Loading Loading @@ -661,7 +685,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) struct dp_catalog_private *catalog; struct dp_catalog_private *catalog; struct dp_io_data *io_data; struct dp_io_data *io_data; u32 header, parity, data, mst_offset = 0; u32 header, parity, data, mst_offset = 0; u8 bpc, off = 0; u8 off = 0; u8 buf[SZ_128]; u8 buf[SZ_128]; if (!panel) { if (!panel) { Loading @@ -681,7 +705,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) io_data = catalog->io.dp_link; io_data = catalog->io.dp_link; /* HEADER BYTE 1 */ /* HEADER BYTE 1 */ header = panel->hdr_data.vsc_header_byte1; header = panel->vsc_colorimetry.header.HB1; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); | (parity << PARITY_BYTE_1_BIT)); Loading @@ -691,7 +715,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) off += sizeof(data); off += sizeof(data); /* HEADER BYTE 2 */ /* HEADER BYTE 2 */ header = panel->hdr_data.vsc_header_byte2; header = panel->vsc_colorimetry.header.HB2; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); | (parity << PARITY_BYTE_2_BIT)); Loading @@ -699,7 +723,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) data); data); /* HEADER BYTE 3 */ /* HEADER BYTE 3 */ header = panel->hdr_data.vsc_header_byte3; header = panel->vsc_colorimetry.header.HB3; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_3_BIT) data = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT)); | (parity << PARITY_BYTE_3_BIT)); Loading Loading @@ -731,24 +755,9 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) memcpy(buf + off, &data, sizeof(data)); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); off += sizeof(data); switch (panel->hdr_data.bpc) { data = (panel->vsc_colorimetry.data[16] & 0xFF) | default: ((panel->vsc_colorimetry.data[17] & 0xFF) << 8) | case 10: ((panel->vsc_colorimetry.data[18] & 0x7) << 16); bpc = BIT(1); break; case 8: bpc = BIT(0); break; case 6: bpc = 0; break; } data = (panel->hdr_data.colorimetry & 0xF) | ((panel->hdr_data.pixel_encoding & 0xF) << 4) | (bpc << 8) | ((panel->hdr_data.dynamic_range & 0x1) << 15) | ((panel->hdr_data.content_type & 0x7) << 16); dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset, dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset, data); data); Loading @@ -775,15 +784,125 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) DUMP_PREFIX_NONE, 16, 4, buf, off, false); DUMP_PREFIX_NONE, 16, 4, buf, off, false); } } static void dp_catalog_panel_config_sdp(struct dp_catalog_panel *panel, bool en) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 cfg, cfg2; u32 sdp_cfg_off = 0; u32 sdp_cfg2_off = 0; if (panel->stream_id >= DP_STREAM_MAX) { DP_ERR("invalid stream_id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (panel->stream_id == DP_STREAM_1) { sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; } cfg = dp_read(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off); cfg2 = dp_read(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off); if (en) { /* GEN0_SDP_EN */ cfg |= BIT(17); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE */ cfg2 |= BIT(16); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); /* setup the GENERIC0 in case of en = true */ dp_catalog_panel_setup_vsc_sdp(panel); } else { /* GEN0_SDP_EN */ cfg &= ~BIT(17); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE */ cfg2 &= ~BIT(16); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); } dp_catalog_panel_sdp_update(panel); } static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 reg_offset = 0; if (!panel) { pr_err("invalid input\n"); return; } if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream_id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (panel->stream_id == DP_STREAM_1) reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0; DP_DEBUG("misc settings = 0x%x\n", panel->misc_val); dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset, panel->misc_val); } static int dp_catalog_panel_set_colorspace(struct dp_catalog_panel *panel, bool vsc_supported) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; if (!panel) { pr_err("invalid input\n"); return -EINVAL; } if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream_id:%d\n", panel->stream_id); return -EINVAL; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (vsc_supported) { dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_sdp_update(panel); } else dp_catalog_panel_config_misc(panel); return 0; } static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, u32 dhdr_max_pkts) u32 dhdr_max_pkts, bool flush) { { struct dp_catalog_private *catalog; struct dp_catalog_private *catalog; struct dp_io_data *io_data; struct dp_io_data *io_data; u32 cfg, cfg2, cfg4, misc; u32 cfg, cfg2, cfg4, misc; u32 sdp_cfg_off = 0; u32 sdp_cfg_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg3_off = 0; u32 sdp_cfg4_off = 0; u32 sdp_cfg4_off = 0; u32 misc1_misc0_off = 0; u32 misc1_misc0_off = 0; Loading @@ -803,7 +922,6 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, if (panel->stream_id == DP_STREAM_1) { if (panel->stream_id == DP_STREAM_1) { sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4; sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4; misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0; misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0; } } Loading @@ -826,34 +944,30 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, dp_catalog_panel_setup_vsif_infoframe_sdp(panel); dp_catalog_panel_setup_vsif_infoframe_sdp(panel); } } /* GEN0_SDP_EN, GEN2_SDP_EN */ /* GEN2_SDP_EN */ cfg |= BIT(17) | BIT(19); cfg |= BIT(19); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ /* GENERIC2_SDPSIZE */ cfg2 |= BIT(16) | BIT(20); cfg2 |= BIT(20); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_setup_hdr_infoframe_sdp(panel); dp_catalog_panel_setup_hdr_infoframe_sdp(panel); /* indicates presence of VSC (BIT(6) of MISC1) */ if (panel->hdr_meta.eotf) misc |= BIT(14); if (panel->hdr_data.hdr_meta.eotf) DP_DEBUG("Enabled\n"); DP_DEBUG("Enabled\n"); else else DP_DEBUG("Reset\n"); DP_DEBUG("Reset\n"); } else { } else { /* VSCEXT_SDP_EN, GEN0_SDP_EN */ /* VSCEXT_SDP_ENG */ cfg &= ~BIT(16) & ~BIT(17) & ~BIT(19); cfg &= ~BIT(16) & ~BIT(19); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ cfg2 &= ~BIT(16) & ~BIT(20); cfg2 &= ~BIT(20); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); Loading @@ -862,19 +976,13 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4 dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4 + sdp_cfg4_off, cfg4); + sdp_cfg4_off, cfg4); /* switch back to MSA */ misc &= ~BIT(14); DP_DEBUG("Disabled\n"); DP_DEBUG("Disabled\n"); } } dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + misc1_misc0_off, if (flush) { misc); DP_DEBUG("flushing HDR metadata\n"); dp_catalog_panel_sdp_update(panel); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, } 0x01); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x00); } } static void dp_catalog_panel_update_transfer_unit( static void dp_catalog_panel_update_transfer_unit( Loading Loading @@ -1109,33 +1217,6 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl, } } } } static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 reg_offset = 0; if (!panel) { DP_ERR("invalid input\n"); return; } if (panel->stream_id >= DP_STREAM_MAX) { DP_ERR("invalid stream_id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (panel->stream_id == DP_STREAM_1) reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0; DP_DEBUG("misc settings = 0x%x\n", panel->misc_val); dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset, panel->misc_val); } static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel, static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel, u32 rate, u32 stream_rate_khz) u32 rate, u32 stream_rate_khz) { { Loading Loading @@ -2494,7 +2575,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel) u32 offset = 0; u32 offset = 0; u32 sdp_cfg_off = 0; u32 sdp_cfg_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg3_off = 0; /* /* * Source Device Information * Source Device Information Loading Loading @@ -2567,7 +2647,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel) if (panel->stream_id == DP_STREAM_1) { if (panel->stream_id == DP_STREAM_1) { sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; } } spd_cfg = dp_read(catalog->exe_mode, io_data, spd_cfg = dp_read(catalog->exe_mode, io_data, Loading @@ -2584,10 +2663,7 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel) dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, spd_cfg2); spd_cfg2); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, dp_catalog_panel_sdp_update(panel); 0x1); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x0); } } static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog) static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog) Loading Loading @@ -2745,9 +2821,11 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) struct dp_catalog_panel panel = { struct dp_catalog_panel panel = { .timing_cfg = dp_catalog_panel_timing_cfg, .timing_cfg = dp_catalog_panel_timing_cfg, .config_hdr = dp_catalog_panel_config_hdr, .config_hdr = dp_catalog_panel_config_hdr, .config_sdp = dp_catalog_panel_config_sdp, .tpg_config = dp_catalog_panel_tpg_cfg, .tpg_config = dp_catalog_panel_tpg_cfg, .config_spd = dp_catalog_panel_config_spd, .config_spd = dp_catalog_panel_config_spd, .config_misc = dp_catalog_panel_config_misc, .config_misc = dp_catalog_panel_config_misc, .set_colorspace = dp_catalog_panel_set_colorspace, .config_msa = dp_catalog_panel_config_msa, .config_msa = dp_catalog_panel_config_msa, .update_transfer_unit = dp_catalog_panel_update_transfer_unit, .update_transfer_unit = dp_catalog_panel_update_transfer_unit, .config_ctrl = dp_catalog_panel_config_ctrl, .config_ctrl = dp_catalog_panel_config_ctrl, Loading msm/dp/dp_catalog.h +12 −28 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ #ifndef _DP_CATALOG_H_ #ifndef _DP_CATALOG_H_ #define _DP_CATALOG_H_ #define _DP_CATALOG_H_ #include <drm/drm_dp_helper.h> #include <drm/msm_drm.h> #include <drm/msm_drm.h> #include "dp_parser.h" #include "dp_parser.h" Loading Loading @@ -39,32 +40,9 @@ enum dp_stream_id { DP_STREAM_MAX, DP_STREAM_MAX, }; }; struct dp_catalog_hdr_data { struct dp_catalog_vsc_sdp_colorimetry { u32 vsc_header_byte0; struct dp_sdp_header header; u32 vsc_header_byte1; u8 data[32]; u32 vsc_header_byte2; u32 vsc_header_byte3; u32 vscext_header_byte0; u32 vscext_header_byte1; u32 vscext_header_byte2; u32 vscext_header_byte3; u32 shdr_header_byte0; u32 shdr_header_byte1; u32 shdr_header_byte2; u32 shdr_header_byte3; u32 bpc; u32 version; u32 length; u32 pixel_encoding; u32 colorimetry; u32 dynamic_range; u32 content_type; struct drm_msm_ext_hdr_metadata hdr_meta; }; }; struct dp_catalog_aux { struct dp_catalog_aux { Loading Loading @@ -197,7 +175,10 @@ struct dp_catalog_panel { u8 *spd_vendor_name; u8 *spd_vendor_name; u8 *spd_product_description; u8 *spd_product_description; struct dp_catalog_hdr_data hdr_data; struct dp_catalog_vsc_sdp_colorimetry vsc_colorimetry; struct dp_sdp_header dhdr_vsif_sdp; struct dp_sdp_header shdr_if_sdp; struct drm_msm_ext_hdr_metadata hdr_meta; /* TPG */ /* TPG */ u32 hsync_period; u32 hsync_period; Loading @@ -222,7 +203,10 @@ struct dp_catalog_panel { int (*timing_cfg)(struct dp_catalog_panel *panel); int (*timing_cfg)(struct dp_catalog_panel *panel); void (*config_hdr)(struct dp_catalog_panel *panel, bool en, void (*config_hdr)(struct dp_catalog_panel *panel, bool en, u32 dhdr_max_pkts); u32 dhdr_max_pkts, bool flush); void (*config_sdp)(struct dp_catalog_panel *panel, bool en); int (*set_colorspace)(struct dp_catalog_panel *panel, bool vsc_supported); void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); void (*config_spd)(struct dp_catalog_panel *panel); void (*config_spd)(struct dp_catalog_panel *panel); void (*config_misc)(struct dp_catalog_panel *panel); void (*config_misc)(struct dp_catalog_panel *panel); Loading msm/dp/dp_display.c +45 −2 Original line number Original line Diff line number Diff line Loading @@ -1627,7 +1627,7 @@ static void dp_display_stream_post_enable(struct dp_display_private *dp, struct dp_panel *dp_panel) struct dp_panel *dp_panel) { { dp_panel->spd_config(dp_panel); dp_panel->spd_config(dp_panel); dp_panel->setup_hdr(dp_panel, NULL, false, 0); dp_panel->setup_hdr(dp_panel, NULL, false, 0, true); } } static int dp_display_post_enable(struct dp_display *dp_display, void *panel) static int dp_display_post_enable(struct dp_display *dp_display, void *panel) Loading Loading @@ -1676,6 +1676,14 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) return 0; return 0; } } static void dp_display_clear_colorspaces(struct dp_display *dp_display) { struct drm_connector *connector; connector = dp_display->base_connector; connector->color_enc_fmt = 0; } static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) { { struct dp_display_private *dp; struct dp_display_private *dp; Loading Loading @@ -1732,6 +1740,8 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) } } } } dp_display_clear_colorspaces(dp_display); clean: clean: if (dp_panel->audio_supported) if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); dp_panel->audio->off(dp_panel->audio); Loading Loading @@ -2082,8 +2092,10 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update) struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update) { { struct dp_panel *dp_panel; struct dp_panel *dp_panel; struct sde_connector *sde_conn; struct dp_display_private *dp; struct dp_display_private *dp; u64 core_clk_rate; u64 core_clk_rate; bool flush_hdr; if (!dp_display || !panel) { if (!dp_display || !panel) { DP_ERR("invalid input\n"); DP_ERR("invalid input\n"); Loading @@ -2092,6 +2104,7 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, dp_panel = panel; dp_panel = panel; dp = container_of(dp_display, struct dp_display_private, dp_display); dp = container_of(dp_display, struct dp_display_private, dp_display); sde_conn = to_sde_connector(dp_panel->connector); core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk"); core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk"); if (!core_clk_rate) { if (!core_clk_rate) { Loading @@ -2099,7 +2112,36 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, return -EINVAL; return -EINVAL; } } return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate); /* * In rare cases where HDR metadata is updated independently * flush the HDR metadata immediately instead of relying on * the colorspace */ flush_hdr = !sde_conn->colorspace_updated; if (flush_hdr) DP_DEBUG("flushing the HDR metadata\n"); else DP_DEBUG("piggy-backing with colorspace\n"); return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate, flush_hdr); } static int dp_display_setup_colospace(struct dp_display *dp_display, void *panel, u32 colorspace) { struct dp_panel *dp_panel; if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp_panel = panel; return dp_panel->set_colorspace(dp_panel, colorspace); } } static int dp_display_create_workqueue(struct dp_display_private *dp) static int dp_display_create_workqueue(struct dp_display_private *dp) Loading Loading @@ -2623,6 +2665,7 @@ static int dp_display_probe(struct platform_device *pdev) dp_display_mst_get_fixed_topology_port; dp_display_mst_get_fixed_topology_port; g_dp_display->wakeup_phy_layer = g_dp_display->wakeup_phy_layer = dp_display_wakeup_phy_layer; dp_display_wakeup_phy_layer; g_dp_display->set_colorspace = dp_display_setup_colospace; rc = component_add(&pdev->dev, &dp_display_comp_ops); rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { if (rc) { Loading msm/dp/dp_display.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,8 @@ struct dp_display { int (*config_hdr)(struct dp_display *dp_display, void *panel, int (*config_hdr)(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr_meta, struct drm_msm_ext_hdr_metadata *hdr_meta, bool dhdr_update); bool dhdr_update); int (*set_colorspace)(struct dp_display *dp_display, void *panel, u32 colorspace); int (*post_init)(struct dp_display *dp_display); int (*post_init)(struct dp_display *dp_display); int (*mst_install)(struct dp_display *dp_display, int (*mst_install)(struct dp_display *dp_display, struct dp_mst_drm_install_info *mst_install_info); struct dp_mst_drm_install_info *mst_install_info); Loading msm/dp/dp_drm.c +45 −0 Original line number Original line Diff line number Diff line Loading @@ -326,6 +326,25 @@ int dp_connector_config_hdr(struct drm_connector *connector, void *display, c_state->dyn_hdr_meta.dynamic_hdr_update); c_state->dyn_hdr_meta.dynamic_hdr_update); } } int dp_connector_set_colorspace(struct drm_connector *connector, void *display) { struct dp_display *dp_display = display; struct sde_connector *sde_conn; if (!dp_display || !connector) return -EINVAL; sde_conn = to_sde_connector(connector); if (!sde_conn->drv_panel) { pr_err("invalid dp panel\n"); return -EINVAL; } return dp_display->set_colorspace(dp_display, sde_conn->drv_panel, connector->state->colorspace); } int dp_connector_post_init(struct drm_connector *connector, void *display) int dp_connector_post_init(struct drm_connector *connector, void *display) { { int rc; int rc; Loading Loading @@ -469,6 +488,32 @@ void dp_connector_post_open(struct drm_connector *connector, void *display) dp->post_open(dp); dp->post_open(dp); } } int dp_connector_atomic_check(struct drm_connector *connector, void *display, struct drm_connector_state *c_state) { struct sde_connector *sde_conn; struct drm_connector_state *old_state = drm_atomic_get_old_connector_state(c_state->state, connector); if (!connector || !display) return -EINVAL; sde_conn = to_sde_connector(connector); /* * Marking the colorspace has been changed * the flag shall be checked in the pre_kickoff * to configure the new colorspace in HW */ if (c_state->colorspace != old_state->colorspace) { DP_DEBUG("colorspace has been updated\n"); sde_conn->colorspace_updated = true; } return 0; } int dp_connector_get_modes(struct drm_connector *connector, int dp_connector_get_modes(struct drm_connector *connector, void *display, const struct msm_resource_caps_info *avail_res) void *display, const struct msm_resource_caps_info *avail_res) { { Loading Loading
msm/dp/dp_catalog.c +169 −91 Original line number Original line Diff line number Diff line Loading @@ -6,7 +6,6 @@ #include <linux/delay.h> #include <linux/delay.h> #include <linux/iopoll.h> #include <linux/iopoll.h> #include <drm/drm_dp_helper.h> #include "dp_catalog.h" #include "dp_catalog.h" #include "dp_reg.h" #include "dp_reg.h" Loading Loading @@ -478,6 +477,29 @@ static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl) return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS); return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS); } } static void dp_catalog_panel_sdp_update(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 sdp_cfg3_off = 0; if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream_id:%d\n", panel->stream_id); return; } if (panel->stream_id == DP_STREAM_1) sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x01); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x00); } static void dp_catalog_panel_setup_vsif_infoframe_sdp( static void dp_catalog_panel_setup_vsif_infoframe_sdp( struct dp_catalog_panel *panel) struct dp_catalog_panel *panel) { { Loading @@ -496,11 +518,11 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp( mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0; mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0; catalog = dp_catalog_get_priv(panel); catalog = dp_catalog_get_priv(panel); hdr = &panel->hdr_data.hdr_meta; hdr = &panel->hdr_meta; io_data = catalog->io.dp_link; io_data = catalog->io.dp_link; /* HEADER BYTE 1 */ /* HEADER BYTE 1 */ header = panel->hdr_data.vscext_header_byte1; header = panel->dhdr_vsif_sdp.HB1; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); | (parity << PARITY_BYTE_1_BIT)); Loading @@ -510,7 +532,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp( off += sizeof(data); off += sizeof(data); /* HEADER BYTE 2 */ /* HEADER BYTE 2 */ header = panel->hdr_data.vscext_header_byte2; header = panel->dhdr_vsif_sdp.HB2; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); | (parity << PARITY_BYTE_2_BIT)); Loading @@ -518,7 +540,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp( data); data); /* HEADER BYTE 3 */ /* HEADER BYTE 3 */ header = panel->hdr_data.vscext_header_byte3; header = panel->dhdr_vsif_sdp.HB3; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_3_BIT) data = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT)); | (parity << PARITY_BYTE_3_BIT)); Loading @@ -541,6 +563,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( struct dp_io_data *io_data; struct dp_io_data *io_data; u32 header, parity, data, mst_offset = 0; u32 header, parity, data, mst_offset = 0; u8 buf[SZ_64], off = 0; u8 buf[SZ_64], off = 0; u32 const version = 0x01; u32 const length = 0x1a; if (panel->stream_id >= DP_STREAM_MAX) { if (panel->stream_id >= DP_STREAM_MAX) { DP_ERR("invalid stream_id:%d\n", panel->stream_id); DP_ERR("invalid stream_id:%d\n", panel->stream_id); Loading @@ -551,11 +575,11 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0; mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0; catalog = dp_catalog_get_priv(panel); catalog = dp_catalog_get_priv(panel); hdr = &panel->hdr_data.hdr_meta; hdr = &panel->hdr_meta; io_data = catalog->io.dp_link; io_data = catalog->io.dp_link; /* HEADER BYTE 1 */ /* HEADER BYTE 1 */ header = panel->hdr_data.shdr_header_byte1; header = panel->shdr_if_sdp.HB1; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); | (parity << PARITY_BYTE_1_BIT)); Loading @@ -565,7 +589,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( off += sizeof(data); off += sizeof(data); /* HEADER BYTE 2 */ /* HEADER BYTE 2 */ header = panel->hdr_data.shdr_header_byte2; header = panel->shdr_if_sdp.HB2; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); | (parity << PARITY_BYTE_2_BIT)); Loading @@ -573,7 +597,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( data); data); /* HEADER BYTE 3 */ /* HEADER BYTE 3 */ header = panel->hdr_data.shdr_header_byte3; header = panel->shdr_if_sdp.HB3; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_3_BIT) data = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT)); | (parity << PARITY_BYTE_3_BIT)); Loading @@ -584,8 +608,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp( memcpy(buf + off, &data, sizeof(data)); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); off += sizeof(data); data = panel->hdr_data.version; data = version; data |= panel->hdr_data.length << 8; data |= length << 8; data |= hdr->eotf << 16; data |= hdr->eotf << 16; dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset, dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset, data); data); Loading Loading @@ -661,7 +685,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) struct dp_catalog_private *catalog; struct dp_catalog_private *catalog; struct dp_io_data *io_data; struct dp_io_data *io_data; u32 header, parity, data, mst_offset = 0; u32 header, parity, data, mst_offset = 0; u8 bpc, off = 0; u8 off = 0; u8 buf[SZ_128]; u8 buf[SZ_128]; if (!panel) { if (!panel) { Loading @@ -681,7 +705,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) io_data = catalog->io.dp_link; io_data = catalog->io.dp_link; /* HEADER BYTE 1 */ /* HEADER BYTE 1 */ header = panel->hdr_data.vsc_header_byte1; header = panel->vsc_colorimetry.header.HB1; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_1_BIT) data = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT)); | (parity << PARITY_BYTE_1_BIT)); Loading @@ -691,7 +715,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) off += sizeof(data); off += sizeof(data); /* HEADER BYTE 2 */ /* HEADER BYTE 2 */ header = panel->hdr_data.vsc_header_byte2; header = panel->vsc_colorimetry.header.HB2; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_2_BIT) data = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT)); | (parity << PARITY_BYTE_2_BIT)); Loading @@ -699,7 +723,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) data); data); /* HEADER BYTE 3 */ /* HEADER BYTE 3 */ header = panel->hdr_data.vsc_header_byte3; header = panel->vsc_colorimetry.header.HB3; parity = dp_header_get_parity(header); parity = dp_header_get_parity(header); data = ((header << HEADER_BYTE_3_BIT) data = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT)); | (parity << PARITY_BYTE_3_BIT)); Loading Loading @@ -731,24 +755,9 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) memcpy(buf + off, &data, sizeof(data)); memcpy(buf + off, &data, sizeof(data)); off += sizeof(data); off += sizeof(data); switch (panel->hdr_data.bpc) { data = (panel->vsc_colorimetry.data[16] & 0xFF) | default: ((panel->vsc_colorimetry.data[17] & 0xFF) << 8) | case 10: ((panel->vsc_colorimetry.data[18] & 0x7) << 16); bpc = BIT(1); break; case 8: bpc = BIT(0); break; case 6: bpc = 0; break; } data = (panel->hdr_data.colorimetry & 0xF) | ((panel->hdr_data.pixel_encoding & 0xF) << 4) | (bpc << 8) | ((panel->hdr_data.dynamic_range & 0x1) << 15) | ((panel->hdr_data.content_type & 0x7) << 16); dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset, dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset, data); data); Loading @@ -775,15 +784,125 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) DUMP_PREFIX_NONE, 16, 4, buf, off, false); DUMP_PREFIX_NONE, 16, 4, buf, off, false); } } static void dp_catalog_panel_config_sdp(struct dp_catalog_panel *panel, bool en) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 cfg, cfg2; u32 sdp_cfg_off = 0; u32 sdp_cfg2_off = 0; if (panel->stream_id >= DP_STREAM_MAX) { DP_ERR("invalid stream_id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (panel->stream_id == DP_STREAM_1) { sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; } cfg = dp_read(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off); cfg2 = dp_read(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off); if (en) { /* GEN0_SDP_EN */ cfg |= BIT(17); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE */ cfg2 |= BIT(16); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); /* setup the GENERIC0 in case of en = true */ dp_catalog_panel_setup_vsc_sdp(panel); } else { /* GEN0_SDP_EN */ cfg &= ~BIT(17); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE */ cfg2 &= ~BIT(16); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); } dp_catalog_panel_sdp_update(panel); } static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 reg_offset = 0; if (!panel) { pr_err("invalid input\n"); return; } if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream_id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (panel->stream_id == DP_STREAM_1) reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0; DP_DEBUG("misc settings = 0x%x\n", panel->misc_val); dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset, panel->misc_val); } static int dp_catalog_panel_set_colorspace(struct dp_catalog_panel *panel, bool vsc_supported) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; if (!panel) { pr_err("invalid input\n"); return -EINVAL; } if (panel->stream_id >= DP_STREAM_MAX) { pr_err("invalid stream_id:%d\n", panel->stream_id); return -EINVAL; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (vsc_supported) { dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_sdp_update(panel); } else dp_catalog_panel_config_misc(panel); return 0; } static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, u32 dhdr_max_pkts) u32 dhdr_max_pkts, bool flush) { { struct dp_catalog_private *catalog; struct dp_catalog_private *catalog; struct dp_io_data *io_data; struct dp_io_data *io_data; u32 cfg, cfg2, cfg4, misc; u32 cfg, cfg2, cfg4, misc; u32 sdp_cfg_off = 0; u32 sdp_cfg_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg3_off = 0; u32 sdp_cfg4_off = 0; u32 sdp_cfg4_off = 0; u32 misc1_misc0_off = 0; u32 misc1_misc0_off = 0; Loading @@ -803,7 +922,6 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, if (panel->stream_id == DP_STREAM_1) { if (panel->stream_id == DP_STREAM_1) { sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4; sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4; misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0; misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0; } } Loading @@ -826,34 +944,30 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, dp_catalog_panel_setup_vsif_infoframe_sdp(panel); dp_catalog_panel_setup_vsif_infoframe_sdp(panel); } } /* GEN0_SDP_EN, GEN2_SDP_EN */ /* GEN2_SDP_EN */ cfg |= BIT(17) | BIT(19); cfg |= BIT(19); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ /* GENERIC2_SDPSIZE */ cfg2 |= BIT(16) | BIT(20); cfg2 |= BIT(20); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); dp_catalog_panel_setup_vsc_sdp(panel); dp_catalog_panel_setup_hdr_infoframe_sdp(panel); dp_catalog_panel_setup_hdr_infoframe_sdp(panel); /* indicates presence of VSC (BIT(6) of MISC1) */ if (panel->hdr_meta.eotf) misc |= BIT(14); if (panel->hdr_data.hdr_meta.eotf) DP_DEBUG("Enabled\n"); DP_DEBUG("Enabled\n"); else else DP_DEBUG("Reset\n"); DP_DEBUG("Reset\n"); } else { } else { /* VSCEXT_SDP_EN, GEN0_SDP_EN */ /* VSCEXT_SDP_ENG */ cfg &= ~BIT(16) & ~BIT(17) & ~BIT(19); cfg &= ~BIT(16) & ~BIT(19); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ cfg2 &= ~BIT(16) & ~BIT(20); cfg2 &= ~BIT(20); dp_write(catalog->exe_mode, io_data, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); Loading @@ -862,19 +976,13 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4 dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4 + sdp_cfg4_off, cfg4); + sdp_cfg4_off, cfg4); /* switch back to MSA */ misc &= ~BIT(14); DP_DEBUG("Disabled\n"); DP_DEBUG("Disabled\n"); } } dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + misc1_misc0_off, if (flush) { misc); DP_DEBUG("flushing HDR metadata\n"); dp_catalog_panel_sdp_update(panel); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, } 0x01); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x00); } } static void dp_catalog_panel_update_transfer_unit( static void dp_catalog_panel_update_transfer_unit( Loading Loading @@ -1109,33 +1217,6 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl, } } } } static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel) { struct dp_catalog_private *catalog; struct dp_io_data *io_data; u32 reg_offset = 0; if (!panel) { DP_ERR("invalid input\n"); return; } if (panel->stream_id >= DP_STREAM_MAX) { DP_ERR("invalid stream_id:%d\n", panel->stream_id); return; } catalog = dp_catalog_get_priv(panel); io_data = catalog->io.dp_link; if (panel->stream_id == DP_STREAM_1) reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0; DP_DEBUG("misc settings = 0x%x\n", panel->misc_val); dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset, panel->misc_val); } static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel, static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel, u32 rate, u32 stream_rate_khz) u32 rate, u32 stream_rate_khz) { { Loading Loading @@ -2494,7 +2575,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel) u32 offset = 0; u32 offset = 0; u32 sdp_cfg_off = 0; u32 sdp_cfg_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg2_off = 0; u32 sdp_cfg3_off = 0; /* /* * Source Device Information * Source Device Information Loading Loading @@ -2567,7 +2647,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel) if (panel->stream_id == DP_STREAM_1) { if (panel->stream_id == DP_STREAM_1) { sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; } } spd_cfg = dp_read(catalog->exe_mode, io_data, spd_cfg = dp_read(catalog->exe_mode, io_data, Loading @@ -2584,10 +2663,7 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel) dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, spd_cfg2); spd_cfg2); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, dp_catalog_panel_sdp_update(panel); 0x1); dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, 0x0); } } static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog) static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog) Loading Loading @@ -2745,9 +2821,11 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) struct dp_catalog_panel panel = { struct dp_catalog_panel panel = { .timing_cfg = dp_catalog_panel_timing_cfg, .timing_cfg = dp_catalog_panel_timing_cfg, .config_hdr = dp_catalog_panel_config_hdr, .config_hdr = dp_catalog_panel_config_hdr, .config_sdp = dp_catalog_panel_config_sdp, .tpg_config = dp_catalog_panel_tpg_cfg, .tpg_config = dp_catalog_panel_tpg_cfg, .config_spd = dp_catalog_panel_config_spd, .config_spd = dp_catalog_panel_config_spd, .config_misc = dp_catalog_panel_config_misc, .config_misc = dp_catalog_panel_config_misc, .set_colorspace = dp_catalog_panel_set_colorspace, .config_msa = dp_catalog_panel_config_msa, .config_msa = dp_catalog_panel_config_msa, .update_transfer_unit = dp_catalog_panel_update_transfer_unit, .update_transfer_unit = dp_catalog_panel_update_transfer_unit, .config_ctrl = dp_catalog_panel_config_ctrl, .config_ctrl = dp_catalog_panel_config_ctrl, Loading
msm/dp/dp_catalog.h +12 −28 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ #ifndef _DP_CATALOG_H_ #ifndef _DP_CATALOG_H_ #define _DP_CATALOG_H_ #define _DP_CATALOG_H_ #include <drm/drm_dp_helper.h> #include <drm/msm_drm.h> #include <drm/msm_drm.h> #include "dp_parser.h" #include "dp_parser.h" Loading Loading @@ -39,32 +40,9 @@ enum dp_stream_id { DP_STREAM_MAX, DP_STREAM_MAX, }; }; struct dp_catalog_hdr_data { struct dp_catalog_vsc_sdp_colorimetry { u32 vsc_header_byte0; struct dp_sdp_header header; u32 vsc_header_byte1; u8 data[32]; u32 vsc_header_byte2; u32 vsc_header_byte3; u32 vscext_header_byte0; u32 vscext_header_byte1; u32 vscext_header_byte2; u32 vscext_header_byte3; u32 shdr_header_byte0; u32 shdr_header_byte1; u32 shdr_header_byte2; u32 shdr_header_byte3; u32 bpc; u32 version; u32 length; u32 pixel_encoding; u32 colorimetry; u32 dynamic_range; u32 content_type; struct drm_msm_ext_hdr_metadata hdr_meta; }; }; struct dp_catalog_aux { struct dp_catalog_aux { Loading Loading @@ -197,7 +175,10 @@ struct dp_catalog_panel { u8 *spd_vendor_name; u8 *spd_vendor_name; u8 *spd_product_description; u8 *spd_product_description; struct dp_catalog_hdr_data hdr_data; struct dp_catalog_vsc_sdp_colorimetry vsc_colorimetry; struct dp_sdp_header dhdr_vsif_sdp; struct dp_sdp_header shdr_if_sdp; struct drm_msm_ext_hdr_metadata hdr_meta; /* TPG */ /* TPG */ u32 hsync_period; u32 hsync_period; Loading @@ -222,7 +203,10 @@ struct dp_catalog_panel { int (*timing_cfg)(struct dp_catalog_panel *panel); int (*timing_cfg)(struct dp_catalog_panel *panel); void (*config_hdr)(struct dp_catalog_panel *panel, bool en, void (*config_hdr)(struct dp_catalog_panel *panel, bool en, u32 dhdr_max_pkts); u32 dhdr_max_pkts, bool flush); void (*config_sdp)(struct dp_catalog_panel *panel, bool en); int (*set_colorspace)(struct dp_catalog_panel *panel, bool vsc_supported); void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); void (*config_spd)(struct dp_catalog_panel *panel); void (*config_spd)(struct dp_catalog_panel *panel); void (*config_misc)(struct dp_catalog_panel *panel); void (*config_misc)(struct dp_catalog_panel *panel); Loading
msm/dp/dp_display.c +45 −2 Original line number Original line Diff line number Diff line Loading @@ -1627,7 +1627,7 @@ static void dp_display_stream_post_enable(struct dp_display_private *dp, struct dp_panel *dp_panel) struct dp_panel *dp_panel) { { dp_panel->spd_config(dp_panel); dp_panel->spd_config(dp_panel); dp_panel->setup_hdr(dp_panel, NULL, false, 0); dp_panel->setup_hdr(dp_panel, NULL, false, 0, true); } } static int dp_display_post_enable(struct dp_display *dp_display, void *panel) static int dp_display_post_enable(struct dp_display *dp_display, void *panel) Loading Loading @@ -1676,6 +1676,14 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) return 0; return 0; } } static void dp_display_clear_colorspaces(struct dp_display *dp_display) { struct drm_connector *connector; connector = dp_display->base_connector; connector->color_enc_fmt = 0; } static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) { { struct dp_display_private *dp; struct dp_display_private *dp; Loading Loading @@ -1732,6 +1740,8 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) } } } } dp_display_clear_colorspaces(dp_display); clean: clean: if (dp_panel->audio_supported) if (dp_panel->audio_supported) dp_panel->audio->off(dp_panel->audio); dp_panel->audio->off(dp_panel->audio); Loading Loading @@ -2082,8 +2092,10 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update) struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update) { { struct dp_panel *dp_panel; struct dp_panel *dp_panel; struct sde_connector *sde_conn; struct dp_display_private *dp; struct dp_display_private *dp; u64 core_clk_rate; u64 core_clk_rate; bool flush_hdr; if (!dp_display || !panel) { if (!dp_display || !panel) { DP_ERR("invalid input\n"); DP_ERR("invalid input\n"); Loading @@ -2092,6 +2104,7 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, dp_panel = panel; dp_panel = panel; dp = container_of(dp_display, struct dp_display_private, dp_display); dp = container_of(dp_display, struct dp_display_private, dp_display); sde_conn = to_sde_connector(dp_panel->connector); core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk"); core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk"); if (!core_clk_rate) { if (!core_clk_rate) { Loading @@ -2099,7 +2112,36 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, return -EINVAL; return -EINVAL; } } return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate); /* * In rare cases where HDR metadata is updated independently * flush the HDR metadata immediately instead of relying on * the colorspace */ flush_hdr = !sde_conn->colorspace_updated; if (flush_hdr) DP_DEBUG("flushing the HDR metadata\n"); else DP_DEBUG("piggy-backing with colorspace\n"); return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate, flush_hdr); } static int dp_display_setup_colospace(struct dp_display *dp_display, void *panel, u32 colorspace) { struct dp_panel *dp_panel; if (!dp_display || !panel) { pr_err("invalid input\n"); return -EINVAL; } dp_panel = panel; return dp_panel->set_colorspace(dp_panel, colorspace); } } static int dp_display_create_workqueue(struct dp_display_private *dp) static int dp_display_create_workqueue(struct dp_display_private *dp) Loading Loading @@ -2623,6 +2665,7 @@ static int dp_display_probe(struct platform_device *pdev) dp_display_mst_get_fixed_topology_port; dp_display_mst_get_fixed_topology_port; g_dp_display->wakeup_phy_layer = g_dp_display->wakeup_phy_layer = dp_display_wakeup_phy_layer; dp_display_wakeup_phy_layer; g_dp_display->set_colorspace = dp_display_setup_colospace; rc = component_add(&pdev->dev, &dp_display_comp_ops); rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { if (rc) { Loading
msm/dp/dp_display.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,8 @@ struct dp_display { int (*config_hdr)(struct dp_display *dp_display, void *panel, int (*config_hdr)(struct dp_display *dp_display, void *panel, struct drm_msm_ext_hdr_metadata *hdr_meta, struct drm_msm_ext_hdr_metadata *hdr_meta, bool dhdr_update); bool dhdr_update); int (*set_colorspace)(struct dp_display *dp_display, void *panel, u32 colorspace); int (*post_init)(struct dp_display *dp_display); int (*post_init)(struct dp_display *dp_display); int (*mst_install)(struct dp_display *dp_display, int (*mst_install)(struct dp_display *dp_display, struct dp_mst_drm_install_info *mst_install_info); struct dp_mst_drm_install_info *mst_install_info); Loading
msm/dp/dp_drm.c +45 −0 Original line number Original line Diff line number Diff line Loading @@ -326,6 +326,25 @@ int dp_connector_config_hdr(struct drm_connector *connector, void *display, c_state->dyn_hdr_meta.dynamic_hdr_update); c_state->dyn_hdr_meta.dynamic_hdr_update); } } int dp_connector_set_colorspace(struct drm_connector *connector, void *display) { struct dp_display *dp_display = display; struct sde_connector *sde_conn; if (!dp_display || !connector) return -EINVAL; sde_conn = to_sde_connector(connector); if (!sde_conn->drv_panel) { pr_err("invalid dp panel\n"); return -EINVAL; } return dp_display->set_colorspace(dp_display, sde_conn->drv_panel, connector->state->colorspace); } int dp_connector_post_init(struct drm_connector *connector, void *display) int dp_connector_post_init(struct drm_connector *connector, void *display) { { int rc; int rc; Loading Loading @@ -469,6 +488,32 @@ void dp_connector_post_open(struct drm_connector *connector, void *display) dp->post_open(dp); dp->post_open(dp); } } int dp_connector_atomic_check(struct drm_connector *connector, void *display, struct drm_connector_state *c_state) { struct sde_connector *sde_conn; struct drm_connector_state *old_state = drm_atomic_get_old_connector_state(c_state->state, connector); if (!connector || !display) return -EINVAL; sde_conn = to_sde_connector(connector); /* * Marking the colorspace has been changed * the flag shall be checked in the pre_kickoff * to configure the new colorspace in HW */ if (c_state->colorspace != old_state->colorspace) { DP_DEBUG("colorspace has been updated\n"); sde_conn->colorspace_updated = true; } return 0; } int dp_connector_get_modes(struct drm_connector *connector, int dp_connector_get_modes(struct drm_connector *connector, void *display, const struct msm_resource_caps_info *avail_res) void *display, const struct msm_resource_caps_info *avail_res) { { Loading