diff options
author | Emily Deng <Emily.Deng@amd.com> | 2016-09-30 13:02:18 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-10-25 14:38:07 -0400 |
commit | 0f66356d24c6950bf6b1a47df7c77ca57305074d (patch) | |
tree | 54fd08d5459182f64334431bcc3e4e77bf8ca628 /drivers/gpu | |
parent | 483ef98588aa9f2236392f505beadb621f288861 (diff) |
drm/amd/amdgpu: For virtual display, enable multi crtcs. (v3)
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: Emily Deng <Emily.Deng@amd.com>
Reviewed-By: Emily Deng <Emily.Deng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 5 | ||||
-rw-r--r-- | 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 874c33b43955..22d331947aca 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) | |||
1238 | if (amdgpu_virtual_display) { | 1238 | if (amdgpu_virtual_display) { |
1239 | struct drm_device *ddev = adev->ddev; | 1239 | struct drm_device *ddev = adev->ddev; |
1240 | const char *pci_address_name = pci_name(ddev->pdev); | 1240 | const char *pci_address_name = pci_name(ddev->pdev); |
1241 | char *pciaddstr, *pciaddstr_tmp, *pciaddname; | 1241 | char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname; |
1242 | 1242 | ||
1243 | pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL); | 1243 | pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL); |
1244 | pciaddstr_tmp = pciaddstr; | 1244 | pciaddstr_tmp = pciaddstr; |
1245 | while ((pciaddname = strsep(&pciaddstr_tmp, ";"))) { | 1245 | while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) { |
1246 | pciaddname = strsep(&pciaddname_tmp, ","); | ||
1246 | if (!strcmp(pci_address_name, pciaddname)) { | 1247 | if (!strcmp(pci_address_name, pciaddname)) { |
1248 | long num_crtc; | ||
1249 | int res = -1; | ||
1250 | |||
1247 | adev->enable_virtual_display = true; | 1251 | adev->enable_virtual_display = true; |
1252 | |||
1253 | if (pciaddname_tmp) | ||
1254 | res = kstrtol(pciaddname_tmp, 10, | ||
1255 | &num_crtc); | ||
1256 | |||
1257 | if (!res) { | ||
1258 | if (num_crtc < 1) | ||
1259 | num_crtc = 1; | ||
1260 | if (num_crtc > 6) | ||
1261 | num_crtc = 6; | ||
1262 | adev->mode_info.num_crtc = num_crtc; | ||
1263 | } else { | ||
1264 | adev->mode_info.num_crtc = 1; | ||
1265 | } | ||
1248 | break; | 1266 | break; |
1249 | } | 1267 | } |
1250 | } | 1268 | } |
1251 | 1269 | ||
1252 | DRM_INFO("virtual display string:%s, %s:virtual_display:%d\n", | 1270 | DRM_INFO("virtual display string:%s, %s:virtual_display:%d, num_crtc:%d\n", |
1253 | amdgpu_virtual_display, pci_address_name, | 1271 | amdgpu_virtual_display, pci_address_name, |
1254 | adev->enable_virtual_display); | 1272 | adev->enable_virtual_display, adev->mode_info.num_crtc); |
1255 | 1273 | ||
1256 | kfree(pciaddstr); | 1274 | kfree(pciaddstr); |
1257 | } | 1275 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 71ed27eb3dde..2201f05ecc94 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); | |||
201 | MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)"); | 201 | MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)"); |
202 | module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444); | 202 | module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444); |
203 | 203 | ||
204 | MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)"); | 204 | MODULE_PARM_DESC(virtual_display, |
205 | "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x,x;xxxx:xx:xx.x,x)"); | ||
205 | module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444); | 206 | module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444); |
206 | 207 | ||
207 | static const struct pci_device_id pciidlist[] = { | 208 | 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 7b0eff7d060b..1e23334b07fb 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 { | |||
341 | int num_dig; /* number of dig blocks */ | 341 | int num_dig; /* number of dig blocks */ |
342 | int disp_priority; | 342 | int disp_priority; |
343 | const struct amdgpu_display_funcs *funcs; | 343 | const struct amdgpu_display_funcs *funcs; |
344 | struct hrtimer vblank_timer; | ||
345 | enum amdgpu_interrupt_state vsync_timer_enabled; | ||
346 | }; | 344 | }; |
347 | 345 | ||
348 | #define AMDGPU_MAX_BL_LEVEL 0xFF | 346 | #define AMDGPU_MAX_BL_LEVEL 0xFF |
@@ -413,6 +411,9 @@ struct amdgpu_crtc { | |||
413 | u32 wm_high; | 411 | u32 wm_high; |
414 | u32 lb_vblank_lead_lines; | 412 | u32 lb_vblank_lead_lines; |
415 | struct drm_display_mode hw_mode; | 413 | struct drm_display_mode hw_mode; |
414 | /* for virtual dce */ | ||
415 | struct hrtimer vblank_timer; | ||
416 | enum amdgpu_interrupt_state vsync_timer_enabled; | ||
416 | }; | 417 | }; |
417 | 418 | ||
418 | struct amdgpu_encoder_atom_dig { | 419 | 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 b981e769603b..226b914aa315 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) | |||
335 | amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; | 335 | amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; |
336 | amdgpu_crtc->encoder = NULL; | 336 | amdgpu_crtc->encoder = NULL; |
337 | amdgpu_crtc->connector = NULL; | 337 | amdgpu_crtc->connector = NULL; |
338 | amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; | ||
338 | drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); | 339 | drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); |
339 | 340 | ||
340 | return 0; | 341 | return 0; |
@@ -344,11 +345,9 @@ static int dce_virtual_early_init(void *handle) | |||
344 | { | 345 | { |
345 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 346 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
346 | 347 | ||
347 | adev->mode_info.vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; | ||
348 | dce_virtual_set_display_funcs(adev); | 348 | dce_virtual_set_display_funcs(adev); |
349 | dce_virtual_set_irq_funcs(adev); | 349 | dce_virtual_set_irq_funcs(adev); |
350 | 350 | ||
351 | adev->mode_info.num_crtc = 1; | ||
352 | adev->mode_info.num_hpd = 1; | 351 | adev->mode_info.num_hpd = 1; |
353 | adev->mode_info.num_dig = 1; | 352 | adev->mode_info.num_dig = 1; |
354 | return 0; | 353 | return 0; |
@@ -756,14 +755,13 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev, | |||
756 | 755 | ||
757 | static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) | 756 | static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) |
758 | { | 757 | { |
759 | struct amdgpu_mode_info *mode_info = | 758 | struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, |
760 | container_of(vblank_timer, struct amdgpu_mode_info , vblank_timer); | 759 | struct amdgpu_crtc, vblank_timer); |
761 | struct amdgpu_device *adev = | 760 | struct drm_device *ddev = amdgpu_crtc->base.dev; |
762 | container_of(mode_info, struct amdgpu_device , mode_info); | 761 | struct amdgpu_device *adev = ddev->dev_private; |
763 | unsigned crtc = 0; | ||
764 | 762 | ||
765 | drm_handle_vblank(adev->ddev, crtc); | 763 | drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); |
766 | dce_virtual_pageflip(adev, crtc); | 764 | dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); |
767 | hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), | 765 | hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), |
768 | HRTIMER_MODE_REL); | 766 | HRTIMER_MODE_REL); |
769 | 767 | ||
@@ -779,18 +777,22 @@ static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *ad | |||
779 | return; | 777 | return; |
780 | } | 778 | } |
781 | 779 | ||
782 | if (state && !adev->mode_info.vsync_timer_enabled) { | 780 | if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { |
783 | DRM_DEBUG("Enable software vsync timer\n"); | 781 | DRM_DEBUG("Enable software vsync timer\n"); |
784 | hrtimer_init(&adev->mode_info.vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 782 | hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer, |
785 | hrtimer_set_expires(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD)); | 783 | CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
786 | adev->mode_info.vblank_timer.function = dce_virtual_vblank_timer_handle; | 784 | hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer, |
787 | hrtimer_start(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL); | 785 | ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD)); |
788 | } else if (!state && adev->mode_info.vsync_timer_enabled) { | 786 | adev->mode_info.crtcs[crtc]->vblank_timer.function = |
787 | dce_virtual_vblank_timer_handle; | ||
788 | hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer, | ||
789 | ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL); | ||
790 | } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { | ||
789 | DRM_DEBUG("Disable software vsync timer\n"); | 791 | DRM_DEBUG("Disable software vsync timer\n"); |
790 | hrtimer_cancel(&adev->mode_info.vblank_timer); | 792 | hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer); |
791 | } | 793 | } |
792 | 794 | ||
793 | adev->mode_info.vsync_timer_enabled = state; | 795 | adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state; |
794 | DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state); | 796 | DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state); |
795 | } | 797 | } |
796 | 798 | ||
@@ -800,13 +802,11 @@ static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, | |||
800 | unsigned type, | 802 | unsigned type, |
801 | enum amdgpu_interrupt_state state) | 803 | enum amdgpu_interrupt_state state) |
802 | { | 804 | { |
803 | switch (type) { | 805 | if (type > AMDGPU_CRTC_IRQ_VBLANK6) |
804 | case AMDGPU_CRTC_IRQ_VBLANK1: | 806 | return -EINVAL; |
805 | dce_virtual_set_crtc_vblank_interrupt_state(adev, 0, state); | 807 | |
806 | break; | 808 | dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state); |
807 | default: | 809 | |
808 | break; | ||
809 | } | ||
810 | return 0; | 810 | return 0; |
811 | } | 811 | } |
812 | 812 | ||