hx170dec.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include "FreeRTOS.h"
  2. #include "chip.h"
  3. #include "os_adapt.h"
  4. #include "hx170dec.h"
  5. #include "vdec.h"
  6. #define REGS_VDEC_BASE REGS_MFC_BASE
  7. #define VDEC_MAX_CORES 1 /* number of cores of the hardware IP */
  8. #define VDEC_NUM_REGS_DEC 60 /* number of registers of the Decoder part */
  9. #define VDEC_NUM_REGS_PP 41 /* number of registers of the Post Processor part */
  10. #define VDEC_DEC_FIRST_REG 0 /* first register (0-based) index */
  11. #define VDEC_DEC_LAST_REG 59 /* last register (0-based) index */
  12. #define VDEC_PP_FIRST_REG 60
  13. #define VDEC_PP_LAST_REG 100
  14. struct vdec_device {
  15. unsigned int mmio_base;
  16. struct device *dev;
  17. int irq;
  18. int num_cores;
  19. unsigned long iobaseaddr;
  20. unsigned long iosize;
  21. QueueHandle_t dec_irq_done;
  22. SemaphoreHandle_t dec_sem;
  23. u32 regs[VDEC_NUM_REGS_DEC + VDEC_NUM_REGS_PP];
  24. };
  25. static struct vdec_device *vdec6731_global;
  26. static inline void vdec_writel(const struct vdec_device *p, unsigned offset, u32 val)
  27. {
  28. writel(val, p->mmio_base + offset);
  29. }
  30. static inline u32 vdec_readl(const struct vdec_device *p, unsigned offset)
  31. {
  32. return readl(p->mmio_base + offset);
  33. }
  34. /**
  35. * Write a range of registers. First register is assumed to be
  36. * "Interrupt Register" and will be written last.
  37. */
  38. static int vdec_regs_write(struct vdec_device *p, int begin, int end,
  39. const struct core_desc *core)
  40. {
  41. int i;
  42. memcpy(&p->regs[begin], core->regs, (end - begin + 1) * 4);
  43. for (i = end; i >= begin; i--)
  44. vdec_writel(p, 4 * i, p->regs[i]);
  45. return 0;
  46. }
  47. /**
  48. * Read a range of registers [begin..end]
  49. */
  50. static int vdec_regs_read(struct vdec_device *p, int begin, int end,
  51. const struct core_desc *core)
  52. {
  53. int i;
  54. for (i = end; i >= begin; i--)
  55. p->regs[i] = vdec_readl(p, 4 * i);
  56. memcpy(core->regs, &p->regs[begin], (end - begin + 1) * 4);
  57. return 0;
  58. }
  59. long vdec_ioctl(unsigned int cmd, void *arg)
  60. {
  61. int ret = 0;
  62. void *argp = arg;
  63. struct vdec_device *p = vdec6731_global;
  64. struct core_desc core;
  65. u32 reg;
  66. switch (cmd) {
  67. case HX170DEC_IOX_ASIC_ID:
  68. reg = vdec_readl(p, VDEC_IDR);
  69. memcpy(argp, &reg, sizeof(u32));
  70. break;
  71. case HX170DEC_IOC_MC_OFFSETS:
  72. case HX170DEC_IOCGHWOFFSET:
  73. memcpy(argp, &p->iobaseaddr, sizeof(p->iobaseaddr));
  74. break;
  75. case HX170DEC_IOCGHWIOSIZE: /* in bytes */
  76. memcpy(argp, &p->iosize, sizeof(p->iosize));
  77. break;
  78. case HX170DEC_IOC_MC_CORES:
  79. memcpy(argp, &p->num_cores, sizeof(p->num_cores));
  80. break;
  81. case HX170DEC_IOCS_DEC_PUSH_REG:
  82. memcpy(&core, (void *)arg, sizeof(struct core_desc));
  83. /* Skip VDEC_IDR (ID Register, ro) */
  84. core.regs++; // core.size -= 4;
  85. ret = vdec_regs_write(p, VDEC_DEC_FIRST_REG + 1, VDEC_DEC_LAST_REG, &core);
  86. break;
  87. case HX170DEC_IOCS_PP_PUSH_REG:
  88. break;
  89. case HX170DEC_IOCS_DEC_PULL_REG:
  90. memcpy(&core, (void *)arg, sizeof(struct core_desc));
  91. ret = vdec_regs_read(p, VDEC_DEC_FIRST_REG, VDEC_DEC_LAST_REG, &core);
  92. break;
  93. case HX170DEC_IOCS_PP_PULL_REG:
  94. break;
  95. case HX170DEC_IOCX_DEC_WAIT:
  96. memcpy(&core, (void *)arg, sizeof(struct core_desc));
  97. if (xQueueReceive(p->dec_irq_done, NULL, pdMS_TO_TICKS(1000)) != pdTRUE) {
  98. dev_err(p->dev, "wait_event_interruptible dec error %d\n", ret);
  99. ret = -ETIMEDOUT;
  100. } else {
  101. /* Update dec registers */
  102. ret = vdec_regs_read(p, VDEC_DEC_FIRST_REG, VDEC_DEC_LAST_REG, &core);
  103. }
  104. xQueueReset(p->dec_irq_done);
  105. break;
  106. case HX170DEC_IOCX_PP_WAIT:
  107. break;
  108. case HX170DEC_IOCH_DEC_RESERVE:
  109. if (xSemaphoreTake(p->dec_sem, pdMS_TO_TICKS(100)) == pdTRUE) {
  110. ret = 0; /* core id */
  111. dev_dbg(p->dev, "down dec_sem (core id %d)\n", ret);
  112. } else {
  113. dev_err(p->dev, "down_interruptible dec error\n");
  114. ret = -ETIMEDOUT;
  115. }
  116. break;
  117. case HX170DEC_IOCT_DEC_RELEASE:
  118. dev_dbg(p->dev, "up dec_sem\n");
  119. xSemaphoreGive(p->dec_sem);
  120. break;
  121. case HX170DEC_IOCQ_PP_RESERVE:
  122. break;
  123. case HX170DEC_IOCT_PP_RELEASE:
  124. break;
  125. default:
  126. dev_warn(p->dev, "unknown ioctl %x\n", cmd);
  127. ret = -EINVAL;
  128. }
  129. return ret;
  130. }
  131. /*
  132. * Platform driver related
  133. */
  134. /* Should we use spin_lock_irqsave here? */
  135. static void vdec_isr(void *dev_id)
  136. {
  137. struct vdec_device *p = dev_id;
  138. u32 irq_status_dec;
  139. int handled = 0;
  140. /* interrupt status register read */
  141. irq_status_dec = vdec_readl(p, VDEC_DIR);
  142. //printf("irq_status=0x%x.\n", irq_status_dec);
  143. if (irq_status_dec & VDEC_DIR_ISET) {
  144. /* Clear IRQ */
  145. vdec_writel(p, VDEC_DIR, irq_status_dec & ~VDEC_DIR_ISET);
  146. xQueueSendFromISR(p->dec_irq_done, NULL, 0);
  147. handled++;
  148. }
  149. if (handled == 0) {
  150. dev_warn(p->dev, "Spurious IRQ (DIR=%08x)\n", irq_status_dec);
  151. }
  152. }
  153. #if 0
  154. static void vdec_iram_mode_select(void)
  155. {
  156. //0 MFC ram use as iram; 1 MFCram use MFC REF buffer
  157. u32 val = readl(REGS_SYSCTL_BASE + 0x78);
  158. val |= (1<<0);
  159. writel(val, REGS_SYSCTL_BASE + 0x78);
  160. }
  161. #endif
  162. int vdec_init(void)
  163. {
  164. struct vdec_device *p;
  165. int hwid;
  166. vClkEnable(CLK_MFC);
  167. /* Allocate private data */
  168. p = pvPortMalloc(sizeof(struct vdec_device));
  169. if (!p) {
  170. dev_dbg(&pdev->dev, "out of memory\n");
  171. return -ENOMEM;
  172. }
  173. memset(p, 0, sizeof(struct vdec_device));
  174. p->mmio_base = REGS_VDEC_BASE;
  175. p->irq = MFC_IRQn;
  176. p->num_cores = VDEC_MAX_CORES;
  177. p->iosize = 0x200;
  178. p->iobaseaddr = REGS_VDEC_BASE;
  179. vdec6731_global = p;
  180. request_irq(p->irq, 0, vdec_isr, p);
  181. p->dec_irq_done = xQueueCreate(1, 0);
  182. p->dec_sem = xSemaphoreCreateCounting(VDEC_MAX_CORES, 1);
  183. dev_info(&pdev->dev, "VDEC controller at 0x%x, irq = %d\n",
  184. p->mmio_base, p->irq);
  185. /* Reset Asic (just in case..) */
  186. vdec_writel(p, VDEC_DIR, VDEC_DIR_ID | VDEC_DIR_ABORT);
  187. vdec_writel(p, VDEC_PPIR, VDEC_PPIR_ID);
  188. hwid = vdec_readl(p, VDEC_IDR);
  189. printf("Product ID: %#x (revision %d.%d.%d)\n", \
  190. (hwid & VDEC_IDR_PROD_ID) >> 16,
  191. (hwid & VDEC_IDR_MAJOR_VER) >> 12,
  192. (hwid & VDEC_IDR_MINOR_VER) >> 4,
  193. (hwid & VDEC_IDR_BUILD_VER));
  194. return 0;
  195. }