sunxi_display.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
  1. /*
  2. * Display driver for Allwinner SoCs.
  3. *
  4. * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
  5. * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <common.h>
  10. #include <asm/arch/clock.h>
  11. #include <asm/arch/display.h>
  12. #include <asm/arch/gpio.h>
  13. #include <asm/arch/pwm.h>
  14. #include <asm/global_data.h>
  15. #include <asm/gpio.h>
  16. #include <asm/io.h>
  17. #include <axp_pmic.h>
  18. #include <errno.h>
  19. #include <fdtdec.h>
  20. #include <fdt_support.h>
  21. #include <i2c.h>
  22. #include <malloc.h>
  23. #include <video_fb.h>
  24. #include "videomodes.h"
  25. #include "anx9804.h"
  26. #include "hitachi_tx18d42vm_lcd.h"
  27. #include "ssd2828.h"
  28. #ifdef CONFIG_VIDEO_LCD_BL_PWM_ACTIVE_LOW
  29. #define PWM_ON 0
  30. #define PWM_OFF 1
  31. #else
  32. #define PWM_ON 1
  33. #define PWM_OFF 0
  34. #endif
  35. DECLARE_GLOBAL_DATA_PTR;
  36. enum sunxi_monitor {
  37. sunxi_monitor_none,
  38. sunxi_monitor_dvi,
  39. sunxi_monitor_hdmi,
  40. sunxi_monitor_lcd,
  41. sunxi_monitor_vga,
  42. sunxi_monitor_composite_pal,
  43. sunxi_monitor_composite_ntsc,
  44. sunxi_monitor_composite_pal_m,
  45. sunxi_monitor_composite_pal_nc,
  46. };
  47. #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
  48. struct sunxi_display {
  49. GraphicDevice graphic_device;
  50. enum sunxi_monitor monitor;
  51. unsigned int depth;
  52. unsigned int fb_addr;
  53. unsigned int fb_size;
  54. } sunxi_display;
  55. const struct ctfb_res_modes composite_video_modes[2] = {
  56. /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
  57. { 720, 576, 50, 37037, 27000, 137, 5, 20, 27, 2, 2, 0, FB_VMODE_INTERLACED },
  58. { 720, 480, 60, 37037, 27000, 116, 20, 16, 27, 2, 2, 0, FB_VMODE_INTERLACED },
  59. };
  60. #ifdef CONFIG_VIDEO_HDMI
  61. /*
  62. * Wait up to 200ms for value to be set in given part of reg.
  63. */
  64. static int await_completion(u32 *reg, u32 mask, u32 val)
  65. {
  66. unsigned long tmo = timer_get_us() + 200000;
  67. while ((readl(reg) & mask) != val) {
  68. if (timer_get_us() > tmo) {
  69. printf("DDC: timeout reading EDID\n");
  70. return -ETIME;
  71. }
  72. }
  73. return 0;
  74. }
  75. static int sunxi_hdmi_hpd_detect(int hpd_delay)
  76. {
  77. struct sunxi_ccm_reg * const ccm =
  78. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  79. struct sunxi_hdmi_reg * const hdmi =
  80. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  81. unsigned long tmo = timer_get_us() + hpd_delay * 1000;
  82. /* Set pll3 to 300MHz */
  83. clock_set_pll3(300000000);
  84. /* Set hdmi parent to pll3 */
  85. clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
  86. CCM_HDMI_CTRL_PLL3);
  87. /* Set ahb gating to pass */
  88. #ifdef CONFIG_SUNXI_GEN_SUN6I
  89. setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
  90. #endif
  91. setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
  92. /* Clock on */
  93. setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
  94. writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl);
  95. writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0);
  96. while (timer_get_us() < tmo) {
  97. if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
  98. return 1;
  99. }
  100. return 0;
  101. }
  102. static void sunxi_hdmi_shutdown(void)
  103. {
  104. struct sunxi_ccm_reg * const ccm =
  105. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  106. struct sunxi_hdmi_reg * const hdmi =
  107. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  108. clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
  109. clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
  110. clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
  111. #ifdef CONFIG_SUNXI_GEN_SUN6I
  112. clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
  113. #endif
  114. clock_set_pll3(0);
  115. }
  116. static int sunxi_hdmi_ddc_do_command(u32 cmnd, int offset, int n)
  117. {
  118. struct sunxi_hdmi_reg * const hdmi =
  119. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  120. setbits_le32(&hdmi->ddc_fifo_ctrl, SUNXI_HDMI_DDC_FIFO_CTRL_CLEAR);
  121. writel(SUNXI_HMDI_DDC_ADDR_EDDC_SEGMENT(offset >> 8) |
  122. SUNXI_HMDI_DDC_ADDR_EDDC_ADDR |
  123. SUNXI_HMDI_DDC_ADDR_OFFSET(offset) |
  124. SUNXI_HMDI_DDC_ADDR_SLAVE_ADDR, &hdmi->ddc_addr);
  125. #ifndef CONFIG_MACH_SUN6I
  126. writel(n, &hdmi->ddc_byte_count);
  127. writel(cmnd, &hdmi->ddc_cmnd);
  128. #else
  129. writel(n << 16 | cmnd, &hdmi->ddc_cmnd);
  130. #endif
  131. setbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START);
  132. return await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_START, 0);
  133. }
  134. static int sunxi_hdmi_ddc_read(int offset, u8 *buf, int count)
  135. {
  136. struct sunxi_hdmi_reg * const hdmi =
  137. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  138. int i, n;
  139. while (count > 0) {
  140. if (count > 16)
  141. n = 16;
  142. else
  143. n = count;
  144. if (sunxi_hdmi_ddc_do_command(
  145. SUNXI_HDMI_DDC_CMND_EXPLICIT_EDDC_READ,
  146. offset, n))
  147. return -ETIME;
  148. for (i = 0; i < n; i++)
  149. *buf++ = readb(&hdmi->ddc_fifo_data);
  150. offset += n;
  151. count -= n;
  152. }
  153. return 0;
  154. }
  155. static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
  156. {
  157. int r, retries = 2;
  158. do {
  159. r = sunxi_hdmi_ddc_read(block * 128, buf, 128);
  160. if (r)
  161. continue;
  162. r = edid_check_checksum(buf);
  163. if (r) {
  164. printf("EDID block %d: checksum error%s\n",
  165. block, retries ? ", retrying" : "");
  166. }
  167. } while (r && retries--);
  168. return r;
  169. }
  170. static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode)
  171. {
  172. struct edid1_info edid1;
  173. struct edid_cea861_info cea681[4];
  174. struct edid_detailed_timing *t =
  175. (struct edid_detailed_timing *)edid1.monitor_details.timing;
  176. struct sunxi_hdmi_reg * const hdmi =
  177. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  178. struct sunxi_ccm_reg * const ccm =
  179. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  180. int i, r, ext_blocks = 0;
  181. /* SUNXI_HDMI_CTRL_ENABLE & PAD_CTRL0 are already set by hpd_detect */
  182. writel(SUNXI_HDMI_PAD_CTRL1 | SUNXI_HDMI_PAD_CTRL1_HALVE,
  183. &hdmi->pad_ctrl1);
  184. writel(SUNXI_HDMI_PLL_CTRL | SUNXI_HDMI_PLL_CTRL_DIV(15),
  185. &hdmi->pll_ctrl);
  186. writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
  187. /* Reset i2c controller */
  188. setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
  189. writel(SUNXI_HMDI_DDC_CTRL_ENABLE |
  190. SUNXI_HMDI_DDC_CTRL_SDA_ENABLE |
  191. SUNXI_HMDI_DDC_CTRL_SCL_ENABLE |
  192. SUNXI_HMDI_DDC_CTRL_RESET, &hdmi->ddc_ctrl);
  193. if (await_completion(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_RESET, 0))
  194. return -EIO;
  195. writel(SUNXI_HDMI_DDC_CLOCK, &hdmi->ddc_clock);
  196. #ifndef CONFIG_MACH_SUN6I
  197. writel(SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE |
  198. SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE, &hdmi->ddc_line_ctrl);
  199. #endif
  200. r = sunxi_hdmi_edid_get_block(0, (u8 *)&edid1);
  201. if (r == 0) {
  202. r = edid_check_info(&edid1);
  203. if (r) {
  204. printf("EDID: invalid EDID data\n");
  205. r = -EINVAL;
  206. }
  207. }
  208. if (r == 0) {
  209. ext_blocks = edid1.extension_flag;
  210. if (ext_blocks > 4)
  211. ext_blocks = 4;
  212. for (i = 0; i < ext_blocks; i++) {
  213. if (sunxi_hdmi_edid_get_block(1 + i,
  214. (u8 *)&cea681[i]) != 0) {
  215. ext_blocks = i;
  216. break;
  217. }
  218. }
  219. }
  220. /* Disable DDC engine, no longer needed */
  221. clrbits_le32(&hdmi->ddc_ctrl, SUNXI_HMDI_DDC_CTRL_ENABLE);
  222. clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_DDC_GATE);
  223. if (r)
  224. return r;
  225. /* We want version 1.3 or 1.2 with detailed timing info */
  226. if (edid1.version != 1 || (edid1.revision < 3 &&
  227. !EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(edid1))) {
  228. printf("EDID: unsupported version %d.%d\n",
  229. edid1.version, edid1.revision);
  230. return -EINVAL;
  231. }
  232. /* Take the first usable detailed timing */
  233. for (i = 0; i < 4; i++, t++) {
  234. r = video_edid_dtd_to_ctfb_res_modes(t, mode);
  235. if (r == 0)
  236. break;
  237. }
  238. if (i == 4) {
  239. printf("EDID: no usable detailed timing found\n");
  240. return -ENOENT;
  241. }
  242. /* Check for basic audio support, if found enable hdmi output */
  243. sunxi_display.monitor = sunxi_monitor_dvi;
  244. for (i = 0; i < ext_blocks; i++) {
  245. if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
  246. cea681[i].revision < 2)
  247. continue;
  248. if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
  249. sunxi_display.monitor = sunxi_monitor_hdmi;
  250. }
  251. return 0;
  252. }
  253. #endif /* CONFIG_VIDEO_HDMI */
  254. #ifdef CONFIG_MACH_SUN4I
  255. /*
  256. * Testing has shown that on sun4i the display backend engine does not have
  257. * deep enough fifo-s causing flickering / tearing in full-hd mode due to
  258. * fifo underruns. So on sun4i we use the display frontend engine to do the
  259. * dma from memory, as the frontend does have deep enough fifo-s.
  260. */
  261. static const u32 sun4i_vert_coef[32] = {
  262. 0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
  263. 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
  264. 0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb,
  265. 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
  266. 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
  267. 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
  268. 0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff,
  269. 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
  270. };
  271. static const u32 sun4i_horz_coef[64] = {
  272. 0x40000000, 0x00000000, 0x40fe0000, 0x0000ff03,
  273. 0x3ffd0000, 0x0000ff05, 0x3ffc0000, 0x0000ff06,
  274. 0x3efb0000, 0x0000ff08, 0x3dfb0000, 0x0000ff09,
  275. 0x3bfa0000, 0x0000fe0d, 0x39fa0000, 0x0000fe0f,
  276. 0x38fa0000, 0x0000fe10, 0x36fa0000, 0x0000fe12,
  277. 0x33fa0000, 0x0000fd16, 0x31fa0000, 0x0000fd18,
  278. 0x2ffa0000, 0x0000fd1a, 0x2cfa0000, 0x0000fc1e,
  279. 0x29fa0000, 0x0000fc21, 0x27fb0000, 0x0000fb23,
  280. 0x24fb0000, 0x0000fb26, 0x21fb0000, 0x0000fb29,
  281. 0x1ffc0000, 0x0000fa2b, 0x1cfc0000, 0x0000fa2e,
  282. 0x19fd0000, 0x0000fa30, 0x16fd0000, 0x0000fa33,
  283. 0x14fd0000, 0x0000fa35, 0x11fe0000, 0x0000fa37,
  284. 0x0ffe0000, 0x0000fa39, 0x0dfe0000, 0x0000fa3b,
  285. 0x0afe0000, 0x0000fa3e, 0x08ff0000, 0x0000fb3e,
  286. 0x06ff0000, 0x0000fb40, 0x05ff0000, 0x0000fc40,
  287. 0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
  288. };
  289. static void sunxi_frontend_init(void)
  290. {
  291. struct sunxi_ccm_reg * const ccm =
  292. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  293. struct sunxi_de_fe_reg * const de_fe =
  294. (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
  295. int i;
  296. /* Clocks on */
  297. setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_FE0);
  298. setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_FE0);
  299. clock_set_de_mod_clock(&ccm->fe0_clk_cfg, 300000000);
  300. setbits_le32(&de_fe->enable, SUNXI_DE_FE_ENABLE_EN);
  301. for (i = 0; i < 32; i++) {
  302. writel(sun4i_horz_coef[2 * i], &de_fe->ch0_horzcoef0[i]);
  303. writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch0_horzcoef1[i]);
  304. writel(sun4i_vert_coef[i], &de_fe->ch0_vertcoef[i]);
  305. writel(sun4i_horz_coef[2 * i], &de_fe->ch1_horzcoef0[i]);
  306. writel(sun4i_horz_coef[2 * i + 1], &de_fe->ch1_horzcoef1[i]);
  307. writel(sun4i_vert_coef[i], &de_fe->ch1_vertcoef[i]);
  308. }
  309. setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_COEF_RDY);
  310. }
  311. static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
  312. unsigned int address)
  313. {
  314. struct sunxi_de_fe_reg * const de_fe =
  315. (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
  316. setbits_le32(&de_fe->bypass, SUNXI_DE_FE_BYPASS_CSC_BYPASS);
  317. writel(CONFIG_SYS_SDRAM_BASE + address, &de_fe->ch0_addr);
  318. writel(mode->xres * 4, &de_fe->ch0_stride);
  319. writel(SUNXI_DE_FE_INPUT_FMT_ARGB8888, &de_fe->input_fmt);
  320. writel(SUNXI_DE_FE_OUTPUT_FMT_ARGB8888, &de_fe->output_fmt);
  321. writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
  322. &de_fe->ch0_insize);
  323. writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
  324. &de_fe->ch0_outsize);
  325. writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_horzfact);
  326. writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch0_vertfact);
  327. writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
  328. &de_fe->ch1_insize);
  329. writel(SUNXI_DE_FE_HEIGHT(mode->yres) | SUNXI_DE_FE_WIDTH(mode->xres),
  330. &de_fe->ch1_outsize);
  331. writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_horzfact);
  332. writel(SUNXI_DE_FE_FACTOR_INT(1), &de_fe->ch1_vertfact);
  333. setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_REG_RDY);
  334. }
  335. static void sunxi_frontend_enable(void)
  336. {
  337. struct sunxi_de_fe_reg * const de_fe =
  338. (struct sunxi_de_fe_reg *)SUNXI_DE_FE0_BASE;
  339. setbits_le32(&de_fe->frame_ctrl, SUNXI_DE_FE_FRAME_CTRL_FRM_START);
  340. }
  341. #else
  342. static void sunxi_frontend_init(void) {}
  343. static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
  344. unsigned int address) {}
  345. static void sunxi_frontend_enable(void) {}
  346. #endif
  347. static bool sunxi_is_composite(void)
  348. {
  349. switch (sunxi_display.monitor) {
  350. case sunxi_monitor_none:
  351. case sunxi_monitor_dvi:
  352. case sunxi_monitor_hdmi:
  353. case sunxi_monitor_lcd:
  354. case sunxi_monitor_vga:
  355. return false;
  356. case sunxi_monitor_composite_pal:
  357. case sunxi_monitor_composite_ntsc:
  358. case sunxi_monitor_composite_pal_m:
  359. case sunxi_monitor_composite_pal_nc:
  360. return true;
  361. }
  362. return false; /* Never reached */
  363. }
  364. /*
  365. * This is the entity that mixes and matches the different layers and inputs.
  366. * Allwinner calls it the back-end, but i like composer better.
  367. */
  368. static void sunxi_composer_init(void)
  369. {
  370. struct sunxi_ccm_reg * const ccm =
  371. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  372. struct sunxi_de_be_reg * const de_be =
  373. (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
  374. int i;
  375. sunxi_frontend_init();
  376. #ifdef CONFIG_SUNXI_GEN_SUN6I
  377. /* Reset off */
  378. setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0);
  379. #endif
  380. /* Clocks on */
  381. setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0);
  382. #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
  383. setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0);
  384. #endif
  385. clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000);
  386. /* Engine bug, clear registers after reset */
  387. for (i = 0x0800; i < 0x1000; i += 4)
  388. writel(0, SUNXI_DE_BE0_BASE + i);
  389. setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE);
  390. }
  391. static u32 sunxi_rgb2yuv_coef[12] = {
  392. 0x00000107, 0x00000204, 0x00000064, 0x00000108,
  393. 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
  394. 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
  395. };
  396. static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
  397. unsigned int address)
  398. {
  399. struct sunxi_de_be_reg * const de_be =
  400. (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
  401. int i;
  402. sunxi_frontend_mode_set(mode, address);
  403. writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
  404. &de_be->disp_size);
  405. writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
  406. &de_be->layer0_size);
  407. #ifndef CONFIG_MACH_SUN4I /* On sun4i the frontend does the dma */
  408. writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride);
  409. writel(address << 3, &de_be->layer0_addr_low32b);
  410. writel(address >> 29, &de_be->layer0_addr_high4b);
  411. #else
  412. writel(SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0, &de_be->layer0_attr0_ctrl);
  413. #endif
  414. writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
  415. setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
  416. if (mode->vmode == FB_VMODE_INTERLACED)
  417. setbits_le32(&de_be->mode,
  418. #ifndef CONFIG_MACH_SUN5I
  419. SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
  420. #endif
  421. SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
  422. if (sunxi_is_composite()) {
  423. writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
  424. &de_be->output_color_ctrl);
  425. for (i = 0; i < 12; i++)
  426. writel(sunxi_rgb2yuv_coef[i],
  427. &de_be->output_color_coef[i]);
  428. }
  429. }
  430. static void sunxi_composer_enable(void)
  431. {
  432. struct sunxi_de_be_reg * const de_be =
  433. (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
  434. sunxi_frontend_enable();
  435. setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
  436. setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
  437. }
  438. /*
  439. * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
  440. */
  441. static void sunxi_lcdc_pll_set(int tcon, int dotclock,
  442. int *clk_div, int *clk_double)
  443. {
  444. struct sunxi_ccm_reg * const ccm =
  445. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  446. int value, n, m, min_m, max_m, diff;
  447. int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
  448. int best_double = 0;
  449. bool use_mipi_pll = false;
  450. if (tcon == 0) {
  451. #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
  452. min_m = 6;
  453. max_m = 127;
  454. #endif
  455. #ifdef CONFIG_VIDEO_LCD_IF_LVDS
  456. min_m = max_m = 7;
  457. #endif
  458. } else {
  459. min_m = 1;
  460. max_m = 15;
  461. }
  462. /*
  463. * Find the lowest divider resulting in a matching clock, if there
  464. * is no match, pick the closest lower clock, as monitors tend to
  465. * not sync to higher frequencies.
  466. */
  467. for (m = min_m; m <= max_m; m++) {
  468. n = (m * dotclock) / 3000;
  469. if ((n >= 9) && (n <= 127)) {
  470. value = (3000 * n) / m;
  471. diff = dotclock - value;
  472. if (diff < best_diff) {
  473. best_diff = diff;
  474. best_m = m;
  475. best_n = n;
  476. best_double = 0;
  477. }
  478. }
  479. /* These are just duplicates */
  480. if (!(m & 1))
  481. continue;
  482. n = (m * dotclock) / 6000;
  483. if ((n >= 9) && (n <= 127)) {
  484. value = (6000 * n) / m;
  485. diff = dotclock - value;
  486. if (diff < best_diff) {
  487. best_diff = diff;
  488. best_m = m;
  489. best_n = n;
  490. best_double = 1;
  491. }
  492. }
  493. }
  494. #ifdef CONFIG_MACH_SUN6I
  495. /*
  496. * Use the MIPI pll if we've been unable to find any matching setting
  497. * for PLL3, this happens with high dotclocks because of min_m = 6.
  498. */
  499. if (tcon == 0 && best_n == 0) {
  500. use_mipi_pll = true;
  501. best_m = 6; /* Minimum m for tcon0 */
  502. }
  503. if (use_mipi_pll) {
  504. clock_set_pll3(297000000); /* Fix the video pll at 297 MHz */
  505. clock_set_mipi_pll(best_m * dotclock * 1000);
  506. debug("dotclock: %dkHz = %dkHz via mipi pll\n",
  507. dotclock, clock_get_mipi_pll() / best_m / 1000);
  508. } else
  509. #endif
  510. {
  511. clock_set_pll3(best_n * 3000000);
  512. debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
  513. dotclock,
  514. (best_double + 1) * clock_get_pll3() / best_m / 1000,
  515. best_double + 1, best_n, best_m);
  516. }
  517. if (tcon == 0) {
  518. u32 pll;
  519. if (use_mipi_pll)
  520. pll = CCM_LCD_CH0_CTRL_MIPI_PLL;
  521. else if (best_double)
  522. pll = CCM_LCD_CH0_CTRL_PLL3_2X;
  523. else
  524. pll = CCM_LCD_CH0_CTRL_PLL3;
  525. writel(CCM_LCD_CH0_CTRL_GATE | CCM_LCD_CH0_CTRL_RST | pll,
  526. &ccm->lcd0_ch0_clk_cfg);
  527. } else {
  528. writel(CCM_LCD_CH1_CTRL_GATE |
  529. (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
  530. CCM_LCD_CH1_CTRL_PLL3) |
  531. CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
  532. if (sunxi_is_composite())
  533. setbits_le32(&ccm->lcd0_ch1_clk_cfg,
  534. CCM_LCD_CH1_CTRL_HALF_SCLK1);
  535. }
  536. *clk_div = best_m;
  537. *clk_double = best_double;
  538. }
  539. static void sunxi_lcdc_init(void)
  540. {
  541. struct sunxi_ccm_reg * const ccm =
  542. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  543. struct sunxi_lcdc_reg * const lcdc =
  544. (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
  545. /* Reset off */
  546. #ifdef CONFIG_SUNXI_GEN_SUN6I
  547. setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
  548. #else
  549. setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
  550. #endif
  551. /* Clock on */
  552. setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
  553. #ifdef CONFIG_VIDEO_LCD_IF_LVDS
  554. #ifdef CONFIG_SUNXI_GEN_SUN6I
  555. setbits_le32(&ccm->ahb_reset2_cfg, 1 << AHB_RESET_OFFSET_LVDS);
  556. #else
  557. setbits_le32(&ccm->lvds_clk_cfg, CCM_LVDS_CTRL_RST);
  558. #endif
  559. #endif
  560. /* Init lcdc */
  561. writel(0, &lcdc->ctrl); /* Disable tcon */
  562. writel(0, &lcdc->int0); /* Disable all interrupts */
  563. /* Disable tcon0 dot clock */
  564. clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE);
  565. /* Set all io lines to tristate */
  566. writel(0xffffffff, &lcdc->tcon0_io_tristate);
  567. writel(0xffffffff, &lcdc->tcon1_io_tristate);
  568. }
  569. static void sunxi_lcdc_enable(void)
  570. {
  571. struct sunxi_lcdc_reg * const lcdc =
  572. (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
  573. setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
  574. #ifdef CONFIG_VIDEO_LCD_IF_LVDS
  575. setbits_le32(&lcdc->tcon0_lvds_intf, SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE);
  576. setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0);
  577. #ifdef CONFIG_SUNXI_GEN_SUN6I
  578. udelay(2); /* delay at least 1200 ns */
  579. setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_EN_MB);
  580. udelay(2); /* delay at least 1200 ns */
  581. setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVC);
  582. if (sunxi_display.depth == 18)
  583. setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0x7));
  584. else
  585. setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_DRVD(0xf));
  586. #else
  587. setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
  588. udelay(2); /* delay at least 1200 ns */
  589. setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT1);
  590. udelay(1); /* delay at least 120 ns */
  591. setbits_le32(&lcdc->lvds_ana1, SUNXI_LCDC_LVDS_ANA1_INIT2);
  592. setbits_le32(&lcdc->lvds_ana0, SUNXI_LCDC_LVDS_ANA0_UPDATE);
  593. #endif
  594. #endif
  595. }
  596. static void sunxi_lcdc_panel_enable(void)
  597. {
  598. int pin, reset_pin;
  599. /*
  600. * Start with backlight disabled to avoid the screen flashing to
  601. * white while the lcd inits.
  602. */
  603. pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
  604. if (pin >= 0) {
  605. gpio_request(pin, "lcd_backlight_enable");
  606. gpio_direction_output(pin, 0);
  607. }
  608. pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
  609. if (pin >= 0) {
  610. gpio_request(pin, "lcd_backlight_pwm");
  611. gpio_direction_output(pin, PWM_OFF);
  612. }
  613. reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET);
  614. if (reset_pin >= 0) {
  615. gpio_request(reset_pin, "lcd_reset");
  616. gpio_direction_output(reset_pin, 0); /* Assert reset */
  617. }
  618. /* Give the backlight some time to turn off and power up the panel. */
  619. mdelay(40);
  620. pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER);
  621. if (pin >= 0) {
  622. gpio_request(pin, "lcd_power");
  623. gpio_direction_output(pin, 1);
  624. }
  625. if (reset_pin >= 0)
  626. gpio_direction_output(reset_pin, 1); /* De-assert reset */
  627. }
  628. static void sunxi_lcdc_backlight_enable(void)
  629. {
  630. int pin;
  631. /*
  632. * We want to have scanned out at least one frame before enabling the
  633. * backlight to avoid the screen flashing to white when we enable it.
  634. */
  635. mdelay(40);
  636. pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN);
  637. if (pin >= 0)
  638. gpio_direction_output(pin, 1);
  639. pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM);
  640. #ifdef SUNXI_PWM_PIN0
  641. if (pin == SUNXI_PWM_PIN0) {
  642. writel(SUNXI_PWM_CTRL_POLARITY0(PWM_ON) |
  643. SUNXI_PWM_CTRL_ENABLE0 |
  644. SUNXI_PWM_CTRL_PRESCALE0(0xf), SUNXI_PWM_CTRL_REG);
  645. writel(SUNXI_PWM_PERIOD_80PCT, SUNXI_PWM_CH0_PERIOD);
  646. sunxi_gpio_set_cfgpin(pin, SUNXI_PWM_MUX);
  647. return;
  648. }
  649. #endif
  650. if (pin >= 0)
  651. gpio_direction_output(pin, PWM_ON);
  652. }
  653. static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
  654. {
  655. int delay;
  656. delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
  657. if (mode->vmode == FB_VMODE_INTERLACED)
  658. delay /= 2;
  659. if (tcon == 1)
  660. delay -= 2;
  661. return (delay > 30) ? 30 : delay;
  662. }
  663. static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
  664. bool for_ext_vga_dac)
  665. {
  666. struct sunxi_lcdc_reg * const lcdc =
  667. (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
  668. int bp, clk_delay, clk_div, clk_double, pin, total, val;
  669. #if defined CONFIG_MACH_SUN8I && defined CONFIG_VIDEO_LCD_IF_LVDS
  670. for (pin = SUNXI_GPD(18); pin <= SUNXI_GPD(27); pin++) {
  671. #else
  672. for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) {
  673. #endif
  674. #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
  675. sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LCD0);
  676. #endif
  677. #ifdef CONFIG_VIDEO_LCD_IF_LVDS
  678. sunxi_gpio_set_cfgpin(pin, SUNXI_GPD_LVDS0);
  679. #endif
  680. #ifdef CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804
  681. sunxi_gpio_set_drv(pin, 3);
  682. #endif
  683. }
  684. sunxi_lcdc_pll_set(0, mode->pixclock_khz, &clk_div, &clk_double);
  685. /* Use tcon0 */
  686. clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
  687. SUNXI_LCDC_CTRL_IO_MAP_TCON0);
  688. clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
  689. writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
  690. SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
  691. writel(SUNXI_LCDC_TCON0_DCLK_ENABLE |
  692. SUNXI_LCDC_TCON0_DCLK_DIV(clk_div), &lcdc->tcon0_dclk);
  693. writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
  694. &lcdc->tcon0_timing_active);
  695. bp = mode->hsync_len + mode->left_margin;
  696. total = mode->xres + mode->right_margin + bp;
  697. writel(SUNXI_LCDC_TCON0_TIMING_H_TOTAL(total) |
  698. SUNXI_LCDC_TCON0_TIMING_H_BP(bp), &lcdc->tcon0_timing_h);
  699. bp = mode->vsync_len + mode->upper_margin;
  700. total = mode->yres + mode->lower_margin + bp;
  701. writel(SUNXI_LCDC_TCON0_TIMING_V_TOTAL(total) |
  702. SUNXI_LCDC_TCON0_TIMING_V_BP(bp), &lcdc->tcon0_timing_v);
  703. #ifdef CONFIG_VIDEO_LCD_IF_PARALLEL
  704. writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
  705. &lcdc->tcon0_timing_sync);
  706. writel(0, &lcdc->tcon0_hv_intf);
  707. writel(0, &lcdc->tcon0_cpu_intf);
  708. #endif
  709. #ifdef CONFIG_VIDEO_LCD_IF_LVDS
  710. val = (sunxi_display.depth == 18) ? 1 : 0;
  711. writel(SUNXI_LCDC_TCON0_LVDS_INTF_BITWIDTH(val) |
  712. SUNXI_LCDC_TCON0_LVDS_CLK_SEL_TCON0, &lcdc->tcon0_lvds_intf);
  713. #endif
  714. if (sunxi_display.depth == 18 || sunxi_display.depth == 16) {
  715. writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[0]);
  716. writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[1]);
  717. writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[2]);
  718. writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[3]);
  719. writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[4]);
  720. writel(SUNXI_LCDC_TCON0_FRM_SEED, &lcdc->tcon0_frm_seed[5]);
  721. writel(SUNXI_LCDC_TCON0_FRM_TAB0, &lcdc->tcon0_frm_table[0]);
  722. writel(SUNXI_LCDC_TCON0_FRM_TAB1, &lcdc->tcon0_frm_table[1]);
  723. writel(SUNXI_LCDC_TCON0_FRM_TAB2, &lcdc->tcon0_frm_table[2]);
  724. writel(SUNXI_LCDC_TCON0_FRM_TAB3, &lcdc->tcon0_frm_table[3]);
  725. writel(((sunxi_display.depth == 18) ?
  726. SUNXI_LCDC_TCON0_FRM_CTRL_RGB666 :
  727. SUNXI_LCDC_TCON0_FRM_CTRL_RGB565),
  728. &lcdc->tcon0_frm_ctrl);
  729. }
  730. val = SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(CONFIG_VIDEO_LCD_DCLK_PHASE);
  731. if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
  732. val |= SUNXI_LCDC_TCON_HSYNC_MASK;
  733. if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
  734. val |= SUNXI_LCDC_TCON_VSYNC_MASK;
  735. #ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
  736. if (for_ext_vga_dac)
  737. val = 0;
  738. #endif
  739. writel(val, &lcdc->tcon0_io_polarity);
  740. writel(0, &lcdc->tcon0_io_tristate);
  741. }
  742. #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
  743. static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
  744. int *clk_div, int *clk_double,
  745. bool use_portd_hvsync)
  746. {
  747. struct sunxi_lcdc_reg * const lcdc =
  748. (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
  749. int bp, clk_delay, total, val, yres;
  750. /* Use tcon1 */
  751. clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
  752. SUNXI_LCDC_CTRL_IO_MAP_TCON1);
  753. clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
  754. writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
  755. ((mode->vmode == FB_VMODE_INTERLACED) ?
  756. SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE : 0) |
  757. SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
  758. yres = mode->yres;
  759. if (mode->vmode == FB_VMODE_INTERLACED)
  760. yres /= 2;
  761. writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
  762. &lcdc->tcon1_timing_source);
  763. writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
  764. &lcdc->tcon1_timing_scale);
  765. writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
  766. &lcdc->tcon1_timing_out);
  767. bp = mode->hsync_len + mode->left_margin;
  768. total = mode->xres + mode->right_margin + bp;
  769. writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
  770. SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
  771. bp = mode->vsync_len + mode->upper_margin;
  772. total = mode->yres + mode->lower_margin + bp;
  773. if (mode->vmode == FB_VMODE_NONINTERLACED)
  774. total *= 2;
  775. writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
  776. SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
  777. writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
  778. &lcdc->tcon1_timing_sync);
  779. if (use_portd_hvsync) {
  780. sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
  781. sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD_LCD0);
  782. val = 0;
  783. if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
  784. val |= SUNXI_LCDC_TCON_HSYNC_MASK;
  785. if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
  786. val |= SUNXI_LCDC_TCON_VSYNC_MASK;
  787. writel(val, &lcdc->tcon1_io_polarity);
  788. clrbits_le32(&lcdc->tcon1_io_tristate,
  789. SUNXI_LCDC_TCON_VSYNC_MASK |
  790. SUNXI_LCDC_TCON_HSYNC_MASK);
  791. }
  792. #ifdef CONFIG_MACH_SUN5I
  793. if (sunxi_is_composite())
  794. clrsetbits_le32(&lcdc->mux_ctrl, SUNXI_LCDC_MUX_CTRL_SRC0_MASK,
  795. SUNXI_LCDC_MUX_CTRL_SRC0(1));
  796. #endif
  797. sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
  798. }
  799. #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
  800. #ifdef CONFIG_VIDEO_HDMI
  801. static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
  802. {
  803. struct sunxi_hdmi_reg * const hdmi =
  804. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  805. u8 checksum = 0;
  806. u8 avi_info_frame[17] = {
  807. 0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
  808. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  809. 0x00
  810. };
  811. u8 vendor_info_frame[19] = {
  812. 0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
  813. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  814. 0x00, 0x00, 0x00
  815. };
  816. int i;
  817. if (mode->pixclock_khz <= 27000)
  818. avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
  819. else
  820. avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
  821. if (mode->xres * 100 / mode->yres < 156)
  822. avi_info_frame[5] |= 0x18; /* 4 : 3 */
  823. else
  824. avi_info_frame[5] |= 0x28; /* 16 : 9 */
  825. for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
  826. checksum += avi_info_frame[i];
  827. avi_info_frame[3] = 0x100 - checksum;
  828. for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
  829. writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
  830. writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
  831. writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
  832. for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
  833. writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
  834. writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
  835. writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
  836. setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
  837. }
  838. static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
  839. int clk_div, int clk_double)
  840. {
  841. struct sunxi_hdmi_reg * const hdmi =
  842. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  843. int x, y;
  844. /* Write clear interrupt status bits */
  845. writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
  846. if (sunxi_display.monitor == sunxi_monitor_hdmi)
  847. sunxi_hdmi_setup_info_frames(mode);
  848. /* Set input sync enable */
  849. writel(SUNXI_HDMI_UNKNOWN_INPUT_SYNC, &hdmi->unknown);
  850. /* Init various registers, select pll3 as clock source */
  851. writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
  852. writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
  853. writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
  854. writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
  855. writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
  856. /* Setup clk div and doubler */
  857. clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
  858. SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
  859. if (!clk_double)
  860. setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
  861. /* Setup timing registers */
  862. writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
  863. &hdmi->video_size);
  864. x = mode->hsync_len + mode->left_margin;
  865. y = mode->vsync_len + mode->upper_margin;
  866. writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
  867. x = mode->right_margin;
  868. y = mode->lower_margin;
  869. writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
  870. x = mode->hsync_len;
  871. y = mode->vsync_len;
  872. writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
  873. if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
  874. setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
  875. if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
  876. setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
  877. }
  878. static void sunxi_hdmi_enable(void)
  879. {
  880. struct sunxi_hdmi_reg * const hdmi =
  881. (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
  882. udelay(100);
  883. setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
  884. }
  885. #endif /* CONFIG_VIDEO_HDMI */
  886. #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
  887. static void sunxi_tvencoder_mode_set(void)
  888. {
  889. struct sunxi_ccm_reg * const ccm =
  890. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  891. struct sunxi_tve_reg * const tve =
  892. (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
  893. /* Reset off */
  894. setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_TVE_RST);
  895. /* Clock on */
  896. setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
  897. switch (sunxi_display.monitor) {
  898. case sunxi_monitor_vga:
  899. writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
  900. SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
  901. SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
  902. writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
  903. writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
  904. writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
  905. break;
  906. case sunxi_monitor_composite_pal_nc:
  907. writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
  908. /* Fall through */
  909. case sunxi_monitor_composite_pal:
  910. writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
  911. SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
  912. SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
  913. SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
  914. writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
  915. writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
  916. writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
  917. writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
  918. writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
  919. writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
  920. writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
  921. writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
  922. writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
  923. writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
  924. writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
  925. writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
  926. writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
  927. writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
  928. writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
  929. break;
  930. case sunxi_monitor_composite_pal_m:
  931. writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
  932. writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
  933. /* Fall through */
  934. case sunxi_monitor_composite_ntsc:
  935. writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
  936. SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
  937. SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
  938. SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
  939. writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
  940. writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
  941. writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
  942. writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
  943. writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
  944. writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
  945. writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
  946. writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
  947. writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
  948. writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
  949. writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
  950. writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
  951. writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
  952. writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
  953. writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
  954. writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
  955. writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
  956. break;
  957. case sunxi_monitor_none:
  958. case sunxi_monitor_dvi:
  959. case sunxi_monitor_hdmi:
  960. case sunxi_monitor_lcd:
  961. break;
  962. }
  963. }
  964. static void sunxi_tvencoder_enable(void)
  965. {
  966. struct sunxi_tve_reg * const tve =
  967. (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
  968. setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
  969. }
  970. #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
  971. static void sunxi_drc_init(void)
  972. {
  973. #ifdef CONFIG_SUNXI_GEN_SUN6I
  974. struct sunxi_ccm_reg * const ccm =
  975. (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
  976. /* On sun6i the drc must be clocked even when in pass-through mode */
  977. #ifdef CONFIG_MACH_SUN8I_A33
  978. setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT);
  979. #endif
  980. setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
  981. clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
  982. #endif
  983. }
  984. #ifdef CONFIG_VIDEO_VGA_VIA_LCD
  985. static void sunxi_vga_external_dac_enable(void)
  986. {
  987. int pin;
  988. pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN);
  989. if (pin >= 0) {
  990. gpio_request(pin, "vga_enable");
  991. gpio_direction_output(pin, 1);
  992. }
  993. }
  994. #endif /* CONFIG_VIDEO_VGA_VIA_LCD */
  995. #ifdef CONFIG_VIDEO_LCD_SSD2828
  996. static int sunxi_ssd2828_init(const struct ctfb_res_modes *mode)
  997. {
  998. struct ssd2828_config cfg = {
  999. .csx_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_CS),
  1000. .sck_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_SCLK),
  1001. .sdi_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MOSI),
  1002. .sdo_pin = name_to_gpio(CONFIG_VIDEO_LCD_SPI_MISO),
  1003. .reset_pin = name_to_gpio(CONFIG_VIDEO_LCD_SSD2828_RESET),
  1004. .ssd2828_tx_clk_khz = CONFIG_VIDEO_LCD_SSD2828_TX_CLK * 1000,
  1005. .ssd2828_color_depth = 24,
  1006. #ifdef CONFIG_VIDEO_LCD_PANEL_MIPI_4_LANE_513_MBPS_VIA_SSD2828
  1007. .mipi_dsi_number_of_data_lanes = 4,
  1008. .mipi_dsi_bitrate_per_data_lane_mbps = 513,
  1009. .mipi_dsi_delay_after_exit_sleep_mode_ms = 100,
  1010. .mipi_dsi_delay_after_set_display_on_ms = 200
  1011. #else
  1012. #error MIPI LCD panel needs configuration parameters
  1013. #endif
  1014. };
  1015. if (cfg.csx_pin == -1 || cfg.sck_pin == -1 || cfg.sdi_pin == -1) {
  1016. printf("SSD2828: SPI pins are not properly configured\n");
  1017. return 1;
  1018. }
  1019. if (cfg.reset_pin == -1) {
  1020. printf("SSD2828: Reset pin is not properly configured\n");
  1021. return 1;
  1022. }
  1023. return ssd2828_init(&cfg, mode);
  1024. }
  1025. #endif /* CONFIG_VIDEO_LCD_SSD2828 */
  1026. static void sunxi_engines_init(void)
  1027. {
  1028. sunxi_composer_init();
  1029. sunxi_lcdc_init();
  1030. sunxi_drc_init();
  1031. }
  1032. static void sunxi_mode_set(const struct ctfb_res_modes *mode,
  1033. unsigned int address)
  1034. {
  1035. int __maybe_unused clk_div, clk_double;
  1036. switch (sunxi_display.monitor) {
  1037. case sunxi_monitor_none:
  1038. break;
  1039. case sunxi_monitor_dvi:
  1040. case sunxi_monitor_hdmi:
  1041. #ifdef CONFIG_VIDEO_HDMI
  1042. sunxi_composer_mode_set(mode, address);
  1043. sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
  1044. sunxi_hdmi_mode_set(mode, clk_div, clk_double);
  1045. sunxi_composer_enable();
  1046. sunxi_lcdc_enable();
  1047. sunxi_hdmi_enable();
  1048. #endif
  1049. break;
  1050. case sunxi_monitor_lcd:
  1051. sunxi_lcdc_panel_enable();
  1052. if (IS_ENABLED(CONFIG_VIDEO_LCD_PANEL_EDP_4_LANE_1620M_VIA_ANX9804)) {
  1053. /*
  1054. * The anx9804 needs 1.8V from eldo3, we do this here
  1055. * and not via CONFIG_AXP_ELDO3_VOLT from board_init()
  1056. * to avoid turning this on when using hdmi output.
  1057. */
  1058. axp_set_eldo(3, 1800);
  1059. anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
  1060. ANX9804_DATA_RATE_1620M,
  1061. sunxi_display.depth);
  1062. }
  1063. if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
  1064. mdelay(50); /* Wait for lcd controller power on */
  1065. hitachi_tx18d42vm_init();
  1066. }
  1067. if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) {
  1068. unsigned int orig_i2c_bus = i2c_get_bus_num();
  1069. i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS);
  1070. i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
  1071. i2c_set_bus_num(orig_i2c_bus);
  1072. }
  1073. sunxi_composer_mode_set(mode, address);
  1074. sunxi_lcdc_tcon0_mode_set(mode, false);
  1075. sunxi_composer_enable();
  1076. sunxi_lcdc_enable();
  1077. #ifdef CONFIG_VIDEO_LCD_SSD2828
  1078. sunxi_ssd2828_init(mode);
  1079. #endif
  1080. sunxi_lcdc_backlight_enable();
  1081. break;
  1082. case sunxi_monitor_vga:
  1083. #ifdef CONFIG_VIDEO_VGA
  1084. sunxi_composer_mode_set(mode, address);
  1085. sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
  1086. sunxi_tvencoder_mode_set();
  1087. sunxi_composer_enable();
  1088. sunxi_lcdc_enable();
  1089. sunxi_tvencoder_enable();
  1090. #elif defined CONFIG_VIDEO_VGA_VIA_LCD
  1091. sunxi_composer_mode_set(mode, address);
  1092. sunxi_lcdc_tcon0_mode_set(mode, true);
  1093. sunxi_composer_enable();
  1094. sunxi_lcdc_enable();
  1095. sunxi_vga_external_dac_enable();
  1096. #endif
  1097. break;
  1098. case sunxi_monitor_composite_pal:
  1099. case sunxi_monitor_composite_ntsc:
  1100. case sunxi_monitor_composite_pal_m:
  1101. case sunxi_monitor_composite_pal_nc:
  1102. #ifdef CONFIG_VIDEO_COMPOSITE
  1103. sunxi_composer_mode_set(mode, address);
  1104. sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
  1105. sunxi_tvencoder_mode_set();
  1106. sunxi_composer_enable();
  1107. sunxi_lcdc_enable();
  1108. sunxi_tvencoder_enable();
  1109. #endif
  1110. break;
  1111. }
  1112. }
  1113. static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
  1114. {
  1115. switch (monitor) {
  1116. case sunxi_monitor_none: return "none";
  1117. case sunxi_monitor_dvi: return "dvi";
  1118. case sunxi_monitor_hdmi: return "hdmi";
  1119. case sunxi_monitor_lcd: return "lcd";
  1120. case sunxi_monitor_vga: return "vga";
  1121. case sunxi_monitor_composite_pal: return "composite-pal";
  1122. case sunxi_monitor_composite_ntsc: return "composite-ntsc";
  1123. case sunxi_monitor_composite_pal_m: return "composite-pal-m";
  1124. case sunxi_monitor_composite_pal_nc: return "composite-pal-nc";
  1125. }
  1126. return NULL; /* never reached */
  1127. }
  1128. ulong board_get_usable_ram_top(ulong total_size)
  1129. {
  1130. return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
  1131. }
  1132. static bool sunxi_has_hdmi(void)
  1133. {
  1134. #ifdef CONFIG_VIDEO_HDMI
  1135. return true;
  1136. #else
  1137. return false;
  1138. #endif
  1139. }
  1140. static bool sunxi_has_lcd(void)
  1141. {
  1142. char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
  1143. return lcd_mode[0] != 0;
  1144. }
  1145. static bool sunxi_has_vga(void)
  1146. {
  1147. #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
  1148. return true;
  1149. #else
  1150. return false;
  1151. #endif
  1152. }
  1153. static bool sunxi_has_composite(void)
  1154. {
  1155. #ifdef CONFIG_VIDEO_COMPOSITE
  1156. return true;
  1157. #else
  1158. return false;
  1159. #endif
  1160. }
  1161. static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
  1162. {
  1163. if (allow_hdmi && sunxi_has_hdmi())
  1164. return sunxi_monitor_dvi;
  1165. else if (sunxi_has_lcd())
  1166. return sunxi_monitor_lcd;
  1167. else if (sunxi_has_vga())
  1168. return sunxi_monitor_vga;
  1169. else if (sunxi_has_composite())
  1170. return sunxi_monitor_composite_pal;
  1171. else
  1172. return sunxi_monitor_none;
  1173. }
  1174. void *video_hw_init(void)
  1175. {
  1176. static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
  1177. const struct ctfb_res_modes *mode;
  1178. struct ctfb_res_modes custom;
  1179. const char *options;
  1180. #ifdef CONFIG_VIDEO_HDMI
  1181. int ret, hpd, hpd_delay, edid;
  1182. #endif
  1183. int i, overscan_offset, overscan_x, overscan_y;
  1184. unsigned int fb_dma_addr;
  1185. char mon[16];
  1186. char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
  1187. memset(&sunxi_display, 0, sizeof(struct sunxi_display));
  1188. video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
  1189. &sunxi_display.depth, &options);
  1190. #ifdef CONFIG_VIDEO_HDMI
  1191. hpd = video_get_option_int(options, "hpd", 1);
  1192. hpd_delay = video_get_option_int(options, "hpd_delay", 500);
  1193. edid = video_get_option_int(options, "edid", 1);
  1194. #endif
  1195. overscan_x = video_get_option_int(options, "overscan_x", -1);
  1196. overscan_y = video_get_option_int(options, "overscan_y", -1);
  1197. sunxi_display.monitor = sunxi_get_default_mon(true);
  1198. video_get_option_string(options, "monitor", mon, sizeof(mon),
  1199. sunxi_get_mon_desc(sunxi_display.monitor));
  1200. for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
  1201. if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
  1202. sunxi_display.monitor = i;
  1203. break;
  1204. }
  1205. }
  1206. if (i > SUNXI_MONITOR_LAST)
  1207. printf("Unknown monitor: '%s', falling back to '%s'\n",
  1208. mon, sunxi_get_mon_desc(sunxi_display.monitor));
  1209. #ifdef CONFIG_VIDEO_HDMI
  1210. /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
  1211. if (sunxi_display.monitor == sunxi_monitor_dvi ||
  1212. sunxi_display.monitor == sunxi_monitor_hdmi) {
  1213. /* Always call hdp_detect, as it also enables clocks, etc. */
  1214. ret = sunxi_hdmi_hpd_detect(hpd_delay);
  1215. if (ret) {
  1216. printf("HDMI connected: ");
  1217. if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0)
  1218. mode = &custom;
  1219. } else if (hpd) {
  1220. sunxi_hdmi_shutdown();
  1221. sunxi_display.monitor = sunxi_get_default_mon(false);
  1222. } /* else continue with hdmi/dvi without a cable connected */
  1223. }
  1224. #endif
  1225. switch (sunxi_display.monitor) {
  1226. case sunxi_monitor_none:
  1227. return NULL;
  1228. case sunxi_monitor_dvi:
  1229. case sunxi_monitor_hdmi:
  1230. if (!sunxi_has_hdmi()) {
  1231. printf("HDMI/DVI not supported on this board\n");
  1232. sunxi_display.monitor = sunxi_monitor_none;
  1233. return NULL;
  1234. }
  1235. break;
  1236. case sunxi_monitor_lcd:
  1237. if (!sunxi_has_lcd()) {
  1238. printf("LCD not supported on this board\n");
  1239. sunxi_display.monitor = sunxi_monitor_none;
  1240. return NULL;
  1241. }
  1242. sunxi_display.depth = video_get_params(&custom, lcd_mode);
  1243. mode = &custom;
  1244. break;
  1245. case sunxi_monitor_vga:
  1246. if (!sunxi_has_vga()) {
  1247. printf("VGA not supported on this board\n");
  1248. sunxi_display.monitor = sunxi_monitor_none;
  1249. return NULL;
  1250. }
  1251. sunxi_display.depth = 18;
  1252. break;
  1253. case sunxi_monitor_composite_pal:
  1254. case sunxi_monitor_composite_ntsc:
  1255. case sunxi_monitor_composite_pal_m:
  1256. case sunxi_monitor_composite_pal_nc:
  1257. if (!sunxi_has_composite()) {
  1258. printf("Composite video not supported on this board\n");
  1259. sunxi_display.monitor = sunxi_monitor_none;
  1260. return NULL;
  1261. }
  1262. if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
  1263. sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
  1264. mode = &composite_video_modes[0];
  1265. else
  1266. mode = &composite_video_modes[1];
  1267. sunxi_display.depth = 24;
  1268. break;
  1269. }
  1270. /* Yes these defaults are quite high, overscan on composite sucks... */
  1271. if (overscan_x == -1)
  1272. overscan_x = sunxi_is_composite() ? 32 : 0;
  1273. if (overscan_y == -1)
  1274. overscan_y = sunxi_is_composite() ? 20 : 0;
  1275. sunxi_display.fb_size =
  1276. (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
  1277. overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
  1278. /* We want to keep the fb_base for simplefb page aligned, where as
  1279. * the sunxi dma engines will happily accept an unaligned address. */
  1280. if (overscan_offset)
  1281. sunxi_display.fb_size += 0x1000;
  1282. if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
  1283. printf("Error need %dkB for fb, but only %dkB is reserved\n",
  1284. sunxi_display.fb_size >> 10,
  1285. CONFIG_SUNXI_MAX_FB_SIZE >> 10);
  1286. return NULL;
  1287. }
  1288. printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
  1289. mode->xres, mode->yres,
  1290. (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
  1291. sunxi_get_mon_desc(sunxi_display.monitor),
  1292. overscan_x, overscan_y);
  1293. gd->fb_base = gd->bd->bi_dram[0].start +
  1294. gd->bd->bi_dram[0].size - sunxi_display.fb_size;
  1295. sunxi_engines_init();
  1296. fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
  1297. sunxi_display.fb_addr = gd->fb_base;
  1298. if (overscan_offset) {
  1299. fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
  1300. sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
  1301. memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
  1302. flush_cache(gd->fb_base, sunxi_display.fb_size);
  1303. }
  1304. sunxi_mode_set(mode, fb_dma_addr);
  1305. /*
  1306. * These are the only members of this structure that are used. All the
  1307. * others are driver specific. The pitch is stored in plnSizeX.
  1308. */
  1309. graphic_device->frameAdrs = sunxi_display.fb_addr;
  1310. graphic_device->gdfIndex = GDF_32BIT_X888RGB;
  1311. graphic_device->gdfBytesPP = 4;
  1312. graphic_device->winSizeX = mode->xres - 2 * overscan_x;
  1313. graphic_device->winSizeY = mode->yres - 2 * overscan_y;
  1314. graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
  1315. return graphic_device;
  1316. }
  1317. /*
  1318. * Simplefb support.
  1319. */
  1320. #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
  1321. int sunxi_simplefb_setup(void *blob)
  1322. {
  1323. static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
  1324. int offset, ret;
  1325. u64 start, size;
  1326. const char *pipeline = NULL;
  1327. #ifdef CONFIG_MACH_SUN4I
  1328. #define PIPELINE_PREFIX "de_fe0-"
  1329. #else
  1330. #define PIPELINE_PREFIX
  1331. #endif
  1332. switch (sunxi_display.monitor) {
  1333. case sunxi_monitor_none:
  1334. return 0;
  1335. case sunxi_monitor_dvi:
  1336. case sunxi_monitor_hdmi:
  1337. pipeline = PIPELINE_PREFIX "de_be0-lcd0-hdmi";
  1338. break;
  1339. case sunxi_monitor_lcd:
  1340. pipeline = PIPELINE_PREFIX "de_be0-lcd0";
  1341. break;
  1342. case sunxi_monitor_vga:
  1343. #ifdef CONFIG_VIDEO_VGA
  1344. pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
  1345. #elif defined CONFIG_VIDEO_VGA_VIA_LCD
  1346. pipeline = PIPELINE_PREFIX "de_be0-lcd0";
  1347. #endif
  1348. break;
  1349. case sunxi_monitor_composite_pal:
  1350. case sunxi_monitor_composite_ntsc:
  1351. case sunxi_monitor_composite_pal_m:
  1352. case sunxi_monitor_composite_pal_nc:
  1353. pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
  1354. break;
  1355. }
  1356. /* Find a prefilled simpefb node, matching out pipeline config */
  1357. offset = fdt_node_offset_by_compatible(blob, -1,
  1358. "allwinner,simple-framebuffer");
  1359. while (offset >= 0) {
  1360. ret = fdt_stringlist_search(blob, offset, "allwinner,pipeline",
  1361. pipeline);
  1362. if (ret == 0)
  1363. break;
  1364. offset = fdt_node_offset_by_compatible(blob, offset,
  1365. "allwinner,simple-framebuffer");
  1366. }
  1367. if (offset < 0) {
  1368. eprintf("Cannot setup simplefb: node not found\n");
  1369. return 0; /* Keep older kernels working */
  1370. }
  1371. /*
  1372. * Do not report the framebuffer as free RAM to the OS, note we cannot
  1373. * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
  1374. * and e.g. Linux refuses to iomap RAM on ARM, see:
  1375. * linux/arch/arm/mm/ioremap.c around line 301.
  1376. */
  1377. start = gd->bd->bi_dram[0].start;
  1378. size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
  1379. ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
  1380. if (ret) {
  1381. eprintf("Cannot setup simplefb: Error reserving memory\n");
  1382. return ret;
  1383. }
  1384. ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
  1385. graphic_device->winSizeX, graphic_device->winSizeY,
  1386. graphic_device->plnSizeX, "x8r8g8b8");
  1387. if (ret)
  1388. eprintf("Cannot setup simplefb: Error setting properties\n");
  1389. return ret;
  1390. }
  1391. #endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */