[PATCH 2/2] Allow/Fix use of multiple ZaphodHead outputs per x-screen.

Alex Deucher alexdeucher at gmail.com
Fri Jun 5 06:12:21 PDT 2015


On Fri, Jun 5, 2015 at 8:33 AM, Mario Kleiner
<mario.kleiner.de at gmail.com> wrote:
> Defining multiple ZaphodHead outputs per x-screen in a
> multiple x-screen's per gpu configuration caused all
> outputs except one per x-screen to go dark, because
> there was a fixed mapping x-screen number -> crtc number,
> limiting the number of crtc's per x-screen to one.
>
> On a ZaphodHead's setup, be more clever and assign
> as many crtc's to a given x-screen as there are
> ZaphodHeads defined for that screen, assuming
> there are enough unused crtc's available.
>
> Tested on a triple display setup with different combos
> of one, two or three ZaphodHeads per one, two or three
> x-screens.
>
> This is a port of almost identical code from
> nouveau-ddx.
>
> Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

> ---
>  src/drmmode_display.c | 44 +++++++++++++++++++++++++++++++-------------
>  src/radeon_probe.c    | 15 +++++++++++++++
>  src/radeon_probe.h    |  2 ++
>  3 files changed, 48 insertions(+), 13 deletions(-)
>
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index c12bf51..a9f5481 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -1012,15 +1012,16 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
>         drmmode_crtc->hw_id = tmp;
>  }
>
> -static void
> +static unsigned int
>  drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
>  {
>         xf86CrtcPtr crtc;
>         drmmode_crtc_private_ptr drmmode_crtc;
> +       RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
>
>         crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
>         if (crtc == NULL)
> -               return;
> +               return 0;
>
>         drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
>         drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
> @@ -1028,7 +1029,12 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
>         crtc->driver_private = drmmode_crtc;
>         drmmode_crtc_hw_id(crtc);
>
> -       return;
> +       /* Mark num'th crtc as in use on this device. */
> +       pRADEONEnt->assigned_crtcs |= (1 << num);
> +       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
> +                  "Allocated crtc nr. %d to this screen.\n", num);
> +
> +       return 1;
>  }
>
>  static xf86OutputStatus
> @@ -1461,7 +1467,7 @@ drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
>         }
>  }
>
> -static void
> +static unsigned int
>  drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic)
>  {
>         xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
> @@ -1478,7 +1484,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
>
>         koutput = drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
>         if (!koutput)
> -               return;
> +               return 0;
>
>         for (i = 0; i < koutput->count_props; i++) {
>                 props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
> @@ -1524,7 +1530,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
>                         for (i = 0; i < koutput->count_encoders; i++)
>                                 drmModeFreeEncoder(kencoders[i]);
>                         free(kencoders);
> -                       return;
> +                       return 0;
>                 }
>         }
>
> @@ -1587,7 +1593,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
>                 drmmode_output_create_resources(output);
>         }
>
> -       return;
> +       return 1;
>  out_free_encoders:
>         if (kencoders){
>                 for (i = 0; i < koutput->count_encoders; i++)
> @@ -1595,7 +1601,7 @@ out_free_encoders:
>                 free(kencoders);
>         }
>         drmModeFreeConnector(koutput);
> -
> +       return 0;
>  }
>
>  uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
> @@ -2030,8 +2036,10 @@ drm_wakeup_handler(pointer data, int err, pointer p)
>
>  Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
>  {
> +       RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
>         int i, num_dvi = 0, num_hdmi = 0;
>         drmModeResPtr mode_res;
> +       unsigned int crtcs_needed = 0;
>
>         xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
>
> @@ -2041,14 +2049,24 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
>         if (!mode_res)
>                 return FALSE;
>
> +       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing outputs ...\n");
> +       for (i = 0; i < mode_res->count_connectors; i++)
> +               crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res,
> +                                                   i, &num_dvi, &num_hdmi, 0);
> +       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
> +                  "%d crtcs needed for screen.\n", crtcs_needed);
> +
>         drmmode->count_crtcs = mode_res->count_crtcs;
>         xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height);
>         for (i = 0; i < mode_res->count_crtcs; i++)
> -               if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
> -                       drmmode_crtc_init(pScrn, drmmode, mode_res, i);
> -
> -       for (i = 0; i < mode_res->count_connectors; i++)
> -               drmmode_output_init(pScrn, drmmode, mode_res, i, &num_dvi, &num_hdmi, 0);
> +               if (!xf86IsEntityShared(pScrn->entityList[0]) ||
> +                   (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i))))
> +                       crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
> +
> +       /* All ZaphodHeads outputs provided with matching crtcs? */
> +       if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
> +               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
> +                          "%d ZaphodHeads crtcs unavailable. Trouble!\n", crtcs_needed);
>
>         /* workout clones */
>         drmmode_clones_init(pScrn, drmmode, mode_res);
> diff --git a/src/radeon_probe.c b/src/radeon_probe.c
> index ad1e96e..45a89f3 100644
> --- a/src/radeon_probe.c
> +++ b/src/radeon_probe.c
> @@ -174,6 +174,13 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
>              pRADEONEnt = pPriv->ptr;
>              pRADEONEnt->HasSecondary = TRUE;
>          }
> +
> +        /* Reset settings which must not persist across server regeneration */
> +        if (pRADEONEnt->reinitGeneration != serverGeneration) {
> +            pRADEONEnt->reinitGeneration = serverGeneration;
> +            /* Clear mask of assigned crtc's in this generation to "none" */
> +            pRADEONEnt->assigned_crtcs = 0;
> +        }
>      }
>
>      free(pEnt);
> @@ -272,11 +279,19 @@ radeon_platform_probe(DriverPtr pDriver,
>              pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
>              pRADEONEnt = pPriv->ptr;
>              pRADEONEnt->HasSecondary = FALSE;
> +            pRADEONEnt->assigned_crtcs = 0;
>          } else {
>              pRADEONEnt = pPriv->ptr;
>              pRADEONEnt->HasSecondary = TRUE;
>          }
>          pRADEONEnt->platform_dev = dev;
> +
> +        /* Reset settings which must not persist across server regeneration */
> +        if (pRADEONEnt->reinitGeneration != serverGeneration) {
> +            pRADEONEnt->reinitGeneration = serverGeneration;
> +            /* Clear mask of assigned crtc's in this generation to "none" */
> +            pRADEONEnt->assigned_crtcs = 0;
> +        }
>      }
>
>      free(pEnt);
> diff --git a/src/radeon_probe.h b/src/radeon_probe.h
> index 3fe4644..cfe5091 100644
> --- a/src/radeon_probe.h
> +++ b/src/radeon_probe.h
> @@ -142,6 +142,8 @@ typedef struct
>      int fd_ref;
>      unsigned long     fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */
>      int fd_wakeup_ref;
> +    unsigned int assigned_crtcs;
> +    unsigned long reinitGeneration;
>  #ifdef XSERVER_PLATFORM_BUS
>      struct xf86_platform_device *platform_dev;
>  #endif
> --
> 1.9.1
>
> _______________________________________________
> xorg-driver-ati mailing list
> xorg-driver-ati at lists.x.org
> http://lists.x.org/mailman/listinfo/xorg-driver-ati


More information about the xorg-driver-ati mailing list