arkn141_lcdc_funcs.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. /*
  2. * Arkmicro arkn141_lcdc_funcs.c driver
  3. *
  4. * Licensed under GPLv2 or later.
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/fb.h>
  8. #include <linux/poll.h>
  9. #include "arkn141_lcdc.h"
  10. #define ARKN141_LCDC_DEBUG(fmt,arg...) printk(KERN_DEBUG "### %s--> "fmt,__FUNCTION__,##arg)
  11. #define ARKN141_LCDC_ERR(fmt,arg...) printk(KERN_ERR "###ERR %s--> "fmt,__FUNCTION__,##arg)
  12. static unsigned int arkn141_lcdc_width = 0;
  13. static unsigned int arkn141_lcdc_height = 0;
  14. static int arkn141_lcdc_mode[OSD_LAYER_MAX] = {-1, -1, -1};
  15. static void *lcdc_base = NULL;
  16. static struct arkn141_lcdfb_info *lcdfb_info = NULL;
  17. extern volatile int arkn141_lcdc_frame_sync;
  18. /* synchronizing lcdc osd register value */
  19. static int arkn141_lcdc_osd_set_coef_sync(unsigned int layer)
  20. {
  21. unsigned int val = -1;
  22. if (!ARKN141_LAYER_IS_VALID(layer)) {
  23. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  24. return -1;
  25. }
  26. val = readl(lcdc_base + ARKN141_LCDC_OSD_COEF_SYNC);
  27. switch(layer)
  28. {
  29. case OSD_LAYER0: {
  30. val |= (1<<0);
  31. //val |= (1<<0) | (1<<3);
  32. break;
  33. }
  34. case OSD_LAYER1: {
  35. val |= (1<<1);
  36. //val |= (1<<1) | (1<<4);
  37. break;
  38. }
  39. case OSD_LAYER2: {
  40. val |= (1<<2) ;
  41. //val |= (1<<2) | (1<<4);
  42. break;
  43. }
  44. case OSD_LAYER_MAX: {
  45. val |= 0x7;
  46. //val |= 0x3F;
  47. break;
  48. }
  49. default: {
  50. return -1;
  51. //break;
  52. }
  53. }
  54. if(val > 0)
  55. writel(val, lcdc_base + ARKN141_LCDC_OSD_COEF_SYNC);
  56. return 0;
  57. }
  58. static void arkn141_lcdc_set_osd_size(int layer, int width, int height)
  59. {
  60. unsigned int val;
  61. int size_reg = -1, source_size_reg = -1;
  62. if (!ARKN141_LAYER_IS_VALID(layer)) {
  63. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  64. return;
  65. }
  66. if((width <= 0) || (width > 0xFFF)) {
  67. ARKN141_LCDC_ERR("invalid width:%d\n", width);
  68. return ;
  69. }
  70. if((height <= 0) || (height > 0xFFF)) {
  71. ARKN141_LCDC_ERR("invalid height:%d\n", height);
  72. return ;
  73. }
  74. ARKN141_LCDC_DEBUG("width:%d height:%d\n", width, height);
  75. switch (layer) {
  76. case OSD_LAYER0:
  77. size_reg = ARKN141_LCDC_OSD0_PARAM0;
  78. source_size_reg = ARKN141_LCDC_OSD0_PARAM5;
  79. break;
  80. case OSD_LAYER1:
  81. size_reg = ARKN141_LCDC_OSD1_PARAM0;
  82. source_size_reg = ARKN141_LCDC_OSD1_PARAM5;
  83. break;
  84. case OSD_LAYER2:
  85. size_reg = ARKN141_LCDC_OSD2_PARAM0;
  86. source_size_reg = ARKN141_LCDC_OSD2_PARAM5;
  87. break;
  88. default:
  89. break;
  90. }
  91. if(size_reg > 0) {
  92. val = readl(lcdc_base + size_reg);
  93. val &= ~((0xFFF<<6) | (0xFFF<<18));
  94. val |= ((width<<6) | (height<<18));
  95. writel(val, lcdc_base + size_reg);
  96. }
  97. if(source_size_reg > 0) {
  98. val = readl(lcdc_base + source_size_reg);
  99. val &= ~(0xFFF);
  100. val |= width;
  101. writel(val, lcdc_base + source_size_reg);
  102. }
  103. }
  104. static int arkn141_lcdc_get_osd_size(int layer, int *width, int *height)
  105. {
  106. unsigned int val;
  107. int reg = -1;
  108. int ret = -1;
  109. if (!ARKN141_LAYER_IS_VALID(layer)) {
  110. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  111. return ret;
  112. }
  113. switch (layer) {
  114. case OSD_LAYER0:
  115. reg = ARKN141_LCDC_OSD0_PARAM0;
  116. break;
  117. case OSD_LAYER1:
  118. reg = ARKN141_LCDC_OSD1_PARAM0;
  119. break;
  120. case OSD_LAYER2:
  121. reg = ARKN141_LCDC_OSD2_PARAM0;
  122. break;
  123. default:
  124. break;
  125. }
  126. if(reg > 0) {
  127. val = readl(lcdc_base + reg);
  128. *width = (val>>6)&0xFFF;
  129. *height = (val>>18)&0xFFF;
  130. ret = 0;
  131. }
  132. return ret;
  133. }
  134. static void arkn141_lcdc_set_osd_pos(int layer, int x, int y)
  135. {
  136. int reg = -1;
  137. unsigned int val;
  138. if (!ARKN141_LAYER_IS_VALID(layer)) {
  139. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  140. return;
  141. }
  142. if ((x < 0) || (x > 0xfff)) {
  143. ARKN141_LCDC_ERR("invalid h_position:%d\n", x);
  144. return ;
  145. }
  146. if ((y < 0) || (y > 0xfff)) {
  147. ARKN141_LCDC_ERR("invalid h_position:%d\n", y);
  148. return ;
  149. }
  150. switch (layer) {
  151. case OSD_LAYER0:
  152. reg = ARKN141_LCDC_OSD0_PARAM1;
  153. break;
  154. case OSD_LAYER1:
  155. reg = ARKN141_LCDC_OSD1_PARAM1;
  156. break;
  157. case OSD_LAYER2:
  158. reg = ARKN141_LCDC_OSD2_PARAM1;
  159. break;
  160. default:
  161. break;
  162. }
  163. if(reg > 0) {
  164. val = readl(lcdc_base + reg);
  165. val &= 0xFF000000;
  166. val |= (y << 12) | x;
  167. writel(val, lcdc_base + reg);
  168. }
  169. }
  170. static void arkn141_lcdc_set_alpha_blend_enable(int layer, int enable)
  171. {
  172. int reg = -1;
  173. unsigned int val;
  174. if (!ARKN141_LAYER_IS_VALID(layer)) {
  175. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  176. return;
  177. }
  178. switch (layer) {
  179. case OSD_LAYER0:
  180. reg = ARKN141_LCDC_OSD0_PARAM0;
  181. break;
  182. case OSD_LAYER1:
  183. reg = ARKN141_LCDC_OSD1_PARAM0;
  184. break;
  185. case OSD_LAYER2:
  186. reg = ARKN141_LCDC_OSD2_PARAM0;
  187. break;
  188. default:
  189. break;
  190. }
  191. if(reg > 0) {
  192. val = readl(lcdc_base + reg);
  193. if(enable)
  194. val |= (1<<0);
  195. else
  196. val &= ~(1<<0);
  197. writel(val, lcdc_base + reg);
  198. }
  199. }
  200. static void arkn141_lcdc_set_alpha_blend_value(int layer, int value)
  201. {
  202. int reg = -1;
  203. unsigned int val;
  204. if (!ARKN141_LAYER_IS_VALID(layer)) {
  205. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  206. return;
  207. }
  208. switch (layer) {
  209. case OSD_LAYER0:
  210. reg = ARKN141_LCDC_OSD0_PARAM1;
  211. break;
  212. case OSD_LAYER1:
  213. reg = ARKN141_LCDC_OSD1_PARAM1;
  214. break;
  215. case OSD_LAYER2:
  216. reg = ARKN141_LCDC_OSD2_PARAM1;
  217. break;
  218. default:
  219. break;
  220. }
  221. if(reg > 0) {
  222. val = readl(lcdc_base + reg);
  223. val &= ~(0x7F<<24);
  224. val |= (val << 24);
  225. writel(val, lcdc_base + reg);
  226. }
  227. }
  228. static char* arkn141_lcdc_get_osd_fomat_string(int format)
  229. {
  230. switch(format) {
  231. case ARKN141_LCDC_FORMAT_YUV420:
  232. return "YUV420";
  233. case ARKN141_LCDC_FORMAT_ARGB888:
  234. return "ARGB888";
  235. case ARKN141_LCDC_FORMAT_RGB565:
  236. return "RGB565";
  237. case ARKN141_LCDC_FORMAT_RGB454:
  238. return "RGB454";
  239. case ARKN141_LCDC_FORMAT_AYUV444:
  240. return "AYUV444";
  241. case ARKN141_LCDC_FORMAT_Y_UV420:
  242. return "Y_UV420";
  243. default:
  244. break;
  245. }
  246. return "NONE";
  247. }
  248. static void arkn141_lcdc_set_osd_format(int layer, int format, int yuv_order, int rgb_order)
  249. {
  250. int reg = -1;
  251. unsigned int val;
  252. if (!ARKN141_LAYER_IS_VALID(layer)) {
  253. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  254. return;
  255. }
  256. switch(format) {
  257. case ARK_LCDC_FORMAT_YUV420:
  258. format = ARKN141_LCDC_FORMAT_YUV420;
  259. break;
  260. case ARK_LCDC_FORMAT_RGB888:
  261. case ARK_LCDC_FORMAT_RGBA888:
  262. format = ARKN141_LCDC_FORMAT_ARGB888;
  263. break;
  264. case ARK_LCDC_FORMAT_R5G6B5:
  265. format = ARKN141_LCDC_FORMAT_RGB565;
  266. break;
  267. case ARK_LCDC_FORMAT_Y_UV420:
  268. format = ARKN141_LCDC_FORMAT_Y_UV420;
  269. break;
  270. //case ARK_LCDC_FORMAT_YUV422:
  271. //case ARK_LCDC_FORMAT_VYUY:
  272. //case ARK_LCDC_FORMAT_YUV:
  273. //case ARK_LCDC_FORMAT_RGBI555:
  274. //case ARK_LCDC_FORMAT_Y_UV422:
  275. default:
  276. format = ARKN141_LCDC_FORMAT_END;
  277. break;
  278. }
  279. if((format < ARKN141_LCDC_FORMAT_YUV420) || (format >= ARKN141_LCDC_FORMAT_END)) {
  280. ARKN141_LCDC_ERR("invalid osd format:%d\n", format);
  281. return;
  282. }
  283. ARKN141_LCDC_DEBUG("osd[%d] format:%s\n", layer, arkn141_lcdc_get_osd_fomat_string(format));
  284. switch (layer) {
  285. case OSD_LAYER0:
  286. reg = ARKN141_LCDC_OSD0_PARAM0;
  287. arkn141_lcdc_mode[layer] = format;
  288. break;
  289. case OSD_LAYER1:
  290. reg = ARKN141_LCDC_OSD1_PARAM0;
  291. arkn141_lcdc_mode[layer] = format;
  292. if(format == ARKN141_LCDC_FORMAT_ARGB888) {
  293. arkn141_lcdc_set_alpha_blend_enable(layer, 0);
  294. //arkn141_lcdc_set_alpha_blend_value(layer, 0xFF);
  295. }
  296. break;
  297. case OSD_LAYER2:
  298. reg = ARKN141_LCDC_OSD2_PARAM0;
  299. arkn141_lcdc_mode[layer] = format;
  300. if(format == ARKN141_LCDC_FORMAT_ARGB888) {
  301. arkn141_lcdc_set_alpha_blend_enable(layer, 0);
  302. //arkn141_lcdc_set_alpha_blend_value(layer, 0xFF);
  303. }
  304. break;
  305. default:
  306. break;
  307. }
  308. if(format == ARKN141_LCDC_FORMAT_Y_UV420)
  309. format = ARKN141_LCDC_FORMAT_YUV420;
  310. if(reg >= 0) {
  311. val = readl(lcdc_base + reg);
  312. val &= ~(0x3<<3);
  313. val |= ((format&0x3)<<3);
  314. writel(val, lcdc_base + reg);
  315. }
  316. val = readl(lcdc_base + ARKN141_LCDC_OSD_012_PARAM);
  317. //yuv order
  318. val &= ~(0x3<<(12+(layer<<1)));
  319. if((yuv_order == ARK_LCDC_ORDER_UYVY) || (yuv_order == ARK_LCDC_ORDER_YUYV)) {
  320. if(arkn141_lcdc_mode[layer] == ARKN141_LCDC_FORMAT_Y_UV420)
  321. val |= (0x3<<(12+(layer<<1)));// 如设为此值, 红蓝交换颜色(交换UV数据的位置) Y_UV420
  322. else if(arkn141_lcdc_mode[layer] == ARKN141_LCDC_FORMAT_YUV420)
  323. val |= (0x2<<(12+(layer<<1)));
  324. } else if((yuv_order == ARK_LCDC_ORDER_VYUY) || (yuv_order == ARK_LCDC_ORDER_YVYU)) {
  325. if(arkn141_lcdc_mode[layer] == ARKN141_LCDC_FORMAT_Y_UV420)
  326. val |= (0x1<<(12+(layer<<1)));
  327. else if(arkn141_lcdc_mode[layer] == ARKN141_LCDC_FORMAT_YUV420)
  328. val |= (0x0<<(12+(layer<<1)));
  329. }
  330. //rgb order
  331. val &= ~(0xF<<(layer*4));
  332. val |= rgb_order;
  333. writel(val, lcdc_base + ARKN141_LCDC_OSD_012_PARAM);
  334. }
  335. static void arkn141_lcdc_set_osd_addr(int layer, struct ark_disp_addr addr)
  336. {
  337. unsigned int y = 0,u = 0,v = 0;
  338. if (!ARKN141_LAYER_IS_VALID(layer)) {
  339. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  340. return;
  341. }
  342. if(!addr.yaddr) {
  343. ARKN141_LCDC_ERR("invalid y_addr:0x%x\n", addr.yaddr);
  344. return;
  345. }
  346. y = addr.yaddr;
  347. if(arkn141_lcdc_mode[layer] == ARKN141_LCDC_FORMAT_Y_UV420) {
  348. if(!addr.cbaddr) {
  349. int w, h;
  350. if(arkn141_lcdc_get_osd_size(layer, &w, &h) == 0) {
  351. u = addr.yaddr + w * h;
  352. ARKN141_LCDC_DEBUG("osd(%d) mode(%s) invalid cbaddr:0x%x, calculate new addr:0x%x\n",layer, arkn141_lcdc_get_osd_fomat_string(arkn141_lcdc_mode[layer]), addr.cbaddr, u);
  353. } else {
  354. ARKN141_LCDC_ERR("osd(%d) mode(%s) invalid cbaddr:0x%x\n",layer, arkn141_lcdc_get_osd_fomat_string(arkn141_lcdc_mode[layer]), addr.cbaddr);
  355. }
  356. } else {
  357. u = addr.cbaddr;
  358. }
  359. v = 0;
  360. } else if(arkn141_lcdc_mode[layer] == ARKN141_LCDC_FORMAT_YUV420) {
  361. if(!addr.cbaddr) {
  362. int w, h;
  363. if(arkn141_lcdc_get_osd_size(layer, &w, &h) == 0) {
  364. u = addr.yaddr + w * h;
  365. ARKN141_LCDC_DEBUG("osd(%d) mode(%s) invalid cbaddr:0x%x, calculate new addr:0x%x\n",layer, arkn141_lcdc_get_osd_fomat_string(arkn141_lcdc_mode[layer]), addr.cbaddr, u);
  366. } else {
  367. ARKN141_LCDC_ERR("osd(%d) mode(%s) invalid cbaddr:0x%x\n",layer, arkn141_lcdc_get_osd_fomat_string(arkn141_lcdc_mode[layer]), addr.cbaddr);
  368. }
  369. } else {
  370. u = addr.cbaddr;
  371. }
  372. if(!addr.craddr) {
  373. int w, h;
  374. if(arkn141_lcdc_get_osd_size(layer, &w, &h) == 0) {
  375. v = addr.yaddr + w * h *5 /4;
  376. ARKN141_LCDC_DEBUG("osd(%d) mode(%s) invalid craddr:0x%x, calculate new addr:0x%x\n",layer, arkn141_lcdc_get_osd_fomat_string(arkn141_lcdc_mode[layer]), addr.craddr, v);
  377. } else {
  378. ARKN141_LCDC_ERR("osd(%d) mode(%s) invalid craddr:0x%x\n",layer, arkn141_lcdc_get_osd_fomat_string(arkn141_lcdc_mode[layer]), addr.craddr);
  379. }
  380. } else {
  381. v = addr.craddr;
  382. }
  383. } else {
  384. u = 0;
  385. v = 0;
  386. }
  387. switch (layer)
  388. {
  389. case OSD_LAYER0:
  390. writel(y, lcdc_base + ARKN141_LCDC_OSD0_PARAM2);
  391. writel(u, lcdc_base + ARKN141_LCDC_OSD0_PARAM3);
  392. writel(v, lcdc_base + ARKN141_LCDC_OSD0_PARAM4);
  393. break;
  394. case OSD_LAYER1:
  395. writel(y, lcdc_base + ARKN141_LCDC_OSD1_PARAM2);
  396. writel(u, lcdc_base + ARKN141_LCDC_OSD1_PARAM3);
  397. writel(v, lcdc_base + ARKN141_LCDC_OSD1_PARAM4);
  398. break;
  399. case OSD_LAYER2:
  400. writel(y, lcdc_base + ARKN141_LCDC_OSD2_PARAM2);
  401. writel(u, lcdc_base + ARKN141_LCDC_OSD2_PARAM3);
  402. writel(v, lcdc_base + ARKN141_LCDC_OSD2_PARAM4);
  403. break;
  404. default:
  405. break;
  406. }
  407. }
  408. static int arkn141_lcdc_get_osd_addr(int layer, unsigned int *y, unsigned int *u, unsigned int *v)
  409. {
  410. if (!ARKN141_LAYER_IS_VALID(layer)) {
  411. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  412. return -EFAULT;
  413. }
  414. switch (layer) {
  415. case OSD_LAYER0:
  416. *y = readl(lcdc_base + ARKN141_LCDC_OSD0_PARAM2);
  417. *u = readl(lcdc_base + ARKN141_LCDC_OSD0_PARAM3);
  418. *v = readl(lcdc_base + ARKN141_LCDC_OSD0_PARAM4);
  419. break;
  420. case OSD_LAYER1:
  421. *y = readl(lcdc_base + ARKN141_LCDC_OSD1_PARAM2);
  422. *u = readl(lcdc_base + ARKN141_LCDC_OSD1_PARAM3);
  423. *v = readl(lcdc_base + ARKN141_LCDC_OSD1_PARAM4);
  424. break;
  425. case OSD_LAYER2:
  426. *y = readl(lcdc_base + ARKN141_LCDC_OSD2_PARAM2);
  427. *u = readl(lcdc_base + ARKN141_LCDC_OSD2_PARAM3);
  428. *v = readl(lcdc_base + ARKN141_LCDC_OSD2_PARAM4);
  429. break;
  430. default:
  431. break;
  432. }
  433. return 0;
  434. }
  435. static void arkn141_lcdc_set_enbale(int enable)
  436. {
  437. unsigned int val;
  438. val = readl(lcdc_base + ARKN141_LCDC_PARAM0);
  439. if(enable) {
  440. val |= (1<<0);
  441. } else {
  442. val &= ~(1<<0);
  443. }
  444. writel(val, lcdc_base + ARKN141_LCDC_PARAM0);
  445. }
  446. static void arkn141_lcdc_set_osd_enable(int layer, int enable)
  447. {
  448. unsigned int val;
  449. int reg;
  450. if (!ARKN141_LAYER_IS_VALID(layer)) {
  451. ARKN141_LCDC_ERR("invalid osd layer:%d\n", layer);
  452. return;
  453. }
  454. switch(layer)
  455. {
  456. case OSD_LAYER0: {
  457. reg = ARKN141_LCDC_OSD0_PARAM0;
  458. break;
  459. }
  460. case OSD_LAYER1: {
  461. reg = ARKN141_LCDC_OSD1_PARAM0;
  462. break;
  463. }
  464. case OSD_LAYER2: {
  465. reg = ARKN141_LCDC_OSD2_PARAM0;
  466. break;
  467. }
  468. default: {
  469. break;
  470. }
  471. }
  472. //lcd osd enable/disable
  473. val = readl(lcdc_base + reg);
  474. if(enable)
  475. val |= (1<<1);
  476. else
  477. val &= ~(1<<1);
  478. writel(val, lcdc_base + reg);
  479. #if 0
  480. //lcdc enable/disable
  481. if(enable) {
  482. arkn141_lcdc_set_enbale(1);
  483. } else {
  484. int lcdc_disable = 0;
  485. lcdc_disable += (readl(lcdc_base + ARKN141_LCDC_OSD0_PARAM0)>>1) & 0x1;
  486. lcdc_disable += (readl(lcdc_base + ARKN141_LCDC_OSD1_PARAM0)>>1) & 0x1;
  487. lcdc_disable += (readl(lcdc_base + ARKN141_LCDC_OSD2_PARAM0)>>1) & 0x1;
  488. if(lcdc_disable == 0) {
  489. arkn141_lcdc_set_enbale(0);
  490. }
  491. }
  492. #endif
  493. }
  494. void arkn141_lcdc_display_update_atomic(struct arkn141_lcdfb_info* sinfo)
  495. {
  496. unsigned int format, yuv_order, rgb_order, i, layer;
  497. struct ark_disp_atomic* p = NULL;
  498. if(!sinfo || !sinfo->atomic_flag) {
  499. ARKN141_LCDC_ERR("!sinfo || !sinfo->atomic_flag\n");
  500. return;
  501. }
  502. for(i = 0; i < OSD_LAYER_MAX; i++){
  503. if(!(sinfo->atomic_flag & (1 << i)))
  504. continue;
  505. p = &sinfo->patomic[i];
  506. if(!p->atomic_stat || !ARKN141_LAYER_IS_VALID(p->layer)) {
  507. sinfo->atomic_flag &= ~(1 << i);
  508. memset(&sinfo->patomic[i], 0 ,sizeof(struct ark_disp_atomic));
  509. continue;
  510. }
  511. //printk(KERN_ALERT "%s: atomic_stat=0x%0x, layer=%d.\n ",__func__, p->atomic_stat, p->layer);
  512. if(ARKN141_LAYER_IS_VALID(p->layer)){
  513. layer = p->layer;
  514. if(p->atomic_stat & ATOMIC_SET_LAYER_POS)
  515. arkn141_lcdc_set_osd_pos(layer, p->pos_x, p->pos_y);
  516. if(p->atomic_stat & ATOMIC_SET_LAYER_SIZE)
  517. arkn141_lcdc_set_osd_size(layer, p->width, p->height);
  518. if(p->atomic_stat & ATOMIC_SET_LAYER_FMT){
  519. format = (p->format >> 0) & 0xFF;
  520. yuv_order = (p->format >> 16) & 0xF;
  521. rgb_order = (p->format >> 24) & 0xF;
  522. arkn141_lcdc_set_osd_format(layer, format, yuv_order, rgb_order);
  523. ARKN141_LCDC_DEBUG("format=%d, yuv_order=%d, rgb_order=%d\n", format, yuv_order, rgb_order);
  524. }
  525. if(p->atomic_stat & ATOMIC_SET_LAYER_ADDR)
  526. arkn141_lcdc_set_osd_addr(layer, p->addr);
  527. arkn141_lcdc_osd_set_coef_sync(layer);
  528. }
  529. sinfo->atomic_flag &= ~(1 << i);
  530. memset(&sinfo->patomic[i], 0 ,sizeof(struct ark_disp_atomic));
  531. }
  532. }
  533. int arkn141_lcdc_wait_for_vsync(void)
  534. {
  535. struct arkn141_lcdfb_info *sinfo = lcdfb_info;
  536. int ret;
  537. if(!sinfo)
  538. return -EINVAL;
  539. sinfo->vsync_flag = 0;
  540. ret = wait_event_interruptible_timeout(sinfo->vsync_waitq,
  541. sinfo->vsync_flag != 0,
  542. msecs_to_jiffies(100)); // 100ms at most
  543. if (ret < 0)
  544. return ret;
  545. if (ret == 0)
  546. return -ETIMEDOUT;
  547. if(sinfo->atomic_flag)
  548. arkn141_lcdc_display_update_atomic(sinfo);
  549. return 0;
  550. }
  551. EXPORT_SYMBOL(arkn141_lcdc_wait_for_vsync);
  552. int arkn141_lcdfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
  553. {
  554. struct arkn141_lcdfb_info *sinfo = NULL;
  555. int error = 0;
  556. int layer;
  557. if(!info) {
  558. ARKN141_LCDC_ERR("fb_info == NULL\n");
  559. return -1;
  560. }
  561. sinfo = info->par;
  562. layer = info->node;
  563. mutex_lock(&sinfo->mutex_lock);
  564. switch (cmd) {
  565. case ARKFB_GET_VSYNC_STATUS: {
  566. u32 vsync;
  567. spin_lock(&sinfo->lock);
  568. vsync = sinfo->frame_vsync;
  569. spin_unlock(&sinfo->lock);
  570. if(copy_to_user((void *)arg, &vsync, sizeof(u32))) {
  571. ARKN141_LCDC_ERR("ARKFB_GET_REG_VALUE copy to user para error\n");
  572. error = -EFAULT;
  573. goto end;
  574. }
  575. break;
  576. }
  577. case ARKFB_WAITFORVSYNC: {
  578. error = arkn141_lcdc_wait_for_vsync();
  579. break;
  580. }
  581. case ARKFB_SHOW_WINDOW: {
  582. arkn141_lcdc_set_osd_enable(layer, 1);
  583. arkn141_lcdc_osd_set_coef_sync(layer);
  584. ARKN141_LCDC_DEBUG("ARKFB_SHOW_WINDOW osd layer=%d: show window.\n", layer);
  585. break;
  586. }
  587. case ARKFB_HIDE_WINDOW: {
  588. arkn141_lcdc_set_osd_enable(layer, 0);
  589. arkn141_lcdc_osd_set_coef_sync(layer);
  590. ARKN141_LCDC_DEBUG("ARKFB_HIDE_WINDOW osd layer=%d: hide window.\n", layer);
  591. break;
  592. }
  593. case ARKFB_SET_WINDOW_POS: {
  594. unsigned int x,y,data;
  595. if(copy_from_user(&data, (void *)arg, sizeof(unsigned int))) {
  596. ARKN141_LCDC_ERR("ARKFB_SET_WINDOW_POS copy from user para error\n");
  597. error = -EFAULT;
  598. goto end;
  599. }
  600. x = data & 0xFFFF;
  601. y = (data >> 16) & 0xFFFF;
  602. arkn141_lcdc_set_osd_pos(layer, x, y);
  603. arkn141_lcdc_osd_set_coef_sync(layer);
  604. ARKN141_LCDC_DEBUG("osd layer=%d, x=%d, y=%d.\n", layer, x, y);
  605. break;
  606. }
  607. case ARKFB_SET_WINDOW_SIZE:
  608. {
  609. unsigned int width, height, data;
  610. if(copy_from_user(&data, (void *)arg, sizeof(unsigned int))) {
  611. ARKN141_LCDC_ERR("ARKFB_SET_WINDOW_SIZE copy from user para error\n");
  612. error = -EFAULT;
  613. goto end;
  614. }
  615. width = data & 0xFFFF;
  616. height = (data >> 16) & 0xFFFF;
  617. arkn141_lcdc_set_osd_size(layer, width, height);
  618. arkn141_lcdc_osd_set_coef_sync(layer);
  619. ARKN141_LCDC_DEBUG("ARKFB_SET_WINDOW_SIZE osd layer=%d, width=%d, height=%d.\n", layer, width, height);
  620. break;
  621. }
  622. case ARKFB_SET_WINDOW_FORMAT:
  623. {
  624. unsigned int data, format, yuv_order, rgb_order;
  625. if(copy_from_user(&data, (void *)arg, sizeof(unsigned int))){
  626. ARKN141_LCDC_ERR("ARKFB_SET_WINDOW_FORMAT copy from user para error\n");
  627. error = -EFAULT;
  628. goto end;
  629. }
  630. format = (data >> 0) & 0xFF;
  631. yuv_order = (data >> 16) & 0xF;
  632. rgb_order = (data >> 24) & 0xF;
  633. arkn141_lcdc_set_osd_format(layer, format, yuv_order, rgb_order);
  634. arkn141_lcdc_osd_set_coef_sync(layer);
  635. ARKN141_LCDC_DEBUG("osd layer=%d, format=%d, yuv_order:%d, rgb_order:%d\n", layer, format, yuv_order, rgb_order);
  636. break;
  637. }
  638. case ARKFB_SET_WINDOW_ADDR:
  639. {
  640. struct ark_disp_addr addr;
  641. if(copy_from_user(&addr, (void *)arg, sizeof(struct ark_disp_addr))){
  642. ARKN141_LCDC_ERR("ARKFB_SET_WINDOW_ADDR copy from user para error\n");
  643. error = -EFAULT;
  644. goto end;
  645. }
  646. arkn141_lcdc_set_osd_addr(layer, addr);
  647. arkn141_lcdc_osd_set_coef_sync(layer);
  648. spin_lock(&sinfo->lock);
  649. sinfo->frame_vsync = 0;
  650. spin_unlock(&sinfo->lock);
  651. //ARKN141_LCDC_DEBUG("ARKFB_SET_WINDOW_ADDR osd layer=%d, yaddr=0x%0x, cbaddr=0x%0x, craddr=0x%0x\n", layer, addr.yaddr, addr.cbaddr, addr.craddr);
  652. break;
  653. }
  654. case ARKFB_SET_WINDOW_SCALER:
  655. {
  656. error = -ENXIO;
  657. ARKN141_LCDC_ERR("ARKFB_SET_WINDOW_SCALER Not support window scaler\n");
  658. break;
  659. }
  660. case ARKFB_SET_WINDOW_ATOMIC:
  661. {
  662. struct ark_disp_atomic atomic;
  663. if(copy_from_user(&atomic, (void *)arg, sizeof(struct ark_disp_atomic))){
  664. ARKN141_LCDC_ERR("ARKFB_SET_WINDOW_ATOMIC copy from user para error\n");
  665. error = -EFAULT;
  666. goto end;
  667. }
  668. if(!atomic.atomic_stat || atomic.layer != layer){
  669. ARKN141_LCDC_ERR("ARKFB_SET_WINDOW_ATOMIC atomic_stat or layer error\n");
  670. error = -EFAULT;
  671. goto end;
  672. }
  673. ARKN141_LCDC_DEBUG("ARKFB_SET_WINDOW_ATOMIC osd layer=%d, atomic_stat=0x%0x\n", layer, atomic.atomic_stat);
  674. sinfo->atomic_flag |= (1 << layer);
  675. memcpy(&sinfo->patomic[layer], &atomic, sizeof(struct ark_disp_atomic));
  676. arkn141_lcdc_wait_for_vsync();
  677. break;
  678. }
  679. case ARKFB_SET_REG_VALUE:
  680. {
  681. struct ark_disp_reg reg;
  682. if(copy_from_user(&reg, (void *)arg, sizeof(struct ark_disp_reg))){
  683. ARKN141_LCDC_ERR("ARKFB_SET_REG_VALUE copy from user para error\n");
  684. error = -EFAULT;
  685. goto end;
  686. }
  687. if((reg.addr & 0xffff0000) == 0x70190000){
  688. writel(reg.value, lcdc_base + (reg.addr&0xfff));
  689. ARKN141_LCDC_DEBUG("ARKFB_SET_REG_VALUE arkfb write reg:0x%0x=0x%0x\n", reg.addr, reg.value);
  690. }else{
  691. error = -EINVAL;
  692. goto end;
  693. }
  694. break;
  695. }
  696. case ARKFB_GET_REG_VALUE:
  697. {
  698. struct ark_disp_reg reg;
  699. if(copy_from_user(&reg, (void *)arg, sizeof(struct ark_disp_reg))) {
  700. ARKN141_LCDC_ERR("ARKFB_GET_REG_VALUE copy from user para error\n");
  701. error = -EFAULT;
  702. goto end;
  703. }
  704. if((reg.addr & 0xffff0000) == 0x70190000) {
  705. reg.value = readl(lcdc_base + (reg.addr&0xfff));
  706. ARKN141_LCDC_DEBUG("ARKFB_GET_REG_VALUE arkfb read reg:0x%0x=0x%0x\n", reg.addr, reg.value);
  707. } else {
  708. error = -EINVAL;
  709. goto end;
  710. }
  711. if(copy_to_user((void *)arg, &reg, sizeof(struct ark_disp_reg))) {
  712. ARKN141_LCDC_ERR("ARKFB_GET_REG_VALUE copy to user para error\n");
  713. error = -EFAULT;
  714. goto end;
  715. }
  716. break;
  717. }
  718. case ARKFB_GET_WINDOW_ADDR:
  719. {
  720. struct ark_disp_addr addr;
  721. memset(&addr, 0, sizeof(struct ark_disp_addr));
  722. error = arkn141_lcdc_get_osd_addr(layer, &addr.yaddr, &addr.cbaddr, &addr.craddr);
  723. if(error < 0) {
  724. ARKN141_LCDC_ERR("ARKFB_GET_WINDOW_ADDR arkn141_lcdc_get_osd_addr error\n");
  725. goto end;
  726. }
  727. if(copy_to_user((void *)arg, &addr, sizeof(struct ark_disp_addr))){
  728. ARKN141_LCDC_ERR("ARKFB_GET_WINDOW_ADDR copy to user para error\n");
  729. error = -EFAULT;
  730. goto end;
  731. }
  732. //ARKN141_LCDC_DEBUG("ARKFB_GET_WINDOW_ADDR osd layer=%d: yaddr=0x%0x, cbaddr=0x%0x, craddr=0x%0x\n", layer, addr.yaddr, addr.cbaddr, addr.craddr);
  733. break;
  734. }
  735. case ARKFB_GET_SCREEN_INFO:
  736. {
  737. struct ark_screen screen;
  738. memset(&screen, 0, sizeof(struct ark_screen));
  739. if(lcdfb_info && lcdfb_info->info) {
  740. arkn141_lcdc_width = screen.width = screen.disp_width = lcdfb_info->info->var.xres;
  741. arkn141_lcdc_height = screen.height = screen.disp_height = lcdfb_info->info->var.yres;
  742. } else {
  743. screen.width = screen.disp_width = arkn141_lcdc_width;
  744. screen.height = screen.disp_height = arkn141_lcdc_height;
  745. }
  746. if(copy_to_user((void *)arg, &screen, sizeof(struct ark_screen))){
  747. ARKN141_LCDC_ERR("ARKFB_GET_SCREEN_INFO copy to user para error\n");
  748. error = -EFAULT;
  749. goto end;
  750. }
  751. ARKN141_LCDC_DEBUG("ARKFB_GET_SCREEN_INFO type=%d, width=%d, height=%d\n", screen.type, screen.width,screen.height);
  752. break;
  753. }
  754. #if 0
  755. case ARKFB_SET_SCREEN_INFO: //not use
  756. {
  757. struct ark_screen screen;
  758. if(copy_from_user(&screen, (void *)arg, sizeof(struct ark_screen))) {
  759. ARKN141_LCDC_ERR("ARKFB_SET_SCREEN_INFO copy from user para error\n");
  760. error = -EFAULT;
  761. goto end;
  762. }
  763. if((screen.width > 0xFFF) || (screen.height > 0xFFF)) {
  764. ARKN141_LCDC_ERR("ARKFB_SET_SCREEN_INFO invalid width:%d, height:%d\n", screen.width, screen.height);
  765. error = -EFAULT;
  766. goto end;
  767. }
  768. arkn141_lcdc_width = screen.width;
  769. arkn141_lcdc_height = screen.height;
  770. ARKN141_LCDC_DEBUG("ARKFB_SET_SCREEN_INFO type=%d, width=%d, height=%d\n", screen.type, screen.width,screen.height);
  771. break;
  772. }
  773. #endif
  774. case ARKFB_GET_PLATFORM_INFO:
  775. {
  776. struct ark_platform_info platform;
  777. memset(&platform, 0, sizeof(struct ark_platform_info));
  778. platform.type = ARK_PLATFORM_ARKN141;
  779. if(copy_to_user((void *)arg, &platform, sizeof(struct ark_platform_info))){
  780. ARKN141_LCDC_ERR("ARKFB_GET_PLATFORM_INFO copy to user para error\n");
  781. error = -EFAULT;
  782. goto end;
  783. }
  784. break;
  785. }
  786. default:
  787. ARKN141_LCDC_ERR("unknown ioctl %08x\n", cmd);
  788. error = -EFAULT;
  789. break;
  790. }
  791. end:
  792. mutex_unlock(&sinfo->mutex_lock);
  793. return error;
  794. }
  795. EXPORT_SYMBOL(arkn141_lcdfb_ioctl);
  796. int arkn141_lcdc_funcs_init(struct arkn141_lcdfb_info *sinfo)
  797. {
  798. struct fb_info *info = sinfo->info;
  799. struct fb_var_screeninfo *var = &info->var;
  800. lcdfb_info = sinfo;
  801. arkn141_lcdc_width = var->xres;
  802. arkn141_lcdc_height = var->yres;
  803. lcdc_base = sinfo->mmio;
  804. return 0;
  805. }
  806. EXPORT_SYMBOL(arkn141_lcdc_funcs_init);