s5p_mfc_ctrl.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * linux/drivers/media/video/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 "regs-mfc.h"
  18. #include "s5p_mfc_cmd.h"
  19. #include "s5p_mfc_common.h"
  20. #include "s5p_mfc_debug.h"
  21. #include "s5p_mfc_intr.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 = 0;
  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 = 0;
  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 = 0;
  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_BANK2_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 = 0;
  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 = 0;
  94. release_firmware(fw_blob);
  95. return -EIO;
  96. }
  97. dev->bank2 = bank2_base_phys;
  98. memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
  99. wmb();
  100. release_firmware(fw_blob);
  101. mfc_debug_leave();
  102. return 0;
  103. }
  104. /* Reload firmware to MFC */
  105. int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
  106. {
  107. struct firmware *fw_blob;
  108. int err;
  109. /* Firmare has to be present as a separate file or compiled
  110. * into kernel. */
  111. mfc_debug_enter();
  112. err = request_firmware((const struct firmware **)&fw_blob,
  113. "s5p-mfc.fw", dev->v4l2_dev.dev);
  114. if (err != 0) {
  115. mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
  116. return -EINVAL;
  117. }
  118. if (fw_blob->size > dev->fw_size) {
  119. mfc_err("MFC firmware is too big to be loaded\n");
  120. release_firmware(fw_blob);
  121. return -ENOMEM;
  122. }
  123. if (s5p_mfc_bitproc_buf == 0 || s5p_mfc_bitproc_phys == 0) {
  124. mfc_err("MFC firmware is not allocated or was not mapped correctly\n");
  125. release_firmware(fw_blob);
  126. return -EINVAL;
  127. }
  128. memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
  129. wmb();
  130. release_firmware(fw_blob);
  131. mfc_debug_leave();
  132. return 0;
  133. }
  134. /* Release firmware memory */
  135. int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
  136. {
  137. /* Before calling this function one has to make sure
  138. * that MFC is no longer processing */
  139. if (!s5p_mfc_bitproc_buf)
  140. return -EINVAL;
  141. vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
  142. s5p_mfc_bitproc_virt = 0;
  143. s5p_mfc_bitproc_phys = 0;
  144. s5p_mfc_bitproc_buf = 0;
  145. return 0;
  146. }
  147. /* Reset the device */
  148. int s5p_mfc_reset(struct s5p_mfc_dev *dev)
  149. {
  150. unsigned int mc_status;
  151. unsigned long timeout;
  152. mfc_debug_enter();
  153. /* Stop procedure */
  154. /* reset RISC */
  155. mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
  156. /* All reset except for MC */
  157. mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
  158. mdelay(10);
  159. timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
  160. /* Check MC status */
  161. do {
  162. if (time_after(jiffies, timeout)) {
  163. mfc_err("Timeout while resetting MFC\n");
  164. return -EIO;
  165. }
  166. mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
  167. } while (mc_status & 0x3);
  168. mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
  169. mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
  170. mfc_debug_leave();
  171. return 0;
  172. }
  173. static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
  174. {
  175. mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
  176. mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
  177. mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
  178. }
  179. static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
  180. {
  181. mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
  182. mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
  183. mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
  184. mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
  185. }
  186. /* Initialize hardware */
  187. int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
  188. {
  189. unsigned int ver;
  190. int ret;
  191. mfc_debug_enter();
  192. if (!s5p_mfc_bitproc_buf)
  193. return -EINVAL;
  194. /* 0. MFC reset */
  195. mfc_debug(2, "MFC reset..\n");
  196. s5p_mfc_clock_on();
  197. ret = s5p_mfc_reset(dev);
  198. if (ret) {
  199. mfc_err("Failed to reset MFC - timeout\n");
  200. return ret;
  201. }
  202. mfc_debug(2, "Done MFC reset..\n");
  203. /* 1. Set DRAM base Addr */
  204. s5p_mfc_init_memctrl(dev);
  205. /* 2. Initialize registers of channel I/F */
  206. s5p_mfc_clear_cmds(dev);
  207. /* 3. Release reset signal to the RISC */
  208. s5p_mfc_clean_dev_int_flags(dev);
  209. mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
  210. mfc_debug(2, "Will now wait for completion of firmware transfer\n");
  211. if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
  212. mfc_err("Failed to load firmware\n");
  213. s5p_mfc_reset(dev);
  214. s5p_mfc_clock_off();
  215. return -EIO;
  216. }
  217. s5p_mfc_clean_dev_int_flags(dev);
  218. /* 4. Initialize firmware */
  219. ret = s5p_mfc_sys_init_cmd(dev);
  220. if (ret) {
  221. mfc_err("Failed to send command to MFC - timeout\n");
  222. s5p_mfc_reset(dev);
  223. s5p_mfc_clock_off();
  224. return ret;
  225. }
  226. mfc_debug(2, "Ok, now will write a command to init the system\n");
  227. if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
  228. mfc_err("Failed to load firmware\n");
  229. s5p_mfc_reset(dev);
  230. s5p_mfc_clock_off();
  231. return -EIO;
  232. }
  233. dev->int_cond = 0;
  234. if (dev->int_err != 0 || dev->int_type !=
  235. S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
  236. /* Failure. */
  237. mfc_err("Failed to init firmware - error: %d int: %d\n",
  238. dev->int_err, dev->int_type);
  239. s5p_mfc_reset(dev);
  240. s5p_mfc_clock_off();
  241. return -EIO;
  242. }
  243. ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
  244. mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
  245. (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
  246. s5p_mfc_clock_off();
  247. mfc_debug_leave();
  248. return 0;
  249. }
  250. int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
  251. {
  252. int ret;
  253. mfc_debug_enter();
  254. s5p_mfc_clock_on();
  255. s5p_mfc_clean_dev_int_flags(dev);
  256. ret = s5p_mfc_sleep_cmd(dev);
  257. if (ret) {
  258. mfc_err("Failed to send command to MFC - timeout\n");
  259. return ret;
  260. }
  261. if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
  262. mfc_err("Failed to sleep\n");
  263. return -EIO;
  264. }
  265. s5p_mfc_clock_off();
  266. dev->int_cond = 0;
  267. if (dev->int_err != 0 || dev->int_type !=
  268. S5P_FIMV_R2H_CMD_SLEEP_RET) {
  269. /* Failure. */
  270. mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
  271. dev->int_type);
  272. return -EIO;
  273. }
  274. mfc_debug_leave();
  275. return ret;
  276. }
  277. int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
  278. {
  279. int ret;
  280. mfc_debug_enter();
  281. /* 0. MFC reset */
  282. mfc_debug(2, "MFC reset..\n");
  283. s5p_mfc_clock_on();
  284. ret = s5p_mfc_reset(dev);
  285. if (ret) {
  286. mfc_err("Failed to reset MFC - timeout\n");
  287. return ret;
  288. }
  289. mfc_debug(2, "Done MFC reset..\n");
  290. /* 1. Set DRAM base Addr */
  291. s5p_mfc_init_memctrl(dev);
  292. /* 2. Initialize registers of channel I/F */
  293. s5p_mfc_clear_cmds(dev);
  294. s5p_mfc_clean_dev_int_flags(dev);
  295. /* 3. Initialize firmware */
  296. ret = s5p_mfc_wakeup_cmd(dev);
  297. if (ret) {
  298. mfc_err("Failed to send command to MFC - timeout\n");
  299. return ret;
  300. }
  301. /* 4. Release reset signal to the RISC */
  302. mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
  303. mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
  304. if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
  305. mfc_err("Failed to load firmware\n");
  306. return -EIO;
  307. }
  308. s5p_mfc_clock_off();
  309. dev->int_cond = 0;
  310. if (dev->int_err != 0 || dev->int_type !=
  311. S5P_FIMV_R2H_CMD_WAKEUP_RET) {
  312. /* Failure. */
  313. mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
  314. dev->int_type);
  315. return -EIO;
  316. }
  317. mfc_debug_leave();
  318. return 0;
  319. }