Reviewed-By: Emily Deng <Emily.Deng at amd.com> > -----Original Message----- > From: Alex Deucher [mailto:alexdeucher at gmail.com] > Sent: Saturday, October 01, 2016 1:09 AM > To: amd-gfx at lists.freedesktop.org > Cc: Deng, Emily <Emily.Deng at amd.com>; Deucher, Alexander > <Alexander.Deucher at amd.com> > Subject: [PATCH 7/7] drm/amd/amdgpu: For virtual display, enable multi > crtcs. (v3) > > From: Emily Deng <Emily.Deng at amd.com> > > Enable multi crtcs for virtual display, user can set the number of crtcs by > amdgpu module parameter virtual_display. > > v2: make timers per crtc > v3: agd: simplify implementation > > Signed-off-by: Alex Deucher <alexander.deucher at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 28 +++++++++++++---- > drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- > drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 5 ++-- > drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 48 +++++++++++++++-------- > ------- > 4 files changed, 52 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > index 13caa52..91dc851 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c > @@ -1238,20 +1238,38 @@ static void > amdgpu_device_enable_virtual_display(struct amdgpu_device *adev) > if (amdgpu_virtual_display) { > struct drm_device *ddev = adev->ddev; > const char *pci_address_name = pci_name(ddev->pdev); > - char *pciaddstr, *pciaddstr_tmp, *pciaddname; > + char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, > *pciaddname; > > pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL); > pciaddstr_tmp = pciaddstr; > - while ((pciaddname = strsep(&pciaddstr_tmp, ";"))) { > + while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) { > + pciaddname = strsep(&pciaddname_tmp, ","); > if (!strcmp(pci_address_name, pciaddname)) { > + long num_crtc; > + int res = -1; > + > adev->enable_virtual_display = true; > + > + if (pciaddname_tmp) > + res = kstrtol(pciaddname_tmp, 10, > + &num_crtc); > + > + if (!res) { > + if (num_crtc < 1) > + num_crtc = 1; > + if (num_crtc > 6) > + num_crtc = 6; > + adev->mode_info.num_crtc = > num_crtc; > + } else { > + adev->mode_info.num_crtc = 1; > + } > break; > } > } > > - DRM_INFO("virtual display > string:%s, %s:virtual_display:%d\n", > - amdgpu_virtual_display, pci_address_name, > - adev->enable_virtual_display); > + DRM_INFO("virtual display string:%s, %s:virtual_display:%d, > num_crtc:%d\n", > + amdgpu_virtual_display, pci_address_name, > + adev->enable_virtual_display, adev- > >mode_info.num_crtc); > > kfree(pciaddstr); > } > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c > index 728e8ca..721ef24 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c > @@ -201,7 +201,8 @@ module_param_named(pg_mask, amdgpu_pg_mask, > uint, 0444); MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)"); > module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444); > > -MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the > virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)"); > +MODULE_PARM_DESC(virtual_display, > + "Enable virtual display feature (the virtual_display will be set > +like xxxx:xx:xx.x,x;xxxx:xx:xx.x,x)"); > module_param_named(virtual_display, amdgpu_virtual_display, charp, > 0444); > > static const struct pci_device_id pciidlist[] = { diff --git > a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h > index 7b0eff7..1e23334 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h > @@ -341,8 +341,6 @@ struct amdgpu_mode_info { > int num_dig; /* number of dig blocks */ > int disp_priority; > const struct amdgpu_display_funcs *funcs; > - struct hrtimer vblank_timer; > - enum amdgpu_interrupt_state vsync_timer_enabled; > }; > > #define AMDGPU_MAX_BL_LEVEL 0xFF > @@ -413,6 +411,9 @@ struct amdgpu_crtc { > u32 wm_high; > u32 lb_vblank_lead_lines; > struct drm_display_mode hw_mode; > + /* for virtual dce */ > + struct hrtimer vblank_timer; > + enum amdgpu_interrupt_state vsync_timer_enabled; > }; > > struct amdgpu_encoder_atom_dig { > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c > index 0c8b21e..682e066 100644 > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c > @@ -335,6 +335,7 @@ static int dce_virtual_crtc_init(struct amdgpu_device > *adev, int index) > amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; > amdgpu_crtc->encoder = NULL; > amdgpu_crtc->connector = NULL; > + amdgpu_crtc->vsync_timer_enabled = > AMDGPU_IRQ_STATE_DISABLE; > drm_crtc_helper_add(&amdgpu_crtc->base, > &dce_virtual_crtc_helper_funcs); > > return 0; > @@ -344,11 +345,9 @@ static int dce_virtual_early_init(void *handle) { > struct amdgpu_device *adev = (struct amdgpu_device *)handle; > > - adev->mode_info.vsync_timer_enabled = > AMDGPU_IRQ_STATE_DISABLE; > dce_virtual_set_display_funcs(adev); > dce_virtual_set_irq_funcs(adev); > > - adev->mode_info.num_crtc = 1; > adev->mode_info.num_hpd = 1; > adev->mode_info.num_dig = 1; > return 0; > @@ -760,14 +759,13 @@ static int dce_virtual_pageflip(struct > amdgpu_device *adev, > > static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer > *vblank_timer) { > - struct amdgpu_mode_info *mode_info = > - container_of(vblank_timer, struct amdgpu_mode_info , > vblank_timer); > - struct amdgpu_device *adev = > - container_of(mode_info, struct amdgpu_device , > mode_info); > - unsigned crtc = 0; > + struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, > + struct amdgpu_crtc, > vblank_timer); > + struct drm_device *ddev = amdgpu_crtc->base.dev; > + struct amdgpu_device *adev = ddev->dev_private; > > - drm_handle_vblank(adev->ddev, crtc); > - dce_virtual_pageflip(adev, crtc); > + drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); > + dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); > hrtimer_start(vblank_timer, ktime_set(0, > DCE_VIRTUAL_VBLANK_PERIOD), > HRTIMER_MODE_REL); > > @@ -783,18 +781,22 @@ static void > dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *ad > return; > } > > - if (state && !adev->mode_info.vsync_timer_enabled) { > + if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { > DRM_DEBUG("Enable software vsync timer\n"); > - hrtimer_init(&adev->mode_info.vblank_timer, > CLOCK_MONOTONIC, HRTIMER_MODE_REL); > - hrtimer_set_expires(&adev->mode_info.vblank_timer, > ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD)); > - adev->mode_info.vblank_timer.function = > dce_virtual_vblank_timer_handle; > - hrtimer_start(&adev->mode_info.vblank_timer, ktime_set(0, > DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL); > - } else if (!state && adev->mode_info.vsync_timer_enabled) { > + hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer, > + CLOCK_MONOTONIC, HRTIMER_MODE_REL); > + hrtimer_set_expires(&adev->mode_info.crtcs[crtc]- > >vblank_timer, > + ktime_set(0, > DCE_VIRTUAL_VBLANK_PERIOD)); > + adev->mode_info.crtcs[crtc]->vblank_timer.function = > + dce_virtual_vblank_timer_handle; > + hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer, > + ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), > HRTIMER_MODE_REL); > + } else if (!state && adev->mode_info.crtcs[crtc]- > >vsync_timer_enabled) > +{ > DRM_DEBUG("Disable software vsync timer\n"); > - hrtimer_cancel(&adev->mode_info.vblank_timer); > + hrtimer_cancel(&adev->mode_info.crtcs[crtc]- > >vblank_timer); > } > > - adev->mode_info.vsync_timer_enabled = state; > + adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state; > DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, > state); } > > @@ -804,13 +806,11 @@ static int dce_virtual_set_crtc_irq_state(struct > amdgpu_device *adev, > unsigned type, > enum amdgpu_interrupt_state state) > { > - switch (type) { > - case AMDGPU_CRTC_IRQ_VBLANK1: > - dce_virtual_set_crtc_vblank_interrupt_state(adev, 0, state); > - break; > - default: > - break; > - } > + if (type > AMDGPU_CRTC_IRQ_VBLANK6) > + return -EINVAL; > + > + dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state); > + > return 0; > } > > -- > 2.5.5