[Nouveau] [PATCH 1/6] drm/nouveau: Extend NVKM HDMI power control method to set InfoFrames
Ilia Mirkin
imirkin at alum.mit.edu
Wed Jan 18 03:19:04 UTC 2017
On Tue, Jan 17, 2017 at 5:41 PM, Alastair Bridgewater
<alastair.bridgewater at gmail.com> wrote:
> The nouveau driver, in the Linux 3.7 days, used to try and set the
> AVI InfoFrame based on the selected display mode. These days, it
> uses a fixed set of InfoFrames. Start to correct that, by
> providing a mechanism whereby InfoFrame data may be passed to the
> NVKM functions that do the actual configuration.
>
> At this point, only establish the new parameters and their parsing,
> don't actually use the data anywhere yet (since it's not supplied
> anywhere).
>
> Signed-off-by: Alastair Bridgewater <alastair.bridgewater at gmail.com>
> ---
> drivers/gpu/drm/nouveau/include/nvif/cl5070.h | 16 ++++++++++-
> drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c | 32 +++++++++++++++++++++-
> .../gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c | 32 +++++++++++++++++++++-
> .../gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c | 32 +++++++++++++++++++++-
> .../gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c | 32 +++++++++++++++++++++-
> 5 files changed, 139 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
> index ae49dfd..a3ce3bf 100644
> --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
> +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
> @@ -76,7 +76,21 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
> __u8 state;
> __u8 max_ac_packet;
> __u8 rekey;
> - __u8 pad04[4];
> + __u8 flags;
> +#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME 0x01
> +#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME 0x02
> +#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME 0x04
These should come before flags, not after (based on the other ones).
Also, this is nv50_disp_sor_hdmi_pwr_v0, so they should be
NV50_DISP_SOR_HDMI_PWR_V0_FLAG_AUDIO_INFOFRAME
and so on.
> + __u8 pad05[3];
> +};
> +
> +struct nv50_disp_sor_hdmi_pwr_v0_infoframe {
> + __u8 version;
Why do you need a version here? Do you anticipate mixing and matching,
e.g. calling the sor_hdmi_pwr_v0 method with v0 or v1 infoframes
attached, and needing to tell them apart? I'd just as soon drop it and
not use nvif_unpack for these.
> + __u8 pad01[3];
> + __u32 header;
> + __u32 subpack0_low;
> + __u32 subpack0_high;
> + __u32 subpack1_low;
> + __u32 subpack1_high;
Is this nomenclature from the spec? I've never seen it... (not that
I'm some spec expert). Why not make it a __u8 buffer[20]?
> };
>
> struct nv50_disp_sor_lvds_script_v0 {
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
> index 1c4256e..f767588 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c
> @@ -36,11 +36,14 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
> union {
> struct nv50_disp_sor_hdmi_pwr_v0 v0;
> } *args = data;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
> u32 ctrl;
> int ret = -ENOSYS;
>
> nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
> - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
> + if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
> nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
> "max_ac_packet %d rekey %d\n",
> args->v0.version, args->v0.state,
> @@ -54,6 +57,33 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
> } else
> return ret;
>
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
> + audio_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *audio_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
> + avi_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *avi_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
> + vendor_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *vendor_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (size)
> + return -E2BIG;
> +
> if (!(ctrl & 0x40000000)) {
> nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000);
> nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000);
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
> index 632f02d..c492cd7 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c
> @@ -36,11 +36,14 @@ gf119_hdmi_ctrl(NV50_DISP_MTHD_V1)
> union {
> struct nv50_disp_sor_hdmi_pwr_v0 v0;
> } *args = data;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
> u32 ctrl;
> int ret = -ENOSYS;
>
> nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
> - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
> + if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
> nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
> "max_ac_packet %d rekey %d\n",
> args->v0.version, args->v0.state,
> @@ -53,6 +56,33 @@ gf119_hdmi_ctrl(NV50_DISP_MTHD_V1)
> } else
> return ret;
>
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
> + audio_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *audio_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
> + avi_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *avi_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
> + vendor_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *vendor_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (size)
> + return -E2BIG;
> +
> if (!(ctrl & 0x40000000)) {
> nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
> nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000);
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
> index 4e8067d..6c38d6d 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c
> @@ -37,11 +37,14 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
> union {
> struct nv50_disp_sor_hdmi_pwr_v0 v0;
> } *args = data;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
> u32 ctrl;
> int ret = -ENOSYS;
>
> nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
> - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
> + if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
> nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
> "max_ac_packet %d rekey %d\n",
> args->v0.version, args->v0.state,
> @@ -54,6 +57,33 @@ gk104_hdmi_ctrl(NV50_DISP_MTHD_V1)
> } else
> return ret;
>
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
> + audio_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *audio_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
> + avi_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *avi_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
> + vendor_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *vendor_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (size)
> + return -E2BIG;
> +
> if (!(ctrl & 0x40000000)) {
> nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
> nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000);
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
> index f1afc16..e2fbe4c 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c
> @@ -37,11 +37,14 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1)
> union {
> struct nv50_disp_sor_hdmi_pwr_v0 v0;
> } *args = data;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *audio_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *avi_infoframe = NULL;
> + struct nv50_disp_sor_hdmi_pwr_v0_infoframe *vendor_infoframe = NULL;
> u32 ctrl;
> int ret = -ENOSYS;
>
> nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
> - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
> + if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
> nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
> "max_ac_packet %d rekey %d\n",
> args->v0.version, args->v0.state,
> @@ -55,6 +58,33 @@ gt215_hdmi_ctrl(NV50_DISP_MTHD_V1)
> } else
> return ret;
>
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AUDIO_INFOFRAME) {
> + audio_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *audio_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_AVI_INFOFRAME) {
> + avi_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *avi_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (args->v0.flags &
> + NV50_DISP_MTHD_V1_SOR_HDMI_PWR_FLAG_VENDOR_INFOFRAME) {
> + vendor_infoframe = data;
> + if ((ret = nvif_unpack(-ENOSYS, &data, &size,
> + *vendor_infoframe, 0, 0, true)))
> + return ret;
> + }
> +
> + if (size)
> + return -E2BIG;
> +
> if (!(ctrl & 0x40000000)) {
> nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000);
> nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000);
> --
> 2.10.2
>
> _______________________________________________
> Nouveau mailing list
> Nouveau at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/nouveau
More information about the Nouveau
mailing list