mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-19 09:04:51 +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;
|
struct drm_hdmi_info *hdmi = &nv_connector->base.display_info.hdmi;
|
||||||
union hdmi_infoframe infoframe = { 0 };
|
union hdmi_infoframe infoframe = { 0 };
|
||||||
const u8 rekey = 56; /* binary driver, and tegra, constant */
|
const u8 rekey = 56; /* binary driver, and tegra, constant */
|
||||||
u8 scdc = 0;
|
|
||||||
u32 max_ac_packet;
|
u32 max_ac_packet;
|
||||||
struct {
|
struct {
|
||||||
struct nvif_outp_infoframe_v0 infoframe;
|
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 -= 18; /* constant from tegra */
|
||||||
max_ac_packet /= 32;
|
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;
|
const bool high_tmds_clock_ratio = mode->clock > 340000;
|
||||||
|
u8 scdc;
|
||||||
|
|
||||||
ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &scdc);
|
ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &scdc);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -812,8 +812,9 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
|
|||||||
scdc, ret);
|
scdc, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nvif_outp_acquire_tmds(&nv_encoder->outp, nv_crtc->index, true,
|
ret = nvif_outp_hdmi(&nv_encoder->outp, nv_crtc->index, true, max_ac_packet, rekey,
|
||||||
max_ac_packet, rekey, scdc, hda);
|
mode->clock, hdmi->scdc.supported, hdmi->scdc.scrambling.supported,
|
||||||
|
hdmi->scdc.scrambling.low_rates);
|
||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1852,7 +1853,6 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
|
|||||||
switch (nv_encoder->dcb->type) {
|
switch (nv_encoder->dcb->type) {
|
||||||
case DCB_OUTPUT_TMDS:
|
case DCB_OUTPUT_TMDS:
|
||||||
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
|
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
|
||||||
nvif_outp_acquire_tmds(&nv_encoder->outp, false, false, 0, 0, 0, false);
|
|
||||||
break;
|
break;
|
||||||
case DCB_OUTPUT_DP:
|
case DCB_OUTPUT_DP:
|
||||||
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
|
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_LOAD_DETECT 0x20
|
||||||
|
|
||||||
|
#define NVIF_OUTP_V0_HDMI 0x50
|
||||||
|
|
||||||
#define NVIF_OUTP_V0_INFOFRAME 0x60
|
#define NVIF_OUTP_V0_INFOFRAME 0x60
|
||||||
#define NVIF_OUTP_V0_HDA_ELD 0x61
|
#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_DAC 0x00
|
||||||
#define NVIF_OUTP_ACQUIRE_V0_SOR 0x01
|
#define NVIF_OUTP_ACQUIRE_V0_SOR 0x01
|
||||||
#define NVIF_OUTP_ACQUIRE_V0_PIOR 0x02
|
#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_LVDS 0x03
|
||||||
#define NVIF_OUTP_ACQUIRE_V0_DP 0x04
|
#define NVIF_OUTP_ACQUIRE_V0_DP 0x04
|
||||||
__u8 type;
|
__u8 type;
|
||||||
@ -73,17 +74,6 @@ union nvif_outp_acquire_args {
|
|||||||
struct {
|
struct {
|
||||||
__u8 hda;
|
__u8 hda;
|
||||||
} sor;
|
} 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 {
|
struct {
|
||||||
__u8 dual;
|
__u8 dual;
|
||||||
__u8 bpc8;
|
__u8 bpc8;
|
||||||
@ -128,6 +118,20 @@ union nvif_outp_release_args {
|
|||||||
} vn;
|
} 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 {
|
union nvif_outp_infoframe_args {
|
||||||
struct nvif_outp_infoframe_v0 {
|
struct nvif_outp_infoframe_v0 {
|
||||||
__u8 version;
|
__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_dac(struct nvif_outp *);
|
||||||
int nvif_outp_acquire_sor(struct nvif_outp *, bool hda);
|
int nvif_outp_acquire_sor(struct nvif_outp *, bool hda);
|
||||||
int nvif_outp_acquire_pior(struct nvif_outp *);
|
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_lvds(struct nvif_outp *, bool dual, bool bpc8);
|
||||||
int nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
|
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);
|
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;
|
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_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_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
|
||||||
int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
|
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
|
int
|
||||||
nvif_outp_acquire_tmds(struct nvif_outp *outp, int head,
|
nvif_outp_hdmi(struct nvif_outp *outp, int head, bool enable, u8 max_ac_packet, u8 rekey,
|
||||||
bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda)
|
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;
|
int ret;
|
||||||
|
|
||||||
args.tmds.head = head;
|
args.version = 0;
|
||||||
args.tmds.hdmi = hdmi;
|
args.head = head;
|
||||||
args.tmds.hdmi_max_ac_packet = max_ac_packet;
|
args.enable = enable;
|
||||||
args.tmds.hdmi_rekey = rekey;
|
args.max_ac_packet = max_ac_packet;
|
||||||
args.tmds.hdmi_scdc = scdc;
|
args.rekey = rekey;
|
||||||
args.tmds.hdmi_hda = hda;
|
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,
|
NVIF_ERRON(ret, &outp->object,
|
||||||
"[ACQUIRE proto:TMDS head:%d hdmi:%d max_ac_packet:%d rekey:%d scdc:%d hda:%d]"
|
"[HDMI head:%d enable:%d max_ac_packet:%d rekey:%d khz:%d scdc:%d "
|
||||||
" or:%d link:%d", args.tmds.head, args.tmds.hdmi, args.tmds.hdmi_max_ac_packet,
|
"scdc_scrambling:%d scdc_low_rates:%d]",
|
||||||
args.tmds.hdmi_rekey, args.tmds.hdmi_scdc, args.tmds.hdmi_hda,
|
args.head, args.enable, args.max_ac_packet, args.rekey, args.khz,
|
||||||
args.or, args.link);
|
args.scdc, args.scdc_scrambling, args.scdc_low_rates);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,15 +68,23 @@ gm200_sor_dp = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
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;
|
struct nvkm_device *device = ior->disp->engine.subdev.device;
|
||||||
const u32 soff = nv50_ior_base(ior);
|
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);
|
nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl);
|
||||||
|
|
||||||
ior->tmds.high_speed = !!(scdc & 0x2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct nvkm_ior_func_hdmi
|
const struct nvkm_ior_func_hdmi
|
||||||
|
@ -65,7 +65,8 @@ struct nvkm_ior_func {
|
|||||||
|
|
||||||
const struct nvkm_ior_func_hdmi {
|
const struct nvkm_ior_func_hdmi {
|
||||||
void (*ctrl)(struct nvkm_ior *, int head, bool enable, u8 max_ac_packet, u8 rekey);
|
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_avi)(struct nvkm_ior *, int head, void *data, u32 size);
|
||||||
void (*infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 size);
|
void (*infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 size);
|
||||||
} *hdmi;
|
} *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 *);
|
void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *);
|
||||||
int gm200_sor_route_get(struct nvkm_outp *, int *);
|
int gm200_sor_route_get(struct nvkm_outp *, int *);
|
||||||
extern const struct nvkm_ior_func_hdmi gm200_sor_hdmi;
|
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;
|
extern const struct nvkm_ior_func_dp gm200_sor_dp;
|
||||||
void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
|
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
|
static int
|
||||||
nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 head, u8 hdmi, u8 hdmi_max_ac_packet,
|
nvkm_uoutp_mthd_hdmi(struct nvkm_outp *outp, void *argv, u32 argc)
|
||||||
u8 hdmi_rekey, u8 hdmi_scdc, u8 hdmi_hda)
|
|
||||||
{
|
{
|
||||||
|
union nvif_outp_hdmi_args *args = argv;
|
||||||
struct nvkm_ior *ior = outp->ior;
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
if (hdmi) {
|
if (!ior->func->hdmi ||
|
||||||
if (!ior->func->hdmi ||
|
args->v0.max_ac_packet > 0x1f ||
|
||||||
hdmi_max_ac_packet > 0x1f || hdmi_rekey > 0x7f ||
|
args->v0.rekey > 0x7f ||
|
||||||
(hdmi_scdc && !ior->func->hdmi->scdc))
|
(args->v0.scdc && !ior->func->hdmi->scdc))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ior->func->hdmi->ctrl(ior, head, hdmi, hdmi_max_ac_packet, hdmi_rekey);
|
ior->func->hdmi->ctrl(ior, args->v0.head, args->v0.enable,
|
||||||
if (ior->func->hdmi->scdc)
|
args->v0.max_ac_packet, args->v0.rekey);
|
||||||
ior->func->hdmi->scdc(ior, hdmi_scdc);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -209,14 +213,6 @@ nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc)
|
|||||||
case NVIF_OUTP_ACQUIRE_V0_SOR:
|
case NVIF_OUTP_ACQUIRE_V0_SOR:
|
||||||
ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_USER, args->v0.sor.hda);
|
ret = nvkm_outp_acquire_or(outp, NVKM_OUTP_USER, args->v0.sor.hda);
|
||||||
break;
|
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:
|
case NVIF_OUTP_ACQUIRE_V0_LVDS:
|
||||||
ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8);
|
ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8);
|
||||||
break;
|
break;
|
||||||
@ -370,6 +366,7 @@ nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
|
|||||||
{
|
{
|
||||||
switch (mthd) {
|
switch (mthd) {
|
||||||
case NVIF_OUTP_V0_RELEASE : return nvkm_uoutp_mthd_release (outp, argv, argc);
|
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_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_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);
|
case NVIF_OUTP_V0_DP_RETRAIN : return nvkm_uoutp_mthd_dp_retrain (outp, argv, argc);
|
||||||
|
Loading…
Reference in New Issue
Block a user