ddp_rdma_ex.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. #define LOG_TAG "RDMA"
  2. #include "ddp_log.h"
  3. #ifdef CONFIG_MTK_CLKMGR
  4. #include <mach/mt_clkmgr.h>
  5. #endif
  6. #include <linux/delay.h>
  7. #include "ddp_info.h"
  8. #include "ddp_reg.h"
  9. #include "ddp_matrix_para.h"
  10. #include "ddp_rdma.h"
  11. #include "ddp_rdma_ex.h"
  12. #include "ddp_dump.h"
  13. #include "lcm_drv.h"
  14. #include "primary_display.h"
  15. #include "m4u.h"
  16. #include "ddp_drv.h"
  17. #include "ddp_debug.h"
  18. #include "ddp_irq.h"
  19. static unsigned int rdma_fps[RDMA_INSTANCES] = { 60, 60 };
  20. static enum RDMA_INPUT_FORMAT rdma_input_format_convert(DpColorFormat fmt)
  21. {
  22. enum RDMA_INPUT_FORMAT rdma_fmt = RDMA_INPUT_FORMAT_RGB565;
  23. switch (fmt) {
  24. case eBGR565:
  25. rdma_fmt = RDMA_INPUT_FORMAT_BGR565;
  26. break;
  27. case eRGB888:
  28. rdma_fmt = RDMA_INPUT_FORMAT_RGB888;
  29. break;
  30. case eRGBA8888:
  31. rdma_fmt = RDMA_INPUT_FORMAT_RGBA8888;
  32. break;
  33. case eARGB8888:
  34. rdma_fmt = RDMA_INPUT_FORMAT_ARGB8888;
  35. break;
  36. case eVYUY:
  37. rdma_fmt = RDMA_INPUT_FORMAT_VYUY;
  38. break;
  39. case eYVYU:
  40. rdma_fmt = RDMA_INPUT_FORMAT_YVYU;
  41. break;
  42. case eRGB565:
  43. rdma_fmt = RDMA_INPUT_FORMAT_RGB565;
  44. break;
  45. case eBGR888:
  46. rdma_fmt = RDMA_INPUT_FORMAT_BGR888;
  47. break;
  48. case eBGRA8888:
  49. rdma_fmt = RDMA_INPUT_FORMAT_BGRA8888;
  50. break;
  51. case eABGR8888:
  52. rdma_fmt = RDMA_INPUT_FORMAT_ABGR8888;
  53. break;
  54. case eUYVY:
  55. rdma_fmt = RDMA_INPUT_FORMAT_UYVY;
  56. break;
  57. case eYUY2:
  58. rdma_fmt = RDMA_INPUT_FORMAT_YUYV;
  59. break;
  60. default:
  61. DDPERR("rdma_input_format_convert fmt=%d, rdma_fmt=%d\n", fmt, rdma_fmt);
  62. }
  63. return rdma_fmt;
  64. }
  65. static unsigned int rdma_input_format_byte_swap(enum RDMA_INPUT_FORMAT inputFormat)
  66. {
  67. int input_swap = 0;
  68. switch (inputFormat) {
  69. case RDMA_INPUT_FORMAT_BGR565:
  70. case RDMA_INPUT_FORMAT_RGB888:
  71. case RDMA_INPUT_FORMAT_RGBA8888:
  72. case RDMA_INPUT_FORMAT_ARGB8888:
  73. case RDMA_INPUT_FORMAT_VYUY:
  74. case RDMA_INPUT_FORMAT_YVYU:
  75. input_swap = 1;
  76. break;
  77. case RDMA_INPUT_FORMAT_RGB565:
  78. case RDMA_INPUT_FORMAT_BGR888:
  79. case RDMA_INPUT_FORMAT_BGRA8888:
  80. case RDMA_INPUT_FORMAT_ABGR8888:
  81. case RDMA_INPUT_FORMAT_UYVY:
  82. case RDMA_INPUT_FORMAT_YUYV:
  83. input_swap = 0;
  84. break;
  85. default:
  86. DDPERR("unknown RDMA input format is %d\n", inputFormat);
  87. ASSERT(0);
  88. }
  89. return input_swap;
  90. }
  91. static unsigned int rdma_input_format_bpp(enum RDMA_INPUT_FORMAT inputFormat)
  92. {
  93. int bpp = 0;
  94. switch (inputFormat) {
  95. case RDMA_INPUT_FORMAT_BGR565:
  96. case RDMA_INPUT_FORMAT_RGB565:
  97. case RDMA_INPUT_FORMAT_VYUY:
  98. case RDMA_INPUT_FORMAT_UYVY:
  99. case RDMA_INPUT_FORMAT_YVYU:
  100. case RDMA_INPUT_FORMAT_YUYV:
  101. bpp = 2;
  102. break;
  103. case RDMA_INPUT_FORMAT_RGB888:
  104. case RDMA_INPUT_FORMAT_BGR888:
  105. bpp = 3;
  106. break;
  107. case RDMA_INPUT_FORMAT_ARGB8888:
  108. case RDMA_INPUT_FORMAT_ABGR8888:
  109. case RDMA_INPUT_FORMAT_RGBA8888:
  110. case RDMA_INPUT_FORMAT_BGRA8888:
  111. bpp = 4;
  112. break;
  113. default:
  114. DDPERR("unknown RDMA input format = %d\n", inputFormat);
  115. ASSERT(0);
  116. }
  117. return bpp;
  118. }
  119. static unsigned int rdma_input_format_color_space(enum RDMA_INPUT_FORMAT inputFormat)
  120. {
  121. int space = 0;
  122. switch (inputFormat) {
  123. case RDMA_INPUT_FORMAT_BGR565:
  124. case RDMA_INPUT_FORMAT_RGB565:
  125. case RDMA_INPUT_FORMAT_RGB888:
  126. case RDMA_INPUT_FORMAT_BGR888:
  127. case RDMA_INPUT_FORMAT_RGBA8888:
  128. case RDMA_INPUT_FORMAT_BGRA8888:
  129. case RDMA_INPUT_FORMAT_ARGB8888:
  130. case RDMA_INPUT_FORMAT_ABGR8888:
  131. space = 0;
  132. break;
  133. case RDMA_INPUT_FORMAT_VYUY:
  134. case RDMA_INPUT_FORMAT_UYVY:
  135. case RDMA_INPUT_FORMAT_YVYU:
  136. case RDMA_INPUT_FORMAT_YUYV:
  137. space = 1;
  138. break;
  139. default:
  140. DDPERR("unknown RDMA input format = %d\n", inputFormat);
  141. ASSERT(0);
  142. }
  143. return space;
  144. }
  145. static unsigned int rdma_input_format_reg_value(enum RDMA_INPUT_FORMAT inputFormat)
  146. {
  147. int reg_value = 0;
  148. switch (inputFormat) {
  149. case RDMA_INPUT_FORMAT_BGR565:
  150. case RDMA_INPUT_FORMAT_RGB565:
  151. reg_value = 0x0;
  152. break;
  153. case RDMA_INPUT_FORMAT_RGB888:
  154. case RDMA_INPUT_FORMAT_BGR888:
  155. reg_value = 0x1;
  156. break;
  157. case RDMA_INPUT_FORMAT_RGBA8888:
  158. case RDMA_INPUT_FORMAT_BGRA8888:
  159. reg_value = 0x2;
  160. break;
  161. case RDMA_INPUT_FORMAT_ARGB8888:
  162. case RDMA_INPUT_FORMAT_ABGR8888:
  163. reg_value = 0x3;
  164. break;
  165. case RDMA_INPUT_FORMAT_VYUY:
  166. case RDMA_INPUT_FORMAT_UYVY:
  167. reg_value = 0x4;
  168. break;
  169. case RDMA_INPUT_FORMAT_YVYU:
  170. case RDMA_INPUT_FORMAT_YUYV:
  171. reg_value = 0x5;
  172. break;
  173. default:
  174. DDPERR("unknown RDMA input format is %d\n", inputFormat);
  175. ASSERT(0);
  176. }
  177. return reg_value;
  178. }
  179. static char *rdma_intput_format_name(enum RDMA_INPUT_FORMAT fmt, int swap)
  180. {
  181. switch (fmt) {
  182. case RDMA_INPUT_FORMAT_BGR565:
  183. return swap ? "eBGR565" : "eRGB565";
  184. case RDMA_INPUT_FORMAT_RGB565:
  185. return "eRGB565";
  186. case RDMA_INPUT_FORMAT_RGB888:
  187. return swap ? "eRGB888" : "eBGR888";
  188. case RDMA_INPUT_FORMAT_BGR888:
  189. return "eBGR888";
  190. case RDMA_INPUT_FORMAT_RGBA8888:
  191. return swap ? "eRGBA888" : "eBGRA888";
  192. case RDMA_INPUT_FORMAT_BGRA8888:
  193. return "eBGRA888";
  194. case RDMA_INPUT_FORMAT_ARGB8888:
  195. return swap ? "eARGB8888" : "eABGR8888";
  196. case RDMA_INPUT_FORMAT_ABGR8888:
  197. return "eABGR8888";
  198. case RDMA_INPUT_FORMAT_VYUY:
  199. return swap ? "eVYUY" : "eUYVY";
  200. case RDMA_INPUT_FORMAT_UYVY:
  201. return "eUYVY";
  202. case RDMA_INPUT_FORMAT_YVYU:
  203. return swap ? "eYVYU" : "eYUY2";
  204. case RDMA_INPUT_FORMAT_YUYV:
  205. return "eYUY2";
  206. default:
  207. DDPERR("rdma_intput_format_name unknown fmt=%d, swap=%d\n", fmt, swap);
  208. break;
  209. }
  210. return "unknown";
  211. }
  212. int rdma_enable_irq(DISP_MODULE_ENUM module, void *handle, DDP_IRQ_LEVEL irq_level)
  213. {
  214. unsigned int idx = rdma_index(module);
  215. switch (irq_level) {
  216. case DDP_IRQ_LEVEL_ALL:
  217. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x1E);
  218. break;
  219. case DDP_IRQ_LEVEL_ERROR:
  220. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x18);
  221. /* only enable underflow/abnormal irq */
  222. break;
  223. case DDP_IRQ_LEVEL_NONE:
  224. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x0);
  225. break;
  226. default:
  227. break;
  228. }
  229. return 0;
  230. }
  231. int rdma_start(DISP_MODULE_ENUM module, void *handle)
  232. {
  233. unsigned int idx = rdma_index(module);
  234. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0x3E);
  235. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_ENGINE_EN,
  236. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 1);
  237. return 0;
  238. }
  239. int rdma_stop(DISP_MODULE_ENUM module, void *handle)
  240. {
  241. unsigned int idx = rdma_index(module);
  242. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_ENGINE_EN,
  243. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 0);
  244. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_ENABLE, 0);
  245. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_INT_STATUS, 0);
  246. return 0;
  247. }
  248. int rdma_reset(DISP_MODULE_ENUM module, void *handle)
  249. {
  250. unsigned int delay_cnt = 0;
  251. int ret = 0;
  252. unsigned int idx = rdma_index(module);
  253. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_SOFT_RESET,
  254. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 1);
  255. while ((DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON) & 0x700) == 0x100) {
  256. delay_cnt++;
  257. udelay(10);
  258. if (delay_cnt > 10000) {
  259. ret = -1;
  260. DDPERR("rdma%d_reset timeout, stage 1! DISP_REG_RDMA_GLOBAL_CON=0x%x\n",
  261. idx, DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON));
  262. break;
  263. }
  264. }
  265. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_SOFT_RESET,
  266. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, 0);
  267. delay_cnt = 0;
  268. while ((DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON) & 0x700) != 0x100) {
  269. delay_cnt++;
  270. udelay(10);
  271. if (delay_cnt > 10000) {
  272. ret = -1;
  273. DDPERR("rdma%d_reset timeout, stage 2! DISP_REG_RDMA_GLOBAL_CON=0x%x\n",
  274. idx,
  275. DISP_REG_GET(idx * DISP_RDMA_INDEX_OFFSET +
  276. DISP_REG_RDMA_GLOBAL_CON));
  277. break;
  278. }
  279. }
  280. return ret;
  281. }
  282. /* set ultra registers */
  283. void rdma_set_ultra(unsigned int idx, unsigned int width, unsigned int height, unsigned int bpp,
  284. unsigned int frame_rate, void *handle, enum RDMA_MODE mode)
  285. {
  286. /* constant */
  287. static const unsigned int blank_overhead = 115; /* it is 1.15, need to divide 100 later */
  288. static const unsigned int rdma_fifo_width = 16; /* in unit of byte */
  289. static const unsigned int ultra_low_time = 6; /* in unit of us */
  290. static const unsigned int pre_ultra_low_time = 8; /* in unit of us */
  291. static const unsigned int pre_ultra_high_time = 9; /* in unit of us */
  292. static const unsigned int fifo_valid_line_ratio = 125; /* valid size 1/8 line; */
  293. static const unsigned int fifo_min_size = 32;
  294. /* working variables */
  295. unsigned int consume_levels_per_sec;
  296. unsigned int ultra_low_level;
  297. unsigned int pre_ultra_low_level;
  298. unsigned int pre_ultra_high_level;
  299. unsigned int ultra_high_ofs;
  300. unsigned int pre_ultra_low_ofs;
  301. unsigned int pre_ultra_high_ofs;
  302. unsigned int fifo_valid_size = 16;
  303. unsigned int sodi_threshold = 0;
  304. /* compute fifo valid size */
  305. fifo_valid_size = (width * bpp * fifo_valid_line_ratio) / (rdma_fifo_width * 1000);
  306. fifo_valid_size = fifo_valid_size > fifo_min_size ? fifo_valid_size : fifo_min_size;
  307. /* consume_levels_per_sec = ((long long unsigned int)width * height * frame_rate * blank_overhead * bpp) /
  308. rdma_fifo_width / 100;
  309. */
  310. /* change calculation order to prevent overflow of unsigned int */
  311. consume_levels_per_sec = (width * height * frame_rate * bpp / rdma_fifo_width / 100) * blank_overhead;
  312. /* /1000000 for ultra_low_time in unit of us */
  313. ultra_low_level = (unsigned int)(ultra_low_time * consume_levels_per_sec / 1000000);
  314. pre_ultra_low_level = (unsigned int)(pre_ultra_low_time * consume_levels_per_sec / 1000000);
  315. pre_ultra_high_level = (unsigned int)(pre_ultra_high_time * consume_levels_per_sec / 1000000);
  316. pre_ultra_low_ofs = pre_ultra_low_level - ultra_low_level;
  317. ultra_high_ofs = 1;
  318. pre_ultra_high_ofs = pre_ultra_high_level - pre_ultra_low_level;
  319. if (gUltraEnable == 1) {
  320. ultra_low_level = 0x6b;
  321. pre_ultra_low_ofs = 0xa0;
  322. ultra_high_ofs = 1;
  323. pre_ultra_high_ofs = 1;
  324. }
  325. /* write ultra_low_level, ultra_high_ofs, pre_ultra_low_ofs,
  326. * pre_ultra_high_ofs into register DISP_RDMA_MEM_GMC_SETTING_0
  327. */
  328. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0,
  329. ultra_low_level | (pre_ultra_low_ofs << 8) | (ultra_high_ofs << 16) |
  330. (pre_ultra_high_ofs << 24));
  331. /* set rdma ultra/pre-ultra according to resolution */
  332. /* TODO: Need fine tune ultar configurations. */
  333. if (idx == 0) {
  334. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_PSEUDO_SIZE,
  335. idx*DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 512);
  336. DISP_REG_SET(handle, idx*DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_1, 0xFF);
  337. if (width > 800) {/* FHD */
  338. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0,
  339. 0x1c013770);
  340. if (mode == RDMA_MODE_DIRECT_LINK) {
  341. sodi_threshold = 168 | (475 << 10); /* low:168 high:475 (direct link in FHD) */
  342. fifo_valid_size = 0x70 + 1;
  343. } else {
  344. sodi_threshold = 168 | (236 << 10); /* low:168 high:236 (decouple in FHD) */
  345. fifo_valid_size = 0x70 + 1;
  346. }
  347. } else {/* HD */
  348. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0,
  349. 0x0c011832);
  350. if (mode == RDMA_MODE_DIRECT_LINK) {
  351. sodi_threshold = 75 | (455 << 10); /* low:75 high:455 (direct link in HD) */
  352. fifo_valid_size = 0x32 + 1;
  353. } else {
  354. sodi_threshold = 75 | (216 << 10); /* low:75 high:216 (decouple in HD) */
  355. fifo_valid_size = 0x32 + 1;
  356. }
  357. }
  358. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_THRESHOLD_FOR_SODI,
  359. sodi_threshold);
  360. if (gRDMAUltraSetting)
  361. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0,
  362. gRDMAUltraSetting);
  363. } else {
  364. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_GMC_SETTING_0,
  365. 0x1b013ba0);
  366. }
  367. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_OUTPUT_VALID_FIFO_THRESHOLD,
  368. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, fifo_valid_size);
  369. DISP_REG_SET(handle, DISP_REG_CONFIG_MMSYS_DUMMY, DISP_REG_GET(DISP_REG_CONFIG_MMSYS_DUMMY)|(1<<idx));
  370. DDPDBG("FIFO_VALID_Size = 0x%03x = %d\n", fifo_valid_size, fifo_valid_size);
  371. DDPDBG("ultra_low_level = 0x%03x = %d\n", ultra_low_level, ultra_low_level);
  372. DDPDBG("pre_ultra_low_level = 0x%03x = %d\n", pre_ultra_low_level, pre_ultra_low_level);
  373. DDPDBG("pre_ultra_high_level = 0x%03x = %d\n", pre_ultra_high_level, pre_ultra_high_level);
  374. DDPDBG("ultra_high_ofs = 0x%03x = %d\n", ultra_high_ofs, ultra_high_ofs);
  375. DDPDBG("pre_ultra_low_ofs = 0x%03x = %d\n", pre_ultra_low_ofs, pre_ultra_low_ofs);
  376. DDPDBG("pre_ultra_high_ofs = 0x%03x = %d\n", pre_ultra_high_ofs, pre_ultra_high_ofs);
  377. DDPDBG("sodi low threshold(%d) high threshold(%d)\n", (sodi_threshold & 0x3ff),
  378. (sodi_threshold & 0xffc00) >> 10);
  379. }
  380. /* fixme: spec has no RDMA format, fix enum definition here */
  381. static int rdma_config(DISP_MODULE_ENUM module,
  382. enum RDMA_MODE mode,
  383. unsigned long address,
  384. DpColorFormat inFormat,
  385. unsigned pitch,
  386. unsigned width,
  387. unsigned height, unsigned ufoe_enable, DISP_BUFFER_TYPE sec, void *handle)
  388. {
  389. unsigned int output_is_yuv = 0;
  390. enum RDMA_INPUT_FORMAT inputFormat = rdma_input_format_convert(inFormat);
  391. unsigned int bpp = rdma_input_format_bpp(inputFormat);
  392. unsigned int input_is_yuv = rdma_input_format_color_space(inputFormat);
  393. unsigned int input_swap = rdma_input_format_byte_swap(inputFormat);
  394. unsigned int input_format_reg = rdma_input_format_reg_value(inputFormat);
  395. unsigned int color_matrix = 0x6; /* 0110 MTX_BT601_TO_RGB */
  396. unsigned int idx = rdma_index(module);
  397. unsigned int size_con_reg = 0;
  398. unsigned long size_con_handle = 0;
  399. #if defined(CONFIG_TRUSTONIC_TEE_SUPPORT) && defined(CONFIG_MTK_SEC_VIDEO_PATH_SUPPORT)
  400. DDPMSG("RDMAConfig idx %d, mode %d, address 0x%lx, inputformat %s, pitch %u, width %u, height %u,sec%d\n",
  401. idx, mode, address, rdma_intput_format_name(inputFormat, input_swap), pitch, width, height, sec);
  402. #else
  403. DDPDBG("RDMAConfig idx %d, mode %d, address 0x%lx, inputformat %s, pitch %u, width %u, height %u,sec%d\n",
  404. idx, mode, address, rdma_intput_format_name(inputFormat, input_swap), pitch, width, height, sec);
  405. #endif
  406. if ((width > RDMA_MAX_WIDTH) || (height > RDMA_MAX_HEIGHT))
  407. DDPERR("RDMA input overflow, w=%d, h=%d, max_w=%d, max_h=%d\n",
  408. width, height, RDMA_MAX_WIDTH, RDMA_MAX_HEIGHT);
  409. if (input_is_yuv == 1 && output_is_yuv == 0) {
  410. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_ENABLE, &size_con_reg, 1);
  411. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL,
  412. &size_con_reg, color_matrix);
  413. } else if (input_is_yuv == 0 && output_is_yuv == 1) {
  414. color_matrix = 0x2; /* 0x0010, RGB_TO_BT601 */
  415. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_ENABLE, &size_con_reg, 1);
  416. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL,
  417. &size_con_reg, color_matrix);
  418. } else {
  419. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_ENABLE, &size_con_reg, 0);
  420. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_MATRIX_INT_MTX_SEL,
  421. &size_con_reg, 0);
  422. }
  423. DISP_REG_SET_FIELD(handle, GLOBAL_CON_FLD_MODE_SEL,
  424. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_GLOBAL_CON, mode);
  425. /* FORMAT & SWAP only works when RDMA memory mode, set both to 0 when RDMA direct link mode. */
  426. DISP_REG_SET_FIELD(handle, MEM_CON_FLD_MEM_MODE_INPUT_FORMAT,
  427. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_CON,
  428. ((mode == RDMA_MODE_DIRECT_LINK) ? 0 : input_format_reg & 0xf));
  429. DISP_REG_SET_FIELD(handle, MEM_CON_FLD_MEM_MODE_INPUT_SWAP,
  430. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_CON,
  431. ((mode == RDMA_MODE_DIRECT_LINK) ? 0 : input_swap));
  432. if (sec != DISP_SECURE_BUFFER) {
  433. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_START_ADDR, address);
  434. } else {
  435. int m4u_port;
  436. unsigned int size = pitch * height;
  437. m4u_port = idx == 0 ? M4U_PORT_DISP_RDMA0 : M4U_PORT_DISP_RDMA1;
  438. /* for sec layer, addr variable stores sec handle */
  439. /* we need to pass this handle and offset to cmdq driver */
  440. /* cmdq sec driver will help to convert handle to correct address */
  441. cmdqRecWriteSecure(handle,
  442. disp_addr_convert(idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_START_ADDR),
  443. CMDQ_SAM_H_2_MVA, address, 0, size, m4u_port);
  444. /* DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_START_ADDR,
  445. address-0xbc000000+0x8c00000);
  446. */
  447. }
  448. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_MEM_SRC_PITCH, pitch);
  449. /* DISP_REG_SET(handle,idx*DISP_RDMA_INDEX_OFFSET+ DISP_REG_RDMA_INT_ENABLE, 0x3F); */
  450. DISP_REG_SET_FIELD(size_con_handle, SIZE_CON_0_FLD_OUTPUT_FRAME_WIDTH, &size_con_reg, width);
  451. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_0, size_con_reg);
  452. DISP_REG_SET(handle, idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_SIZE_CON_1, height);
  453. rdma_set_ultra(idx, width, height, bpp, rdma_fps[idx], handle, mode);
  454. #if 1
  455. if (ufoe_enable == 0) { /* UFOE bypassed, enable RDMA underflow intr, else disable RDMA underflow intr */
  456. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_UNDERFLOW_EN,
  457. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 1);
  458. /* DISP_REG_SET_FIELD(handle,FIFO_CON_FLD_OUTPUT_VALID_FIFO_THRESHOLD,
  459. idx*DISP_RDMA_INDEX_OFFSET+ DISP_REG_RDMA_FIFO_CON, gRDMAFIFOLen);
  460. */
  461. } else {
  462. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_FIFO_UNDERFLOW_EN,
  463. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON, 1);
  464. DISP_REG_SET_FIELD(handle, FIFO_CON_FLD_OUTPUT_VALID_FIFO_THRESHOLD,
  465. idx * DISP_RDMA_INDEX_OFFSET + DISP_REG_RDMA_FIFO_CON,
  466. width * 3 * 3 / 16 / 2); /* FHD:304, HD:203, QHD:151 */
  467. }
  468. #endif
  469. return 0;
  470. }
  471. int rdma_clock_on(DISP_MODULE_ENUM module, void *handle)
  472. {
  473. unsigned int idx = rdma_index(module);
  474. #ifdef ENABLE_CLK_MGR
  475. if (idx == 0) {
  476. #ifdef CONFIG_MTK_CLKMGR
  477. enable_clock(MT_CG_DISP0_DISP_RDMA0, "RDMA0");
  478. #else
  479. ddp_clk_enable(DISP0_DISP_RDMA0);
  480. #endif
  481. } else {
  482. #ifdef CONFIG_MTK_CLKMGR
  483. enable_clock(MT_CG_DISP0_DISP_RDMA1, "RDMA1");
  484. #else
  485. ddp_clk_enable(DISP0_DISP_RDMA1);
  486. #endif
  487. }
  488. #endif
  489. DDPMSG("rdma_%d_clock_on CG 0x%x\n", idx, DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0));
  490. return 0;
  491. }
  492. int rdma_clock_off(DISP_MODULE_ENUM module, void *handle)
  493. {
  494. unsigned int idx = rdma_index(module);
  495. #ifdef ENABLE_CLK_MGR
  496. if (idx == 0) {
  497. #ifdef CONFIG_MTK_CLKMGR
  498. disable_clock(MT_CG_DISP0_DISP_RDMA0, "RDMA0");
  499. #else
  500. ddp_clk_disable(DISP0_DISP_RDMA0);
  501. #endif
  502. } else {
  503. #ifdef CONFIG_MTK_CLKMGR
  504. disable_clock(MT_CG_DISP0_DISP_RDMA1, "RDMA1");
  505. #else
  506. ddp_clk_disable(DISP0_DISP_RDMA1);
  507. #endif
  508. }
  509. #endif
  510. DDPMSG("rdma_%d_clock_off CG 0x%x\n", idx, DISP_REG_GET(DISP_REG_CONFIG_MMSYS_CG_CON0));
  511. return 0;
  512. }
  513. void rdma_dump_reg(DISP_MODULE_ENUM module)
  514. {
  515. unsigned int idx = rdma_index(module);
  516. DDPDUMP("== DISP RDMA%d REGS ==\n", idx);
  517. DDPDUMP("(0x000)R_INTEN =0x%x\n",
  518. DISP_REG_GET(DISP_REG_RDMA_INT_ENABLE + DISP_RDMA_INDEX_OFFSET * idx));
  519. DDPDUMP("(0x004)R_INTS =0x%x\n",
  520. DISP_REG_GET(DISP_REG_RDMA_INT_STATUS + DISP_RDMA_INDEX_OFFSET * idx));
  521. DDPDUMP("(0x010)R_CON =0x%x\n",
  522. DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx));
  523. DDPDUMP("(0x014)R_SIZE0 =0x%x\n",
  524. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx));
  525. DDPDUMP("(0x018)R_SIZE1 =0x%x\n",
  526. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx));
  527. DDPDUMP("(0x01c)R_TAR_LINE =0x%x\n",
  528. DISP_REG_GET(DISP_REG_RDMA_TARGET_LINE + DISP_RDMA_INDEX_OFFSET * idx));
  529. DDPDUMP("(0x024)R_M_CON =0x%x\n",
  530. DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx));
  531. DDPDUMP("(0xf00)R_M_S_ADDR =0x%x\n",
  532. DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx));
  533. DDPDUMP("(0x02c)R_M_SRC_PITCH =0x%x\n",
  534. DISP_REG_GET(DISP_REG_RDMA_MEM_SRC_PITCH + DISP_RDMA_INDEX_OFFSET * idx));
  535. DDPDUMP("(0x030)R_M_GMC_SET0 =0x%x\n",
  536. DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_0 + DISP_RDMA_INDEX_OFFSET * idx));
  537. DDPDUMP("(0x034)R_M_SLOW_CON =0x%x\n",
  538. DISP_REG_GET(DISP_REG_RDMA_MEM_SLOW_CON + DISP_RDMA_INDEX_OFFSET * idx));
  539. DDPDUMP("(0x038)R_M_GMC_SET1 =0x%x\n",
  540. DISP_REG_GET(DISP_REG_RDMA_MEM_GMC_SETTING_1 + DISP_RDMA_INDEX_OFFSET * idx));
  541. DDPDUMP("(0x040)R_FIFO_CON =0x%x\n",
  542. DISP_REG_GET(DISP_REG_RDMA_FIFO_CON + DISP_RDMA_INDEX_OFFSET * idx));
  543. DDPDUMP("(0x044)R_FIFO_LOG =0x%x\n",
  544. DISP_REG_GET(DISP_REG_RDMA_FIFO_LOG + DISP_RDMA_INDEX_OFFSET * idx));
  545. DDPDUMP("(0x078)R_PRE_ADD0 =0x%x\n",
  546. DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_0 + DISP_RDMA_INDEX_OFFSET * idx));
  547. DDPDUMP("(0x07c)R_PRE_ADD1 =0x%x\n",
  548. DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_1 + DISP_RDMA_INDEX_OFFSET * idx));
  549. DDPDUMP("(0x080)R_PRE_ADD2 =0x%x\n",
  550. DISP_REG_GET(DISP_REG_RDMA_PRE_ADD_2 + DISP_RDMA_INDEX_OFFSET * idx));
  551. DDPDUMP("(0x084)R_POST_ADD0 =0x%x\n",
  552. DISP_REG_GET(DISP_REG_RDMA_POST_ADD_0 + DISP_RDMA_INDEX_OFFSET * idx));
  553. DDPDUMP("(0x088)R_POST_ADD1 =0x%x\n",
  554. DISP_REG_GET(DISP_REG_RDMA_POST_ADD_1 + DISP_RDMA_INDEX_OFFSET * idx));
  555. DDPDUMP("(0x08c)R_POST_ADD2 =0x%x\n",
  556. DISP_REG_GET(DISP_REG_RDMA_POST_ADD_2 + DISP_RDMA_INDEX_OFFSET * idx));
  557. DDPDUMP("(0x090)R_DUMMY =0x%x\n",
  558. DISP_REG_GET(DISP_REG_RDMA_DUMMY + DISP_RDMA_INDEX_OFFSET * idx));
  559. DDPDUMP("(0x094)R_OUT_SEL =0x%x\n",
  560. DISP_REG_GET(DISP_REG_RDMA_DEBUG_OUT_SEL + DISP_RDMA_INDEX_OFFSET * idx));
  561. DDPDUMP("(0x094)R_M_START =0x%x\n",
  562. DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx));
  563. DDPDUMP("(0x0f0)R_IN_PXL_CNT =0x%x\n",
  564. DISP_REG_GET(DISP_REG_RDMA_IN_P_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  565. DDPDUMP("(0x0f4)R_IN_LINE_CNT =0x%x\n",
  566. DISP_REG_GET(DISP_REG_RDMA_IN_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  567. DDPDUMP("(0x0f8)R_OUT_PXL_CNT =0x%x\n",
  568. DISP_REG_GET(DISP_REG_RDMA_OUT_P_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  569. DDPDUMP("(0x0fc)R_OUT_LINE_CNT=0x%x\n",
  570. DISP_REG_GET(DISP_REG_RDMA_OUT_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx));
  571. }
  572. void rdma_dump_analysis(DISP_MODULE_ENUM module)
  573. {
  574. unsigned int idx = rdma_index(module);
  575. DDPDUMP("==DISP RDMA%d ANALYSIS==\n", idx);
  576. DDPDUMP("rdma%d: en=%d, memory mode=%d, w=%d, h=%d, pitch=%d, addr=0x%x, fmt=%s, fifo_min=%d,\n",
  577. idx, DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx) & 0x1,
  578. (DISP_REG_GET(DISP_REG_RDMA_GLOBAL_CON + DISP_RDMA_INDEX_OFFSET * idx) & 0x2) ? 1 : 0,
  579. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfff,
  580. DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfffff,
  581. DISP_REG_GET(DISP_REG_RDMA_MEM_SRC_PITCH + DISP_RDMA_INDEX_OFFSET * idx),
  582. DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx),
  583. rdma_intput_format_name((DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx) >> 4) & 0xf,
  584. (DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx) >> 8) & 0x1),
  585. DISP_REG_GET(DISP_REG_RDMA_FIFO_LOG + DISP_RDMA_INDEX_OFFSET * idx));
  586. DDPDUMP("in_p_cnt=%d, in_l_cnt=%d, out_p_cnt=%d, out_l_cnt=%d, rdma_start_time=%lld ns,rdma_end_time=%lld ns\n",
  587. DISP_REG_GET(DISP_REG_RDMA_IN_P_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  588. DISP_REG_GET(DISP_REG_RDMA_IN_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  589. DISP_REG_GET(DISP_REG_RDMA_OUT_P_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  590. DISP_REG_GET(DISP_REG_RDMA_OUT_LINE_CNT + DISP_RDMA_INDEX_OFFSET * idx),
  591. rdma_start_time[idx], rdma_end_time[idx]);
  592. DDPDUMP("irq cnt: start=%d, end=%d, underflow=%d, targetline=%d\n",
  593. rdma_start_irq_cnt[idx], rdma_done_irq_cnt[idx], rdma_underflow_irq_cnt[idx],
  594. rdma_targetline_irq_cnt[idx]);
  595. }
  596. static int rdma_dump(DISP_MODULE_ENUM module, int level)
  597. {
  598. rdma_dump_analysis(module);
  599. rdma_dump_reg(module);
  600. return 0;
  601. }
  602. void rdma_get_info(int idx, RDMA_BASIC_STRUCT *info)
  603. {
  604. RDMA_BASIC_STRUCT *p = info;
  605. p->addr = DISP_REG_GET(DISP_REG_RDMA_MEM_START_ADDR + DISP_RDMA_INDEX_OFFSET * idx);
  606. p->src_w = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_0 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfff;
  607. p->src_h = DISP_REG_GET(DISP_REG_RDMA_SIZE_CON_1 + DISP_RDMA_INDEX_OFFSET * idx) & 0xfffff;
  608. p->bpp = rdma_input_format_bpp((DISP_REG_GET(DISP_REG_RDMA_MEM_CON + DISP_RDMA_INDEX_OFFSET * idx) >> 4) & 0xf);
  609. }
  610. static inline enum RDMA_MODE rdma_config_mode(unsigned long address)
  611. {
  612. return address ? RDMA_MODE_MEMORY : RDMA_MODE_DIRECT_LINK;
  613. }
  614. static int do_rdma_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle)
  615. {
  616. RDMA_CONFIG_STRUCT *r_config = &pConfig->rdma_config;
  617. enum RDMA_MODE mode = rdma_config_mode(r_config->address);
  618. LCM_PARAMS *lcm_param = &(pConfig->dispif_config);
  619. unsigned int width = pConfig->dst_dirty ? pConfig->dst_w : r_config->width;
  620. unsigned int height = pConfig->dst_dirty ? pConfig->dst_h : r_config->height;
  621. if (pConfig->fps)
  622. rdma_fps[rdma_index(module)] = pConfig->fps / 100;
  623. if (mode == RDMA_MODE_DIRECT_LINK && r_config->security != DISP_NORMAL_BUFFER)
  624. DDPERR("%s: rdma directlink BUT is sec ??!!\n", __func__);
  625. rdma_config(module, mode, (mode == RDMA_MODE_DIRECT_LINK) ? 0 : r_config->address, /* address */
  626. (mode == RDMA_MODE_DIRECT_LINK) ? eRGB888 : r_config->inputFormat, /* inputFormat */
  627. (mode == RDMA_MODE_DIRECT_LINK) ? 0 : r_config->pitch, /* pitch */
  628. width, height, lcm_param->dsi.ufoe_enable, r_config->security, handle);
  629. return 0;
  630. }
  631. static int setup_rdma_sec(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle)
  632. {
  633. static int rdma_is_sec[RDMA_INSTANCES];
  634. CMDQ_ENG_ENUM cmdq_engine;
  635. int rdma_idx = rdma_index(module);
  636. DISP_BUFFER_TYPE security = pConfig->rdma_config.security;
  637. enum RDMA_MODE mode = rdma_config_mode(pConfig->rdma_config.address);
  638. cmdq_engine = rdma_idx == 0 ? CMDQ_ENG_DISP_RDMA0 : CMDQ_ENG_DISP_RDMA1;
  639. if (!handle) {
  640. DDPMSG("[SVP] bypass rdma sec setting sec=%d,handle=NULL\n", security);
  641. return 0;
  642. }
  643. /* sec setting make sence only in memory mode ! */
  644. if (mode == RDMA_MODE_MEMORY) {
  645. if (security == DISP_SECURE_BUFFER) {
  646. cmdqRecSetSecure(handle, 1);
  647. /* set engine as sec */
  648. cmdqRecSecureEnablePortSecurity(handle, (1LL << cmdq_engine));
  649. /* cmdqRecSecureEnableDAPC(handle, (1LL << cmdq_engine)); */
  650. if (rdma_is_sec[rdma_idx] == 0)
  651. DDPMSG("[SVP] switch rdma%d to sec\n", rdma_idx);
  652. rdma_is_sec[rdma_idx] = 1;
  653. } else {
  654. if (rdma_is_sec[rdma_idx]) {
  655. /* rdma is in sec stat, we need to switch it to nonsec */
  656. cmdqRecHandle nonsec_switch_handle;
  657. int ret;
  658. ret =
  659. cmdqRecCreate(CMDQ_SCENARIO_DISP_PRIMARY_DISABLE_SECURE_PATH,
  660. &(nonsec_switch_handle));
  661. if (ret)
  662. DDPAEE("[SVP]fail to create disable handle %s ret=%d\n",
  663. __func__, ret);
  664. cmdqRecReset(nonsec_switch_handle);
  665. _cmdq_insert_wait_frame_done_token_mira(nonsec_switch_handle);
  666. cmdqRecSetSecure(nonsec_switch_handle, 1);
  667. /*ugly work around by kzhang !!. will remove when cmdq delete disable scenario.
  668. * To avoid translation fault like ovl (see notes in ovl.c)*/
  669. do_rdma_config_l(module, pConfig, nonsec_switch_handle);
  670. /*in fact, dapc/port_sec will be disabled by cmdq */
  671. cmdqRecSecureEnablePortSecurity(nonsec_switch_handle,
  672. (1LL << cmdq_engine));
  673. /* cmdqRecSecureEnableDAPC(nonsec_switch_handle, (1LL << cmdq_engine)); */
  674. cmdqRecFlush(nonsec_switch_handle);
  675. cmdqRecDestroy(nonsec_switch_handle);
  676. DDPMSG("[SVP] switch rdma%d to nonsec done\n", rdma_idx);
  677. }
  678. rdma_is_sec[rdma_idx] = 0;
  679. }
  680. }
  681. return 0;
  682. }
  683. static int rdma_config_l(DISP_MODULE_ENUM module, disp_ddp_path_config *pConfig, void *handle)
  684. {
  685. if (pConfig->dst_dirty || pConfig->rdma_dirty) {
  686. setup_rdma_sec(module, pConfig, handle);
  687. do_rdma_config_l(module, pConfig, handle);
  688. }
  689. return 0;
  690. }
  691. DDP_MODULE_DRIVER ddp_driver_rdma = {
  692. .init = rdma_init,
  693. .deinit = rdma_deinit,
  694. .config = rdma_config_l,
  695. .start = rdma_start,
  696. .trigger = NULL,
  697. .stop = rdma_stop,
  698. .reset = rdma_reset,
  699. .power_on = rdma_clock_on,
  700. .power_off = rdma_clock_off,
  701. .is_idle = NULL,
  702. .is_busy = NULL,
  703. .dump_info = rdma_dump,
  704. .bypass = NULL,
  705. .build_cmdq = NULL,
  706. .set_lcm_utils = NULL,
  707. .enable_irq = rdma_enable_irq
  708. };