Added support for a register read, register write and register field write commands. Added support for adjust link training command. Updated cdn_dp_get_event function, so it reads all SW event registers. Added definitions mostly for Framer and Streamer. Signed-off-by: Damian Kos <dkos@xxxxxxxxxxx> --- drivers/gpu/drm/rockchip/cdn-dp-reg.c | 167 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/rockchip/cdn-dp-reg.h | 143 +++++++++++++++++++++++++++- 2 files changed, 305 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c index eb3042c..b061cfc 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c @@ -410,7 +410,10 @@ int cdn_dp_event_config(struct cdn_dp_device *dp) u32 cdn_dp_get_event(struct cdn_dp_device *dp) { - return readl(dp->regs + SW_EVENTS0); + return readl(dp->regs + SW_EVENTS0) + | (readl(dp->regs + SW_EVENTS1) << 8) + | (readl(dp->regs + SW_EVENTS2) << 16) + | (readl(dp->regs + SW_EVENTS3) << 24); } int cdn_dp_get_hpd_status(struct cdn_dp_device *dp) @@ -981,3 +984,165 @@ int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio) DRM_DEV_ERROR(dp->dev, "audio config failed: %d\n", ret); return ret; } + +int cdn_dp_register_read(struct cdn_dp_device *dp, u32 addr, u32 *value) +{ + u8 msg[4], resp[8]; + int ret; + + if (addr == 0) { + ret = -EINVAL; + goto err_register_read; + } + + msg[0] = (u8)(addr >> 24); + msg[1] = (u8)(addr >> 16); + msg[2] = (u8)(addr >> 8); + msg[3] = (u8)addr; + + ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_GENERAL, + GENERAL_REGISTER_READ, + sizeof(msg), msg); + if (ret) + goto err_register_read; + + ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_GENERAL, + GENERAL_REGISTER_READ, + sizeof(resp)); + if (ret) + goto err_register_read; + + ret = cdn_dp_mailbox_read_receive(dp, resp, sizeof(resp)); + if (ret) + goto err_register_read; + + /* Returned address value should be the same as requested */ + if (memcmp(msg, resp, sizeof(msg))) { + ret = -EINVAL; + goto err_register_read; + } + + *value = (resp[4] << 24) | (resp[5] << 16) | (resp[6] << 8) | resp[7]; + +err_register_read: + if (ret) { + DRM_DEV_ERROR(dp->dev, "Failed to read register.\n"); + *value = 0; + } + + return ret; +} + +int cdn_dp_register_write(struct cdn_dp_device *dp, u32 addr, u32 value) +{ + u8 msg[8]; + int ret; + + if (addr == 0) + return -EINVAL; + + msg[0] = (u8)(addr >> 24); + msg[1] = (u8)(addr >> 16); + msg[2] = (u8)(addr >> 8); + msg[3] = (u8)addr; + msg[4] = (u8)(value >> 24); + msg[5] = (u8)(value >> 16); + msg[6] = (u8)(value >> 8); + msg[7] = (u8)value; + + ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_GENERAL, + GENERAL_REGISTER_WRITE, + sizeof(msg), msg); + if (ret) + DRM_DEV_ERROR(dp->dev, "Failed to write register.\n"); + + return ret; +} + +int cdn_dp_register_write_field(struct cdn_dp_device *dp, u32 addr, + u8 index, u8 nbits, u32 value) +{ + u8 msg[10]; + int ret; + + if (addr == 0) + return -EINVAL; + + msg[0] = (u8)(addr >> 24); + msg[1] = (u8)(addr >> 16); + msg[2] = (u8)(addr >> 8); + msg[3] = (u8)addr; + msg[4] = index; + msg[5] = nbits; + msg[6] = (u8)(value >> 24); + msg[7] = (u8)(value >> 16); + msg[8] = (u8)(value >> 8); + msg[9] = (u8)value; + + ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_GENERAL, + GENERAL_REGISTER_WRITE_FIELD, + sizeof(msg), msg); + if (ret) + DRM_DEV_ERROR(dp->dev, "Failed to write register field.\n"); + + return ret; +} +/* rep should be a pointer already allocated with .regs of size 6 */ +int cdn_dp_adjust_lt(struct cdn_dp_device *dp, u8 nlanes, + u16 udelay, u8 *lanes_data, + u8 *dpcd) +{ + u8 payload[10]; + u8 hdr[5]; /* For DPCD read response header */ + u32 addr; + u8 const nregs = 6; /* Registers 0x202-0x207 */ + int ret; + + if (nlanes != 4 && nlanes != 2 && nlanes != 1) { + DRM_DEV_ERROR(dp->dev, "invalid number of lanes: %d\n", nlanes); + ret = -EINVAL; + goto err_adjust_lt; + } + + payload[0] = nlanes; + payload[1] = (u8)(udelay >> 8); + payload[2] = (u8)udelay; + + payload[3] = lanes_data[0]; + if (nlanes > 1) + payload[4] = lanes_data[1]; + if (nlanes > 2) { + payload[5] = lanes_data[2]; + payload[6] = lanes_data[3]; + } + + ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, + DPTX_ADJUST_LT, + sizeof(payload), payload); + if (ret) + goto err_adjust_lt; + + /* Yes, read the DPCD read command response */ + ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX, + DPTX_READ_DPCD, + sizeof(hdr) + nregs); + if (ret) + goto err_adjust_lt; + + ret = cdn_dp_mailbox_read_receive(dp, hdr, sizeof(hdr)); + if (ret) + goto err_adjust_lt; + + addr = (hdr[2] << 24) | (hdr[3] << 8) | hdr[4]; + if (addr != DP_LANE0_1_STATUS) + goto err_adjust_lt; + + ret = cdn_dp_mailbox_read_receive(dp, dpcd, nregs); + +err_adjust_lt: + if (ret) + DRM_DEV_ERROR(dp->dev, "Failed to adjust Link Training.\n"); + + return ret; +} + diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h index c4bbb4a..b5472ad 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h @@ -156,6 +156,14 @@ #define DP_FRONT_BACK_PORCH 0x2278 #define DP_BYTE_COUNT 0x227c +/* dptx framer global config fields */ +#define DP_FRAMER_NUM_LANES(x) (x - 1) +#define DP_FRAMER_EN BIT(3) +#define DP_FRAMER_RATE_GOVERNOR_EN BIT(4) +#define DP_FRAMER_NO_VIDEO_MODE BIT(5) +#define DP_FRAMER_DISABLE_PHY_RST BIT(6) +#define DP_FRAMER_WR_FAILING_EDGE_VSYNC BIT(7) + /* dptx stream addr */ #define MSA_HORIZONTAL_0 0x2280 #define MSA_HORIZONTAL_1 0x2284 @@ -323,10 +331,13 @@ #define MB_MODULE_ID_GENERAL 0x0a /* general opcode */ -#define GENERAL_MAIN_CONTROL 0x01 -#define GENERAL_TEST_ECHO 0x02 -#define GENERAL_BUS_SETTINGS 0x03 -#define GENERAL_TEST_ACCESS 0x04 +#define GENERAL_MAIN_CONTROL 0x01 +#define GENERAL_TEST_ECHO 0x02 +#define GENERAL_BUS_SETTINGS 0x03 +#define GENERAL_TEST_ACCESS 0x04 +#define GENERAL_REGISTER_WRITE 0x05 +#define GENERAL_REGISTER_WRITE_FIELD 0x06 +#define GENERAL_REGISTER_READ 0x07 #define DPTX_SET_POWER_MNG 0x00 #define DPTX_SET_HOST_CAPABILITIES 0x01 @@ -346,6 +357,7 @@ #define DPTX_SET_LINK_BREAK_POINT 0x0f #define DPTX_FORCE_LANES 0x10 #define DPTX_HPD_STATE 0x11 +#define DPTX_ADJUST_LT 0x12 #define FW_STANDBY 0 #define FW_ACTIVE 1 @@ -424,6 +436,122 @@ /* Reference cycles when using lane clock as reference */ #define LANE_REF_CYC 0x8000 +#define CDN_DPTX_FRAMER 0x02200 +#define CDN_DP_FRAMER_GLOBAL_CONFIG (CDN_DPTX_FRAMER + 0x00) +#define CDN_DP_NUM_LANES(x) (x - 1) +#define CDN_DP_FRAMER_EN BIT(3) +#define CDN_DP_RATE_GOVERNOR_EN BIT(4) +#define CDN_DP_NO_VIDEO_MODE BIT(5) +#define CDN_DP_DISABLE_PHY_RST BIT(6) +#define CDN_DP_WR_FAILING_EDGE_VSYNC BIT(7) + +#define CDN_DP_SW_RESET (CDN_DPTX_FRAMER + 0x04) +#define CDN_DP_FRAMER_TU (CDN_DPTX_FRAMER + 0x08) +#define CDN_DP_FRAMER_TU_SIZE(x) (((x) & GENMASK(6, 0)) << 8) +#define CDN_DP_FRAMER_TU_VS(x) ((x) & GENMASK(5, 0)) +#define CDN_DP_FRAMER_TU_CNT_RST_EN BIT(15) + +#define CDN_DPTX_STREAM 0x03000 +#define CDN_DP_MSA_HORIZONTAL_0 (CDN_DPTX_STREAM + 0x00) +#define CDN_DP_MSAH0_H_TOTAL(x) (x) +#define CDN_DP_MSAH0_HSYNC_START(x) ((x) << 16) + +#define CDN_DP_MSA_HORIZONTAL_1 (CDN_DPTX_STREAM + 0x04) +#define CDN_DP_MSAH1_HSYNC_WIDTH(x) (x) +#define CDN_DP_MSAH1_HSYNC_POL_LOW BIT(15) +#define CDN_DP_MSAH1_HDISP_WIDTH(x) ((x) << 16) + +#define CDN_DP_MSA_VERTICAL_0 (CDN_DPTX_STREAM + 0x08) +#define CDN_DP_MSAV0_V_TOTAL(x) (x) +#define CDN_DP_MSAV0_VSYNC_START(x) ((x) << 16) + +#define CDN_DP_MSA_VERTICAL_1 (CDN_DPTX_STREAM + 0x0c) +#define CDN_DP_MSAV1_VSYNC_WIDTH(x) (x) +#define CDN_DP_MSAV1_VSYNC_POL_LOW BIT(15) +#define CDN_DP_MSAV1_VDISP_WIDTH(x) ((x) << 16) + +#define CDN_DP_MSA_MISC (CDN_DPTX_STREAM + 0x10) +#define CDN_DP_STREAM_CONFIG (CDN_DPTX_STREAM + 0x14) +#define CDN_DP_RATE_GOVERNOR_STATUS (CDN_DPTX_STREAM + 0x2c) +#define CDN_DP_RG_TU_VS_DIFF(x) ((x) << 8) + +#define CDN_DP_HORIZONTAL (CDN_DPTX_STREAM + 0x30) +#define CDN_DP_H_HSYNC_WIDTH(x) (x) +#define CDN_DP_H_H_TOTAL(x) ((x) << 16) + +#define CDN_DP_VERTICAL_0 (CDN_DPTX_STREAM + 0x34) +#define CDN_DP_V0_VHEIGHT(x) (x) +#define CDN_DP_V0_VSTART(x) ((x) << 16) + +#define CDN_DP_VERTICAL_1 (CDN_DPTX_STREAM + 0x38) +#define CDN_DP_V1_VTOTAL(x) (x) +#define CDN_DP_V1_VTOTAL_EVEN BIT(16) + +#define CDN_DP_FRAMER_PXL_REPR (CDN_DPTX_STREAM + 0x4c) +#define CDN_DP_FRAMER_6_BPC BIT(0) +#define CDN_DP_FRAMER_8_BPC BIT(1) +#define CDN_DP_FRAMER_10_BPC BIT(2) +#define CDN_DP_FRAMER_12_BPC BIT(3) +#define CDN_DP_FRAMER_16_BPC BIT(4) +#define CDN_DP_FRAMER_PXL_FORMAT 0x8 +#define CDN_DP_FRAMER_RGB BIT(0) +#define CDN_DP_FRAMER_YCBCR444 BIT(1) +#define CDN_DP_FRAMER_YCBCR422 BIT(2) +#define CDN_DP_FRAMER_YCBCR420 BIT(3) +#define CDN_DP_FRAMER_Y_ONLY BIT(4) + +#define CDN_DP_FRAMER_SP (CDN_DPTX_STREAM + 0x10) +#define CDN_DP_FRAMER_VSYNC_POL_LOW BIT(0) +#define CDN_DP_FRAMER_HSYNC_POL_LOW BIT(1) +#define CDN_DP_FRAMER_INTERLACE BIT(2) + +#define CDN_DP_LINE_THRESH (CDN_DPTX_STREAM + 0x64) +#define CDN_DP_VB_ID (CDN_DPTX_STREAM + 0x68) +#define CDN_DP_VB_ID_INTERLACED BIT(2) + +#define CDN_DP_FRONT_BACK_PORCH (CDN_DPTX_STREAM + 0x78) +#define CDN_DP_BACK_PORCH(x) (x) +#define CDN_DP_FRONT_PORCH(x) ((x) << 16) + +#define CDN_DP_BYTE_COUNT (CDN_DPTX_STREAM + 0x7c) + +#define CDN_DPTX_GLOBAL 0x02300 +#define CDN_DP_LANE_EN (CDN_DPTX_GLOBAL + 0x00) +#define CDN_DP_LANE_EN_LANES(x) GENMASK(x - 1, 0) +#define CDN_DP_ENHNCD (CDN_DPTX_GLOBAL + 0x04) + +#define CDN_SOURCE_VIDEO_INTERFACE 0x00b00 +#define CDN_BND_HSYNC2VSYNC (CDN_SOURCE_VIDEO_INTERFACE + 0x00) +#define CDN_IP_DTCT_WIN GENMASK(11, 0) +#define CDN_IP_DET_INTERLACE_FORMAT BIT(12) +#define CDN_IP_BYPASS_V_INTERFACE BIT(13) + +#define CDN_HSYNC2VSYNC_POL_CTRL (CDN_SOURCE_VIDEO_INTERFACE + 0x10) +#define CDN_H2V_HSYNC_POL_ACTIVE_LOW BIT(1) +#define CDN_H2V_VSYNC_POL_ACTIVE_LOW BIT(2) + +#define CDN_DPTX_PHY_CONFIG 0x02000 +#define CDN_PHY_TRAINING_EN BIT(0) +#define CDN_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1) +#define CDN_PHY_SCRAMBLER_BYPASS BIT(5) +#define CDN_PHY_ENCODER_BYPASS BIT(6) +#define CDN_PHY_SKEW_BYPASS BIT(7) +#define CDN_PHY_TRAINING_AUTO BIT(8) +#define CDN_PHY_LANE0_SKEW(x) (((x) & GENMASK(2, 0)) << 9) +#define CDN_PHY_LANE1_SKEW(x) (((x) & GENMASK(2, 0)) << 12) +#define CDN_PHY_LANE2_SKEW(x) (((x) & GENMASK(2, 0)) << 15) +#define CDN_PHY_LANE3_SKEW(x) (((x) & GENMASK(2, 0)) << 18) +#define CDN_PHY_COMMON_CONFIG (CDN_PHY_LANE1_SKEW(1) | CDN_PHY_LANE2_SKEW(2) | CDN_PHY_LANE3_SKEW(3)) +#define CDN_PHY_10BIT_EN BIT(21) + +#define CDN_PRE_EMPHASIS(x) ((x) & GENMASK(1, 0)) +#define CDN_FORCE_PRE_EMPHASIS BIT(2) + +#define CDN_VOLT_SWING(x) ((x) & GENMASK(1, 0)) +#define CDN_FORCE_VOLT_SWING BIT(2) + +#define CDN_DP_TRAINING_PATTERN_4 0x7 + enum voltage_swing_level { VOLTAGE_LEVEL_0, VOLTAGE_LEVEL_1, @@ -479,4 +607,11 @@ int cdn_dp_get_edid_block(void *dp, u8 *edid, int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio); int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable); int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio); +int cdn_dp_register_read(struct cdn_dp_device *dp, u32 addr, u32 *value); +int cdn_dp_register_write(struct cdn_dp_device *dp, u32 addr, u32 value); +int cdn_dp_register_write_field(struct cdn_dp_device *dp, u32 addr, + u8 index, u8 nbits, u32 value); +int cdn_dp_adjust_lt(struct cdn_dp_device *dp, u8 nlanes, + u16 udelay, u8 *lanes_data, + u8 *dpcd); #endif /* _CDN_DP_REG_H */ -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html