aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorEmily Deng <Emily.Deng@amd.com>2016-09-30 13:02:18 -0400
committerAlex Deucher <alexander.deucher@amd.com>2016-10-25 14:38:07 -0400
commit0f66356d24c6950bf6b1a47df7c77ca57305074d (patch)
tree54fd08d5459182f64334431bcc3e4e77bf8ca628 /drivers/gpu
parent483ef98588aa9f2236392f505beadb621f288861 (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.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_virtual.c48
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);
201MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)"); 201MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)");
202module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444); 202module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444);
203 203
204MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)"); 204MODULE_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)");
205module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444); 206module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444);
206 207
207static const struct pci_device_id pciidlist[] = { 208static 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
418struct amdgpu_encoder_atom_dig { 419struct 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
757static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) 756static 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