s5p_mfc_ctrl.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
  3. *
  4. * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  5. * http://www.samsung.com/
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/err.h>
  14. #include <linux/firmware.h>
  15. #include <linux/jiffies.h>
  16. #include <linux/sched.h>
  17. #include "s5p_mfc_cmd.h"
  18. #include "s5p_mfc_common.h"
  19. #include "s5p_mfc_debug.h"
  20. #include "s5p_mfc_intr.h"
  21. #include "s5p_mfc_opr.h"
  22. #include "s5p_mfc_pm.h"
  23. static void *s5p_mfc_bitproc_buf;
  24. static size_t s5p_mfc_bitproc_phys;
  25. static unsigned char *s5p_mfc_bitproc_virt;
  26. /* Allocate and load firmware */
  27. int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
  28. {
  29. struct firmware *fw_blob;
  30. size_t bank2_base_phys;
  31. void *b_base;
  32. int err;
  33. /* Firmare has to be present as a separate file or compiled
  34. * into kernel. */
  35. mfc_debug_enter();
  36. err = request_firmware((const struct firmware **)&fw_blob,
  37. "s5p-mfc.fw", dev->v4l2_dev.dev);
  38. if (err != 0) {
  39. mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
  40. return -EINVAL;
  41. }
  42. dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
  43. if (s5p_mfc_bitproc_buf) {
  44. mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
  45. release_firmware(fw_blob);
  46. return -ENOMEM;
  47. }
  48. s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc(
  49. dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size);
  50. if (IS_ERR(s5p_mfc_bitproc_buf)) {
  51. s5p_mfc_bitproc_buf = NULL;
  52. mfc_err("Allocating bitprocessor buffer failed\n");
  53. release_firmware(fw_blob);
  54. return -ENOMEM;
  55. }
  56. s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie(
  57. dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf);
  58. if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
  59. mfc_err("The base memory for bank 1 is not aligned to 128KB\n");
  60. vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
  61. s5p_mfc_bitproc_phys = 0;
  62. s5p_mfc_bitproc_buf = NULL;
  63. release_firmware(fw_blob);
  64. return -EIO;
  65. }
  66. s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf);
  67. if (!s5p_mfc_bitproc_virt) {
  68. mfc_err("Bitprocessor memory remap failed\n");
  69. vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
  70. s5p_mfc_bitproc_phys = 0;
  71. s5p_mfc_bitproc_buf = NULL;
  72. release_firmware(fw_blob);
  73. return -EIO;
  74. }
  75. dev->bank1 = s5p_mfc_bitproc_phys;
  76. b_base = vb2_dma_contig_memops.alloc(
  77. dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER);
  78. if (IS_ERR(b_base)) {
  79. vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
  80. s5p_mfc_bitproc_phys = 0;
  81. s5p_mfc_bitproc_buf = NULL;
  82. mfc_err("Allocating bank2 base failed\n");
  83. release_firmware(fw_blob);
  84. return -ENOMEM;
  85. }
  86. bank2_base_phys = s5p_mfc_mem_cookie(
  87. dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
  88. vb2_dma_contig_memops.put(b_base);
  89. if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
  90. mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
  91. vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
  92. s5p_mfc_bitproc_phys = 0;
  93. s5p_mfc_bitproc_buf = NULL;
  94. release_firmware(fw_blob);
  95. return -EIO;
  96. }
  97. /* Valid buffers passed to MFC encoder with LAST_FRAME command
  98. * should not have address of bank2 - MFC will treat it as a null frame.
  99. * To avoid such situation we set bank2 address below the pool address.
  100. */
  101. dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
  102. memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
  103. wmb();
  104. release_firmware(fw_blob);
  105. mfc_debug_leave();
  106. return 0;
  107. }
  108. /* Reload firmware to MFC */
  109. int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
  110. {
  111. struct firmware *fw_blob;
  112. int err;
  113. /* Firmare has to be present as a separate file or compiled
  114. * into kernel. */
  115. mfc_debug_enter();
  116. err = request_firmware((const struct firmware **)&fw_blob,
  117. "s5p-mfc.fw", dev->v4l2_dev.dev);
  118. if (err != 0) {
  119. mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
  120. return -EINVAL;
  121. }
  122. if (fw_blob->size > dev->fw_size) {
  123. mfc_err("MFC firmware is too big to be loaded\n");
  124. release_firmware(fw_blob);
  125. return -ENOMEM;
  126. }
  127. if (s5p_mfc_bitproc_buf == NULL || s5p_mfc_bitproc_phys == 0) {
  128. mfc_err("MFC firmware is not allocated or was not mapped correctly\n");
  129. release_firmware(fw_blob);
  130. return -EINVAL;
  131. }
  132. memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
  133. wmb();
  134. release_firmware(fw_blob);
  135. mfc_debug_leave();
  136. return 0;
  137. }
  138. /* Release firmware memory */
  139. int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
  140. {
  141. /* Before calling this function one has to make sure
  142. * that MFC is no longer processing */
  143. if (!s5p_mfc_bitproc_buf)
  144. return -EINVAL;
  145. vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
  146. s5p_mfc_bitproc_virt = NULL;
  147. s5p_mfc_bitproc_phys = 0;
  148. s5p_mfc_bitproc_buf = NULL;
  149. return 0;
  150. }
  151. /* Reset the device */
  152. int s5p_mfc_reset(struct s5p_mfc_dev *dev)
  153. {
  154. unsigned int mc_status;
  155. unsigned long timeout;
  156. mfc_debug_enter();
  157. /* Stop procedure */
  158. /* reset RISC */
  159. mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
  160. /* All reset except for MC */
  161. mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
  162. mdelay(10);
  163. timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
  164. /* Check MC status */
  165. do {
  166. if (time_after(jiffies, timeout)) {
  167. mfc_err("Timeout while resetting MFC\n");
  168. return -EIO;
  169. }
  170. mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
  171. } while (mc_status & 0x3);
  172. mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
  173. mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
  174. mfc_debug_leave();
  175. return 0;
  176. }
  177. static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
  178. {
  179. mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
  180. mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
  181. mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
  182. }
  183. static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
  184. {
  185. mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
  186. mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
  187. mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
  188. mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
  189. }
  190. /* Initialize hardware */
  191. int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
  192. {
  193. unsigned int ver;
  194. int ret;
  195. mfc_debug_enter();
  196. if (!s5p_mfc_bitproc_buf)
  197. return -EINVAL;
  198. /* 0. MFC reset */
  199. mfc_debug(2, "MFC reset..\n");
  200. s5p_mfc_clock_on();
  201. ret = s5p_mfc_reset(dev);
  202. if (ret) {
  203. mfc_err("Failed to reset MFC - timeout\n");
  204. return ret;
  205. }
  206. mfc_debug(2, "Done MFC reset..\n");
  207. /* 1. Set DRAM base Addr */
  208. s5p_mfc_init_memctrl(dev);
  209. /* 2. Initialize registers of channel I/F */
  210. s5p_mfc_clear_cmds(dev);
  211. /* 3. Release reset signal to the RISC */
  212. s5p_mfc_clean_dev_int_flags(dev);
  213. mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
  214. mfc_debug(2, "Will now wait for completion of firmware transfer\n");
  215. if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
  216. mfc_err("Failed to load firmware\n");
  217. s5p_mfc_reset(dev);
  218. s5p_mfc_clock_off();
  219. return -EIO;
  220. }
  221. s5p_mfc_clean_dev_int_flags(dev);
  222. /* 4. Initialize firmware */
  223. ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
  224. if (ret) {
  225. mfc_err("Failed to send command to MFC - timeout\n");
  226. s5p_mfc_reset(dev);
  227. s5p_mfc_clock_off();
  228. return ret;
  229. }
  230. mfc_debug(2, "Ok, now will write a command to init the system\n");
  231. if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
  232. mfc_err("Failed to load firmware\n");
  233. s5p_mfc_reset(dev);
  234. s5p_mfc_clock_off();
  235. return -EIO;
  236. }
  237. dev->int_cond = 0;
  238. if (dev->int_err != 0 || dev->int_type !=
  239. S5P_MFC_R2H_CMD_SYS_INIT_RET) {
  240. /* Failure. */
  241. mfc_err("Failed to init firmware - error: %d int: %d\n",
  242. dev->int_err, dev->int_type);
  243. s5p_mfc_reset(dev);
  244. s5p_mfc_clock_off();
  245. return -EIO;
  246. }
  247. ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
  248. mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
  249. (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
  250. s5p_mfc_clock_off();
  251. mfc_debug_leave();
  252. return 0;
  253. }
  254. /* Deinitialize hardware */
  255. void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
  256. {
  257. s5p_mfc_clock_on();
  258. s5p_mfc_reset(dev);
  259. s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
  260. s5p_mfc_clock_off();
  261. }
  262. int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
  263. {
  264. int ret;
  265. mfc_debug_enter();
  266. s5p_mfc_clock_on();
  267. s5p_mfc_clean_dev_int_flags(dev);
  268. ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
  269. if (ret) {
  270. mfc_err("Failed to send command to MFC - timeout\n");
  271. return ret;
  272. }
  273. if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
  274. mfc_err("Failed to sleep\n");
  275. return -EIO;
  276. }
  277. s5p_mfc_clock_off();
  278. dev->int_cond = 0;
  279. if (dev->int_err != 0 || dev->int_type !=
  280. S5P_MFC_R2H_CMD_SLEEP_RET) {
  281. /* Failure. */
  282. mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
  283. dev->int_type);
  284. return -EIO;
  285. }
  286. mfc_debug_leave();
  287. return ret;
  288. }
  289. int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
  290. {
  291. int ret;
  292. mfc_debug_enter();
  293. /* 0. MFC reset */
  294. mfc_debug(2, "MFC reset..\n");
  295. s5p_mfc_clock_on();
  296. ret = s5p_mfc_reset(dev);
  297. if (ret) {
  298. mfc_err("Failed to reset MFC - timeout\n");
  299. return ret;
  300. }
  301. mfc_debug(2, "Done MFC reset..\n");
  302. /* 1. Set DRAM base Addr */
  303. s5p_mfc_init_memctrl(dev);
  304. /* 2. Initialize registers of channel I/F */
  305. s5p_mfc_clear_cmds(dev);
  306. s5p_mfc_clean_dev_int_flags(dev);
  307. /* 3. Initialize firmware */
  308. ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
  309. if (ret) {
  310. mfc_err("Failed to send command to MFC - timeout\n");
  311. return ret;
  312. }
  313. /* 4. Release reset signal to the RISC */
  314. mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
  315. mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
  316. if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
  317. mfc_err("Failed to load firmware\n");
  318. return -EIO;
  319. }
  320. s5p_mfc_clock_off();
  321. dev->int_cond = 0;
  322. if (dev->int_err != 0 || dev->int_type !=
  323. S5P_MFC_R2H_CMD_WAKEUP_RET) {
  324. /* Failure. */
  325. mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
  326. dev->int_type);
  327. return -EIO;
  328. }
  329. mfc_debug_leave();
  330. return 0;
  331. }