[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