summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv50_display.c
diff options
context:
space:
mode:
authorAlastair Bridgewater <alastair.bridgewater@gmail.com>2017-04-11 13:11:18 -0400
committerBen Skeggs <bskeggs@redhat.com>2017-06-16 14:04:18 +1000
commit34fd3e5d8c5f6bdcc2245084036680a4bfc23370 (patch)
treee6f91f3353ae5474e8f3c0b6088d96a62aaf118e /drivers/gpu/drm/nouveau/nv50_display.c
parent31fe2c200262a512255340d6f9493d51e06a8207 (diff)
downloadop-kernel-dev-34fd3e5d8c5f6bdcc2245084036680a4bfc23370.zip
op-kernel-dev-34fd3e5d8c5f6bdcc2245084036680a4bfc23370.tar.gz
drm/nouveau: Pass mode-dependent AVI and Vendor HDMI InfoFrames to NVKM
Now that we have mechanism by which to pass mode-dependent HDMI InfoFrames to the low-level hardware driver, it is incumbent upon us to do so. Signed-off-by: Alastair Bridgewater <alastair.bridgewater@gmail.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 83eee1f..0f817a6 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -23,6 +23,7 @@
*/
#include <linux/dma-mapping.h>
+#include <linux/hdmi.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
@@ -31,6 +32,7 @@
#include <drm/drm_dp_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_edid.h>
#include <nvif/class.h>
#include <nvif/cl0002.h>
@@ -2710,6 +2712,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
struct {
struct nv50_disp_mthd_v1 base;
struct nv50_disp_sor_hdmi_pwr_v0 pwr;
+ u8 infoframes[2 * 17]; /* two frames, up to 17 bytes each */
} args = {
.base.version = 1,
.base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
@@ -2721,17 +2724,42 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
};
struct nouveau_connector *nv_connector;
u32 max_ac_packet;
+ union hdmi_infoframe avi_frame;
+ union hdmi_infoframe vendor_frame;
+ int ret;
+ int size;
nv_connector = nouveau_encoder_connector_get(nv_encoder);
if (!drm_detect_hdmi_monitor(nv_connector->edid))
return;
+ ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode);
+ if (!ret) {
+ /* We have an AVI InfoFrame, populate it to the display */
+ args.pwr.avi_infoframe_length
+ = hdmi_infoframe_pack(&avi_frame, args.infoframes, 17);
+ }
+
+ ret = drm_hdmi_vendor_infoframe_from_display_mode(&vendor_frame.vendor.hdmi, mode);
+ if (!ret) {
+ /* We have a Vendor InfoFrame, populate it to the display */
+ args.pwr.vendor_infoframe_length
+ = hdmi_infoframe_pack(&vendor_frame,
+ args.infoframes
+ + args.pwr.avi_infoframe_length,
+ 17);
+ }
+
max_ac_packet = mode->htotal - mode->hdisplay;
max_ac_packet -= args.pwr.rekey;
max_ac_packet -= 18; /* constant from tegra */
args.pwr.max_ac_packet = max_ac_packet / 32;
- nvif_mthd(disp->disp, 0, &args, sizeof(args));
+ size = sizeof(args.base)
+ + sizeof(args.pwr)
+ + args.pwr.avi_infoframe_length
+ + args.pwr.vendor_infoframe_length;
+ nvif_mthd(disp->disp, 0, &args, size);
nv50_audio_enable(encoder, mode);
}
OpenPOWER on IntegriCloud