lcd.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. #include <string.h>
  2. #include "FreeRTOS.h"
  3. #include "event_groups.h"
  4. #include "chip.h"
  5. #include "board.h"
  6. #include "fb_queue.h"
  7. /* LCD timing */
  8. #define LCD_PARAM0 0x000
  9. #define LCD_PARAM1 0x004
  10. #define LCD_PARAM2 0x008
  11. #define LCD_PARAM3 0x00C
  12. #define LCD_PARAM4 0x010
  13. #define LCD_PARAM5 0x014
  14. #define LCD_PARAM6 0x018
  15. #define LCD_PARAM7 0x01C
  16. #define LCD_PARAM8 0x020
  17. #define LCD_PARAM9 0x024
  18. #define LCD_PARAM10 0x028
  19. #define LCD_PARAM11 0x02C
  20. #define LCD_PARAM12 0x030
  21. #define LCD_PARAM13 0x034
  22. #define LCD_PARAM14 0x038
  23. #define LCD_PARAM15 0x03C
  24. #define LCD_PARAM16 0x040
  25. #define LCD_PARAM17 0x044
  26. #define LCD_PARAM18 0x048
  27. #define LCD_PARAM19 0x04C
  28. #define LCD_PARAM20 0x050
  29. #define LCD_PARAM21 0x054
  30. #define LCD_PARAM22 0x058
  31. /* OSD */
  32. #define LCD_OSD0_PARAM0 0x05C
  33. #define LCD_OSD0_PARAM1 0x060
  34. #define LCD_OSD0_PARAM2 0x064
  35. #define LCD_OSD0_PARAM3 0x068
  36. #define LCD_OSD0_PARAM4 0x06C
  37. #define LCD_OSD0_PARAM5 0x070
  38. #define LCD_OSD1_PARAM0 0x074
  39. #define LCD_OSD1_PARAM1 0x078
  40. #define LCD_OSD1_PARAM2 0x07C
  41. #define LCD_OSD1_PARAM3 0x080
  42. #define LCD_OSD1_PARAM4 0x084
  43. #define LCD_OSD1_PARAM5 0x088
  44. #define LCD_OSD01_PARAM 0x08C
  45. #define LCD_OSD_COEF_SYNC 0x090
  46. #define LCD_OSD1_PARAM8 0x094
  47. #define LCD_OSD1_PARAM9 0x098
  48. #define LCD_OSD0_PARAM2_RD 0x280
  49. #define LCD_OSD0_PARAM3_RD 0x284
  50. #define LCD_OSD0_PARAM4_RD 0x288
  51. #define LCD_OSD1_PARAM2_RD 0x28C
  52. #define LCD_OSD1_PARAM3_RD 0x290
  53. #define LCD_OSD1_PARAM4_RD 0x294
  54. /* Dithering */
  55. #define LCD_DITHERING_CFG0 0x0BC
  56. #define LCD_DITHERING_CFG1 0x0C0
  57. #define LCD_DITHERING_CFG2 0x0C4
  58. #define LCD_INTR_CLR 0x0C8
  59. #define LCD_STATUS_REG 0x0CC
  60. #define LCD_R_BIT_ORDER 0x130
  61. #define LCD_G_BIT_ORDER 0x134
  62. #define LCD_B_BIT_ORDER 0x138
  63. #define LCD_GAMMA_REG 0x13c
  64. /* CPU screen & SRGB screen */
  65. #define LCD_SRGB_CFG 0x200
  66. #define LCD_CPU_SCR_SOFT_REG 0x0E0
  67. #define LCD_CPU_SCR_CTRL_REG 0x0E4
  68. #define LCD_ADR_CLR_DATA_REG0 0x0E8
  69. #define LCD_ADR_CLR_DATA_REG1 0x0EC
  70. #define LCD_ADR_CLR_DATA_REG2 0x0F0
  71. #define LCD_ADR_CLR_DATA_REG3 0x0F4
  72. #define LCD_ADR_CLR_DATA_REG4 0x0F8
  73. #define LCD_ADR_CLR_DATA_REG5 0x0FC
  74. #define LCD_ADR_CLR_DATA_REG6 0x100
  75. #define LCD_ADR_CLR_DATA_REG7 0x104
  76. #define LCD_ADR_CLR_DATA_REG8 0x108
  77. #define LCD_ADR_CLR_DATA_REG9 0x10C
  78. #define LCD_ADR_CLR_DATA_REGA 0x110
  79. #define LCD_ADR_CLR_DATA_REGB 0x114
  80. #define LCD_ADR_CLR_DATA_REGC 0x118
  81. #define LCD_ADR_CLR_DATA_REGD 0x11C
  82. #define LCD_ADR_CLR_DATA_REGE 0x120
  83. #define LCD_ADR_CLR_DATA_REGF 0x124
  84. #define LCD_CPU_SCREEN_STATUS 0x128
  85. #define LCD_OSD_CCM_REG0 0x208
  86. #define LCD_OSD_CCM_REG1 0x20C
  87. #define LCD_OSD_CCM_REG2 0x210
  88. #define LCD_OSD_CCM_REG3 0x214
  89. #define LCD_OSD_CCM_REG4 0x218
  90. #define LCD_OSD_CCM_REG5 0x21C
  91. #define LCD_CCM_EN_REG0 0x238
  92. #define LCD_CCM_EN_REG1 0x23C
  93. #define LCD_CCM_EN_REG2 0x240
  94. #define LCD_CCM_EN_REG3 0x244
  95. #define LCD_CCM_EN_REG4 0x248
  96. #define LCD_CCM_EN_REG5 0x24C
  97. #define LCD_CCM_EN_REG 0x250
  98. #define LCD_ITU_EAV_CODE_CFG 0x254
  99. #define LCD_ITU_SAV_CODE_CFG 0x258
  100. #define LCD_HLOCK_CFG_RG 0x25C
  101. #define FB_COUNT 3
  102. #if configUSE_16_BIT_TICKS == 1
  103. #define MAX_VSYNC_WAIT_TASKS 8
  104. #else
  105. #define MAX_VSYNC_WAIT_TASKS 24
  106. #endif
  107. typedef struct _ark_lcd_timing
  108. {
  109. uint32_t vs_start;
  110. uint32_t hs_start;
  111. uint32_t hd; //width
  112. uint32_t vd; //height
  113. uint32_t vbp;
  114. uint32_t vfp;
  115. uint32_t vsw;
  116. uint32_t hbp;
  117. uint32_t hfp;
  118. uint32_t hsw;
  119. } ark_lcd_timing_t;
  120. typedef struct _ark_lcd_info
  121. {
  122. ark_lcd_timing_t timing;
  123. EventGroupHandle_t vsync_waitq;
  124. void *waitq_tasks[MAX_VSYNC_WAIT_TASKS];
  125. uint32_t waitbits;
  126. } ark_lcd_t;
  127. static ark_lcd_t *g_lcd = NULL;
  128. static int g_osdConfig[LCD_OSD_NUMS] = {0};
  129. static uint32_t fb_addr = 0;
  130. static uint32_t lcd_boot_status;
  131. static void ark_lcd_writel(uint32_t reg, uint32_t mask, uint8_t offset, uint32_t val)
  132. {
  133. uint32_t tmp = readl(REGS_LCD_BASE+reg);
  134. tmp &= (~(mask << offset));
  135. tmp |= (val << offset);
  136. writel(tmp, REGS_LCD_BASE+reg);
  137. }
  138. int ark_lcd_set_osd_sync(LCD_OSD_LAYER osd)
  139. {
  140. if(osd > LCD_OSD_NUMS) {
  141. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  142. return -1;
  143. }
  144. if(osd == LCD_OSD0)
  145. writel(readl(REGS_LCD_BASE+LCD_OSD_COEF_SYNC)|(1<<0), REGS_LCD_BASE+LCD_OSD_COEF_SYNC);
  146. else if(osd == LCD_OSD1)
  147. writel(readl(REGS_LCD_BASE+LCD_OSD_COEF_SYNC)|(1<<1), REGS_LCD_BASE+LCD_OSD_COEF_SYNC);
  148. else if(osd == LCD_OSD_NUMS)
  149. writel(readl(REGS_LCD_BASE+LCD_OSD_COEF_SYNC)|(3<<0), REGS_LCD_BASE+LCD_OSD_COEF_SYNC);
  150. return 0;
  151. }
  152. static int ark_lcd_set_osd_stride(LCD_OSD_LAYER osd, uint32_t width)
  153. {
  154. uint32_t reg = LCD_OSD0_PARAM5 + osd*0x18;
  155. if(osd >= LCD_OSD_NUMS) {
  156. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  157. return -1;
  158. }
  159. if(width > 0xFFF) {
  160. printf("ERR: %s, Invalid width:0x%x\n", __func__, width);
  161. return -1;
  162. }
  163. ark_lcd_writel(reg, 0xFFF, 0, width);
  164. return 0;
  165. }
  166. int ark_lcd_get_osd_size(LCD_OSD_LAYER osd, uint32_t *width, uint32_t *height)
  167. {
  168. uint32_t reg = LCD_OSD0_PARAM0 + osd*0x18;
  169. uint32_t val;
  170. if(osd>= LCD_OSD_NUMS) {
  171. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  172. return -1;
  173. }
  174. val = readl(REGS_LCD_BASE+reg);
  175. *width = (val >> 6) & 0xFFF;
  176. *height = (val >> 18) & 0xFFF;
  177. return 0;
  178. }
  179. int ark_lcd_set_osd_size(LCD_OSD_LAYER osd, uint32_t width, uint32_t height)
  180. {
  181. uint32_t reg = LCD_OSD0_PARAM0 + osd*0x18;
  182. if(osd>= LCD_OSD_NUMS) {
  183. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  184. return -1;
  185. }
  186. width &= 0xFFF;
  187. height &= 0xFFF;
  188. ark_lcd_writel(reg, 0xFFFFFF, 6, (height<<12)|width);
  189. ark_lcd_set_osd_stride(osd, width);
  190. return 0;
  191. }
  192. int ark_lcd_get_osd_format(LCD_OSD_LAYER osd, LCD_OSD_FORMAT *format)
  193. {
  194. uint32_t reg = LCD_OSD0_PARAM0 + osd*0x18;
  195. uint32_t fmt, val;
  196. if(osd >= LCD_OSD_NUMS) {
  197. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  198. return -1;
  199. }
  200. val = readl(REGS_LCD_BASE + reg);
  201. fmt = (val >> 3) & 0x07;
  202. if(fmt >= LCD_OSD_FORAMT_NUMS) {
  203. printf("ERR: %s, Invalid osd%d format:%d\n", __func__, osd, fmt);
  204. return -1;
  205. }
  206. /* yuv mode */
  207. switch (fmt) {
  208. case LCD_OSD_FMT_TYPE_YUV: {
  209. uint32_t uv = 0;
  210. val = readl(REGS_LCD_BASE + LCD_OSD01_PARAM);
  211. if (osd == LCD_OSD0) {
  212. if (val & (1 << 12))
  213. uv = 1;
  214. } else {
  215. if (val & (1 << 14))
  216. uv = 1;
  217. }
  218. if (val & (1 << 20)) {
  219. if (uv)
  220. fmt = LCD_OSD_FORAMT_Y_UV422;
  221. else
  222. fmt = LCD_OSD_FORAMT_Y_U_V422;
  223. } else {
  224. if (uv)
  225. fmt = LCD_OSD_FORAMT_Y_UV420;
  226. else
  227. fmt = LCD_OSD_FORAMT_Y_U_V420;
  228. }
  229. break;
  230. }
  231. case LCD_OSD_FMT_TYPE_ARGB888: {
  232. fmt = LCD_OSD_FORAMT_ARGB888;
  233. break;
  234. }
  235. case LCD_OSD_FMT_TYPE_RGB565: {
  236. fmt = LCD_OSD_FORAMT_RGB565;
  237. break;
  238. }
  239. case LCD_OSD_FMT_TYPE_RGB454: {
  240. fmt = LCD_OSD_FORAMT_RGB454;
  241. break;
  242. }
  243. default: {
  244. printf("ERR: %s, Invalid osd%d format:%d\n", __func__, osd, fmt);
  245. return -1;
  246. }
  247. }
  248. *format = fmt;
  249. return 0;
  250. }
  251. int ark_lcd_set_osd_format(LCD_OSD_LAYER osd, LCD_OSD_FORMAT format)
  252. {
  253. uint32_t reg = LCD_OSD0_PARAM0 + osd*0x18;
  254. uint32_t val;
  255. if(osd >= LCD_OSD_NUMS) {
  256. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  257. return -1;
  258. }
  259. switch (format) {
  260. case LCD_OSD_FORAMT_Y_UV420:
  261. case LCD_OSD_FORAMT_Y_UV422:
  262. case LCD_OSD_FORAMT_Y_U_V420:
  263. case LCD_OSD_FORAMT_Y_U_V422: {
  264. val = readl(REGS_LCD_BASE + LCD_OSD01_PARAM);
  265. if (format == LCD_OSD_FORAMT_Y_UV420 || format == LCD_OSD_FORAMT_Y_U_V420) {
  266. val &= ~(1 << 20);
  267. } else {
  268. val |= (1 << 20);
  269. }
  270. if (format == LCD_OSD_FORAMT_Y_UV420 || format == LCD_OSD_FORAMT_Y_UV422) {
  271. if (osd == LCD_OSD0) {
  272. val |= (1 << 12);
  273. } else {
  274. val |= (1 << 14);
  275. }
  276. } else {
  277. if (osd == LCD_OSD0) {
  278. val &= ~(1 << 12);
  279. } else {
  280. val &= ~(1 << 14);
  281. }
  282. }
  283. writel(val, REGS_LCD_BASE + LCD_OSD01_PARAM);
  284. format = LCD_OSD_FMT_TYPE_YUV;
  285. break;
  286. }
  287. case LCD_OSD_FORAMT_ARGB888: {
  288. format = LCD_OSD_FMT_TYPE_ARGB888;
  289. break;
  290. }
  291. case LCD_OSD_FORAMT_RGB565: {
  292. format = LCD_OSD_FMT_TYPE_RGB565;
  293. break;
  294. }
  295. case LCD_OSD_FORAMT_RGB454: {
  296. format = LCD_OSD_FMT_TYPE_RGB454;
  297. break;
  298. }
  299. default: {
  300. printf("ERR: %s, Invalid osd%d format:%d\n", __func__, osd, format);
  301. return -1;
  302. }
  303. }
  304. ark_lcd_writel(reg, 0x7, 3, format);
  305. return 0;
  306. }
  307. int ark_lcd_osd_enable(LCD_OSD_LAYER osd, uint8_t enable)
  308. {
  309. uint32_t reg = LCD_OSD0_PARAM0 + osd*0x18;
  310. if(osd >= LCD_OSD_NUMS) {
  311. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  312. return -1;
  313. }
  314. ark_lcd_writel(reg, 0x1, 1, (enable?1:0));
  315. return 0;
  316. }
  317. int ark_lcd_get_osd_enable(LCD_OSD_LAYER osd)
  318. {
  319. uint32_t reg = LCD_OSD0_PARAM0 + osd*0x18;
  320. uint32_t val;
  321. if(osd >= LCD_OSD_NUMS) {
  322. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  323. return -1;
  324. }
  325. val = readl(REGS_LCD_BASE + reg);
  326. return (val >> 1) & 1;
  327. }
  328. int ark_lcd_osd_coeff_enable(LCD_OSD_LAYER osd, uint8_t enable)
  329. {
  330. uint32_t reg = LCD_OSD0_PARAM0 + osd*0x18;
  331. if(osd >= LCD_OSD_NUMS) {
  332. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  333. return -1;
  334. }
  335. ark_lcd_writel(reg, 0x1, 0, (enable?1:0));
  336. return 0;
  337. }
  338. int ark_lcd_osd_set_coeff(LCD_OSD_LAYER osd, uint32_t value)
  339. {
  340. uint32_t reg = LCD_OSD0_PARAM1 + osd*0x18;
  341. if(osd >= LCD_OSD_NUMS) {
  342. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  343. return -1;
  344. }
  345. ark_lcd_writel(reg, 0xFF, 24, value);
  346. return 0;
  347. }
  348. int ark_lcd_set_osd_possition(LCD_OSD_LAYER osd, uint32_t h, uint32_t v)
  349. {
  350. uint32_t reg = LCD_OSD0_PARAM1 + osd*0x18;
  351. if(osd >= LCD_OSD_NUMS) {
  352. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  353. return -1;
  354. }
  355. if((v > 0xFFF) || (h > 0xFFF)) {
  356. printf("ERR: %s, Invalid v:0x%x or h:0x%x\n", __func__, v, h);
  357. return -1;
  358. }
  359. ark_lcd_writel(reg, 0xFFFFFF, 0, ((v<<12)|h));
  360. return 0;
  361. }
  362. int ark_lcd_get_osd_yaddr(LCD_OSD_LAYER osd, uint32_t *yaddr)
  363. {
  364. uint32_t reg = LCD_OSD0_PARAM2 + osd*0x18;
  365. if(osd >= LCD_OSD_NUMS) {
  366. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  367. return -1;
  368. }
  369. *yaddr = readl(REGS_LCD_BASE+reg);
  370. return 0;
  371. }
  372. int ark_lcd_set_osd_yaddr(LCD_OSD_LAYER osd, uint32_t yaddr)
  373. {
  374. uint32_t reg = LCD_OSD0_PARAM2 + osd*0x18;
  375. if(osd >= LCD_OSD_NUMS) {
  376. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  377. return -1;
  378. }
  379. #if LCD_V_FLIP
  380. LCD_OSD_FORMAT format;
  381. uint32_t width, height;
  382. if (ark_lcd_get_osd_format(osd, &format) >= 0) {
  383. ark_lcd_get_osd_size(osd, &width, &height);
  384. if (format <= LCD_OSD_FORAMT_Y_U_V422)
  385. yaddr += width * (height - 1);
  386. else if (format == LCD_OSD_FORAMT_ARGB888)
  387. yaddr += width * (height - 1) * 4;
  388. else if (format == LCD_OSD_FORAMT_RGB565)
  389. yaddr += width * (height - 1) * 2;
  390. }
  391. #endif
  392. writel(yaddr, REGS_LCD_BASE+reg);
  393. return 0;
  394. }
  395. int ark_lcd_set_osd_uaddr(LCD_OSD_LAYER osd, uint32_t uaddr)
  396. {
  397. uint32_t reg = LCD_OSD0_PARAM3 + osd*0x18;
  398. if(osd >= LCD_OSD_NUMS) {
  399. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  400. return -1;
  401. }
  402. #if LCD_V_FLIP
  403. LCD_OSD_FORMAT format;
  404. uint32_t width, height;
  405. if (ark_lcd_get_osd_format(osd, &format) >= 0) {
  406. ark_lcd_get_osd_size(osd, &width, &height);
  407. if ((format == LCD_OSD_FORAMT_Y_UV420) || (format == LCD_OSD_FORAMT_Y_U_V422)) {
  408. uaddr += width * (height - 2) / 2;
  409. } else if (format == LCD_OSD_FORAMT_Y_U_V420) {
  410. uaddr += width * (height - 2) / 4;
  411. } else if (format == LCD_OSD_FORAMT_Y_UV422) {
  412. uaddr += width * (height - 2);
  413. }
  414. }
  415. #endif
  416. writel(uaddr, REGS_LCD_BASE+reg);
  417. return 0;
  418. }
  419. int ark_lcd_set_osd_vaddr(LCD_OSD_LAYER osd, uint32_t vaddr)
  420. {
  421. uint32_t reg = LCD_OSD0_PARAM4 + osd*0x18;
  422. if(osd >= LCD_OSD_NUMS) {
  423. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  424. return -1;
  425. }
  426. #if LCD_V_FLIP
  427. LCD_OSD_FORMAT format;
  428. uint32_t width, height;
  429. if (ark_lcd_get_osd_format(osd, &format) >= 0) {
  430. ark_lcd_get_osd_size(osd, &width, &height);
  431. if (format == LCD_OSD_FORAMT_Y_U_V420) {
  432. vaddr += width * (height - 2) / 4;
  433. } else if (format == LCD_OSD_FORAMT_Y_U_V422) {
  434. vaddr += width * (height - 2) / 2;
  435. }
  436. }
  437. #endif
  438. writel(vaddr, REGS_LCD_BASE+reg);
  439. return 0;
  440. }
  441. int ark_lcd_set_osd_mult_coef(LCD_OSD_LAYER osd, uint32_t value)
  442. {
  443. uint32_t reg = LCD_OSD0_PARAM5 + osd*0x18;
  444. if(osd >= LCD_OSD_NUMS) {
  445. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  446. return -1;
  447. }
  448. if(value > 0x7F) {
  449. printf("ERR: %s, Invalid value:0x%x\n", __func__, value);
  450. return -1;
  451. }
  452. ark_lcd_writel(reg, 0x7F, 24, value);
  453. return 0;
  454. }
  455. int ark_lcd_set_osd_h_offset(LCD_OSD_LAYER osd, uint32_t offset)
  456. {
  457. uint32_t reg = LCD_OSD0_PARAM5 + osd*0x18;
  458. if(osd >= LCD_OSD_NUMS) {
  459. printf("ERR: %s, Invalid osd%d\n", __func__, osd);
  460. return -1;
  461. }
  462. if(offset > 0xFFF) {
  463. printf("ERR: %s, Invalid offset:0x%x\n", __func__, offset);
  464. return -1;
  465. }
  466. ark_lcd_writel(reg, 0xFFF, 12, offset);
  467. return 0;
  468. }
  469. void ark_lcd_set_osd_colorkey_enable(LCD_OSD_LAYER osd, uint8_t enable)
  470. {
  471. if(osd == LCD_OSD1) {
  472. ark_lcd_writel(LCD_OSD01_PARAM, 0x01, 20, (enable?1:0));
  473. ark_lcd_writel(LCD_OSD1_PARAM8, 0x01, 24, (enable?1:0));
  474. }
  475. }
  476. void ark_lcd_set_osd_colorkey(LCD_OSD_LAYER osd, uint8_t r, uint8_t g, uint8_t b)
  477. {
  478. if(osd == LCD_OSD1) {
  479. ark_lcd_writel(LCD_OSD1_PARAM8, 0xFFFFFF, 0, (r << 16) | (g << 8) | (b << 0));
  480. }
  481. }
  482. void ark_lcd_set_osd_colorkey_thld_r(LCD_OSD_LAYER osd, uint8_t thld)
  483. {
  484. if(osd == LCD_OSD1) {
  485. ark_lcd_writel(LCD_OSD1_PARAM9, 0xFF, 16, thld);
  486. }
  487. }
  488. void ark_lcd_set_osd_colorkey_thld_g(LCD_OSD_LAYER osd, uint8_t thld)
  489. {
  490. if(osd == LCD_OSD1) {
  491. ark_lcd_writel(LCD_OSD1_PARAM9, 0xFF, 8, thld);
  492. }
  493. }
  494. void ark_lcd_set_osd_colorkey_thld_b(LCD_OSD_LAYER osd, uint8_t thld)
  495. {
  496. if(osd == LCD_OSD1) {
  497. ark_lcd_writel(LCD_OSD1_PARAM9, 0xFF, 0, thld);
  498. }
  499. }
  500. int ark_lcd_enable(uint8_t enable)
  501. {
  502. ark_lcd_writel(LCD_PARAM0, 0x01, 0, (enable?1:0));
  503. return 0;
  504. }
  505. int ark_lcd_get_boot_status(void)
  506. {
  507. return lcd_boot_status;
  508. }
  509. int ark_lcd_wait_for_vsync(void)
  510. {
  511. ark_lcd_t *lcd = g_lcd;
  512. int i;
  513. if(!lcd) {
  514. printf("ERR: %s, Invalid lcd(NULL)\n", __func__);
  515. return -EINVAL;
  516. }
  517. #if LCD_INTERFACE_TYPE != LCD_INTERFACE_CPU
  518. portENTER_CRITICAL();
  519. for (i = 0; i < MAX_VSYNC_WAIT_TASKS; i++) {
  520. if (lcd->waitq_tasks[i] == xTaskGetCurrentTaskHandle()) {
  521. lcd->waitbits |= 1 << i;
  522. break;
  523. } else if (lcd->waitq_tasks[i] == NULL) {
  524. lcd->waitq_tasks[i] = xTaskGetCurrentTaskHandle();
  525. lcd->waitbits |= 1 << i;
  526. break;
  527. }
  528. }
  529. portEXIT_CRITICAL();
  530. if (i == MAX_VSYNC_WAIT_TASKS) {
  531. printf("ERR: %s, waitq_tasks full\n", __func__);
  532. return -1;
  533. }
  534. xEventGroupClearBits(lcd->vsync_waitq, 1 << i);
  535. xEventGroupWaitBits(lcd->vsync_waitq, 1 << i, pdFALSE, pdFALSE, pdMS_TO_TICKS(50));
  536. portENTER_CRITICAL();
  537. lcd->waitbits &= ~(1 << i);
  538. portEXIT_CRITICAL();
  539. #endif
  540. return 0;
  541. }
  542. int ark_lcd_set_osd_info_atomic(LCD_OSD_LAYER osd, LcdOsdInfo *info)
  543. {
  544. portENTER_CRITICAL();
  545. ark_lcd_set_osd_possition(osd, info->x, info->y);
  546. ark_lcd_set_osd_size(osd, info->width, info->height);
  547. if (info->stride != 0)
  548. ark_lcd_set_osd_stride(osd, info->stride);
  549. ark_lcd_set_osd_format(osd, info->format);
  550. ark_lcd_set_osd_yaddr(osd, info->yaddr);
  551. ark_lcd_set_osd_uaddr(osd, info->uaddr);
  552. ark_lcd_set_osd_vaddr(osd, info->vaddr);
  553. ark_lcd_set_osd_sync(osd);
  554. g_osdConfig[osd - LCD_OSD0] = 1;
  555. portEXIT_CRITICAL();
  556. return 0;
  557. }
  558. int ark_lcd_get_osd_info_atomic_isactive(LCD_OSD_LAYER osd)
  559. {
  560. int active;
  561. portENTER_CRITICAL();
  562. active = !g_osdConfig[osd - LCD_OSD0];
  563. portEXIT_CRITICAL();
  564. return active;
  565. }
  566. int ark_lcd_set_background_color(uint8_t r, uint8_t g, uint8_t b)
  567. {
  568. unsigned int background_color = (r<<16) | (g<<8) | (b);
  569. ark_lcd_writel(LCD_PARAM2, 0xFFFFFF, 0, background_color);
  570. return 0;
  571. }
  572. uint32_t ark_lcd_get_virt_addr(void)
  573. {
  574. return (uint32_t)fb_addr;
  575. }
  576. uint8_t *ark_lcd_get_fb_addr(uint8_t index)
  577. {
  578. if (index > FB_COUNT - 1)
  579. return NULL;
  580. return (uint8_t *)(fb_addr + FB_SIZE * index);
  581. }
  582. static int ark_lcd_timing_init(ark_lcd_t *lcd)
  583. {
  584. ark_lcd_timing_t timing;
  585. uint32_t VS_START, HS_START, HD, VD;
  586. uint32_t VBP, VFP, VSW, TV;
  587. uint32_t HBP, HFP, HSW, TH;
  588. uint32_t lcd_param0, lcd_param1, lcd_param2, lcd_param3 ;
  589. uint32_t lcd_param4, lcd_param5, lcd_param6, lcd_param7 ;
  590. uint32_t lcd_param8, lcd_param9, lcd_param10, lcd_param11 ;
  591. uint32_t lcd_param12, lcd_param13, lcd_param14, lcd_param15 ;
  592. uint32_t lcd_param16, lcd_param17;
  593. uint8_t stop_lcd = 0 ;
  594. if(!lcd) {
  595. printf("ERR: %s, lcd == NULL\n", __func__);
  596. return -1;
  597. }
  598. timing = lcd->timing;
  599. VS_START = timing.vs_start;
  600. HS_START = timing.hs_start;
  601. HD = timing.hd;
  602. VD = timing.vd;
  603. VBP = timing.vbp;
  604. VFP = timing.vfp;
  605. VSW = timing.vsw;
  606. TV =(VS_START+VSW+VBP+VD+VFP);
  607. HBP = timing.hbp;
  608. HFP = timing.hfp;
  609. HSW = timing.hsw;
  610. TH = (HS_START+HSW+HBP+HD+HFP);
  611. #define lcd_enable 0 // 1
  612. #define screen_width HD
  613. #define rgb_pad_mode LCD_WIRING_MODE
  614. #define direct_enable 0
  615. #define mem_lcd_enable 0
  616. #define range_coeff_y 0
  617. #define range_coeff_uv 0
  618. #define lcd_done_intr_enable 1
  619. #define dac_for_video 0
  620. #define dac_for_cvbs 0
  621. #define lcd_interlace_flag 0
  622. #define screen_type 1 //pRGB_i 0 pRGB_p 1 sRGB_p 2 ITU656 3
  623. #define VSW1_enable 0
  624. #define LcdVComp 0
  625. #define itu_pal_ntsc 0
  626. #define hsync_ivs 1
  627. #define vsync_ivs 1
  628. #define lcd_ac_ivs 0
  629. #define test_on_flag 0
  630. #define back_color (0x00<<16)|(0x00<<8)|(0x00)
  631. #define DEN_h_rise (HFP+HSW+HBP)
  632. #define DEN_h_fall (HFP+HSW+HBP+HD)//(20+800*1)
  633. #define DEN0_v_rise (VFP+VSW+VBP)
  634. #define DEN0_v_fall (VFP+VSW+VBP+VD)
  635. #define DEN1_v_rise (VFP+VSW+VBP)
  636. #define DEN1_v_fall (VFP+VSW+VBP+VD)
  637. // ֡Ƶ = LCDʱÖÓ/(CPL * LPS)
  638. // ÿÐÐʱÖÓÖÜÆÚ¸öÊý
  639. #define CPL (TH) // clock cycles per line max 4096 ; from register timing2 16
  640. #define LPS (TV) // Lines per screen value ; from register timing1 0
  641. #define HSW_rise (HFP)
  642. #define HSW_fall (HFP+HSW)
  643. #define VSW0_v_rise (VFP) // Vertical sync width value ; from register timing1 10
  644. #define VSW0_v_fall (VFP+VSW) // Vertical sync width value ; from register timing1 10
  645. #define VSW0_h_rise (HFP)
  646. #define VSW0_h_fall (HFP)
  647. #define VSW1_v_rise (VFP) // Vertical sync width value ; from register timing1 10
  648. #define VSW1_v_fall (VFP+VSW) // Vertical sync width value ; from register timing1 10
  649. #define VSW1_h_rise (HFP)
  650. #define VSW1_h_fall (HFP+HSW)
  651. writel(0, REGS_LCD_BASE+LCD_PARAM0);
  652. lcd_param0 =
  653. lcd_enable |
  654. (screen_width<<1) |
  655. (rgb_pad_mode<<13) |
  656. (direct_enable<<16) |
  657. (mem_lcd_enable<<17)|
  658. (range_coeff_y<<18) |
  659. (range_coeff_uv<<22)|
  660. (lcd_done_intr_enable<<26)|
  661. (dac_for_video<<27) |
  662. (dac_for_cvbs<<28) |
  663. (1<<30) |
  664. (stop_lcd<<31);
  665. lcd_param1 =
  666. (lcd_interlace_flag<<0) |
  667. (screen_type<<1) |
  668. (VSW1_enable<<13) |
  669. (LcdVComp<<14) |
  670. (itu_pal_ntsc<<15) |
  671. (hsync_ivs<<17) |
  672. (vsync_ivs<<18) |
  673. (lcd_ac_ivs<<19) |
  674. (1<<21) |
  675. (1<<23) |
  676. (test_on_flag<<31);
  677. lcd_param2 =
  678. (back_color<<0) |
  679. (1<<24) |
  680. (1<<25);
  681. lcd_param3 =
  682. (DEN_h_rise<<0) |
  683. (DEN_h_fall<<12) ;
  684. lcd_param4 =
  685. (DEN0_v_rise<<0) |
  686. (DEN0_v_fall<<12) ;
  687. lcd_param5 =
  688. (DEN1_v_rise<<0) |
  689. (DEN1_v_fall<<12 ) ;
  690. lcd_param6 =
  691. (CPL<<0) | // clock cycles per line max 4096 ; from register timing2 16
  692. (LPS<<12) ; // Lines per screen value ; from register timing1 0
  693. lcd_param7 =
  694. (HSW_rise<<0)|
  695. (HSW_fall<<12) ;
  696. lcd_param8 =
  697. (VSW0_v_rise<<0)| // Vertical sync width value ; from register timing1 10
  698. (VSW0_v_fall<<12) ; // Vertical sync width value ; from register timing1 10
  699. lcd_param9 =
  700. (VSW0_h_rise <<0 )|
  701. (VSW0_h_fall <<12 ) ;
  702. lcd_param10 =
  703. (VSW1_v_rise<<0)|
  704. (VSW1_v_fall<<12) ;
  705. lcd_param11 =
  706. (VSW1_h_rise<<0)|
  707. (VSW1_h_fall<<12) ;
  708. lcd_param12 = 66 | (129<<9) | (25<<18);
  709. lcd_param13 = 38 | (74<<9) | (112<<18);
  710. lcd_param14 = 112 | (94<<9) | (18<<18);
  711. lcd_param15 = 256 | (0<<9) | (351<<18);
  712. lcd_param16 = 256 | (86<<9) | (179<<18);
  713. lcd_param17 = 256 | (443<<9) | (0<<19);
  714. writel(lcd_param1, REGS_LCD_BASE+LCD_PARAM1);
  715. writel(lcd_param2, REGS_LCD_BASE+LCD_PARAM2);
  716. writel(lcd_param3, REGS_LCD_BASE+LCD_PARAM3);
  717. writel(lcd_param4, REGS_LCD_BASE+LCD_PARAM4);
  718. writel(lcd_param5, REGS_LCD_BASE+LCD_PARAM5);
  719. writel(lcd_param6, REGS_LCD_BASE+LCD_PARAM6);
  720. writel(lcd_param7, REGS_LCD_BASE+LCD_PARAM7);
  721. writel(lcd_param8, REGS_LCD_BASE+LCD_PARAM8);
  722. writel(lcd_param9, REGS_LCD_BASE+LCD_PARAM9);
  723. writel(lcd_param10, REGS_LCD_BASE+LCD_PARAM10);
  724. writel(lcd_param11, REGS_LCD_BASE+LCD_PARAM11);
  725. writel(lcd_param12, REGS_LCD_BASE+LCD_PARAM12);
  726. writel(lcd_param13, REGS_LCD_BASE+LCD_PARAM13);
  727. writel(lcd_param14, REGS_LCD_BASE+LCD_PARAM14);
  728. writel(lcd_param15, REGS_LCD_BASE+LCD_PARAM15);
  729. writel(lcd_param16, REGS_LCD_BASE+LCD_PARAM16);
  730. writel(lcd_param17, REGS_LCD_BASE+LCD_PARAM17);
  731. writel(lcd_param0, REGS_LCD_BASE+LCD_PARAM0);
  732. #if LCD_WIRING_BIT_ORDER == LCD_WIRING_BIT_ORDER_LSB
  733. writel((0<<21|1<<18|2<<15|3<<12|4<<9|5<<6|6<<3|7<<0), REGS_LCD_BASE+LCD_R_BIT_ORDER);
  734. writel((0<<21|1<<18|2<<15|3<<12|4<<9|5<<6|6<<3|7<<0), REGS_LCD_BASE+LCD_G_BIT_ORDER);
  735. writel((0<<21|1<<18|2<<15|3<<12|4<<9|5<<6|6<<3|7<<0), REGS_LCD_BASE+LCD_B_BIT_ORDER);
  736. #elif LCD_WIRING_BIT_ORDER == LCD_WIRING_BIT_ORDER_MSB
  737. writel((7<<21|6<<18|5<<15|4<<12|3<<9|2<<6|1<<3|0<<0), REGS_LCD_BASE+LCD_R_BIT_ORDER);
  738. writel((7<<21|6<<18|5<<15|4<<12|3<<9|2<<6|1<<3|0<<0), REGS_LCD_BASE+LCD_G_BIT_ORDER);
  739. writel((7<<21|6<<18|5<<15|4<<12|3<<9|2<<6|1<<3|0<<0), REGS_LCD_BASE+LCD_B_BIT_ORDER);
  740. #endif
  741. return 0;
  742. }
  743. static int ark_lcd_hw_init()
  744. {
  745. uint32_t HD, VD;
  746. #ifdef AWTK
  747. HD = OSD_WIDTH;
  748. VD = OSD_HEIGHT;
  749. #else
  750. HD = LCD_WIDTH;
  751. VD = LCD_HEIGHT;
  752. #endif
  753. #if LCD_H_FLIP
  754. uint8_t osd_0_hflip = 1;
  755. uint8_t osd_1_hflip = 1;
  756. uint8_t osd_0_uvfirst = 1;
  757. #else
  758. uint8_t osd_0_hflip = 0;
  759. uint8_t osd_1_hflip = 0;
  760. uint8_t osd_0_uvfirst = 0;
  761. #endif
  762. #if LCD_V_FLIP
  763. uint8_t osd_0_vflip = 1;
  764. uint8_t osd_1_vflip = 1;
  765. #else
  766. uint8_t osd_0_vflip = 0;
  767. uint8_t osd_1_vflip = 0;
  768. #endif
  769. uint8_t osd_0_yuv420mode = 1;
  770. //uint8_t osd_0_yuv422mode = 0;
  771. uint32_t osd_01_param =
  772. //osd_0_yuv422mode<<20|
  773. osd_0_hflip<<16|
  774. osd_0_vflip<<17|
  775. osd_1_hflip<<18|
  776. osd_1_vflip<<19|
  777. osd_0_yuv420mode<<12|
  778. osd_0_uvfirst<<13;
  779. writel(osd_01_param, REGS_LCD_BASE+LCD_OSD01_PARAM);
  780. //osd0 init
  781. ark_lcd_set_osd_size(LCD_OSD0, HD, VD);
  782. #if LCD_BPP == 32
  783. ark_lcd_set_osd_format(LCD_OSD0, LCD_OSD_FORAMT_ARGB888);
  784. #elif LCD_BPP == 16
  785. ark_lcd_set_osd_format(LCD_OSD0, LCD_OSD_FORAMT_RGB565);
  786. #endif
  787. ark_lcd_set_osd_possition(LCD_OSD0, 0, 0);
  788. ark_lcd_set_osd_yaddr(LCD_OSD0, fb_addr);
  789. ark_lcd_set_osd_h_offset(LCD_OSD0, 0);
  790. ark_lcd_set_osd_mult_coef(LCD_OSD0, 64);
  791. //ark_lcd_osd_enable(LCD_OSD0, 1);
  792. ark_lcd_set_osd_sync(LCD_OSD0);
  793. //osd1 init
  794. ark_lcd_set_osd_size(LCD_OSD1, HD, VD);
  795. #if LCD_BPP == 32
  796. ark_lcd_set_osd_format(LCD_OSD1, LCD_OSD_FORAMT_ARGB888);
  797. ark_lcd_osd_coeff_enable(LCD_OSD1, 0);
  798. #elif LCD_BPP == 16
  799. ark_lcd_set_osd_format(LCD_OSD1, LCD_OSD_FORAMT_RGB565);
  800. ark_lcd_osd_coeff_enable(LCD_OSD1, 1);
  801. ark_lcd_osd_set_coeff(LCD_OSD1, 255);
  802. #endif
  803. ark_lcd_set_osd_possition(LCD_OSD1, 0, 0);
  804. ark_lcd_set_osd_h_offset(LCD_OSD1, 0);
  805. ark_lcd_set_osd_mult_coef(LCD_OSD1, 64);
  806. ark_lcd_set_osd_yaddr(LCD_OSD1, fb_addr);
  807. //ark_lcd_osd_enable(LCD_OSD1, 1);
  808. ark_lcd_set_osd_sync(LCD_OSD1);
  809. CP15_clean_dcache_for_dma(fb_addr, fb_addr + FB_SIZE);
  810. return 0;
  811. }
  812. static unsigned int ark_lcd_set_clk_below16(uint32_t freq)
  813. {
  814. int div;
  815. uint32_t parent_rate;
  816. if (freq < 14000000) {
  817. vSysctlConfigure(SYS_VOU_CLK_CFG, 0, 3, 2);
  818. parent_rate = ulClkGetRate(CLK_XTAL24M);
  819. div = DIV_ROUND_UP(parent_rate, freq);
  820. vSysctlConfigure(SYS_VOU_CLK_CFG, 3, 0x1f, div - 1);
  821. return parent_rate / div;
  822. } else { //14-16MH配置为16MHZ
  823. vClkSetRate(CLK_LCD, 16000000);
  824. return ulClkGetRate(CLK_LCD);
  825. }
  826. return 0;
  827. }
  828. static int ark_lcd_clk_init(uint32_t freq)
  829. {
  830. if (freq >= 16000000) {
  831. vClkSetRate(CLK_LCD, freq);
  832. printf("%s, set clk:%d\n", __func__, ulClkGetRate(CLK_LCD));
  833. } else {
  834. uint32_t real_freq = ark_lcd_set_clk_below16(freq);
  835. printf("%s, set clk:%d\n", __func__, real_freq);
  836. }
  837. return 0;
  838. }
  839. static void ark_lcd_interrupt(void *param)
  840. {
  841. static fb_queue_s *last_fb = NULL;
  842. ark_lcd_t *lcd = (ark_lcd_t *)param;
  843. uint32_t status = readl(REGS_LCD_BASE+LCD_STATUS_REG);
  844. writel(0x07, REGS_LCD_BASE+LCD_INTR_CLR);
  845. /* frame vsync */
  846. /* LCD场结束中断状态位 */
  847. if (status & (0x01 << 0)) {
  848. /* 进入消隐区, 切换framebuffer */
  849. fb_queue_s *next_ready_unit = fb_queue_get_ready_unit_isr();
  850. if (next_ready_unit) {
  851. ark_lcd_set_osd_yaddr(LCD_UI_LAYER, (unsigned int)next_ready_unit->fb_base);
  852. ark_lcd_set_osd_sync(LCD_UI_LAYER);
  853. /* Release last_fb */
  854. if (last_fb) {
  855. fb_queue_set_free_isr (last_fb);
  856. }
  857. last_fb = next_ready_unit;
  858. }
  859. }
  860. if (status & (1<<0)) {
  861. int i;
  862. for (i = 0; i < LCD_OSD_NUMS; i++)
  863. g_osdConfig[i] = 0;
  864. if (lcd->waitbits)
  865. xEventGroupSetBitsFromISR(lcd->vsync_waitq, lcd->waitbits, NULL);
  866. }
  867. }
  868. #if LCD_INTERFACE_TYPE == LCD_INTERFACE_LVDS
  869. static void lvds_screen_reset(void)
  870. {
  871. gpio_direction_output(LVDS_SCREEN_RST_GPIO, 0);
  872. udelay(100);
  873. gpio_direction_output(LVDS_SCREEN_RST_GPIO, 1);
  874. mdelay(20);
  875. }
  876. #endif
  877. int lcd_init(void)
  878. {
  879. ark_lcd_t *lcd;
  880. uint32_t value;
  881. lcd = (ark_lcd_t *)pvPortMalloc(sizeof(ark_lcd_t));
  882. if(!lcd) {
  883. printf("ERR: %s, malloc failed\n", __func__);
  884. return -ENOMEM;
  885. }
  886. memset(lcd, 0, sizeof(ark_lcd_t));
  887. fb_addr = (uint32_t)fb_queue_init(FB_COUNT, FB_SIZE);
  888. if (!fb_addr) {
  889. vPortFree(lcd);
  890. printf("ERR: %s, fb_queue_init failed\n", __func__);
  891. return -ENOMEM;
  892. }
  893. /* lcd timing init */
  894. lcd->timing.vs_start = 0;
  895. lcd->timing.hs_start = 0;
  896. lcd->timing.hd = LCD_WIDTH;
  897. lcd->timing.vd = LCD_HEIGHT;
  898. lcd->timing.vbp = LCD_TIMING_VBP;
  899. lcd->timing.vfp = LCD_TIMING_VFP;
  900. lcd->timing.vsw = LCD_TIMING_VSW;
  901. lcd->timing.hbp = LCD_TIMING_HBP;
  902. lcd->timing.hfp = LCD_TIMING_HFP;
  903. lcd->timing.hsw = LCD_TIMING_HSW;
  904. //sys_soft_reset(softreset_lcd);
  905. lcd_boot_status = readl(REGS_LCD_BASE+LCD_PARAM0) & 0x1;
  906. if (!lcd_boot_status) {
  907. /* lcd hlock config */
  908. value = (2<<16) | //bit[16:17]: 0:16; 1:32; 2:64(LCD从DDR取数宽度,宽度越大效率越高)
  909. (0xf<<0); //bit[0:12]:hlock size(固定值)
  910. writel(value, REGS_LCD_BASE + LCD_HLOCK_CFG_RG);
  911. ark_lcd_clk_init(LCD_CLK_FREQ);
  912. ark_lcd_timing_init(lcd);
  913. ark_lcd_hw_init();
  914. #if LCD_INTERFACE_TYPE == LCD_INTERFACE_LVDS
  915. value = readl(REGS_SYSCTL_BASE + 0x94);
  916. #if DOUBLE_LVDS_ENABLE
  917. /*lvds config */
  918. value |= (1 << 31); // 0:clk 1/1; 1:clk 1/2 双路lvds需1/2clk
  919. value |= (1 << 30); // TXCLKSELB2
  920. value &= ~(1 << 27); // PWDN1
  921. value |= (1 << 26); // LVDS_GPIO_SEL_1 为1时对应的管脚变为lvds输出
  922. value |= (1 << 25); // EN1
  923. value |= (1 << 24); // BITSEL1
  924. value |= (1 << 22); // TXCLKSELA2
  925. value &= ~(1 << 19); // PWDN0
  926. value |= (1 << 18); // LVDS_GPIO_SEL_0 为1时对应的管脚变为lvds输出
  927. value |= (1 << 17); // EN0
  928. value |= (1 << 16); // BITSEL0
  929. value |= (1 << 3); // LVDS_CH_SEL 为1时使能双通道
  930. #else
  931. /*lvds config */
  932. value &= ~(1 << 31); // 0:clk 1/1; 1:clk 1/2 双路lvds需1/2clk
  933. value |= (1 << 30); // TXCLKSELB2
  934. value |= (1 << 27); // PWDN1 = 1
  935. value &= ~(1 << 26); // LVDS_GPIO_SEL_1 为1时对应的管脚变为lvds输出
  936. value &= ~(1 << 25); // EN1 = 0
  937. value |= (1 << 24); // BITSEL1
  938. value |= (1 << 22); // TXCLKSELA2
  939. value |= (1 << 19); // PWDN0 = 1
  940. value &= ~(1 << 18); // LVDS_GPIO_SEL_0 为1时对应的管脚变为lvds输出
  941. value &= ~(1 << 17); // EN0 = 0
  942. value |= (1 << 16); // BITSEL0
  943. value &= ~(1 << 3); // LVDS_CH_SEL 为1时使能双通道
  944. #if SINGLE_LVDS_CH0_EN
  945. value &= ~(1 << 19); // PWDN0
  946. value |= (1 << 18); // LVDS_GPIO_SEL_0 为1时对应的管脚变为lvds输出
  947. value |= (1 << 17); // EN0
  948. #endif
  949. #if SINGLE_LVDS_CH1_EN
  950. value &= ~(1 << 27); // PWDN1
  951. value |= (1 << 26); // LVDS_GPIO_SEL_1 为1时对应的管脚变为lvds输出
  952. value |= (1 << 25); // EN1
  953. #endif
  954. #endif
  955. #if LVDS_PANEL_FORMAT == LVDS_PANEL_FORMAT_VESA
  956. value &= ~(1 << 1); //LVDS_TI_SEL 0:VESA mode
  957. #else
  958. value |= (1 << 1); //LVDS_TI_SEL 1:JEDIA mode
  959. #endif
  960. #if LVDS_PANEL_DATA == LVDS_PANEL_DATA_8BIT
  961. value &= ~(1 << 0); //LVDS_6BITS_SEL 0:LVDSTXdatamap选择数据8bit
  962. #else
  963. value |= (1 << 0); //LVDS_6BITS_SEL 1:LVDSTXdatamap选择数据6bit
  964. #endif
  965. writel(value , REGS_SYSCTL_BASE + 0x94);
  966. value = readl(REGS_SYSCTL_BASE + 0x98);
  967. value |= (1 << 21); // VREFEB
  968. value |= (1 << 20); // TX_LCK_EN
  969. value |= (1 << 19); // SRSA
  970. //value |= (1 << 15); // PNSWP 时钟极性
  971. value |= (1 << 14); // ICONT2
  972. value |= (1 << 13); // ICONT1
  973. value |= (1 << 12); // ICONT0
  974. value |= (1 << 11); // PLEB
  975. value |= (1 << 10); // CPEB
  976. #if LVDS_CLKEDGE == LVDS_CLKEDGE_NEGATIVE
  977. value |= (1 << 7); // CLKEDGE 输出时钟边沿选择反向
  978. #else
  979. value &= ~(1 << 7); //CLKEDGE 输出时钟边沿选择正向
  980. #endif
  981. value |= (1 << 6); // DRV_TRM_09
  982. value &= ~(0x7<< 3); // TRM_VCM 0.95
  983. value |= 0x4; // TRM_IREF
  984. writel(value , REGS_SYSCTL_BASE + 0x98);
  985. #ifdef AMT630HV160S
  986. pinctrl_set_group(PGRP_PWM1);
  987. pwm_config(PWM_ID1, 25000, 50000);
  988. pwm_enable(PWM_ID1);
  989. #else
  990. pinctrl_set_group(PGRP_PWM5);
  991. pwm_config(PWM_ID5, 25000, 50000);
  992. pwm_enable(PWM_ID5);
  993. //lvds backlight
  994. gpio_direction_output(135, 1);
  995. #endif
  996. #endif
  997. }
  998. lcd->vsync_waitq = xEventGroupCreate();
  999. request_irq(LCD_IRQn, 0, ark_lcd_interrupt, lcd);
  1000. g_lcd = lcd;
  1001. return 0;
  1002. }
  1003. void lcd_uninit(void)
  1004. {
  1005. if(g_lcd) {
  1006. vPortFree(g_lcd);
  1007. g_lcd = NULL;
  1008. }
  1009. }