Commit 6c6abab2 authored by Ben Skeggs's avatar Ben Skeggs Committed by Lyude Paul
Browse files

drm/nouveau/disp: add output hdmi config method



- was previously part of acquire()
- preparation for GSP-RM

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
Acked-by: default avatarDanilo Krummrich <me@dakr.org>
Signed-off-by: default avatarLyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230919220442.202488-20-lyude@redhat.com
parent c0f7b729
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -778,7 +778,6 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
	struct drm_hdmi_info *hdmi = &nv_connector->base.display_info.hdmi;
	union hdmi_infoframe infoframe = { 0 };
	const u8 rekey = 56; /* binary driver, and tegra, constant */
	u8 scdc = 0;
	u32 max_ac_packet;
	struct {
		struct nvif_outp_infoframe_v0 infoframe;
@@ -791,8 +790,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
	max_ac_packet -= 18; /* constant from tegra */
	max_ac_packet /= 32;

	if (hdmi->scdc.scrambling.supported) {
	if (nv_encoder->i2c && hdmi->scdc.scrambling.supported) {
		const bool high_tmds_clock_ratio = mode->clock > 340000;
		u8 scdc;

		ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &scdc);
		if (ret < 0) {
@@ -812,8 +812,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
				 scdc, ret);
	}

	ret = nvif_outp_acquire_tmds(&nv_encoder->outp, nv_crtc->index, true,
				     max_ac_packet, rekey, scdc, hda);
	ret = nvif_outp_hdmi(&nv_encoder->outp, nv_crtc->index, true, max_ac_packet, rekey,
			     mode->clock, hdmi->scdc.supported, hdmi->scdc.scrambling.supported,
			     hdmi->scdc.scrambling.low_rates);
	if (ret)
		return;

@@ -1852,7 +1853,6 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
	switch (nv_encoder->dcb->type) {
	case DCB_OUTPUT_TMDS:
		ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
		nvif_outp_acquire_tmds(&nv_encoder->outp, false, false, 0, 0, 0, false);
		break;
	case DCB_OUTPUT_DP:
		ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
+16 −12
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ union nvif_outp_args {

#define NVIF_OUTP_V0_LOAD_DETECT   0x20

#define NVIF_OUTP_V0_HDMI          0x50

#define NVIF_OUTP_V0_INFOFRAME     0x60
#define NVIF_OUTP_V0_HDA_ELD       0x61

@@ -62,7 +64,6 @@ union nvif_outp_acquire_args {
#define NVIF_OUTP_ACQUIRE_V0_DAC  0x00
#define NVIF_OUTP_ACQUIRE_V0_SOR  0x01
#define NVIF_OUTP_ACQUIRE_V0_PIOR 0x02
#define NVIF_OUTP_ACQUIRE_V0_TMDS    0x05
#define NVIF_OUTP_ACQUIRE_V0_LVDS    0x03
#define NVIF_OUTP_ACQUIRE_V0_DP      0x04
		__u8 type;
@@ -73,17 +74,6 @@ union nvif_outp_acquire_args {
			struct {
				__u8 hda;
			} sor;
			struct {
				__u8 head;
				__u8 hdmi;
				__u8 hdmi_max_ac_packet;
				__u8 hdmi_rekey;
#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_SCRAMBLE (1 << 0)
#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_DIV_BY_4 (1 << 1)
				__u8 hdmi_scdc;
				__u8 hdmi_hda;
				__u8 pad06[2];
			} tmds;
			struct {
				__u8 dual;
				__u8 bpc8;
@@ -128,6 +118,20 @@ union nvif_outp_release_args {
	} vn;
};

union nvif_outp_hdmi_args {
	struct nvif_outp_hdmi_v0 {
		__u8 version;
		__u8 head;
		__u8 enable;
		__u8 max_ac_packet;
		__u8 rekey;
		__u8 scdc;
		__u8 scdc_scrambling;
		__u8 scdc_low_rates;
		__u32 khz;
	} v0;
};

union nvif_outp_infoframe_args {
	struct nvif_outp_infoframe_v0 {
		__u8 version;
+3 −2
Original line number Diff line number Diff line
@@ -31,8 +31,6 @@ int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
int nvif_outp_acquire_dac(struct nvif_outp *);
int nvif_outp_acquire_sor(struct nvif_outp *, bool hda);
int nvif_outp_acquire_pior(struct nvif_outp *);
int nvif_outp_acquire_tmds(struct nvif_outp *, int head,
			   bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda);
int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8);
int nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
			 int link_nr, int link_bw, bool hda, bool mst);
@@ -49,6 +47,9 @@ nvif_outp_acquired(struct nvif_outp *outp)
	return outp->or.id >= 0;
}

int nvif_outp_hdmi(struct nvif_outp *, int head, bool enable, u8 max_ac_packet, u8 rekey, u32 khz,
		   bool scdc, bool scdc_scrambling, bool scdc_low_rates);

int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size);
int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
+18 −15
Original line number Diff line number Diff line
@@ -124,25 +124,28 @@ nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_
}

int
nvif_outp_acquire_tmds(struct nvif_outp *outp, int head,
		       bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda)
nvif_outp_hdmi(struct nvif_outp *outp, int head, bool enable, u8 max_ac_packet, u8 rekey,
	       u32 khz, bool scdc, bool scdc_scrambling, bool scdc_low_rates)
{
	struct nvif_outp_acquire_v0 args;
	struct nvif_outp_hdmi_v0 args;
	int ret;

	args.tmds.head = head;
	args.tmds.hdmi = hdmi;
	args.tmds.hdmi_max_ac_packet = max_ac_packet;
	args.tmds.hdmi_rekey = rekey;
	args.tmds.hdmi_scdc = scdc;
	args.tmds.hdmi_hda = hda;

	ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_TMDS, &args);
	args.version = 0;
	args.head = head;
	args.enable = enable;
	args.max_ac_packet = max_ac_packet;
	args.rekey = rekey;
	args.khz = khz;
	args.scdc = scdc;
	args.scdc_scrambling = scdc_scrambling;
	args.scdc_low_rates = scdc_low_rates;

	ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDMI, &args, sizeof(args));
	NVIF_ERRON(ret, &outp->object,
		   "[ACQUIRE proto:TMDS head:%d hdmi:%d max_ac_packet:%d rekey:%d scdc:%d hda:%d]"
		   " or:%d link:%d", args.tmds.head, args.tmds.hdmi, args.tmds.hdmi_max_ac_packet,
		   args.tmds.hdmi_rekey, args.tmds.hdmi_scdc, args.tmds.hdmi_hda,
		   args.or, args.link);
		   "[HDMI head:%d enable:%d max_ac_packet:%d rekey:%d khz:%d scdc:%d "
		   "scdc_scrambling:%d scdc_low_rates:%d]",
		   args.head, args.enable, args.max_ac_packet, args.rekey, args.khz,
		   args.scdc, args.scdc_scrambling, args.scdc_low_rates);
	return ret;
}

+12 −4
Original line number Diff line number Diff line
@@ -68,15 +68,23 @@ gm200_sor_dp = {
};

void
gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u8 scdc)
gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u32 khz, bool support, bool scrambling,
		    bool scrambling_low_rates)
{
	struct nvkm_device *device = ior->disp->engine.subdev.device;
	const u32 soff = nv50_ior_base(ior);
	const u32 ctrl = scdc & 0x3;
	u32 ctrl = 0;

	nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl);
	ior->tmds.high_speed = khz > 340000;

	if (support && scrambling) {
		if (ior->tmds.high_speed)
			ctrl |= 0x00000002;
		if (ior->tmds.high_speed || scrambling_low_rates)
			ctrl |= 0x00000001;
	}

	ior->tmds.high_speed = !!(scdc & 0x2);
	nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl);
}

const struct nvkm_ior_func_hdmi
Loading