atmel_hlcdfb.c 15 KB

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