am335x-fb.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2013-2018 Hannes Schmelzer <oe5hpm@oevsv.at>
  4. * B&R Industrial Automation GmbH - http://www.br-automation.com
  5. * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
  6. *
  7. * minimal framebuffer driver for TI's AM335x SoC to be compatible with
  8. * Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c)
  9. *
  10. * - supporting 16/24/32bit RGB/TFT raster Mode (not using palette)
  11. * - sets up LCD controller as in 'am335x_lcdpanel' struct given
  12. * - starts output DMA from gd->fb_base buffer
  13. */
  14. #include <common.h>
  15. #include <dm.h>
  16. #include <lcd.h>
  17. #include <video.h>
  18. #include <asm/arch/clock.h>
  19. #include <asm/arch/hardware.h>
  20. #include <asm/arch/omap.h>
  21. #include <asm/arch/sys_proto.h>
  22. #include <asm/io.h>
  23. #include <asm/utils.h>
  24. #include <linux/err.h>
  25. #include "am335x-fb.h"
  26. #define LCDC_FMAX 200000000
  27. /* LCD Control Register */
  28. #define LCDC_CTRL_CLK_DIVISOR_MASK GENMASK(15, 8)
  29. #define LCDC_CTRL_RASTER_MODE BIT(0)
  30. #define LCDC_CTRL_CLK_DIVISOR(x) (((x) & GENMASK(7, 0)) << 8)
  31. /* LCD Clock Enable Register */
  32. #define LCDC_CLKC_ENABLE_CORECLKEN BIT(0)
  33. #define LCDC_CLKC_ENABLE_LIDDCLKEN BIT(1)
  34. #define LCDC_CLKC_ENABLE_DMACLKEN BIT(2)
  35. /* LCD DMA Control Register */
  36. #define LCDC_DMA_CTRL_BURST_SIZE(x) (((x) & GENMASK(2, 0)) << 4)
  37. #define LCDC_DMA_CTRL_BURST_1 0x0
  38. #define LCDC_DMA_CTRL_BURST_2 0x1
  39. #define LCDC_DMA_CTRL_BURST_4 0x2
  40. #define LCDC_DMA_CTRL_BURST_8 0x3
  41. #define LCDC_DMA_CTRL_BURST_16 0x4
  42. #define LCDC_DMA_CTRL_FIFO_TH(x) (((x) & GENMASK(2, 0)) << 8)
  43. /* LCD Timing_0 Register */
  44. #define LCDC_RASTER_TIMING_0_HORMSB(x) ((((x) - 1) & BIT(10)) >> 7)
  45. #define LCDC_RASTER_TIMING_0_HORLSB(x) (((((x) >> 4) - 1) & GENMASK(5, 0)) << 4)
  46. #define LCDC_RASTER_TIMING_0_HSWLSB(x) ((((x) - 1) & GENMASK(5, 0)) << 10)
  47. #define LCDC_RASTER_TIMING_0_HFPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 16)
  48. #define LCDC_RASTER_TIMING_0_HBPLSB(x) ((((x) - 1) & GENMASK(7, 0)) << 24)
  49. /* LCD Timing_1 Register */
  50. #define LCDC_RASTER_TIMING_1_VERLSB(x) (((x) - 1) & GENMASK(9, 0))
  51. #define LCDC_RASTER_TIMING_1_VSW(x) ((((x) - 1) & GENMASK(5, 0)) << 10)
  52. #define LCDC_RASTER_TIMING_1_VFP(x) (((x) & GENMASK(7, 0)) << 16)
  53. #define LCDC_RASTER_TIMING_1_VBP(x) (((x) & GENMASK(7, 0)) << 24)
  54. /* LCD Timing_2 Register */
  55. #define LCDC_RASTER_TIMING_2_HFPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 8)
  56. #define LCDC_RASTER_TIMING_2_HBPMSB(x) ((((x) - 1) & GENMASK(9, 8)) >> 4)
  57. #define LCDC_RASTER_TIMING_2_ACB(x) (((x) & GENMASK(7, 0)) << 8)
  58. #define LCDC_RASTER_TIMING_2_ACBI(x) (((x) & GENMASK(3, 0)) << 16)
  59. #define LCDC_RASTER_TIMING_2_VSYNC_INVERT BIT(20)
  60. #define LCDC_RASTER_TIMING_2_HSYNC_INVERT BIT(21)
  61. #define LCDC_RASTER_TIMING_2_PXCLK_INVERT BIT(22)
  62. #define LCDC_RASTER_TIMING_2_DE_INVERT BIT(23)
  63. #define LCDC_RASTER_TIMING_2_HSVS_RISEFALL BIT(24)
  64. #define LCDC_RASTER_TIMING_2_HSVS_CONTROL BIT(25)
  65. #define LCDC_RASTER_TIMING_2_VERMSB(x) ((((x) - 1) & BIT(10)) << 16)
  66. #define LCDC_RASTER_TIMING_2_HSWMSB(x) ((((x) - 1) & GENMASK(9, 6)) << 21)
  67. /* LCD Raster Ctrl Register */
  68. #define LCDC_RASTER_CTRL_ENABLE BIT(0)
  69. #define LCDC_RASTER_CTRL_TFT_MODE BIT(7)
  70. #define LCDC_RASTER_CTRL_DATA_ORDER BIT(8)
  71. #define LCDC_RASTER_CTRL_REQDLY(x) (((x) & GENMASK(7, 0)) << 12)
  72. #define LCDC_RASTER_CTRL_PALMODE_RAWDATA (0x02 << 20)
  73. #define LCDC_RASTER_CTRL_TFT_ALT_ENABLE BIT(23)
  74. #define LCDC_RASTER_CTRL_TFT_24BPP_MODE BIT(25)
  75. #define LCDC_RASTER_CTRL_TFT_24BPP_UNPACK BIT(26)
  76. struct am335x_lcdhw {
  77. unsigned int pid; /* 0x00 */
  78. unsigned int ctrl; /* 0x04 */
  79. unsigned int gap0; /* 0x08 */
  80. unsigned int lidd_ctrl; /* 0x0C */
  81. unsigned int lidd_cs0_conf; /* 0x10 */
  82. unsigned int lidd_cs0_addr; /* 0x14 */
  83. unsigned int lidd_cs0_data; /* 0x18 */
  84. unsigned int lidd_cs1_conf; /* 0x1C */
  85. unsigned int lidd_cs1_addr; /* 0x20 */
  86. unsigned int lidd_cs1_data; /* 0x24 */
  87. unsigned int raster_ctrl; /* 0x28 */
  88. unsigned int raster_timing0; /* 0x2C */
  89. unsigned int raster_timing1; /* 0x30 */
  90. unsigned int raster_timing2; /* 0x34 */
  91. unsigned int raster_subpanel; /* 0x38 */
  92. unsigned int raster_subpanel2; /* 0x3C */
  93. unsigned int lcddma_ctrl; /* 0x40 */
  94. unsigned int lcddma_fb0_base; /* 0x44 */
  95. unsigned int lcddma_fb0_ceiling; /* 0x48 */
  96. unsigned int lcddma_fb1_base; /* 0x4C */
  97. unsigned int lcddma_fb1_ceiling; /* 0x50 */
  98. unsigned int sysconfig; /* 0x54 */
  99. unsigned int irqstatus_raw; /* 0x58 */
  100. unsigned int irqstatus; /* 0x5C */
  101. unsigned int irqenable_set; /* 0x60 */
  102. unsigned int irqenable_clear; /* 0x64 */
  103. unsigned int gap1; /* 0x68 */
  104. unsigned int clkc_enable; /* 0x6C */
  105. unsigned int clkc_reset; /* 0x70 */
  106. };
  107. struct dpll_data {
  108. unsigned long rounded_rate;
  109. u16 rounded_m;
  110. u8 rounded_n;
  111. u8 rounded_div;
  112. };
  113. DECLARE_GLOBAL_DATA_PTR;
  114. /**
  115. * am335x_dpll_round_rate() - Round a target rate for an OMAP DPLL
  116. *
  117. * @dpll_data: struct dpll_data pointer for the DPLL
  118. * @rate: New DPLL clock rate
  119. * @return rounded rate and the computed m, n and div values in the dpll_data
  120. * structure, or -ve error code.
  121. */
  122. static ulong am335x_dpll_round_rate(struct dpll_data *dd, ulong rate)
  123. {
  124. unsigned int m, n, d;
  125. unsigned long rounded_rate;
  126. int err, err_r;
  127. dd->rounded_rate = -EFAULT;
  128. err = rate;
  129. err_r = err;
  130. for (d = 2; err && d < 255; d++) {
  131. for (m = 2; m < 2047; m++) {
  132. if ((V_OSCK * m) < (rate * d))
  133. continue;
  134. n = (V_OSCK * m) / (rate * d);
  135. if (n > 127)
  136. break;
  137. if (((V_OSCK * m) / n) > LCDC_FMAX)
  138. break;
  139. rounded_rate = (V_OSCK * m) / n / d;
  140. err = abs(rounded_rate - rate);
  141. if (err < err_r) {
  142. err_r = err;
  143. dd->rounded_rate = rounded_rate;
  144. dd->rounded_m = m;
  145. dd->rounded_n = n;
  146. dd->rounded_div = d;
  147. if (err == 0)
  148. break;
  149. }
  150. }
  151. }
  152. debug("DPLL display: best error %d Hz (M %d, N %d, DIV %d)\n",
  153. err_r, dd->rounded_m, dd->rounded_n, dd->rounded_div);
  154. return dd->rounded_rate;
  155. }
  156. /**
  157. * am335x_fb_set_pixel_clk_rate() - Set pixel clock rate.
  158. *
  159. * @am335x_lcdhw: Base address of the LCD controller registers.
  160. * @rate: New clock rate in Hz.
  161. * @return new rate, or -ve error code.
  162. */
  163. static ulong am335x_fb_set_pixel_clk_rate(struct am335x_lcdhw *regs, ulong rate)
  164. {
  165. struct dpll_params dpll_disp = { 1, 0, 1, -1, -1, -1, -1 };
  166. struct dpll_data dd;
  167. ulong round_rate;
  168. u32 reg;
  169. round_rate = am335x_dpll_round_rate(&dd, rate);
  170. if (IS_ERR_VALUE(round_rate))
  171. return round_rate;
  172. dpll_disp.m = dd.rounded_m;
  173. dpll_disp.n = dd.rounded_n;
  174. do_setup_dpll(&dpll_disp_regs, &dpll_disp);
  175. reg = readl(&regs->ctrl) & ~LCDC_CTRL_CLK_DIVISOR_MASK;
  176. reg |= LCDC_CTRL_CLK_DIVISOR(dd.rounded_div);
  177. writel(reg, &regs->ctrl);
  178. return round_rate;
  179. }
  180. #if !CONFIG_IS_ENABLED(DM_VIDEO)
  181. #if !defined(LCD_CNTL_BASE)
  182. #error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
  183. #endif
  184. /* Macro definitions */
  185. #define FBSIZE(x) (((x)->hactive * (x)->vactive * (x)->bpp) >> 3)
  186. #define LCDC_RASTER_TIMING_2_INVMASK(x) ((x) & GENMASK(25, 20))
  187. static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE;
  188. int lcd_get_size(int *line_length)
  189. {
  190. *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
  191. return *line_length * panel_info.vl_row + 0x20;
  192. }
  193. int am335xfb_init(struct am335x_lcdpanel *panel)
  194. {
  195. u32 raster_ctrl = 0;
  196. struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
  197. ulong rate;
  198. u32 reg;
  199. if (gd->fb_base == 0) {
  200. printf("ERROR: no valid fb_base stored in GLOBAL_DATA_PTR!\n");
  201. return -1;
  202. }
  203. if (panel == NULL) {
  204. printf("ERROR: missing ptr to am335x_lcdpanel!\n");
  205. return -1;
  206. }
  207. /* We can already set the bits for the raster_ctrl in this check */
  208. switch (panel->bpp) {
  209. case 16:
  210. break;
  211. case 32:
  212. raster_ctrl |= LCDC_RASTER_CTRL_TFT_24BPP_UNPACK;
  213. /* fallthrough */
  214. case 24:
  215. raster_ctrl |= LCDC_RASTER_CTRL_TFT_24BPP_MODE;
  216. break;
  217. default:
  218. pr_err("am335x-fb: invalid bpp value: %d\n", panel->bpp);
  219. return -1;
  220. }
  221. /* check given clock-frequency */
  222. if (panel->pxl_clk > (LCDC_FMAX / 2)) {
  223. pr_err("am335x-fb: requested pxl-clk: %d not supported!\n",
  224. panel->pxl_clk);
  225. return -1;
  226. }
  227. debug("setting up LCD-Controller for %dx%dx%d (hfp=%d,hbp=%d,hsw=%d / ",
  228. panel->hactive, panel->vactive, panel->bpp,
  229. panel->hfp, panel->hbp, panel->hsw);
  230. debug("vfp=%d,vbp=%d,vsw=%d / clk=%d)\n",
  231. panel->vfp, panel->vfp, panel->vsw, panel->pxl_clk);
  232. debug("using frambuffer at 0x%08x with size %d.\n",
  233. (unsigned int)gd->fb_base, FBSIZE(panel));
  234. rate = am335x_fb_set_pixel_clk_rate(lcdhw, panel->pxl_clk);
  235. if (IS_ERR_VALUE(rate))
  236. return rate;
  237. /* clock source for LCDC from dispPLL M2 */
  238. writel(0x0, &cmdpll->clklcdcpixelclk);
  239. /* palette default entry */
  240. memset((void *)gd->fb_base, 0, 0x20);
  241. *(unsigned int *)gd->fb_base = 0x4000;
  242. /* point fb behind palette */
  243. gd->fb_base += 0x20;
  244. /* turn ON display through powercontrol function if accessible */
  245. if (panel->panel_power_ctrl != NULL)
  246. panel->panel_power_ctrl(1);
  247. debug("am335x-fb: wait for stable power ...\n");
  248. mdelay(panel->pup_delay);
  249. lcdhw->clkc_enable = LCDC_CLKC_ENABLE_CORECLKEN |
  250. LCDC_CLKC_ENABLE_LIDDCLKEN | LCDC_CLKC_ENABLE_DMACLKEN;
  251. lcdhw->raster_ctrl = 0;
  252. reg = lcdhw->ctrl & LCDC_CTRL_CLK_DIVISOR_MASK;
  253. reg |= LCDC_CTRL_RASTER_MODE;
  254. lcdhw->ctrl = reg;
  255. lcdhw->lcddma_fb0_base = gd->fb_base;
  256. lcdhw->lcddma_fb0_ceiling = gd->fb_base + FBSIZE(panel);
  257. lcdhw->lcddma_fb1_base = gd->fb_base;
  258. lcdhw->lcddma_fb1_ceiling = gd->fb_base + FBSIZE(panel);
  259. lcdhw->lcddma_ctrl = LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16);
  260. lcdhw->raster_timing0 = LCDC_RASTER_TIMING_0_HORLSB(panel->hactive) |
  261. LCDC_RASTER_TIMING_0_HORMSB(panel->hactive) |
  262. LCDC_RASTER_TIMING_0_HFPLSB(panel->hfp) |
  263. LCDC_RASTER_TIMING_0_HBPLSB(panel->hbp) |
  264. LCDC_RASTER_TIMING_0_HSWLSB(panel->hsw);
  265. lcdhw->raster_timing1 = LCDC_RASTER_TIMING_1_VBP(panel->vbp) |
  266. LCDC_RASTER_TIMING_1_VFP(panel->vfp) |
  267. LCDC_RASTER_TIMING_1_VSW(panel->vsw) |
  268. LCDC_RASTER_TIMING_1_VERLSB(panel->vactive);
  269. lcdhw->raster_timing2 = LCDC_RASTER_TIMING_2_HSWMSB(panel->hsw) |
  270. LCDC_RASTER_TIMING_2_VERMSB(panel->vactive) |
  271. LCDC_RASTER_TIMING_2_INVMASK(panel->pol) |
  272. LCDC_RASTER_TIMING_2_HBPMSB(panel->hbp) |
  273. LCDC_RASTER_TIMING_2_HFPMSB(panel->hfp) |
  274. 0x0000FF00; /* clk cycles for ac-bias */
  275. lcdhw->raster_ctrl = raster_ctrl |
  276. LCDC_RASTER_CTRL_PALMODE_RAWDATA |
  277. LCDC_RASTER_CTRL_TFT_MODE |
  278. LCDC_RASTER_CTRL_ENABLE;
  279. debug("am335x-fb: waiting picture to be stable.\n.");
  280. mdelay(panel->pon_delay);
  281. return 0;
  282. }
  283. #else /* CONFIG_DM_VIDEO */
  284. #define FBSIZE(t, p) (((t)->hactive.typ * (t)->vactive.typ * (p)->bpp) >> 3)
  285. enum {
  286. LCD_MAX_WIDTH = 2048,
  287. LCD_MAX_HEIGHT = 2048,
  288. LCD_MAX_LOG2_BPP = VIDEO_BPP32,
  289. };
  290. /**
  291. * tilcdc_panel_info: Panel parameters
  292. *
  293. * @ac_bias: AC Bias Pin Frequency
  294. * @ac_bias_intrpt: AC Bias Pin Transitions per Interrupt
  295. * @dma_burst_sz: DMA burst size
  296. * @bpp: Bits per pixel
  297. * @fdd: FIFO DMA Request Delay
  298. * @tft_alt_mode: TFT Alternative Signal Mapping (Only for active)
  299. * @invert_pxl_clk: Invert pixel clock
  300. * @sync_edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling
  301. * @sync_ctrl: Horizontal and Vertical Sync: Control: 0=ignore
  302. * @raster_order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most
  303. * @fifo_th: DMA FIFO threshold
  304. */
  305. struct tilcdc_panel_info {
  306. u32 ac_bias;
  307. u32 ac_bias_intrpt;
  308. u32 dma_burst_sz;
  309. u32 bpp;
  310. u32 fdd;
  311. bool tft_alt_mode;
  312. bool invert_pxl_clk;
  313. u32 sync_edge;
  314. u32 sync_ctrl;
  315. u32 raster_order;
  316. u32 fifo_th;
  317. };
  318. struct am335x_fb_priv {
  319. struct am335x_lcdhw *regs;
  320. struct tilcdc_panel_info panel;
  321. struct display_timing timing;
  322. };
  323. static int am335x_fb_remove(struct udevice *dev)
  324. {
  325. struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  326. uc_plat->base -= 0x20;
  327. uc_plat->size += 0x20;
  328. return 0;
  329. }
  330. static int am335x_fb_probe(struct udevice *dev)
  331. {
  332. struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  333. struct video_priv *uc_priv = dev_get_uclass_priv(dev);
  334. struct am335x_fb_priv *priv = dev_get_priv(dev);
  335. struct am335x_lcdhw *regs = priv->regs;
  336. struct tilcdc_panel_info *panel = &priv->panel;
  337. struct display_timing *timing = &priv->timing;
  338. struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
  339. u32 reg;
  340. /* Before relocation we don't need to do anything */
  341. if (!(gd->flags & GD_FLG_RELOC))
  342. return 0;
  343. am335x_fb_set_pixel_clk_rate(regs, timing->pixelclock.typ);
  344. /* clock source for LCDC from dispPLL M2 */
  345. writel(0, &cmdpll->clklcdcpixelclk);
  346. /* palette default entry */
  347. memset((void *)uc_plat->base, 0, 0x20);
  348. *(unsigned int *)uc_plat->base = 0x4000;
  349. /* point fb behind palette */
  350. uc_plat->base += 0x20;
  351. uc_plat->size -= 0x20;
  352. writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN |
  353. LCDC_CLKC_ENABLE_DMACLKEN, &regs->clkc_enable);
  354. writel(0, &regs->raster_ctrl);
  355. reg = readl(&regs->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK;
  356. reg |= LCDC_CTRL_RASTER_MODE;
  357. writel(reg, &regs->ctrl);
  358. writel(uc_plat->base, &regs->lcddma_fb0_base);
  359. writel(uc_plat->base + FBSIZE(timing, panel),
  360. &regs->lcddma_fb0_ceiling);
  361. writel(uc_plat->base, &regs->lcddma_fb1_base);
  362. writel(uc_plat->base + FBSIZE(timing, panel),
  363. &regs->lcddma_fb1_ceiling);
  364. reg = LCDC_DMA_CTRL_FIFO_TH(panel->fifo_th);
  365. switch (panel->dma_burst_sz) {
  366. case 1:
  367. reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1);
  368. break;
  369. case 2:
  370. reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2);
  371. break;
  372. case 4:
  373. reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4);
  374. break;
  375. case 8:
  376. reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8);
  377. break;
  378. case 16:
  379. reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16);
  380. break;
  381. }
  382. writel(reg, &regs->lcddma_ctrl);
  383. writel(LCDC_RASTER_TIMING_0_HORLSB(timing->hactive.typ) |
  384. LCDC_RASTER_TIMING_0_HORMSB(timing->hactive.typ) |
  385. LCDC_RASTER_TIMING_0_HFPLSB(timing->hfront_porch.typ) |
  386. LCDC_RASTER_TIMING_0_HBPLSB(timing->hback_porch.typ) |
  387. LCDC_RASTER_TIMING_0_HSWLSB(timing->hsync_len.typ),
  388. &regs->raster_timing0);
  389. writel(LCDC_RASTER_TIMING_1_VBP(timing->vback_porch.typ) |
  390. LCDC_RASTER_TIMING_1_VFP(timing->vfront_porch.typ) |
  391. LCDC_RASTER_TIMING_1_VSW(timing->vsync_len.typ) |
  392. LCDC_RASTER_TIMING_1_VERLSB(timing->vactive.typ),
  393. &regs->raster_timing1);
  394. reg = LCDC_RASTER_TIMING_2_ACB(panel->ac_bias) |
  395. LCDC_RASTER_TIMING_2_ACBI(panel->ac_bias_intrpt) |
  396. LCDC_RASTER_TIMING_2_HSWMSB(timing->hsync_len.typ) |
  397. LCDC_RASTER_TIMING_2_VERMSB(timing->vactive.typ) |
  398. LCDC_RASTER_TIMING_2_HBPMSB(timing->hback_porch.typ) |
  399. LCDC_RASTER_TIMING_2_HFPMSB(timing->hfront_porch.typ);
  400. if (timing->flags & DISPLAY_FLAGS_VSYNC_LOW)
  401. reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT;
  402. if (timing->flags & DISPLAY_FLAGS_HSYNC_LOW)
  403. reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT;
  404. if (panel->invert_pxl_clk)
  405. reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT;
  406. if (panel->sync_edge)
  407. reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL;
  408. if (panel->sync_ctrl)
  409. reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL;
  410. writel(reg, &regs->raster_timing2);
  411. reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE |
  412. LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(panel->fdd);
  413. if (panel->tft_alt_mode)
  414. reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE;
  415. if (panel->bpp == 24)
  416. reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE;
  417. else if (panel->bpp == 32)
  418. reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE |
  419. LCDC_RASTER_CTRL_TFT_24BPP_UNPACK;
  420. if (panel->raster_order)
  421. reg |= LCDC_RASTER_CTRL_DATA_ORDER;
  422. writel(reg, &regs->raster_ctrl);
  423. uc_priv->xsize = timing->hactive.typ;
  424. uc_priv->ysize = timing->vactive.typ;
  425. uc_priv->bpix = log_2_n_round_up(panel->bpp);
  426. return 0;
  427. }
  428. static int am335x_fb_ofdata_to_platdata(struct udevice *dev)
  429. {
  430. struct am335x_fb_priv *priv = dev_get_priv(dev);
  431. struct tilcdc_panel_info *panel = &priv->panel;
  432. struct display_timing *timing = &priv->timing;
  433. ofnode node;
  434. int err;
  435. node = ofnode_by_compatible(ofnode_null(), "ti,am33xx-tilcdc");
  436. if (!ofnode_valid(node)) {
  437. dev_err(dev, "missing 'ti,am33xx-tilcdc' node\n");
  438. return -ENXIO;
  439. }
  440. priv->regs = (struct am335x_lcdhw *)ofnode_get_addr(node);
  441. dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs);
  442. err = ofnode_decode_display_timing(dev_ofnode(dev), 0, timing);
  443. if (err) {
  444. dev_err(dev, "failed to get display timing\n");
  445. return err;
  446. }
  447. if (timing->pixelclock.typ > (LCDC_FMAX / 2)) {
  448. dev_err(dev, "invalid display clock-frequency: %d Hz\n",
  449. timing->pixelclock.typ);
  450. return -EINVAL;
  451. }
  452. if (timing->hactive.typ > LCD_MAX_WIDTH)
  453. timing->hactive.typ = LCD_MAX_WIDTH;
  454. if (timing->vactive.typ > LCD_MAX_HEIGHT)
  455. timing->vactive.typ = LCD_MAX_HEIGHT;
  456. node = ofnode_find_subnode(dev_ofnode(dev), "panel-info");
  457. if (!ofnode_valid(node)) {
  458. dev_err(dev, "missing 'panel-info' node\n");
  459. return -ENXIO;
  460. }
  461. err |= ofnode_read_u32(node, "ac-bias", &panel->ac_bias);
  462. err |= ofnode_read_u32(node, "ac-bias-intrpt", &panel->ac_bias_intrpt);
  463. err |= ofnode_read_u32(node, "dma-burst-sz", &panel->dma_burst_sz);
  464. err |= ofnode_read_u32(node, "bpp", &panel->bpp);
  465. err |= ofnode_read_u32(node, "fdd", &panel->fdd);
  466. err |= ofnode_read_u32(node, "sync-edge", &panel->sync_edge);
  467. err |= ofnode_read_u32(node, "sync-ctrl", &panel->sync_ctrl);
  468. err |= ofnode_read_u32(node, "raster-order", &panel->raster_order);
  469. err |= ofnode_read_u32(node, "fifo-th", &panel->fifo_th);
  470. if (err) {
  471. dev_err(dev, "failed to get panel info\n");
  472. return err;
  473. }
  474. switch (panel->bpp) {
  475. case 16:
  476. case 24:
  477. case 32:
  478. break;
  479. default:
  480. dev_err(dev, "invalid seting, bpp: %d\n", panel->bpp);
  481. return -EINVAL;
  482. }
  483. switch (panel->dma_burst_sz) {
  484. case 1:
  485. case 2:
  486. case 4:
  487. case 8:
  488. case 16:
  489. break;
  490. default:
  491. dev_err(dev, "invalid setting, dma-burst-sz: %d\n",
  492. panel->dma_burst_sz);
  493. return -EINVAL;
  494. }
  495. /* optional */
  496. panel->tft_alt_mode = ofnode_read_bool(node, "tft-alt-mode");
  497. panel->invert_pxl_clk = ofnode_read_bool(node, "invert-pxl-clk");
  498. dev_dbg(dev, "LCD: %dx%d, bpp=%d, clk=%d Hz\n", timing->hactive.typ,
  499. timing->vactive.typ, panel->bpp, timing->pixelclock.typ);
  500. dev_dbg(dev, " hbp=%d, hfp=%d, hsw=%d\n", timing->hback_porch.typ,
  501. timing->hfront_porch.typ, timing->hsync_len.typ);
  502. dev_dbg(dev, " vbp=%d, vfp=%d, vsw=%d\n", timing->vback_porch.typ,
  503. timing->vfront_porch.typ, timing->vsync_len.typ);
  504. return 0;
  505. }
  506. static int am335x_fb_bind(struct udevice *dev)
  507. {
  508. struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  509. uc_plat->size = ((LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
  510. (1 << LCD_MAX_LOG2_BPP)) >> 3) + 0x20;
  511. dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size);
  512. return 0;
  513. }
  514. static const struct udevice_id am335x_fb_ids[] = {
  515. { .compatible = "ti,tilcdc,panel" },
  516. { }
  517. };
  518. U_BOOT_DRIVER(am335x_fb) = {
  519. .name = "am335x_fb",
  520. .id = UCLASS_VIDEO,
  521. .of_match = am335x_fb_ids,
  522. .bind = am335x_fb_bind,
  523. .ofdata_to_platdata = am335x_fb_ofdata_to_platdata,
  524. .probe = am335x_fb_probe,
  525. .remove = am335x_fb_remove,
  526. .priv_auto_alloc_size = sizeof(struct am335x_fb_priv),
  527. };
  528. #endif /* CONFIG_DM_VIDEO */