atmel_hlcdfb.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Driver for AT91/AT32 MULTI LAYER LCD Controller
  4. *
  5. * Copyright (C) 2012 Atmel Corporation
  6. */
  7. #include <common.h>
  8. #include <asm/io.h>
  9. #include <asm/arch/gpio.h>
  10. #include <asm/arch/clk.h>
  11. #include <clk.h>
  12. #include <dm.h>
  13. #include <fdtdec.h>
  14. #include <lcd.h>
  15. #include <video.h>
  16. #include <wait_bit.h>
  17. #include <atmel_hlcdc.h>
  18. #if defined(CONFIG_LCD_LOGO)
  19. #include <bmp_logo.h>
  20. #endif
  21. DECLARE_GLOBAL_DATA_PTR;
  22. #ifndef CONFIG_DM_VIDEO
  23. /* configurable parameters */
  24. #define ATMEL_LCDC_CVAL_DEFAULT 0xc8
  25. #define ATMEL_LCDC_DMA_BURST_LEN 8
  26. #ifndef ATMEL_LCDC_GUARD_TIME
  27. #define ATMEL_LCDC_GUARD_TIME 1
  28. #endif
  29. #define ATMEL_LCDC_FIFO_SIZE 512
  30. /*
  31. * the CLUT register map as following
  32. * RCLUT(24 ~ 16), GCLUT(15 ~ 8), BCLUT(7 ~ 0)
  33. */
  34. void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
  35. {
  36. writel(panel_info.mmio + ATMEL_LCDC_LUT(regno),
  37. ((red << LCDC_BASECLUT_RCLUT_Pos) & LCDC_BASECLUT_RCLUT_Msk)
  38. | ((green << LCDC_BASECLUT_GCLUT_Pos) & LCDC_BASECLUT_GCLUT_Msk)
  39. | ((blue << LCDC_BASECLUT_BCLUT_Pos) & LCDC_BASECLUT_BCLUT_Msk));
  40. }
  41. ushort *configuration_get_cmap(void)
  42. {
  43. #if defined(CONFIG_LCD_LOGO)
  44. return bmp_logo_palette;
  45. #else
  46. return NULL;
  47. #endif
  48. }
  49. void lcd_ctrl_init(void *lcdbase)
  50. {
  51. unsigned long value;
  52. struct lcd_dma_desc *desc;
  53. struct atmel_hlcd_regs *regs;
  54. int ret;
  55. if (!has_lcdc())
  56. return; /* No lcdc */
  57. regs = (struct atmel_hlcd_regs *)panel_info.mmio;
  58. /* Disable DISP signal */
  59. writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
  60. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
  61. false, 1000, false);
  62. if (ret)
  63. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  64. /* Disable synchronization */
  65. writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
  66. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
  67. false, 1000, false);
  68. if (ret)
  69. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  70. /* Disable pixel clock */
  71. writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
  72. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
  73. false, 1000, false);
  74. if (ret)
  75. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  76. /* Disable PWM */
  77. writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
  78. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
  79. false, 1000, false);
  80. if (ret)
  81. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  82. /* Set pixel clock */
  83. value = get_lcdc_clk_rate(0) / panel_info.vl_clk;
  84. if (get_lcdc_clk_rate(0) % panel_info.vl_clk)
  85. value++;
  86. if (value < 1) {
  87. /* Using system clock as pixel clock */
  88. writel(LCDC_LCDCFG0_CLKDIV(0)
  89. | LCDC_LCDCFG0_CGDISHCR
  90. | LCDC_LCDCFG0_CGDISHEO
  91. | LCDC_LCDCFG0_CGDISOVR1
  92. | LCDC_LCDCFG0_CGDISBASE
  93. | panel_info.vl_clk_pol
  94. | LCDC_LCDCFG0_CLKSEL,
  95. &regs->lcdc_lcdcfg0);
  96. } else {
  97. writel(LCDC_LCDCFG0_CLKDIV(value - 2)
  98. | LCDC_LCDCFG0_CGDISHCR
  99. | LCDC_LCDCFG0_CGDISHEO
  100. | LCDC_LCDCFG0_CGDISOVR1
  101. | LCDC_LCDCFG0_CGDISBASE
  102. | panel_info.vl_clk_pol,
  103. &regs->lcdc_lcdcfg0);
  104. }
  105. /* Initialize control register 5 */
  106. value = 0;
  107. value |= panel_info.vl_sync;
  108. #ifndef LCD_OUTPUT_BPP
  109. /* Output is 24bpp */
  110. value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
  111. #else
  112. switch (LCD_OUTPUT_BPP) {
  113. case 12:
  114. value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
  115. break;
  116. case 16:
  117. value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP;
  118. break;
  119. case 18:
  120. value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP;
  121. break;
  122. case 24:
  123. value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
  124. break;
  125. default:
  126. BUG();
  127. break;
  128. }
  129. #endif
  130. value |= LCDC_LCDCFG5_GUARDTIME(ATMEL_LCDC_GUARD_TIME);
  131. value |= (LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS);
  132. writel(value, &regs->lcdc_lcdcfg5);
  133. /* Vertical & Horizontal Timing */
  134. value = LCDC_LCDCFG1_VSPW(panel_info.vl_vsync_len - 1);
  135. value |= LCDC_LCDCFG1_HSPW(panel_info.vl_hsync_len - 1);
  136. writel(value, &regs->lcdc_lcdcfg1);
  137. value = LCDC_LCDCFG2_VBPW(panel_info.vl_upper_margin);
  138. value |= LCDC_LCDCFG2_VFPW(panel_info.vl_lower_margin - 1);
  139. writel(value, &regs->lcdc_lcdcfg2);
  140. value = LCDC_LCDCFG3_HBPW(panel_info.vl_left_margin - 1);
  141. value |= LCDC_LCDCFG3_HFPW(panel_info.vl_right_margin - 1);
  142. writel(value, &regs->lcdc_lcdcfg3);
  143. /* Display size */
  144. value = LCDC_LCDCFG4_RPF(panel_info.vl_row - 1);
  145. value |= LCDC_LCDCFG4_PPL(panel_info.vl_col - 1);
  146. writel(value, &regs->lcdc_lcdcfg4);
  147. writel(LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO,
  148. &regs->lcdc_basecfg0);
  149. switch (NBITS(panel_info.vl_bpix)) {
  150. case 16:
  151. writel(LCDC_BASECFG1_RGBMODE_16BPP_RGB_565,
  152. &regs->lcdc_basecfg1);
  153. break;
  154. case 32:
  155. writel(LCDC_BASECFG1_RGBMODE_24BPP_RGB_888,
  156. &regs->lcdc_basecfg1);
  157. break;
  158. default:
  159. BUG();
  160. break;
  161. }
  162. writel(LCDC_BASECFG2_XSTRIDE(0), &regs->lcdc_basecfg2);
  163. writel(0, &regs->lcdc_basecfg3);
  164. writel(LCDC_BASECFG4_DMA, &regs->lcdc_basecfg4);
  165. /* Disable all interrupts */
  166. writel(~0UL, &regs->lcdc_lcdidr);
  167. writel(~0UL, &regs->lcdc_baseidr);
  168. /* Setup the DMA descriptor, this descriptor will loop to itself */
  169. desc = (struct lcd_dma_desc *)(lcdbase - 16);
  170. desc->address = (u32)lcdbase;
  171. /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
  172. desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
  173. | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
  174. desc->next = (u32)desc;
  175. /* Flush the DMA descriptor if we enabled dcache */
  176. flush_dcache_range((u32)desc, (u32)desc + sizeof(*desc));
  177. writel(desc->address, &regs->lcdc_baseaddr);
  178. writel(desc->control, &regs->lcdc_basectrl);
  179. writel(desc->next, &regs->lcdc_basenext);
  180. writel(LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN,
  181. &regs->lcdc_basecher);
  182. /* Enable LCD */
  183. value = readl(&regs->lcdc_lcden);
  184. writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
  185. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
  186. true, 1000, false);
  187. if (ret)
  188. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  189. value = readl(&regs->lcdc_lcden);
  190. writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
  191. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
  192. true, 1000, false);
  193. if (ret)
  194. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  195. value = readl(&regs->lcdc_lcden);
  196. writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
  197. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
  198. true, 1000, false);
  199. if (ret)
  200. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  201. value = readl(&regs->lcdc_lcden);
  202. writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
  203. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
  204. true, 1000, false);
  205. if (ret)
  206. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  207. /* Enable flushing if we enabled dcache */
  208. lcd_set_flush_dcache(1);
  209. }
  210. #else
  211. enum {
  212. LCD_MAX_WIDTH = 1024,
  213. LCD_MAX_HEIGHT = 768,
  214. LCD_MAX_LOG2_BPP = VIDEO_BPP16,
  215. };
  216. struct atmel_hlcdc_priv {
  217. struct atmel_hlcd_regs *regs;
  218. struct display_timing timing;
  219. unsigned int vl_bpix;
  220. unsigned int output_mode;
  221. unsigned int guard_time;
  222. ulong clk_rate;
  223. };
  224. static int at91_hlcdc_enable_clk(struct udevice *dev)
  225. {
  226. struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
  227. struct clk clk;
  228. ulong clk_rate;
  229. int ret;
  230. ret = clk_get_by_index(dev, 0, &clk);
  231. if (ret)
  232. return -EINVAL;
  233. ret = clk_enable(&clk);
  234. if (ret)
  235. return ret;
  236. clk_rate = clk_get_rate(&clk);
  237. if (!clk_rate) {
  238. clk_disable(&clk);
  239. return -ENODEV;
  240. }
  241. priv->clk_rate = clk_rate;
  242. clk_free(&clk);
  243. return 0;
  244. }
  245. static void atmel_hlcdc_init(struct udevice *dev)
  246. {
  247. struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  248. struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
  249. struct atmel_hlcd_regs *regs = priv->regs;
  250. struct display_timing *timing = &priv->timing;
  251. struct lcd_dma_desc *desc;
  252. unsigned long value, vl_clk_pol;
  253. int ret;
  254. /* Disable DISP signal */
  255. writel(LCDC_LCDDIS_DISPDIS, &regs->lcdc_lcddis);
  256. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
  257. false, 1000, false);
  258. if (ret)
  259. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  260. /* Disable synchronization */
  261. writel(LCDC_LCDDIS_SYNCDIS, &regs->lcdc_lcddis);
  262. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
  263. false, 1000, false);
  264. if (ret)
  265. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  266. /* Disable pixel clock */
  267. writel(LCDC_LCDDIS_CLKDIS, &regs->lcdc_lcddis);
  268. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
  269. false, 1000, false);
  270. if (ret)
  271. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  272. /* Disable PWM */
  273. writel(LCDC_LCDDIS_PWMDIS, &regs->lcdc_lcddis);
  274. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
  275. false, 1000, false);
  276. if (ret)
  277. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  278. /* Set pixel clock */
  279. value = priv->clk_rate / timing->pixelclock.typ;
  280. if (priv->clk_rate % timing->pixelclock.typ)
  281. value++;
  282. vl_clk_pol = 0;
  283. if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
  284. vl_clk_pol = LCDC_LCDCFG0_CLKPOL;
  285. if (value < 1) {
  286. /* Using system clock as pixel clock */
  287. writel(LCDC_LCDCFG0_CLKDIV(0)
  288. | LCDC_LCDCFG0_CGDISHCR
  289. | LCDC_LCDCFG0_CGDISHEO
  290. | LCDC_LCDCFG0_CGDISOVR1
  291. | LCDC_LCDCFG0_CGDISBASE
  292. | vl_clk_pol
  293. | LCDC_LCDCFG0_CLKSEL,
  294. &regs->lcdc_lcdcfg0);
  295. } else {
  296. writel(LCDC_LCDCFG0_CLKDIV(value - 2)
  297. | LCDC_LCDCFG0_CGDISHCR
  298. | LCDC_LCDCFG0_CGDISHEO
  299. | LCDC_LCDCFG0_CGDISOVR1
  300. | LCDC_LCDCFG0_CGDISBASE
  301. | vl_clk_pol,
  302. &regs->lcdc_lcdcfg0);
  303. }
  304. /* Initialize control register 5 */
  305. value = 0;
  306. if (!(timing->flags & DISPLAY_FLAGS_HSYNC_HIGH))
  307. value |= LCDC_LCDCFG5_HSPOL;
  308. if (!(timing->flags & DISPLAY_FLAGS_VSYNC_HIGH))
  309. value |= LCDC_LCDCFG5_VSPOL;
  310. switch (priv->output_mode) {
  311. case 12:
  312. value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP;
  313. break;
  314. case 16:
  315. value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP;
  316. break;
  317. case 18:
  318. value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP;
  319. break;
  320. case 24:
  321. value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP;
  322. break;
  323. default:
  324. BUG();
  325. break;
  326. }
  327. value |= LCDC_LCDCFG5_GUARDTIME(priv->guard_time);
  328. value |= (LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS);
  329. writel(value, &regs->lcdc_lcdcfg5);
  330. /* Vertical & Horizontal Timing */
  331. value = LCDC_LCDCFG1_VSPW(timing->vsync_len.typ - 1);
  332. value |= LCDC_LCDCFG1_HSPW(timing->hsync_len.typ - 1);
  333. writel(value, &regs->lcdc_lcdcfg1);
  334. value = LCDC_LCDCFG2_VBPW(timing->vback_porch.typ);
  335. value |= LCDC_LCDCFG2_VFPW(timing->vfront_porch.typ - 1);
  336. writel(value, &regs->lcdc_lcdcfg2);
  337. value = LCDC_LCDCFG3_HBPW(timing->hback_porch.typ - 1);
  338. value |= LCDC_LCDCFG3_HFPW(timing->hfront_porch.typ - 1);
  339. writel(value, &regs->lcdc_lcdcfg3);
  340. /* Display size */
  341. value = LCDC_LCDCFG4_RPF(timing->vactive.typ - 1);
  342. value |= LCDC_LCDCFG4_PPL(timing->hactive.typ - 1);
  343. writel(value, &regs->lcdc_lcdcfg4);
  344. writel(LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO,
  345. &regs->lcdc_basecfg0);
  346. switch (VNBITS(priv->vl_bpix)) {
  347. case 16:
  348. writel(LCDC_BASECFG1_RGBMODE_16BPP_RGB_565,
  349. &regs->lcdc_basecfg1);
  350. break;
  351. case 32:
  352. writel(LCDC_BASECFG1_RGBMODE_24BPP_RGB_888,
  353. &regs->lcdc_basecfg1);
  354. break;
  355. default:
  356. BUG();
  357. break;
  358. }
  359. writel(LCDC_BASECFG2_XSTRIDE(0), &regs->lcdc_basecfg2);
  360. writel(0, &regs->lcdc_basecfg3);
  361. writel(LCDC_BASECFG4_DMA, &regs->lcdc_basecfg4);
  362. /* Disable all interrupts */
  363. writel(~0UL, &regs->lcdc_lcdidr);
  364. writel(~0UL, &regs->lcdc_baseidr);
  365. /* Setup the DMA descriptor, this descriptor will loop to itself */
  366. desc = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*desc));
  367. if (!desc)
  368. return;
  369. desc->address = (u32)uc_plat->base;
  370. /* Disable DMA transfer interrupt & descriptor loaded interrupt. */
  371. desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN
  372. | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH;
  373. desc->next = (u32)desc;
  374. /* Flush the DMA descriptor if we enabled dcache */
  375. flush_dcache_range((u32)desc,
  376. ALIGN(((u32)desc + sizeof(*desc)),
  377. CONFIG_SYS_CACHELINE_SIZE));
  378. writel(desc->address, &regs->lcdc_baseaddr);
  379. writel(desc->control, &regs->lcdc_basectrl);
  380. writel(desc->next, &regs->lcdc_basenext);
  381. writel(LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN,
  382. &regs->lcdc_basecher);
  383. /* Enable LCD */
  384. value = readl(&regs->lcdc_lcden);
  385. writel(value | LCDC_LCDEN_CLKEN, &regs->lcdc_lcden);
  386. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_CLKSTS,
  387. true, 1000, false);
  388. if (ret)
  389. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  390. value = readl(&regs->lcdc_lcden);
  391. writel(value | LCDC_LCDEN_SYNCEN, &regs->lcdc_lcden);
  392. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_LCDSTS,
  393. true, 1000, false);
  394. if (ret)
  395. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  396. value = readl(&regs->lcdc_lcden);
  397. writel(value | LCDC_LCDEN_DISPEN, &regs->lcdc_lcden);
  398. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_DISPSTS,
  399. true, 1000, false);
  400. if (ret)
  401. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  402. value = readl(&regs->lcdc_lcden);
  403. writel(value | LCDC_LCDEN_PWMEN, &regs->lcdc_lcden);
  404. ret = wait_for_bit_le32(&regs->lcdc_lcdsr, LCDC_LCDSR_PWMSTS,
  405. true, 1000, false);
  406. if (ret)
  407. printf("%s: %d: Timeout!\n", __func__, __LINE__);
  408. }
  409. static int atmel_hlcdc_probe(struct udevice *dev)
  410. {
  411. struct video_priv *uc_priv = dev_get_uclass_priv(dev);
  412. struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
  413. int ret;
  414. ret = at91_hlcdc_enable_clk(dev);
  415. if (ret)
  416. return ret;
  417. atmel_hlcdc_init(dev);
  418. uc_priv->xsize = priv->timing.hactive.typ;
  419. uc_priv->ysize = priv->timing.vactive.typ;
  420. uc_priv->bpix = priv->vl_bpix;
  421. /* Enable flushing if we enabled dcache */
  422. video_set_flush_dcache(dev, true);
  423. return 0;
  424. }
  425. static int atmel_hlcdc_ofdata_to_platdata(struct udevice *dev)
  426. {
  427. struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
  428. const void *blob = gd->fdt_blob;
  429. int node = dev_of_offset(dev);
  430. priv->regs = (struct atmel_hlcd_regs *)devfdt_get_addr(dev);
  431. if (!priv->regs) {
  432. debug("%s: No display controller address\n", __func__);
  433. return -EINVAL;
  434. }
  435. if (fdtdec_decode_display_timing(blob, dev_of_offset(dev),
  436. 0, &priv->timing)) {
  437. debug("%s: Failed to decode display timing\n", __func__);
  438. return -EINVAL;
  439. }
  440. if (priv->timing.hactive.typ > LCD_MAX_WIDTH)
  441. priv->timing.hactive.typ = LCD_MAX_WIDTH;
  442. if (priv->timing.vactive.typ > LCD_MAX_HEIGHT)
  443. priv->timing.vactive.typ = LCD_MAX_HEIGHT;
  444. priv->vl_bpix = fdtdec_get_int(blob, node, "atmel,vl-bpix", 0);
  445. if (!priv->vl_bpix) {
  446. debug("%s: Failed to get bits per pixel\n", __func__);
  447. return -EINVAL;
  448. }
  449. priv->output_mode = fdtdec_get_int(blob, node, "atmel,output-mode", 24);
  450. priv->guard_time = fdtdec_get_int(blob, node, "atmel,guard-time", 1);
  451. return 0;
  452. }
  453. static int atmel_hlcdc_bind(struct udevice *dev)
  454. {
  455. struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  456. uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
  457. (1 << LCD_MAX_LOG2_BPP) / 8;
  458. debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
  459. return 0;
  460. }
  461. static const struct udevice_id atmel_hlcdc_ids[] = {
  462. { .compatible = "atmel,sama5d2-hlcdc" },
  463. { .compatible = "atmel,at91sam9x5-hlcdc" },
  464. { }
  465. };
  466. U_BOOT_DRIVER(atmel_hlcdfb) = {
  467. .name = "atmel_hlcdfb",
  468. .id = UCLASS_VIDEO,
  469. .of_match = atmel_hlcdc_ids,
  470. .bind = atmel_hlcdc_bind,
  471. .probe = atmel_hlcdc_probe,
  472. .ofdata_to_platdata = atmel_hlcdc_ofdata_to_platdata,
  473. .priv_auto_alloc_size = sizeof(struct atmel_hlcdc_priv),
  474. };
  475. #endif