display.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * (C) Copyright 2012 CompuLab, Ltd. <www.compulab.co.il>
  3. *
  4. * Authors: Nikita Kiryanov <nikita@compulab.co.il>
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc.
  22. */
  23. #include <common.h>
  24. #include <asm/gpio.h>
  25. #include <asm/io.h>
  26. #include <stdio_dev.h>
  27. #include <asm/arch/dss.h>
  28. #include <lcd.h>
  29. #include <asm/arch-omap3/dss.h>
  30. DECLARE_GLOBAL_DATA_PTR;
  31. enum display_type {
  32. NONE,
  33. DVI,
  34. };
  35. #define CMAP_ADDR 0x80100000
  36. /*
  37. * The frame buffer is allocated before we have the chance to parse user input.
  38. * To make sure enough memory is allocated for all resolutions, we define
  39. * vl_{col | row} to the maximal resolution supported by OMAP3.
  40. */
  41. vidinfo_t panel_info = {
  42. .vl_col = 1400,
  43. .vl_row = 1050,
  44. .vl_bpix = LCD_BPP,
  45. .cmap = (ushort *)CMAP_ADDR,
  46. };
  47. static struct panel_config panel_cfg;
  48. static enum display_type lcd_def;
  49. /*
  50. * A note on DVI presets;
  51. * U-Boot can convert 8 bit BMP data to 16 bit BMP data, and OMAP DSS can
  52. * convert 16 bit data into 24 bit data. Thus, GFXFORMAT_RGB16 allows us to
  53. * support two BMP types with one setting.
  54. */
  55. static const struct panel_config preset_dvi_640X480 = {
  56. .lcd_size = PANEL_LCD_SIZE(640, 480),
  57. .timing_h = DSS_HBP(48) | DSS_HFP(16) | DSS_HSW(96),
  58. .timing_v = DSS_VBP(33) | DSS_VFP(10) | DSS_VSW(2),
  59. .divisor = 12 | (1 << 16),
  60. .data_lines = LCD_INTERFACE_24_BIT,
  61. .panel_type = ACTIVE_DISPLAY,
  62. .load_mode = 2,
  63. .gfx_format = GFXFORMAT_RGB16,
  64. };
  65. static const struct panel_config preset_dvi_800X600 = {
  66. .lcd_size = PANEL_LCD_SIZE(800, 600),
  67. .timing_h = DSS_HBP(88) | DSS_HFP(40) | DSS_HSW(128),
  68. .timing_v = DSS_VBP(23) | DSS_VFP(1) | DSS_VSW(4),
  69. .divisor = 8 | (1 << 16),
  70. .data_lines = LCD_INTERFACE_24_BIT,
  71. .panel_type = ACTIVE_DISPLAY,
  72. .load_mode = 2,
  73. .gfx_format = GFXFORMAT_RGB16,
  74. };
  75. static const struct panel_config preset_dvi_1024X768 = {
  76. .lcd_size = PANEL_LCD_SIZE(1024, 768),
  77. .timing_h = DSS_HBP(160) | DSS_HFP(24) | DSS_HSW(136),
  78. .timing_v = DSS_VBP(29) | DSS_VFP(3) | DSS_VSW(6),
  79. .divisor = 5 | (1 << 16),
  80. .data_lines = LCD_INTERFACE_24_BIT,
  81. .panel_type = ACTIVE_DISPLAY,
  82. .load_mode = 2,
  83. .gfx_format = GFXFORMAT_RGB16,
  84. };
  85. static const struct panel_config preset_dvi_1152X864 = {
  86. .lcd_size = PANEL_LCD_SIZE(1152, 864),
  87. .timing_h = DSS_HBP(256) | DSS_HFP(64) | DSS_HSW(128),
  88. .timing_v = DSS_VBP(32) | DSS_VFP(1) | DSS_VSW(3),
  89. .divisor = 3 | (1 << 16),
  90. .data_lines = LCD_INTERFACE_24_BIT,
  91. .panel_type = ACTIVE_DISPLAY,
  92. .load_mode = 2,
  93. .gfx_format = GFXFORMAT_RGB16,
  94. };
  95. static const struct panel_config preset_dvi_1280X960 = {
  96. .lcd_size = PANEL_LCD_SIZE(1280, 960),
  97. .timing_h = DSS_HBP(312) | DSS_HFP(96) | DSS_HSW(112),
  98. .timing_v = DSS_VBP(36) | DSS_VFP(1) | DSS_VSW(3),
  99. .divisor = 3 | (1 << 16),
  100. .data_lines = LCD_INTERFACE_24_BIT,
  101. .panel_type = ACTIVE_DISPLAY,
  102. .load_mode = 2,
  103. .gfx_format = GFXFORMAT_RGB16,
  104. };
  105. static const struct panel_config preset_dvi_1280X1024 = {
  106. .lcd_size = PANEL_LCD_SIZE(1280, 1024),
  107. .timing_h = DSS_HBP(248) | DSS_HFP(48) | DSS_HSW(112),
  108. .timing_v = DSS_VBP(38) | DSS_VFP(1) | DSS_VSW(3),
  109. .divisor = 3 | (1 << 16),
  110. .data_lines = LCD_INTERFACE_24_BIT,
  111. .panel_type = ACTIVE_DISPLAY,
  112. .load_mode = 2,
  113. .gfx_format = GFXFORMAT_RGB16,
  114. };
  115. /*
  116. * set_resolution_params()
  117. *
  118. * Due to usage of multiple display related APIs resolution data is located in
  119. * more than one place. This function updates them all.
  120. */
  121. static void set_resolution_params(int x, int y)
  122. {
  123. panel_cfg.lcd_size = PANEL_LCD_SIZE(x, y);
  124. panel_info.vl_col = x;
  125. panel_info.vl_row = y;
  126. lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
  127. }
  128. static void set_preset(const struct panel_config preset, int x_res, int y_res)
  129. {
  130. panel_cfg = preset;
  131. set_resolution_params(x_res, y_res);
  132. }
  133. static enum display_type set_dvi_preset(const struct panel_config preset,
  134. int x_res, int y_res)
  135. {
  136. set_preset(preset, x_res, y_res);
  137. return DVI;
  138. }
  139. /*
  140. * env_parse_displaytype() - parse display type.
  141. *
  142. * Parses the environment variable "displaytype", which contains the
  143. * name of the display type or preset, in which case it applies its
  144. * configurations.
  145. *
  146. * Returns the type of display that was specified.
  147. */
  148. static enum display_type env_parse_displaytype(char *displaytype)
  149. {
  150. if (!strncmp(displaytype, "dvi640x480", 10))
  151. return set_dvi_preset(preset_dvi_640X480, 640, 480);
  152. else if (!strncmp(displaytype, "dvi800x600", 10))
  153. return set_dvi_preset(preset_dvi_800X600, 800, 600);
  154. else if (!strncmp(displaytype, "dvi1024x768", 11))
  155. return set_dvi_preset(preset_dvi_1024X768, 1024, 768);
  156. else if (!strncmp(displaytype, "dvi1152x864", 11))
  157. return set_dvi_preset(preset_dvi_1152X864, 1152, 864);
  158. else if (!strncmp(displaytype, "dvi1280x960", 11))
  159. return set_dvi_preset(preset_dvi_1280X960, 1280, 960);
  160. else if (!strncmp(displaytype, "dvi1280x1024", 12))
  161. return set_dvi_preset(preset_dvi_1280X1024, 1280, 1024);
  162. return NONE;
  163. }
  164. int lcd_line_length;
  165. int lcd_color_fg;
  166. int lcd_color_bg;
  167. void *lcd_base;
  168. short console_col;
  169. short console_row;
  170. void *lcd_console_address;
  171. void lcd_ctrl_init(void *lcdbase)
  172. {
  173. struct prcm *prcm = (struct prcm *)PRCM_BASE;
  174. char *displaytype = getenv("displaytype");
  175. if (displaytype == NULL)
  176. return;
  177. lcd_def = env_parse_displaytype(displaytype);
  178. if (lcd_def == NONE)
  179. return;
  180. panel_cfg.frame_buffer = lcdbase;
  181. omap3_dss_panel_config(&panel_cfg);
  182. /*
  183. * Pixel clock is defined with many divisions and only few
  184. * multiplications of the system clock. Since DSS FCLK divisor is set
  185. * to 16 by default, we need to set it to a smaller value, like 3
  186. * (chosen via trial and error).
  187. */
  188. clrsetbits_le32(&prcm->clksel_dss, 0xF, 3);
  189. }
  190. void lcd_enable(void)
  191. {
  192. if (lcd_def == DVI) {
  193. gpio_direction_output(54, 0); /* Turn on DVI */
  194. omap3_dss_enable();
  195. }
  196. }
  197. void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) {}