mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-18 16:44:27 +08:00
drm/nouveau/disp: add output hdmi config method
- was previously part of acquire() - preparation for GSP-RM Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Danilo Krummrich <me@dakr.org> Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230919220442.202488-20-lyude@redhat.com
This commit is contained in:
parent
c0f7b72942
commit
6c6abab20b
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
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_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_TMDS, &args);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl);
|
||||
|
||||
ior->tmds.high_speed = !!(scdc & 0x2);
|
||||
}
|
||||
|
||||
const struct nvkm_ior_func_hdmi
|
||||
|
@ -65,7 +65,8 @@ struct nvkm_ior_func {
|
||||
|
||||
const struct nvkm_ior_func_hdmi {
|
||||
void (*ctrl)(struct nvkm_ior *, int head, bool enable, u8 max_ac_packet, u8 rekey);
|
||||
void (*scdc)(struct nvkm_ior *, u8 scdc);
|
||||
void (*scdc)(struct nvkm_ior *, u32 khz, bool support, bool scrambling,
|
||||
bool scrambling_low_rates);
|
||||
void (*infoframe_avi)(struct nvkm_ior *, int head, void *data, u32 size);
|
||||
void (*infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 size);
|
||||
} *hdmi;
|
||||
@ -167,7 +168,7 @@ void gm107_sor_dp_pattern(struct nvkm_ior *, int);
|
||||
void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *);
|
||||
int gm200_sor_route_get(struct nvkm_outp *, int *);
|
||||
extern const struct nvkm_ior_func_hdmi gm200_sor_hdmi;
|
||||
void gm200_sor_hdmi_scdc(struct nvkm_ior *, u8);
|
||||
void gm200_sor_hdmi_scdc(struct nvkm_ior *, u32, bool, bool, bool);
|
||||
extern const struct nvkm_ior_func_dp gm200_sor_dp;
|
||||
void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
|
||||
|
||||
|
@ -137,24 +137,28 @@ nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc)
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 head, u8 hdmi, u8 hdmi_max_ac_packet,
|
||||
u8 hdmi_rekey, u8 hdmi_scdc, u8 hdmi_hda)
|
||||
nvkm_uoutp_mthd_hdmi(struct nvkm_outp *outp, void *argv, u32 argc)
|
||||
{
|
||||
union nvif_outp_hdmi_args *args = argv;
|
||||
struct nvkm_ior *ior = outp->ior;
|
||||
|
||||
if (!(outp->asy.head = nvkm_head_find(outp->disp, head)))
|
||||
if (argc != sizeof(args->v0) || args->v0.version != 0)
|
||||
return -ENOSYS;
|
||||
|
||||
if (!(outp->asy.head = nvkm_head_find(outp->disp, args->v0.head)))
|
||||
return -EINVAL;
|
||||
|
||||
if (hdmi) {
|
||||
if (!ior->func->hdmi ||
|
||||
hdmi_max_ac_packet > 0x1f || hdmi_rekey > 0x7f ||
|
||||
(hdmi_scdc && !ior->func->hdmi->scdc))
|
||||
return -EINVAL;
|
||||
if (!ior->func->hdmi ||
|
||||
args->v0.max_ac_packet > 0x1f ||
|
||||
args->v0.rekey > 0x7f ||
|
||||
(args->v0.scdc && !ior->func->hdmi->scdc))
|
||||
return -EINVAL;
|
||||
|
||||
ior->func->hdmi->ctrl(ior, head, hdmi, hdmi_max_ac_packet, hdmi_rekey);
|
||||
if (ior->func->hdmi->scdc)
|
||||
ior->func->hdmi->scdc(ior, hdmi_scdc);
|
||||
}
|
||||
ior->func->hdmi->ctrl(ior, args->v0.head, args->v0.enable,
|
||||
args->v0.max_ac_packet, args->v0.rekey);
|
||||
if (ior->func->hdmi->scdc)
|
||||
ior->func->hdmi->scdc(ior, args->v0.khz, args->v0.scdc, args->v0.scdc_scrambling,
|
||||
args->v0.scdc_low_rates);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -209,14 +213,6 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc)
|
||||
case NVIF_OUTP_ACQUIRE_V0_SOR:
|
||||
ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_USER, args->v0.sor.hda);
|
||||
break;
|
||||
case NVIF_OUTP_ACQUIRE_V0_TMDS:
|
||||
ret = nvkm_uoutp_mthd_acquire_tmds(outp, args->v0.tmds.head,
|
||||
args->v0.tmds.hdmi,
|
||||
args->v0.tmds.hdmi_max_ac_packet,
|
||||
args->v0.tmds.hdmi_rekey,
|
||||
args->v0.tmds.hdmi_scdc,
|
||||
args->v0.tmds.hdmi_hda);
|
||||
break;
|
||||
case NVIF_OUTP_ACQUIRE_V0_LVDS:
|
||||
ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8);
|
||||
break;
|
||||
@ -370,6 +366,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
|
||||
{
|
||||
switch (mthd) {
|
||||
case NVIF_OUTP_V0_RELEASE : return nvkm_uoutp_mthd_release (outp, argv, argc);
|
||||
case NVIF_OUTP_V0_HDMI : return nvkm_uoutp_mthd_hdmi (outp, argv, argc);
|
||||
case NVIF_OUTP_V0_INFOFRAME : return nvkm_uoutp_mthd_infoframe (outp, argv, argc);
|
||||
case NVIF_OUTP_V0_HDA_ELD : return nvkm_uoutp_mthd_hda_eld (outp, argv, argc);
|
||||
case NVIF_OUTP_V0_DP_RETRAIN : return nvkm_uoutp_mthd_dp_retrain (outp, argv, argc);
|
||||
|
Loading…
Reference in New Issue
Block a user