--- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 5 ++ drivers/gpu/drm/amd/amdgpu/atombios_crtc.c | 27 ++++---- drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 86 ++++++++++++++++++++++++-- 4 files changed, 100 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index d18061b..d21f30e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -1165,6 +1165,10 @@ static int amdgpu_connector_dvi_mode_valid(struct drm_connector *connector, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + if (((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) && + (mode->flags & DRM_MODE_FLAG_INTERLACE)) + return MODE_BAD; + /* XXX check mode bandwidth */ if (amdgpu_connector->use_digital && (mode->clock > 165000)) { @@ -1802,6 +1806,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, AMDGPU_FMT_DITHER_DISABLE); subpixel_order = SubPixelHorizontalRGB; connector->interlace_allowed = true; + connector->stereo_allowed = true; if (connector_type == DRM_MODE_CONNECTOR_HDMIB) connector->doublescan_allowed = true; else diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c index 49a39b1..8114858 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c @@ -301,8 +301,7 @@ union adjust_pixel_clock { ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3; }; -static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc, - struct drm_display_mode *mode) +static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc, u32 clock) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -310,12 +309,11 @@ static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc, struct drm_encoder *encoder = amdgpu_crtc->encoder; struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); - u32 adjusted_clock = mode->clock; + u32 adjusted_clock = clock; int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(encoder); - u32 dp_clock = mode->clock; - u32 clock = mode->clock; + u32 dp_clock = clock; int bpc = amdgpu_crtc->bpc; - bool is_duallink = amdgpu_dig_monitor_is_duallink(encoder, mode->clock); + bool is_duallink = amdgpu_dig_monitor_is_duallink(encoder, clock); union adjust_pixel_clock args; u8 frev, crev; int index; @@ -346,7 +344,7 @@ static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc, /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ if (amdgpu_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) - adjusted_clock = mode->clock * 2; + adjusted_clock = clock * 2; if (amdgpu_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) amdgpu_crtc->pll_flags |= AMDGPU_PLL_PREFER_CLOSEST_LOWER; if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) @@ -746,6 +744,7 @@ int amdgpu_atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(amdgpu_crtc->encoder); int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder); + u32 clock = mode->crtc_clock; amdgpu_crtc->bpc = 8; amdgpu_crtc->ss_enabled = false; @@ -762,7 +761,7 @@ int amdgpu_atombios_crtc_prepare_pll(struct drm_crtc *crtc, int dp_clock; /* Assign mode clock for hdmi deep color max clock limit check */ - amdgpu_connector->pixelclock_for_modeset = mode->clock; + amdgpu_connector->pixelclock_for_modeset = clock; amdgpu_crtc->bpc = amdgpu_connector_get_monitor_bpc(connector); switch (encoder_mode) { @@ -780,21 +779,21 @@ int amdgpu_atombios_crtc_prepare_pll(struct drm_crtc *crtc, amdgpu_atombios_get_asic_ss_info(adev, &amdgpu_crtc->ss, dig->lcd_ss_id, - mode->clock / 10); + clock / 10); break; case ATOM_ENCODER_MODE_DVI: amdgpu_crtc->ss_enabled = amdgpu_atombios_get_asic_ss_info(adev, &amdgpu_crtc->ss, ASIC_INTERNAL_SS_ON_TMDS, - mode->clock / 10); + clock / 10); break; case ATOM_ENCODER_MODE_HDMI: amdgpu_crtc->ss_enabled = amdgpu_atombios_get_asic_ss_info(adev, &amdgpu_crtc->ss, ASIC_INTERNAL_SS_ON_HDMI, - mode->clock / 10); + clock / 10); break; default: break; @@ -802,7 +801,7 @@ int amdgpu_atombios_crtc_prepare_pll(struct drm_crtc *crtc, } /* adjust pixel clock as needed */ - amdgpu_crtc->adjusted_clock = amdgpu_atombios_crtc_adjust_pll(crtc, mode); + amdgpu_crtc->adjusted_clock = amdgpu_atombios_crtc_adjust_pll(crtc, clock); return 0; } @@ -814,8 +813,8 @@ void amdgpu_atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode struct amdgpu_device *adev = dev->dev_private; struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(amdgpu_crtc->encoder); - u32 pll_clock = mode->clock; - u32 clock = mode->clock; + u32 pll_clock = mode->crtc_clock; + u32 clock = mode->crtc_clock; u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; struct amdgpu_pll *pll; int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder); diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index c32eca2..793aaa8 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -292,7 +292,7 @@ bool amdgpu_atombios_encoder_mode_fixup(struct drm_encoder *encoder, /* set the active encoder to connector routing */ amdgpu_encoder_set_active_device(encoder); - drm_mode_set_crtcinfo(adjusted_mode, 0); + drm_mode_set_crtcinfo(adjusted_mode, CRTC_STEREO_DOUBLE); /* hw bug */ if ((mode->flags & DRM_MODE_FLAG_INTERLACE) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 67c7c05..96aa984 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -1722,6 +1722,51 @@ static void dce_v11_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, frame[0xC] | (frame[0xD] << 8) | (header[1] << 24)); } +/* + * build a HDMI Generic Packet + */ +static void dce_v11_0_afmt_update_generic_packet(struct drm_encoder *encoder, + void *buffer, size_t size, uint32_t generic_index) +{ + struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; + uint8_t *frame = buffer + 3; + uint8_t *header = buffer; + u32 tmp; + + tmp = RREG32(mmAFMT_VBI_PACKET_CONTROL + dig->afmt->offset); + tmp = REG_SET_FIELD(tmp, AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, generic_index); + WREG32(mmAFMT_VBI_PACKET_CONTROL + dig->afmt->offset, tmp); + + tmp = REG_SET_FIELD(0, AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, header[0]); + tmp = REG_SET_FIELD(tmp, AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, header[1]); + tmp = REG_SET_FIELD(tmp, AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, header[2]); + WREG32(mmAFMT_GENERIC_HDR + dig->afmt->offset, tmp); + + WREG32(mmAFMT_GENERIC_0 + dig->afmt->offset, + frame[0x00] | (frame[0x01] << 8) | (frame[0x02] << 16) | (frame[0x03] << 24)); + WREG32(mmAFMT_GENERIC_1 + dig->afmt->offset, + frame[0x04] | (frame[0x05] << 8) | (frame[0x06] << 16) | (frame[0x07] << 24)); + WREG32(mmAFMT_GENERIC_2 + dig->afmt->offset, + frame[0x08] | (frame[0x09] << 8) | (frame[0x0A] << 16) | (frame[0x0B] << 24)); + WREG32(mmAFMT_GENERIC_3 + dig->afmt->offset, + frame[0x0C] | (frame[0x0D] << 8) | (frame[0x0E] << 16) | (frame[0x0F] << 24)); + WREG32(mmAFMT_GENERIC_4 + dig->afmt->offset, + frame[0x10] | (frame[0x11] << 8) | (frame[0x12] << 16) | (frame[0x13] << 24)); + WREG32(mmAFMT_GENERIC_5 + dig->afmt->offset, + frame[0x14] | (frame[0x15] << 8) | (frame[0x16] << 16) | (frame[0x17] << 24)); + WREG32(mmAFMT_GENERIC_6 + dig->afmt->offset, + frame[0x18] | (frame[0x19] << 8) | (frame[0x1A] << 16) | (frame[0x1B] << 24)); + WREG32(mmAFMT_GENERIC_7 + dig->afmt->offset, 0); + + tmp = RREG32(mmAFMT_VBI_PACKET_CONTROL + dig->afmt->offset); + /* AFMT_GENERIC1_UPDATE, AFMT_GENERIC3_UPDATE are not defined */ + tmp = REG_SET_FIELD(tmp, AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, (generic_index == 0)); + tmp = REG_SET_FIELD(tmp, AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, (generic_index == 2)); + WREG32(mmAFMT_VBI_PACKET_CONTROL + dig->afmt->offset, tmp); +} + static void dce_v11_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; @@ -1749,6 +1794,8 @@ static void dce_v11_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) WREG32(mmDCCG_AUDIO_DTO0_MODULE, dto_modulo); } +#define HDMI_MAX_INFOFRAME_SIZE 27 + /* * update the info frames with the data from the current display mode */ @@ -1760,8 +1807,9 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); - u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_MAX_INFOFRAME_SIZE]; struct hdmi_avi_infoframe frame; + struct hdmi_vendor_infoframe frame_vendor; ssize_t err; u32 tmp; int bpc = 8; @@ -1779,6 +1827,13 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, bpc = amdgpu_crtc->bpc; } + /* Disable sending generic packet */ + tmp = RREG32(mmHDMI_GENERIC_PACKET_CONTROL0 + dig->afmt->offset); + tmp = REG_SET_FIELD(tmp, HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, 0); + tmp = REG_SET_FIELD(tmp, HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, 0); + tmp = REG_SET_FIELD(tmp, HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, 0); + WREG32(mmHDMI_GENERIC_PACKET_CONTROL0 + dig->afmt->offset, tmp); + /* disable audio prior to setting up hw */ dig->afmt->pin = dce_v11_0_audio_get_pin(adev); dce_v11_0_audio_enable(adev, dig->afmt->pin, false); @@ -1919,6 +1974,27 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, tmp = REG_SET_FIELD(tmp, HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, 2); WREG32(mmHDMI_INFOFRAME_CONTROL1 + dig->afmt->offset, tmp); + err = drm_hdmi_vendor_infoframe_from_display_mode(&frame_vendor, mode); + if (err == -EINVAL) { + } else if (err < 0) { + DRM_ERROR("failed to set up HDMI vendor infoframe: %zd\n", err); + } else { + err = hdmi_vendor_infoframe_pack(&frame_vendor, buffer, sizeof(buffer)); + if (err < 0) { + DRM_ERROR("failed to pack HDMI vendor infoframe: %zd\n", err); + return; + } + + dce_v11_0_afmt_update_generic_packet(encoder, buffer, sizeof(buffer), 0); + + /* Enable sending generic packet */ + tmp = RREG32(mmHDMI_GENERIC_PACKET_CONTROL0 + dig->afmt->offset); + tmp = REG_SET_FIELD(tmp, HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, 1); + tmp = REG_SET_FIELD(tmp, HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, 1); + tmp = REG_SET_FIELD(tmp, HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, 2); + WREG32(mmHDMI_GENERIC_PACKET_CONTROL0 + dig->afmt->offset, tmp); + } + tmp = RREG32(mmAFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset); /* send audio packets */ tmp = REG_SET_FIELD(tmp, AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, 1); @@ -2248,8 +2324,8 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, y &= ~1; WREG32(mmVIEWPORT_START + amdgpu_crtc->crtc_offset, (x << 16) | y); - viewport_w = crtc->mode.hdisplay; - viewport_h = (crtc->mode.vdisplay + 1) & ~1; + viewport_w = crtc->hwmode.crtc_hdisplay; + viewport_h = (crtc->hwmode.crtc_vdisplay + 1) & ~1; WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset, (viewport_w << 16) | viewport_h); @@ -2858,7 +2934,7 @@ static int dce_v11_0_crtc_mode_set(struct drm_crtc *crtc, amdgpu_atombios_crtc_program_pll(crtc, amdgpu_crtc->crtc_id, amdgpu_crtc->pll_id, encoder_mode, amdgpu_encoder->encoder_id, - adjusted_mode->clock, 0, 0, 0, 0, + adjusted_mode->crtc_clock, 0, 0, 0, 0, amdgpu_crtc->bpc, amdgpu_crtc->ss_enabled, &amdgpu_crtc->ss); } else { amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode); @@ -3588,7 +3664,7 @@ dce_v11_0_encoder_mode_set(struct drm_encoder *encoder, { struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); - amdgpu_encoder->pixel_clock = adjusted_mode->clock; + amdgpu_encoder->pixel_clock = adjusted_mode->crtc_clock; /* need to call this here rather than in prepare() since we need some crtc info */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); -- 2.9.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel