Skip to content

Commit c02f20d

Browse files
Ben Skeggsairlied
authored andcommitted
drm/nouveau/disp: fix incorrect/broken hdmi methods
These are fixes from Lyude, and were meant to have been included in the last round of drm-next patches. - Fix some nasty memory issues that broke Lyude's display: - 0 initialize both nvif args and parsed HDMI infoframe buffers - Fixed missing memset(…, 0, …) for nvif args before sending VSI infoframe - Fixed incorrect data pointer and size in nvkm_uoutp_mthd_infoframe() (was previously pointing at the start of the nvif_outp_infoframe_args struct instead of at the start of the infoframe data - Get rid of duplicated scdc assignments, since we only use it to write the scdc registers Signed-off-by: Ben Skeggs <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent a143bc5 commit c02f20d

File tree

2 files changed

+15
-18
lines changed

2 files changed

+15
-18
lines changed

drivers/gpu/drm/nouveau/dispnv50/disp.c

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -739,14 +739,14 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
739739
struct nouveau_drm *drm = nouveau_drm(encoder->dev);
740740
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
741741
struct drm_hdmi_info *hdmi = &nv_connector->base.display_info.hdmi;
742-
union hdmi_infoframe infoframe;
742+
union hdmi_infoframe infoframe = { 0 };
743743
const u8 rekey = 56; /* binary driver, and tegra, constant */
744-
u8 config, scdc = 0;
744+
u8 scdc = 0;
745745
u32 max_ac_packet;
746746
struct {
747747
struct nvif_outp_infoframe_v0 infoframe;
748748
u8 data[17];
749-
} args;
749+
} args = { 0 };
750750
int ret, size;
751751

752752
max_ac_packet = mode->htotal - mode->hdisplay;
@@ -757,27 +757,22 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
757757
if (hdmi->scdc.scrambling.supported) {
758758
const bool high_tmds_clock_ratio = mode->clock > 340000;
759759

760-
ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &config);
760+
ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &scdc);
761761
if (ret < 0) {
762762
NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret);
763763
return;
764764
}
765765

766-
config &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE);
766+
scdc &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE);
767767
if (high_tmds_clock_ratio || hdmi->scdc.scrambling.low_rates)
768-
config |= SCDC_SCRAMBLING_ENABLE;
768+
scdc |= SCDC_SCRAMBLING_ENABLE;
769769
if (high_tmds_clock_ratio)
770-
config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40;
770+
scdc |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40;
771771

772-
ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, config);
772+
ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, scdc);
773773
if (ret < 0)
774774
NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n",
775-
config, ret);
776-
777-
if (high_tmds_clock_ratio || hdmi->scdc.scrambling.low_rates)
778-
scdc |= NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_SCRAMBLE;
779-
if (high_tmds_clock_ratio)
780-
scdc |= NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_DIV_BY_4;
775+
scdc, ret);
781776
}
782777

783778
ret = nvif_outp_acquire_tmds(&nv_encoder->outp, nv_crtc->index, true,
@@ -793,17 +788,18 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
793788
drm_hdmi_avi_infoframe_quant_range(&infoframe.avi, &nv_connector->base, mode,
794789
HDMI_QUANTIZATION_RANGE_FULL);
795790

796-
size = hdmi_infoframe_pack(&infoframe, args.data, 17);
791+
size = hdmi_infoframe_pack(&infoframe, args.data, ARRAY_SIZE(args.data));
797792
} else {
798793
size = 0;
799794
}
800795

801796
nvif_outp_infoframe(&nv_encoder->outp, NVIF_OUTP_INFOFRAME_V0_AVI, &args.infoframe, size);
802797

803798
/* Vendor InfoFrame. */
799+
memset(&args.data, 0, sizeof(args.data));
804800
if (!drm_hdmi_vendor_infoframe_from_display_mode(&infoframe.vendor.hdmi,
805801
&nv_connector->base, mode))
806-
size = hdmi_infoframe_pack(&infoframe, args.data, 17);
802+
size = hdmi_infoframe_pack(&infoframe, args.data, ARRAY_SIZE(args.data));
807803
else
808804
size = 0;
809805

drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc)
104104
{
105105
struct nvkm_ior *ior = outp->ior;
106106
union nvif_outp_infoframe_args *args = argv;
107+
ssize_t size = argc - sizeof(*args);
107108

108109
if (argc < sizeof(args->v0) || args->v0.version != 0)
109110
return -ENOSYS;
@@ -112,10 +113,10 @@ nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc)
112113

113114
switch (ior->func->hdmi ? args->v0.type : 0xff) {
114115
case NVIF_OUTP_INFOFRAME_V0_AVI:
115-
ior->func->hdmi->infoframe_avi(ior, args->v0.head, argv, argc);
116+
ior->func->hdmi->infoframe_avi(ior, args->v0.head, &args->v0.data, size);
116117
return 0;
117118
case NVIF_OUTP_INFOFRAME_V0_VSI:
118-
ior->func->hdmi->infoframe_vsi(ior, args->v0.head, argv, argc);
119+
ior->func->hdmi->infoframe_vsi(ior, args->v0.head, &args->v0.data, size);
119120
return 0;
120121
default:
121122
break;

0 commit comments

Comments
 (0)