+ /* HACK ALERT:
+ * global variable from common/lcd.c
+ * Set to 0 here to prevent messages from going to LCD
+ * rather than serial console
+ */
+ lcd_is_enabled = 0;
+
+ karo_load_splashimage(1);
+ if (lcd_enabled) {
+ debug("Switching LCD on\n");
+ gpio_set_value(TX28_LCD_PWR_GPIO, 1);
+ udelay(100);
+ gpio_set_value(TX28_LCD_RST_GPIO, 1);
+ udelay(300000);
+ gpio_set_value(TX28_LCD_BACKLIGHT_GPIO,
+ lcd_backlight_polarity());
+ }
+}
+
+void lcd_disable(void)
+{
+}
+
+void lcd_panel_disable(void)
+{
+ if (lcd_enabled) {
+ debug("Switching LCD off\n");
+ gpio_set_value(TX28_LCD_BACKLIGHT_GPIO,
+ !lcd_backlight_polarity());
+ gpio_set_value(TX28_LCD_RST_GPIO, 0);
+ gpio_set_value(TX28_LCD_PWR_GPIO, 0);
+ }
+}
+
+static const iomux_cfg_t stk5_lcd_pads[] = {
+ /* LCD RESET */
+ MX28_PAD_LCD_RESET__GPIO_3_30 | MXS_PAD_CTRL,
+ /* LCD POWER_ENABLE */
+ MX28_PAD_LCD_ENABLE__GPIO_1_31 | MXS_PAD_CTRL,
+ /* LCD Backlight (PWM) */
+ MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
+
+ /* Display */
+ MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+ MX28_PAD_LCD_RD_E__LCD_VSYNC | MXS_PAD_CTRL,
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MXS_PAD_CTRL,
+ MX28_PAD_LCD_RS__LCD_DOTCLK | MXS_PAD_CTRL,
+ MX28_PAD_LCD_CS__LCD_CS | MXS_PAD_CTRL,
+};
+
+static const struct gpio stk5_lcd_gpios[] = {
+ { TX28_LCD_RST_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD RESET", },
+ { TX28_LCD_PWR_GPIO, GPIOFLAG_OUTPUT_INIT_LOW, "LCD POWER", },
+ { TX28_LCD_BACKLIGHT_GPIO, GPIOFLAG_OUTPUT_INIT_HIGH, "LCD BACKLIGHT", },
+};
+
+extern void video_hw_init(void *lcdbase);
+
+void lcd_ctrl_init(void *lcdbase)
+{
+ int color_depth = 24;
+ const char *video_mode = karo_get_vmode(getenv("video_mode"));
+ const char *vm;
+ unsigned long val;
+ int refresh = 60;
+ struct fb_videomode *p = tx28_fb_modes;
+ struct fb_videomode fb_mode;
+ int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0;
+
+ if (!lcd_enabled) {
+ debug("LCD disabled\n");
+ return;
+ }
+
+ if (had_ctrlc()) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ setenv("splashimage", NULL);
+ return;
+ }
+
+ karo_fdt_move_fdt();
+ lcd_bl_polarity = karo_fdt_get_backlight_polarity(working_fdt);
+
+ if (video_mode == NULL) {
+ debug("Disabling LCD\n");
+ lcd_enabled = 0;
+ return;
+ }
+ vm = video_mode;
+ if (karo_fdt_get_fb_mode(working_fdt, video_mode, &fb_mode) == 0) {
+ p = &fb_mode;
+ debug("Using video mode from FDT\n");
+ vm += strlen(vm);
+ if (fb_mode.xres > panel_info.vl_col ||
+ fb_mode.yres > panel_info.vl_row) {
+ printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n",
+ fb_mode.xres, fb_mode.yres,
+ panel_info.vl_col, panel_info.vl_row);
+ lcd_enabled = 0;
+ return;
+ }
+ }
+ if (p->name != NULL)
+ debug("Trying compiled-in video modes\n");
+ while (p->name != NULL) {
+ if (strcmp(p->name, vm) == 0) {
+ debug("Using video mode: '%s'\n", p->name);
+ vm += strlen(vm);
+ break;
+ }
+ p++;
+ }
+ if (*vm != '\0')
+ debug("Trying to decode video_mode: '%s'\n", vm);
+ while (*vm != '\0') {
+ if (*vm >= '0' && *vm <= '9') {
+ char *end;
+
+ val = simple_strtoul(vm, &end, 0);
+ if (end > vm) {
+ if (!xres_set) {
+ if (val > panel_info.vl_col)
+ val = panel_info.vl_col;
+ p->xres = val;
+ panel_info.vl_col = val;
+ xres_set = 1;
+ } else if (!yres_set) {
+ if (val > panel_info.vl_row)
+ val = panel_info.vl_row;
+ p->yres = val;
+ panel_info.vl_row = val;
+ yres_set = 1;
+ } else if (!bpp_set) {
+ switch (val) {
+ case 8:
+ case 16:
+ case 18:
+ case 24:
+ color_depth = val;
+ break;
+
+ default:
+ printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n",
+ end - vm, vm, color_depth);
+ }
+ bpp_set = 1;
+ } else if (!refresh_set) {
+ refresh = val;
+ refresh_set = 1;
+ }
+ }
+ vm = end;
+ }
+ switch (*vm) {
+ case '@':
+ bpp_set = 1;
+ /* fallthru */
+ case '-':
+ yres_set = 1;
+ /* fallthru */
+ case 'x':
+ xres_set = 1;
+ /* fallthru */
+ case 'M':
+ case 'R':
+ vm++;