drm/radeon: add VCE version parsing and checking
authorChristian König <christian.koenig@amd.com>
Thu, 23 Jan 2014 16:50:49 +0000 (09:50 -0700)
committerChristian König <christian.koenig@amd.com>
Tue, 18 Feb 2014 15:11:26 +0000 (16:11 +0100)
Also make the result available to userspace.

Signed-off-by: Christian König <christian.koenig@amd.com>
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_vce.c
include/uapi/drm/radeon_drm.h

index a58a38942c73657f3eac79f4ed6afc19c6ee5898..d1491d41fc2d665e71d4989232d7b159437b3e28 100644 (file)
@@ -1606,6 +1606,8 @@ struct radeon_vce {
        struct radeon_bo        *vcpu_bo;
        void                    *cpu_addr;
        uint64_t                gpu_addr;
+       unsigned                fw_version;
+       unsigned                fb_version;
        atomic_t                handles[RADEON_MAX_VCE_HANDLES];
        struct drm_file         *filp[RADEON_MAX_VCE_HANDLES];
 };
index ea018d53a85e1ffc5e9b7685dbae98db7b770909..baff98be65b1ea9e0b0f068e91f31d7245a43c69 100644 (file)
@@ -480,6 +480,12 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                else
                        *value = rdev->pm.default_sclk * 10;
                break;
+       case RADEON_INFO_VCE_FW_VERSION:
+               *value = rdev->vce.fw_version;
+               break;
+       case RADEON_INFO_VCE_FB_VERSION:
+               *value = rdev->vce.fb_version;
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
index 2547d8ea347a4a34f4a73487acf98c68d7ac3a59..f46563b609219da1a24bbc7328125fc12508e35e 100644 (file)
@@ -48,8 +48,11 @@ MODULE_FIRMWARE(FIRMWARE_BONAIRE);
  */
 int radeon_vce_init(struct radeon_device *rdev)
 {
-       unsigned long bo_size;
-       const char *fw_name;
+       static const char *fw_version = "[ATI LIB=VCEFW,";
+       static const char *fb_version = "[ATI LIB=VCEFWSTATS,";
+       unsigned long size;
+       const char *fw_name, *c;
+       uint8_t start, mid, end;
        int i, r;
 
        switch (rdev->family) {
@@ -70,9 +73,50 @@ int radeon_vce_init(struct radeon_device *rdev)
                return r;
        }
 
-       bo_size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
-                 RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
-       r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
+       /* search for firmware version */
+
+       size = rdev->vce_fw->size - strlen(fw_version) - 9;
+       c = rdev->vce_fw->data;
+       for (;size > 0; --size, ++c)
+               if (strncmp(c, fw_version, strlen(fw_version)) == 0)
+                       break;
+
+       if (size == 0)
+               return -EINVAL;
+
+       c += strlen(fw_version);
+       if (sscanf(c, "%2hhd.%2hhd.%2hhd]", &start, &mid, &end) != 3)
+               return -EINVAL;
+
+       /* search for feedback version */
+
+       size = rdev->vce_fw->size - strlen(fb_version) - 3;
+       c = rdev->vce_fw->data;
+       for (;size > 0; --size, ++c)
+               if (strncmp(c, fb_version, strlen(fb_version)) == 0)
+                       break;
+
+       if (size == 0)
+               return -EINVAL;
+
+       c += strlen(fb_version);
+       if (sscanf(c, "%2u]", &rdev->vce.fb_version) != 1)
+               return -EINVAL;
+
+       DRM_INFO("Found VCE firmware/feedback version %hhd.%hhd.%hhd / %d!\n",
+                start, mid, end, rdev->vce.fb_version);
+
+       rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8);
+
+       /* we can only work with this fw version for now */
+       if (rdev->vce.fw_version != ((40 << 24) | (2 << 16) | (2 << 8)))
+               return -EINVAL;
+
+       /* load firmware into VRAM */
+
+       size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
+              RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
+       r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
                             RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo);
        if (r) {
                dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r);
@@ -83,7 +127,7 @@ int radeon_vce_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       memset(rdev->vce.cpu_addr, 0, bo_size);
+       memset(rdev->vce.cpu_addr, 0, size);
        memcpy(rdev->vce.cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size);
 
        r = radeon_vce_suspend(rdev);
index 6493ca55b46357e56ac066fdca015f6d782ab073..1cf18b4a39ec1ca4403393664b7aba00c9a9bd5d 100644 (file)
@@ -988,6 +988,10 @@ struct drm_radeon_cs {
 #define RADEON_INFO_SI_BACKEND_ENABLED_MASK    0x19
 /* max engine clock - needed for OpenCL */
 #define RADEON_INFO_MAX_SCLK           0x1a
+/* version of VCE firmware */
+#define RADEON_INFO_VCE_FW_VERSION     0x1b
+/* version of VCE feedback */
+#define RADEON_INFO_VCE_FB_VERSION     0x1c
 
 
 struct drm_radeon_info {