]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/amdgpu: use begin/end_use for VCE power/clock gating
authorChristian König <christian.koenig@amd.com>
Wed, 20 Jul 2016 14:53:36 +0000 (16:53 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 29 Jul 2016 18:37:03 +0000 (14:37 -0400)
This fixes turning power and clock on when it is actually needed.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Edward O'Callaghan <funfunctor@folklore1984.net>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c

index 51c4924b60b7fdaf12cb37974fe624a89db8cd73..02a0d19ce54cbf5e5e886b2844b458bc66322826 100644 (file)
@@ -1702,6 +1702,7 @@ struct amdgpu_vce {
        struct drm_file         *filp[AMDGPU_MAX_VCE_HANDLES];
        uint32_t                img_size[AMDGPU_MAX_VCE_HANDLES];
        struct delayed_work     idle_work;
+       struct mutex            idle_mutex;
        const struct firmware   *fw;    /* VCE firmware */
        struct amdgpu_ring      ring[AMDGPU_MAX_VCE_RINGS];
        struct amdgpu_irq_src   irq;
index aeeeb72ebbc4052dc45d22935dea9f66b4870225..6b49d406daf6493d3017ab7bea1a0524007f6121 100644 (file)
@@ -85,8 +85,6 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
        unsigned ucode_version, version_major, version_minor, binary_id;
        int i, r;
 
-       INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler);
-
        switch (adev->asic_type) {
 #ifdef CONFIG_DRM_AMDGPU_CIK
        case CHIP_BONAIRE:
@@ -197,6 +195,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
                adev->vce.filp[i] = NULL;
        }
 
+       INIT_DELAYED_WORK(&adev->vce.idle_work, amdgpu_vce_idle_work_handler);
+       mutex_init(&adev->vce.idle_mutex);
+
        return 0;
 }
 
@@ -220,6 +221,7 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
        amdgpu_ring_fini(&adev->vce.ring[1]);
 
        release_firmware(adev->vce.fw);
+       mutex_destroy(&adev->vce.idle_mutex);
 
        return 0;
 }
@@ -315,19 +317,19 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work)
 }
 
 /**
- * amdgpu_vce_note_usage - power up VCE
+ * amdgpu_vce_ring_begin_use - power up VCE
  *
- * @adev: amdgpu_device pointer
+ * @ring: amdgpu ring
  *
  * Make sure VCE is powerd up when we want to use it
  */
-static void amdgpu_vce_note_usage(struct amdgpu_device *adev)
+void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring)
 {
-       bool set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work);
-
-       set_clocks &= schedule_delayed_work(&adev->vce.idle_work,
-                                           VCE_IDLE_TIMEOUT);
+       struct amdgpu_device *adev = ring->adev;
+       bool set_clocks;
 
+       mutex_lock(&adev->vce.idle_mutex);
+       set_clocks = !cancel_delayed_work_sync(&adev->vce.idle_work);
        if (set_clocks) {
                if (adev->pm.dpm_enabled) {
                        amdgpu_dpm_enable_vce(adev, true);
@@ -335,6 +337,19 @@ static void amdgpu_vce_note_usage(struct amdgpu_device *adev)
                        amdgpu_asic_set_vce_clocks(adev, 53300, 40000);
                }
        }
+       mutex_unlock(&adev->vce.idle_mutex);
+}
+
+/**
+ * amdgpu_vce_ring_end_use - power VCE down
+ *
+ * @ring: amdgpu ring
+ *
+ * Schedule work to power VCE down again
+ */
+void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring)
+{
+       schedule_delayed_work(&ring->adev->vce.idle_work, VCE_IDLE_TIMEOUT);
 }
 
 /**
@@ -355,8 +370,6 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
                if (!handle || adev->vce.filp[i] != filp)
                        continue;
 
-               amdgpu_vce_note_usage(adev);
-
                r = amdgpu_vce_get_destroy_msg(ring, handle, false, NULL);
                if (r)
                        DRM_ERROR("Error destroying VCE handle (%d)!\n", r);
@@ -622,8 +635,6 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
        uint32_t *size = &tmp;
        int i, r = 0, idx = 0;
 
-       amdgpu_vce_note_usage(p->adev);
-
        while (idx < ib->length_dw) {
                uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
                uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1);
index f40cf761c66f45f40fe5cf1d42646852d82101fb..fe84b80dbbeddb0be6638bba5a4ec2cbf06cdfd3 100644 (file)
@@ -40,5 +40,7 @@ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
                                unsigned flags);
 int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring);
 int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring);
+void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring);
+void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring);
 
 #endif
index 45d92aceb485f7477ec80c4d31aca52228c2c20a..80a37a60218136b5912ec7db9be5e8d21fb9ebd0 100644 (file)
@@ -594,6 +594,8 @@ static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
        .test_ib = amdgpu_vce_ring_test_ib,
        .insert_nop = amdgpu_ring_insert_nop,
        .pad_ib = amdgpu_ring_generic_pad_ib,
+       .begin_use = amdgpu_vce_ring_begin_use,
+       .end_use = amdgpu_vce_ring_end_use,
 };
 
 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
index 800c10bcb6cdb5fc59372838f8ee794abdae0ad7..c271abffd8dd7475ea0b25101a86d1b32b53696c 100644 (file)
@@ -767,6 +767,8 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
        .test_ib = amdgpu_vce_ring_test_ib,
        .insert_nop = amdgpu_ring_insert_nop,
        .pad_ib = amdgpu_ring_generic_pad_ib,
+       .begin_use = amdgpu_vce_ring_begin_use,
+       .end_use = amdgpu_vce_ring_end_use,
 };
 
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)