Signed-off-by: Jeff Smith <whydo...@gmail.com>
---
 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 b487aa0..5a40ef4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -1175,6 +1175,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)) {
@@ -1815,6 +1819,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 8c9bc75..475393e 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
@@ -302,8 +302,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;
@@ -311,12 +310,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;
@@ -347,7 +345,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))
@@ -753,6 +751,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;
@@ -769,7 +768,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) {
@@ -787,21 +786,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;
@@ -809,7 +808,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;
 }
@@ -821,8 +820,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 2af26d2..540dc08 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -286,7 +286,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 459afac..b4df662 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -1689,6 +1689,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;
@@ -1716,6 +1761,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
  */
@@ -1727,8 +1774,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;
@@ -1746,6 +1794,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);
@@ -1886,6 +1941,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);
@@ -2217,8 +2293,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;
+       drm_crtc_get_hv_timing(&crtc->mode, &viewport_w, &viewport_h);
+       viewport_h = (viewport_h + 1) & ~1;
        WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
               (viewport_w << 16) | viewport_h);
 
@@ -2830,7 +2906,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);
@@ -3554,7 +3630,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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to