Subversion Repositories Kolibri OS

Rev

Rev 6104 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2011 Advanced Micro Devices, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sub license, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  16.  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  17.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  18.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  19.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  20.  *
  21.  * The above copyright notice and this permission notice (including the
  22.  * next paragraph) shall be included in all copies or substantial portions
  23.  * of the Software.
  24.  *
  25.  */
  26. /*
  27.  * Authors:
  28.  *    Christian König <deathsimple@vodafone.de>
  29.  */
  30.  
  31. #include <linux/firmware.h>
  32. #include <linux/module.h>
  33. #include <drm/drmP.h>
  34. #include <drm/drm.h>
  35.  
  36. #include "radeon.h"
  37. #include "r600d.h"
  38.  
  39. /* 1 second timeout */
  40. #define UVD_IDLE_TIMEOUT_MS     1000
  41.  
  42. /* Firmware Names */
  43. #define FIRMWARE_RV710          "radeon/RV710_uvd.bin"
  44. #define FIRMWARE_CYPRESS        "radeon/CYPRESS_uvd.bin"
  45. #define FIRMWARE_SUMO           "radeon/SUMO_uvd.bin"
  46. #define FIRMWARE_TAHITI         "radeon/TAHITI_uvd.bin"
  47. #define FIRMWARE_BONAIRE        "radeon/BONAIRE_uvd.bin"
  48.  
  49. MODULE_FIRMWARE(FIRMWARE_RV710);
  50. MODULE_FIRMWARE(FIRMWARE_CYPRESS);
  51. MODULE_FIRMWARE(FIRMWARE_SUMO);
  52. MODULE_FIRMWARE(FIRMWARE_TAHITI);
  53. MODULE_FIRMWARE(FIRMWARE_BONAIRE);
  54.  
  55. static void radeon_uvd_idle_work_handler(struct work_struct *work);
  56.  
  57. int radeon_uvd_init(struct radeon_device *rdev)
  58. {
  59.         unsigned long bo_size;
  60.         const char *fw_name;
  61.         int i, r;
  62.  
  63. //   INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler);
  64.  
  65.         switch (rdev->family) {
  66.         case CHIP_RV710:
  67.         case CHIP_RV730:
  68.         case CHIP_RV740:
  69.                 fw_name = FIRMWARE_RV710;
  70.                 break;
  71.  
  72.         case CHIP_CYPRESS:
  73.         case CHIP_HEMLOCK:
  74.         case CHIP_JUNIPER:
  75.         case CHIP_REDWOOD:
  76.         case CHIP_CEDAR:
  77.                 fw_name = FIRMWARE_CYPRESS;
  78.                 break;
  79.  
  80.         case CHIP_SUMO:
  81.         case CHIP_SUMO2:
  82.         case CHIP_PALM:
  83.         case CHIP_CAYMAN:
  84.         case CHIP_BARTS:
  85.         case CHIP_TURKS:
  86.         case CHIP_CAICOS:
  87.                 fw_name = FIRMWARE_SUMO;
  88.                 break;
  89.  
  90.         case CHIP_TAHITI:
  91.         case CHIP_VERDE:
  92.         case CHIP_PITCAIRN:
  93.         case CHIP_ARUBA:
  94.         case CHIP_OLAND:
  95.                 fw_name = FIRMWARE_TAHITI;
  96.                 break;
  97.  
  98.         case CHIP_BONAIRE:
  99.         case CHIP_KABINI:
  100.         case CHIP_KAVERI:
  101.         case CHIP_HAWAII:
  102.         case CHIP_MULLINS:
  103.                 fw_name = FIRMWARE_BONAIRE;
  104.                 break;
  105.  
  106.         default:
  107.                 return -EINVAL;
  108.         }
  109.  
  110.         r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
  111.         if (r) {
  112.                 dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
  113.                         fw_name);
  114.                 return r;
  115.         }
  116.  
  117.         bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
  118.                   RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
  119.         r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
  120.                              RADEON_GEM_DOMAIN_VRAM, 0, NULL, &rdev->uvd.vcpu_bo);
  121.         if (r) {
  122.                 dev_err(rdev->dev, "(%d) failed to allocate UVD bo\n", r);
  123.                 return r;
  124.         }
  125.  
  126.         r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
  127.         if (r) {
  128.                 radeon_bo_unref(&rdev->uvd.vcpu_bo);
  129.                 dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r);
  130.                 return r;
  131.         }
  132.  
  133.         r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
  134.                           &rdev->uvd.gpu_addr);
  135.         if (r) {
  136.                 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
  137.                 radeon_bo_unref(&rdev->uvd.vcpu_bo);
  138.                 dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r);
  139.                 return r;
  140.         }
  141.  
  142.         r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr);
  143.         if (r) {
  144.                 dev_err(rdev->dev, "(%d) UVD map failed\n", r);
  145.                 return r;
  146.         }
  147.  
  148.         radeon_bo_unreserve(rdev->uvd.vcpu_bo);
  149.  
  150.         for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
  151.                 atomic_set(&rdev->uvd.handles[i], 0);
  152.                 rdev->uvd.filp[i] = NULL;
  153.                 rdev->uvd.img_size[i] = 0;
  154.         }
  155.  
  156.         return 0;
  157. }
  158.  
  159. void radeon_uvd_fini(struct radeon_device *rdev)
  160. {
  161.         int r;
  162.  
  163.         if (rdev->uvd.vcpu_bo == NULL)
  164.                 return;
  165.  
  166.         r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false);
  167.         if (!r) {
  168.                 radeon_bo_kunmap(rdev->uvd.vcpu_bo);
  169.                 radeon_bo_unpin(rdev->uvd.vcpu_bo);
  170.                 radeon_bo_unreserve(rdev->uvd.vcpu_bo);
  171.         }
  172.  
  173.         radeon_bo_unref(&rdev->uvd.vcpu_bo);
  174.  
  175.         radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
  176.  
  177.         release_firmware(rdev->uvd_fw);
  178. }
  179.  
  180. int radeon_uvd_suspend(struct radeon_device *rdev)
  181. {
  182.         unsigned size;
  183.         void *ptr;
  184.         int i;
  185.  
  186.         if (rdev->uvd.vcpu_bo == NULL)
  187.                 return 0;
  188.  
  189.         for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
  190.                 if (atomic_read(&rdev->uvd.handles[i]))
  191.                         break;
  192.  
  193.         if (i == RADEON_MAX_UVD_HANDLES)
  194.                 return 0;
  195.  
  196.         size = radeon_bo_size(rdev->uvd.vcpu_bo);
  197.         size -= rdev->uvd_fw->size;
  198.  
  199.         ptr = rdev->uvd.cpu_addr;
  200.         ptr += rdev->uvd_fw->size;
  201.  
  202.         rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
  203.         memcpy(rdev->uvd.saved_bo, ptr, size);
  204.  
  205.         return 0;
  206. }
  207.  
  208. int radeon_uvd_resume(struct radeon_device *rdev)
  209. {
  210.         unsigned size;
  211.         void *ptr;
  212.  
  213.         if (rdev->uvd.vcpu_bo == NULL)
  214.                 return -EINVAL;
  215.  
  216.         memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
  217.  
  218.         size = radeon_bo_size(rdev->uvd.vcpu_bo);
  219.         size -= rdev->uvd_fw->size;
  220.  
  221.         ptr = rdev->uvd.cpu_addr;
  222.         ptr += rdev->uvd_fw->size;
  223.  
  224.         if (rdev->uvd.saved_bo != NULL) {
  225.                 memcpy(ptr, rdev->uvd.saved_bo, size);
  226.                 kfree(rdev->uvd.saved_bo);
  227.                 rdev->uvd.saved_bo = NULL;
  228.         } else
  229.                 memset(ptr, 0, size);
  230.  
  231.         return 0;
  232. }
  233.  
  234. void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo)
  235. {
  236.         rbo->placement.fpfn = 0 >> PAGE_SHIFT;
  237.         rbo->placement.lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;
  238. }
  239.  
  240. void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
  241. {
  242.         int i, r;
  243.         for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
  244.                 uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
  245.                 if (handle != 0 && rdev->uvd.filp[i] == filp) {
  246.                         struct radeon_fence *fence;
  247.  
  248.                         radeon_uvd_note_usage(rdev);
  249.  
  250.                         r = radeon_uvd_get_destroy_msg(rdev,
  251.                                 R600_RING_TYPE_UVD_INDEX, handle, &fence);
  252.                         if (r) {
  253.                                 DRM_ERROR("Error destroying UVD (%d)!\n", r);
  254.                                 continue;
  255.                         }
  256.  
  257.                         radeon_fence_wait(fence, false);
  258.                         radeon_fence_unref(&fence);
  259.  
  260.                         rdev->uvd.filp[i] = NULL;
  261.                         atomic_set(&rdev->uvd.handles[i], 0);
  262.                 }
  263.         }
  264. }
  265.  
  266. static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
  267. {
  268.         unsigned stream_type = msg[4];
  269.         unsigned width = msg[6];
  270.         unsigned height = msg[7];
  271.         unsigned dpb_size = msg[9];
  272.         unsigned pitch = msg[28];
  273.  
  274.         unsigned width_in_mb = width / 16;
  275.         unsigned height_in_mb = ALIGN(height / 16, 2);
  276.  
  277.         unsigned image_size, tmp, min_dpb_size;
  278.  
  279.         image_size = width * height;
  280.         image_size += image_size / 2;
  281.         image_size = ALIGN(image_size, 1024);
  282.  
  283.         switch (stream_type) {
  284.         case 0: /* H264 */
  285.  
  286.                 /* reference picture buffer */
  287.                 min_dpb_size = image_size * 17;
  288.  
  289.                 /* macroblock context buffer */
  290.                 min_dpb_size += width_in_mb * height_in_mb * 17 * 192;
  291.  
  292.                 /* IT surface buffer */
  293.                 min_dpb_size += width_in_mb * height_in_mb * 32;
  294.                 break;
  295.  
  296.         case 1: /* VC1 */
  297.  
  298.                 /* reference picture buffer */
  299.                 min_dpb_size = image_size * 3;
  300.  
  301.                 /* CONTEXT_BUFFER */
  302.                 min_dpb_size += width_in_mb * height_in_mb * 128;
  303.  
  304.                 /* IT surface buffer */
  305.                 min_dpb_size += width_in_mb * 64;
  306.  
  307.                 /* DB surface buffer */
  308.                 min_dpb_size += width_in_mb * 128;
  309.  
  310.                 /* BP */
  311.                 tmp = max(width_in_mb, height_in_mb);
  312.                 min_dpb_size += ALIGN(tmp * 7 * 16, 64);
  313.                 break;
  314.  
  315.         case 3: /* MPEG2 */
  316.  
  317.                 /* reference picture buffer */
  318.                 min_dpb_size = image_size * 3;
  319.                 break;
  320.  
  321.         case 4: /* MPEG4 */
  322.  
  323.                 /* reference picture buffer */
  324.                 min_dpb_size = image_size * 3;
  325.  
  326.                 /* CM */
  327.                 min_dpb_size += width_in_mb * height_in_mb * 64;
  328.  
  329.                 /* IT surface buffer */
  330.                 min_dpb_size += ALIGN(width_in_mb * height_in_mb * 32, 64);
  331.                 break;
  332.  
  333.         default:
  334.                 DRM_ERROR("UVD codec not handled %d!\n", stream_type);
  335.                 return -EINVAL;
  336.         }
  337.  
  338.         if (width > pitch) {
  339.                 DRM_ERROR("Invalid UVD decoding target pitch!\n");
  340.                 return -EINVAL;
  341.         }
  342.  
  343.         if (dpb_size < min_dpb_size) {
  344.                 DRM_ERROR("Invalid dpb_size in UVD message (%d / %d)!\n",
  345.                           dpb_size, min_dpb_size);
  346.                 return -EINVAL;
  347.         }
  348.  
  349.         buf_sizes[0x1] = dpb_size;
  350.         buf_sizes[0x2] = image_size;
  351.         return 0;
  352. }
  353.  
  354. static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
  355.                              unsigned offset, unsigned buf_sizes[])
  356. {
  357.         int32_t *msg, msg_type, handle;
  358.         unsigned img_size = 0;
  359.         void *ptr;
  360.  
  361.         int i, r;
  362.  
  363.         if (offset & 0x3F) {
  364.                 DRM_ERROR("UVD messages must be 64 byte aligned!\n");
  365.                 return -EINVAL;
  366.         }
  367.  
  368.         if (bo->tbo.sync_obj) {
  369.                 r = radeon_fence_wait(bo->tbo.sync_obj, false);
  370.                 if (r) {
  371.                         DRM_ERROR("Failed waiting for UVD message (%d)!\n", r);
  372.                         return r;
  373.                 }
  374.         }
  375.  
  376.         r = radeon_bo_kmap(bo, &ptr);
  377.         if (r) {
  378.                 DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
  379.                 return r;
  380.         }
  381.  
  382.         msg = ptr + offset;
  383.  
  384.         msg_type = msg[1];
  385.         handle = msg[2];
  386.  
  387.         if (handle == 0) {
  388.                 DRM_ERROR("Invalid UVD handle!\n");
  389.                 return -EINVAL;
  390.         }
  391.  
  392.         if (msg_type == 1) {
  393.                 /* it's a decode msg, calc buffer sizes */
  394.                 r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
  395.                 /* calc image size (width * height) */
  396.                 img_size = msg[6] * msg[7];
  397.                 radeon_bo_kunmap(bo);
  398.                 if (r)
  399.                         return r;
  400.  
  401.         } else if (msg_type == 2) {
  402.                 /* it's a destroy msg, free the handle */
  403.                 for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
  404.                         atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
  405.                 radeon_bo_kunmap(bo);
  406.                 return 0;
  407.         } else {
  408.                 /* it's a create msg, calc image size (width * height) */
  409.                 img_size = msg[7] * msg[8];
  410.                 radeon_bo_kunmap(bo);
  411.  
  412.                 if (msg_type != 0) {
  413.                         DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
  414.                         return -EINVAL;
  415.                 }
  416.  
  417.                 /* it's a create msg, no special handling needed */
  418.         }
  419.  
  420.         /* create or decode, validate the handle */
  421.         for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
  422.                 if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
  423.                         return 0;
  424.         }
  425.  
  426.         /* handle not found try to alloc a new one */
  427.         for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
  428.                 if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
  429.                         p->rdev->uvd.filp[i] = p->filp;
  430.                         p->rdev->uvd.img_size[i] = img_size;
  431.                         return 0;
  432.                 }
  433.         }
  434.  
  435.         DRM_ERROR("No more free UVD handles!\n");
  436.         return -EINVAL;
  437. }
  438.  
  439. static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
  440.                                int data0, int data1,
  441.                                unsigned buf_sizes[], bool *has_msg_cmd)
  442. {
  443.         struct radeon_cs_chunk *relocs_chunk;
  444.         struct radeon_cs_reloc *reloc;
  445.         unsigned idx, cmd, offset;
  446.         uint64_t start, end;
  447.         int r;
  448.  
  449.         relocs_chunk = &p->chunks[p->chunk_relocs_idx];
  450.         offset = radeon_get_ib_value(p, data0);
  451.         idx = radeon_get_ib_value(p, data1);
  452.         if (idx >= relocs_chunk->length_dw) {
  453.                 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
  454.                           idx, relocs_chunk->length_dw);
  455.                 return -EINVAL;
  456.         }
  457.  
  458.         reloc = p->relocs_ptr[(idx / 4)];
  459.         start = reloc->gpu_offset;
  460.         end = start + radeon_bo_size(reloc->robj);
  461.         start += offset;
  462.  
  463.         p->ib.ptr[data0] = start & 0xFFFFFFFF;
  464.         p->ib.ptr[data1] = start >> 32;
  465.  
  466.         cmd = radeon_get_ib_value(p, p->idx) >> 1;
  467.  
  468.         if (cmd < 0x4) {
  469.                 if (end <= start) {
  470.                         DRM_ERROR("invalid reloc offset %X!\n", offset);
  471.                         return -EINVAL;
  472.                 }
  473.                 if ((end - start) < buf_sizes[cmd]) {
  474.                         DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
  475.                                   (unsigned)(end - start), buf_sizes[cmd]);
  476.                         return -EINVAL;
  477.                 }
  478.  
  479.         } else if (cmd != 0x100) {
  480.                 DRM_ERROR("invalid UVD command %X!\n", cmd);
  481.                 return -EINVAL;
  482.         }
  483.  
  484.         if ((start >> 28) != ((end - 1) >> 28)) {
  485.                 DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
  486.                           start, end);
  487.                 return -EINVAL;
  488.         }
  489.  
  490.         /* TODO: is this still necessary on NI+ ? */
  491.         if ((cmd == 0 || cmd == 0x3) &&
  492.             (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
  493.                 DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
  494.                           start, end);
  495.                 return -EINVAL;
  496.         }
  497.  
  498.         if (cmd == 0) {
  499.                 if (*has_msg_cmd) {
  500.                         DRM_ERROR("More than one message in a UVD-IB!\n");
  501.                         return -EINVAL;
  502.                 }
  503.                 *has_msg_cmd = true;
  504.                 r = radeon_uvd_cs_msg(p, reloc->robj, offset, buf_sizes);
  505.                 if (r)
  506.                         return r;
  507.         } else if (!*has_msg_cmd) {
  508.                 DRM_ERROR("Message needed before other commands are send!\n");
  509.                 return -EINVAL;
  510.         }
  511.  
  512.         return 0;
  513. }
  514.  
  515. static int radeon_uvd_cs_reg(struct radeon_cs_parser *p,
  516.                              struct radeon_cs_packet *pkt,
  517.                              int *data0, int *data1,
  518.                              unsigned buf_sizes[],
  519.                              bool *has_msg_cmd)
  520. {
  521.         int i, r;
  522.  
  523.         p->idx++;
  524.         for (i = 0; i <= pkt->count; ++i) {
  525.                 switch (pkt->reg + i*4) {
  526.                 case UVD_GPCOM_VCPU_DATA0:
  527.                         *data0 = p->idx;
  528.                         break;
  529.                 case UVD_GPCOM_VCPU_DATA1:
  530.                         *data1 = p->idx;
  531.                         break;
  532.                 case UVD_GPCOM_VCPU_CMD:
  533.                         r = radeon_uvd_cs_reloc(p, *data0, *data1,
  534.                                                 buf_sizes, has_msg_cmd);
  535.                         if (r)
  536.                                 return r;
  537.                         break;
  538.                 case UVD_ENGINE_CNTL:
  539.                         break;
  540.                 default:
  541.                         DRM_ERROR("Invalid reg 0x%X!\n",
  542.                                   pkt->reg + i*4);
  543.                         return -EINVAL;
  544.                 }
  545.                 p->idx++;
  546.         }
  547.         return 0;
  548. }
  549.  
  550. int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
  551. {
  552.         struct radeon_cs_packet pkt;
  553.         int r, data0 = 0, data1 = 0;
  554.  
  555.         /* does the IB has a msg command */
  556.         bool has_msg_cmd = false;
  557.  
  558.         /* minimum buffer sizes */
  559.         unsigned buf_sizes[] = {
  560.                 [0x00000000]    =       2048,
  561.                 [0x00000001]    =       32 * 1024 * 1024,
  562.                 [0x00000002]    =       2048 * 1152 * 3,
  563.                 [0x00000003]    =       2048,
  564.         };
  565.  
  566.         if (p->chunks[p->chunk_ib_idx].length_dw % 16) {
  567.                 DRM_ERROR("UVD IB length (%d) not 16 dwords aligned!\n",
  568.                           p->chunks[p->chunk_ib_idx].length_dw);
  569.                 return -EINVAL;
  570.         }
  571.  
  572.         if (p->chunk_relocs_idx == -1) {
  573.                 DRM_ERROR("No relocation chunk !\n");
  574.                 return -EINVAL;
  575.         }
  576.  
  577.  
  578.         do {
  579.                 r = radeon_cs_packet_parse(p, &pkt, p->idx);
  580.                 if (r)
  581.                         return r;
  582.                 switch (pkt.type) {
  583.                 case RADEON_PACKET_TYPE0:
  584.                         r = radeon_uvd_cs_reg(p, &pkt, &data0, &data1,
  585.                                               buf_sizes, &has_msg_cmd);
  586.                         if (r)
  587.                                 return r;
  588.                         break;
  589.                 case RADEON_PACKET_TYPE2:
  590.                         p->idx += pkt.count + 2;
  591.                         break;
  592.                 default:
  593.                         DRM_ERROR("Unknown packet type %d !\n", pkt.type);
  594.                         return -EINVAL;
  595.                 }
  596.         } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
  597.  
  598.         if (!has_msg_cmd) {
  599.                 DRM_ERROR("UVD-IBs need a msg command!\n");
  600.                 return -EINVAL;
  601.         }
  602.  
  603.         return 0;
  604. }
  605.  
  606. static int radeon_uvd_send_msg(struct radeon_device *rdev,
  607.                                int ring, struct radeon_bo *bo,
  608.                                struct radeon_fence **fence)
  609. {
  610.         struct ttm_validate_buffer tv;
  611.         struct ww_acquire_ctx ticket;
  612.         struct list_head head;
  613.         struct radeon_ib ib;
  614.         uint64_t addr;
  615.         int i, r;
  616.  
  617.         memset(&tv, 0, sizeof(tv));
  618.         tv.bo = &bo->tbo;
  619.  
  620.         INIT_LIST_HEAD(&head);
  621.         list_add(&tv.head, &head);
  622.  
  623.         r = ttm_eu_reserve_buffers(&ticket, &head);
  624.         if (r)
  625.                 return r;
  626.  
  627.         radeon_ttm_placement_from_domain(bo, RADEON_GEM_DOMAIN_VRAM);
  628.         radeon_uvd_force_into_uvd_segment(bo);
  629.  
  630.         r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
  631.         if (r)
  632.                 goto err;
  633.  
  634.         r = radeon_ib_get(rdev, ring, &ib, NULL, 64);
  635.         if (r)
  636.                 goto err;
  637.  
  638.         addr = radeon_bo_gpu_offset(bo);
  639.         ib.ptr[0] = PACKET0(UVD_GPCOM_VCPU_DATA0, 0);
  640.         ib.ptr[1] = addr;
  641.         ib.ptr[2] = PACKET0(UVD_GPCOM_VCPU_DATA1, 0);
  642.         ib.ptr[3] = addr >> 32;
  643.         ib.ptr[4] = PACKET0(UVD_GPCOM_VCPU_CMD, 0);
  644.         ib.ptr[5] = 0;
  645.         for (i = 6; i < 16; ++i)
  646.                 ib.ptr[i] = PACKET2(0);
  647.         ib.length_dw = 16;
  648.  
  649.         r = radeon_ib_schedule(rdev, &ib, NULL, false);
  650.         if (r)
  651.                 goto err;
  652.         ttm_eu_fence_buffer_objects(&ticket, &head, ib.fence);
  653.  
  654.         if (fence)
  655.                 *fence = radeon_fence_ref(ib.fence);
  656.  
  657.         radeon_ib_free(rdev, &ib);
  658.         radeon_bo_unref(&bo);
  659.         return 0;
  660.  
  661. err:
  662.         ttm_eu_backoff_reservation(&ticket, &head);
  663.         return r;
  664. }
  665.  
  666. /* multiple fence commands without any stream commands in between can
  667.    crash the vcpu so just try to emmit a dummy create/destroy msg to
  668.    avoid this */
  669. int radeon_uvd_get_create_msg(struct radeon_device *rdev, int ring,
  670.                               uint32_t handle, struct radeon_fence **fence)
  671. {
  672.         struct radeon_bo *bo;
  673.         uint32_t *msg;
  674.         int r, i;
  675.  
  676.         r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
  677.                              RADEON_GEM_DOMAIN_VRAM, 0, NULL, &bo);
  678.         if (r)
  679.                 return r;
  680.  
  681.         r = radeon_bo_reserve(bo, false);
  682.         if (r) {
  683.                 radeon_bo_unref(&bo);
  684.                 return r;
  685.         }
  686.  
  687.         r = radeon_bo_kmap(bo, (void **)&msg);
  688.         if (r) {
  689.                 radeon_bo_unreserve(bo);
  690.                 radeon_bo_unref(&bo);
  691.                 return r;
  692.         }
  693.  
  694.         /* stitch together an UVD create msg */
  695.         msg[0] = cpu_to_le32(0x00000de4);
  696.         msg[1] = cpu_to_le32(0x00000000);
  697.         msg[2] = cpu_to_le32(handle);
  698.         msg[3] = cpu_to_le32(0x00000000);
  699.         msg[4] = cpu_to_le32(0x00000000);
  700.         msg[5] = cpu_to_le32(0x00000000);
  701.         msg[6] = cpu_to_le32(0x00000000);
  702.         msg[7] = cpu_to_le32(0x00000780);
  703.         msg[8] = cpu_to_le32(0x00000440);
  704.         msg[9] = cpu_to_le32(0x00000000);
  705.         msg[10] = cpu_to_le32(0x01b37000);
  706.         for (i = 11; i < 1024; ++i)
  707.                 msg[i] = cpu_to_le32(0x0);
  708.  
  709.         radeon_bo_kunmap(bo);
  710.         radeon_bo_unreserve(bo);
  711.  
  712.         return radeon_uvd_send_msg(rdev, ring, bo, fence);
  713. }
  714.  
  715. int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring,
  716.                                uint32_t handle, struct radeon_fence **fence)
  717. {
  718.         struct radeon_bo *bo;
  719.         uint32_t *msg;
  720.         int r, i;
  721.  
  722.         r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
  723.                              RADEON_GEM_DOMAIN_VRAM, 0, NULL, &bo);
  724.         if (r)
  725.                 return r;
  726.  
  727.         r = radeon_bo_reserve(bo, false);
  728.         if (r) {
  729.                 radeon_bo_unref(&bo);
  730.                 return r;
  731.         }
  732.  
  733.         r = radeon_bo_kmap(bo, (void **)&msg);
  734.         if (r) {
  735.                 radeon_bo_unreserve(bo);
  736.                 radeon_bo_unref(&bo);
  737.                 return r;
  738.         }
  739.  
  740.         /* stitch together an UVD destroy msg */
  741.         msg[0] = cpu_to_le32(0x00000de4);
  742.         msg[1] = cpu_to_le32(0x00000002);
  743.         msg[2] = cpu_to_le32(handle);
  744.         msg[3] = cpu_to_le32(0x00000000);
  745.         for (i = 4; i < 1024; ++i)
  746.                 msg[i] = cpu_to_le32(0x0);
  747.  
  748.         radeon_bo_kunmap(bo);
  749.         radeon_bo_unreserve(bo);
  750.  
  751.         return radeon_uvd_send_msg(rdev, ring, bo, fence);
  752. }
  753.  
  754. /**
  755.  * radeon_uvd_count_handles - count number of open streams
  756.  *
  757.  * @rdev: radeon_device pointer
  758.  * @sd: number of SD streams
  759.  * @hd: number of HD streams
  760.  *
  761.  * Count the number of open SD/HD streams as a hint for power mangement
  762.  */
  763. static void radeon_uvd_count_handles(struct radeon_device *rdev,
  764.                                      unsigned *sd, unsigned *hd)
  765. {
  766.         unsigned i;
  767.  
  768.         *sd = 0;
  769.         *hd = 0;
  770.  
  771.         for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
  772.                 if (!atomic_read(&rdev->uvd.handles[i]))
  773.                         continue;
  774.  
  775.                 if (rdev->uvd.img_size[i] >= 720*576)
  776.                         ++(*hd);
  777.                 else
  778.                         ++(*sd);
  779.         }
  780. }
  781.  
  782. static void radeon_uvd_idle_work_handler(struct work_struct *work)
  783. {
  784.         struct radeon_device *rdev =
  785.                 container_of(work, struct radeon_device, uvd.idle_work.work);
  786.  
  787.         if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) {
  788.                 if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
  789.                         radeon_uvd_count_handles(rdev, &rdev->pm.dpm.sd,
  790.                                                  &rdev->pm.dpm.hd);
  791.                         radeon_dpm_enable_uvd(rdev, false);
  792.                 } else {
  793.                         radeon_set_uvd_clocks(rdev, 0, 0);
  794.                 }
  795.         } else {
  796.                 schedule_delayed_work(&rdev->uvd.idle_work,
  797.                                       msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
  798.         }
  799. }
  800.  
  801. void radeon_uvd_note_usage(struct radeon_device *rdev)
  802. {
  803.         bool streams_changed = false;
  804.         bool set_clocks = !cancel_delayed_work_sync(&rdev->uvd.idle_work);
  805.         set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work,
  806.                                             msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
  807.  
  808.         if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
  809.                 unsigned hd = 0, sd = 0;
  810.                 radeon_uvd_count_handles(rdev, &sd, &hd);
  811.                 if ((rdev->pm.dpm.sd != sd) ||
  812.                     (rdev->pm.dpm.hd != hd)) {
  813.                         rdev->pm.dpm.sd = sd;
  814.                         rdev->pm.dpm.hd = hd;
  815.                         /* disable this for now */
  816.                         /*streams_changed = true;*/
  817.                 }
  818.         }
  819.  
  820.         if (set_clocks || streams_changed) {
  821.                 if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
  822.                         radeon_dpm_enable_uvd(rdev, true);
  823.                 } else {
  824.                         radeon_set_uvd_clocks(rdev, 53300, 40000);
  825.                 }
  826.         }
  827. }
  828.  
  829. static unsigned radeon_uvd_calc_upll_post_div(unsigned vco_freq,
  830.                                               unsigned target_freq,
  831.                                               unsigned pd_min,
  832.                                               unsigned pd_even)
  833. {
  834.         unsigned post_div = vco_freq / target_freq;
  835.  
  836.         /* adjust to post divider minimum value */
  837.         if (post_div < pd_min)
  838.                 post_div = pd_min;
  839.  
  840.         /* we alway need a frequency less than or equal the target */
  841.         if ((vco_freq / post_div) > target_freq)
  842.                 post_div += 1;
  843.  
  844.         /* post dividers above a certain value must be even */
  845.         if (post_div > pd_even && post_div % 2)
  846.                 post_div += 1;
  847.  
  848.         return post_div;
  849. }
  850.  
  851. /**
  852.  * radeon_uvd_calc_upll_dividers - calc UPLL clock dividers
  853.  *
  854.  * @rdev: radeon_device pointer
  855.  * @vclk: wanted VCLK
  856.  * @dclk: wanted DCLK
  857.  * @vco_min: minimum VCO frequency
  858.  * @vco_max: maximum VCO frequency
  859.  * @fb_factor: factor to multiply vco freq with
  860.  * @fb_mask: limit and bitmask for feedback divider
  861.  * @pd_min: post divider minimum
  862.  * @pd_max: post divider maximum
  863.  * @pd_even: post divider must be even above this value
  864.  * @optimal_fb_div: resulting feedback divider
  865.  * @optimal_vclk_div: resulting vclk post divider
  866.  * @optimal_dclk_div: resulting dclk post divider
  867.  *
  868.  * Calculate dividers for UVDs UPLL (R6xx-SI, except APUs).
  869.  * Returns zero on success -EINVAL on error.
  870.  */
  871. int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev,
  872.                                   unsigned vclk, unsigned dclk,
  873.                                   unsigned vco_min, unsigned vco_max,
  874.                                   unsigned fb_factor, unsigned fb_mask,
  875.                                   unsigned pd_min, unsigned pd_max,
  876.                                   unsigned pd_even,
  877.                                   unsigned *optimal_fb_div,
  878.                                   unsigned *optimal_vclk_div,
  879.                                   unsigned *optimal_dclk_div)
  880. {
  881.         unsigned vco_freq, ref_freq = rdev->clock.spll.reference_freq;
  882.  
  883.         /* start off with something large */
  884.         unsigned optimal_score = ~0;
  885.  
  886.         /* loop through vco from low to high */
  887.         vco_min = max(max(vco_min, vclk), dclk);
  888.         for (vco_freq = vco_min; vco_freq <= vco_max; vco_freq += 100) {
  889.  
  890.                 uint64_t fb_div = (uint64_t)vco_freq * fb_factor;
  891.                 unsigned vclk_div, dclk_div, score;
  892.  
  893.                 do_div(fb_div, ref_freq);
  894.  
  895.                 /* fb div out of range ? */
  896.                 if (fb_div > fb_mask)
  897.                         break; /* it can oly get worse */
  898.  
  899.                 fb_div &= fb_mask;
  900.  
  901.                 /* calc vclk divider with current vco freq */
  902.                 vclk_div = radeon_uvd_calc_upll_post_div(vco_freq, vclk,
  903.                                                          pd_min, pd_even);
  904.                 if (vclk_div > pd_max)
  905.                         break; /* vco is too big, it has to stop */
  906.  
  907.                 /* calc dclk divider with current vco freq */
  908.                 dclk_div = radeon_uvd_calc_upll_post_div(vco_freq, dclk,
  909.                                                          pd_min, pd_even);
  910.                 if (vclk_div > pd_max)
  911.                         break; /* vco is too big, it has to stop */
  912.  
  913.                 /* calc score with current vco freq */
  914.                 score = vclk - (vco_freq / vclk_div) + dclk - (vco_freq / dclk_div);
  915.  
  916.                 /* determine if this vco setting is better than current optimal settings */
  917.                 if (score < optimal_score) {
  918.                         *optimal_fb_div = fb_div;
  919.                         *optimal_vclk_div = vclk_div;
  920.                         *optimal_dclk_div = dclk_div;
  921.                         optimal_score = score;
  922.                         if (optimal_score == 0)
  923.                                 break; /* it can't get better than this */
  924.                 }
  925.         }
  926.  
  927.         /* did we found a valid setup ? */
  928.         if (optimal_score == ~0)
  929.                 return -EINVAL;
  930.  
  931.         return 0;
  932. }
  933.  
  934. int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
  935.                                 unsigned cg_upll_func_cntl)
  936. {
  937.         unsigned i;
  938.  
  939.         /* make sure UPLL_CTLREQ is deasserted */
  940.         WREG32_P(cg_upll_func_cntl, 0, ~UPLL_CTLREQ_MASK);
  941.  
  942.         mdelay(10);
  943.  
  944.         /* assert UPLL_CTLREQ */
  945.         WREG32_P(cg_upll_func_cntl, UPLL_CTLREQ_MASK, ~UPLL_CTLREQ_MASK);
  946.  
  947.         /* wait for CTLACK and CTLACK2 to get asserted */
  948.         for (i = 0; i < 100; ++i) {
  949.                 uint32_t mask = UPLL_CTLACK_MASK | UPLL_CTLACK2_MASK;
  950.                 if ((RREG32(cg_upll_func_cntl) & mask) == mask)
  951.                         break;
  952.                 mdelay(10);
  953.         }
  954.  
  955.         /* deassert UPLL_CTLREQ */
  956.         WREG32_P(cg_upll_func_cntl, 0, ~UPLL_CTLREQ_MASK);
  957.  
  958.         if (i == 100) {
  959.                 DRM_ERROR("Timeout setting UVD clocks!\n");
  960.                 return -ETIMEDOUT;
  961.         }
  962.  
  963.         return 0;
  964. }
  965.