exynos_drm_buf.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* exynos_drm_buf.c
  2. *
  3. * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  4. * Author: Inki Dae <inki.dae@samsung.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2 of the License, or (at your
  9. * option) any later version.
  10. */
  11. #include <drm/drmP.h>
  12. #include <drm/exynos_drm.h>
  13. #include "exynos_drm_drv.h"
  14. #include "exynos_drm_gem.h"
  15. #include "exynos_drm_buf.h"
  16. #include "exynos_drm_iommu.h"
  17. static int lowlevel_buffer_allocate(struct drm_device *dev,
  18. unsigned int flags, struct exynos_drm_gem_buf *buf)
  19. {
  20. int ret = 0;
  21. enum dma_attr attr;
  22. unsigned int nr_pages;
  23. DRM_DEBUG_KMS("%s\n", __FILE__);
  24. if (buf->dma_addr) {
  25. DRM_DEBUG_KMS("already allocated.\n");
  26. return 0;
  27. }
  28. init_dma_attrs(&buf->dma_attrs);
  29. /*
  30. * if EXYNOS_BO_CONTIG, fully physically contiguous memory
  31. * region will be allocated else physically contiguous
  32. * as possible.
  33. */
  34. if (!(flags & EXYNOS_BO_NONCONTIG))
  35. dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs);
  36. /*
  37. * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
  38. * else cachable mapping.
  39. */
  40. if (flags & EXYNOS_BO_WC || !(flags & EXYNOS_BO_CACHABLE))
  41. attr = DMA_ATTR_WRITE_COMBINE;
  42. else
  43. attr = DMA_ATTR_NON_CONSISTENT;
  44. dma_set_attr(attr, &buf->dma_attrs);
  45. dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
  46. nr_pages = buf->size >> PAGE_SHIFT;
  47. if (!is_drm_iommu_supported(dev)) {
  48. dma_addr_t start_addr;
  49. unsigned int i = 0;
  50. buf->pages = kzalloc(sizeof(struct page) * nr_pages,
  51. GFP_KERNEL);
  52. if (!buf->pages) {
  53. DRM_ERROR("failed to allocate pages.\n");
  54. return -ENOMEM;
  55. }
  56. buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
  57. &buf->dma_addr, GFP_KERNEL,
  58. &buf->dma_attrs);
  59. if (!buf->kvaddr) {
  60. DRM_ERROR("failed to allocate buffer.\n");
  61. kfree(buf->pages);
  62. return -ENOMEM;
  63. }
  64. start_addr = buf->dma_addr;
  65. while (i < nr_pages) {
  66. buf->pages[i] = phys_to_page(start_addr);
  67. start_addr += PAGE_SIZE;
  68. i++;
  69. }
  70. } else {
  71. buf->pages = dma_alloc_attrs(dev->dev, buf->size,
  72. &buf->dma_addr, GFP_KERNEL,
  73. &buf->dma_attrs);
  74. if (!buf->pages) {
  75. DRM_ERROR("failed to allocate buffer.\n");
  76. return -ENOMEM;
  77. }
  78. }
  79. buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
  80. if (!buf->sgt) {
  81. DRM_ERROR("failed to get sg table.\n");
  82. ret = -ENOMEM;
  83. goto err_free_attrs;
  84. }
  85. DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
  86. (unsigned long)buf->dma_addr,
  87. buf->size);
  88. return ret;
  89. err_free_attrs:
  90. dma_free_attrs(dev->dev, buf->size, buf->pages,
  91. (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
  92. buf->dma_addr = (dma_addr_t)NULL;
  93. if (!is_drm_iommu_supported(dev))
  94. kfree(buf->pages);
  95. return ret;
  96. }
  97. static void lowlevel_buffer_deallocate(struct drm_device *dev,
  98. unsigned int flags, struct exynos_drm_gem_buf *buf)
  99. {
  100. DRM_DEBUG_KMS("%s.\n", __FILE__);
  101. if (!buf->dma_addr) {
  102. DRM_DEBUG_KMS("dma_addr is invalid.\n");
  103. return;
  104. }
  105. DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
  106. (unsigned long)buf->dma_addr,
  107. buf->size);
  108. sg_free_table(buf->sgt);
  109. kfree(buf->sgt);
  110. buf->sgt = NULL;
  111. if (!is_drm_iommu_supported(dev)) {
  112. dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
  113. (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
  114. kfree(buf->pages);
  115. } else
  116. dma_free_attrs(dev->dev, buf->size, buf->pages,
  117. (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
  118. buf->dma_addr = (dma_addr_t)NULL;
  119. }
  120. struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
  121. unsigned int size)
  122. {
  123. struct exynos_drm_gem_buf *buffer;
  124. DRM_DEBUG_KMS("%s.\n", __FILE__);
  125. DRM_DEBUG_KMS("desired size = 0x%x\n", size);
  126. buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
  127. if (!buffer) {
  128. DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
  129. return NULL;
  130. }
  131. buffer->size = size;
  132. return buffer;
  133. }
  134. void exynos_drm_fini_buf(struct drm_device *dev,
  135. struct exynos_drm_gem_buf *buffer)
  136. {
  137. DRM_DEBUG_KMS("%s.\n", __FILE__);
  138. if (!buffer) {
  139. DRM_DEBUG_KMS("buffer is null.\n");
  140. return;
  141. }
  142. kfree(buffer);
  143. buffer = NULL;
  144. }
  145. int exynos_drm_alloc_buf(struct drm_device *dev,
  146. struct exynos_drm_gem_buf *buf, unsigned int flags)
  147. {
  148. /*
  149. * allocate memory region and set the memory information
  150. * to vaddr and dma_addr of a buffer object.
  151. */
  152. if (lowlevel_buffer_allocate(dev, flags, buf) < 0)
  153. return -ENOMEM;
  154. return 0;
  155. }
  156. void exynos_drm_free_buf(struct drm_device *dev,
  157. unsigned int flags, struct exynos_drm_gem_buf *buffer)
  158. {
  159. lowlevel_buffer_deallocate(dev, flags, buffer);
  160. }