+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2007, 2010-2011 Freescale Semiconductor, Inc.
* Authors: York Sun <yorksun@freescale.com>
* Timur Tabi <timur@freescale.com>
*
* FSL DIU Framebuffer driver
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
*/
#include <common.h>
#include "videomodes.h"
#include <video_fb.h>
#include <fsl_diu_fb.h>
-
-struct fb_var_screeninfo {
- unsigned int xres; /* visible resolution */
- unsigned int yres;
-
- unsigned int bits_per_pixel; /* guess what */
-
- /* Timing: All values in pixclocks, except pixclock (of course) */
- unsigned int pixclock; /* pixel clock in ps (pico seconds) */
- unsigned int left_margin; /* time from sync to picture */
- unsigned int right_margin; /* time from picture to sync */
- unsigned int upper_margin; /* time from sync to picture */
- unsigned int lower_margin;
- unsigned int hsync_len; /* length of horizontal sync */
- unsigned int vsync_len; /* length of vertical sync */
- unsigned int sync; /* see FB_SYNC_* */
- unsigned int vmode; /* see FB_VMODE_* */
- unsigned int rotate; /* angle we rotate counter clockwise */
-};
-
-struct fb_info {
- struct fb_var_screeninfo var; /* Current var */
- unsigned int smem_len; /* Length of frame buffer mem */
- unsigned int type; /* see FB_TYPE_* */
- unsigned int line_length; /* length of a line in bytes */
-
- void *screen_base;
- unsigned long screen_size;
-};
-
-struct fb_videomode {
- const char *name; /* optional */
- unsigned int refresh; /* optional */
- unsigned int xres;
- unsigned int yres;
- unsigned int pixclock;
- unsigned int left_margin;
- unsigned int right_margin;
- unsigned int upper_margin;
- unsigned int lower_margin;
- unsigned int hsync_len;
- unsigned int vsync_len;
- unsigned int sync;
- unsigned int vmode;
- unsigned int flag;
-};
-
-#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
-#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
-#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
+#include <linux/list.h>
+#include <linux/fb.h>
/* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
-static struct fb_videomode fsl_diu_mode_800 = {
- .name = "800x600-60",
+static struct fb_videomode fsl_diu_mode_800_480 = {
+ .name = "800x480-60",
.refresh = 60,
.xres = 800,
.yres = 480,
.vmode = FB_VMODE_NONINTERLACED
};
+/* For the SHARP LQ084S3LG01, used on the P1022DS board */
+static struct fb_videomode fsl_diu_mode_800_600 = {
+ .name = "800x600-60",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 25000,
+ .left_margin = 88,
+ .right_margin = 40,
+ .upper_margin = 23,
+ .lower_margin = 1,
+ .hsync_len = 128,
+ .vsync_len = 4,
+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
/*
* These parameters give default parameters
* for video output 1024x768,
* FIXME - change timing to proper amounts
* hsync 31.5kHz, vsync 60Hz
*/
-static struct fb_videomode fsl_diu_mode_1024 = {
+static struct fb_videomode fsl_diu_mode_1024_768 = {
.name = "1024x768-60",
.refresh = 60,
.xres = 1024,
.vmode = FB_VMODE_NONINTERLACED
};
-static struct fb_videomode fsl_diu_mode_1280 = {
+static struct fb_videomode fsl_diu_mode_1280_1024 = {
.name = "1280x1024-60",
.refresh = 60,
.xres = 1280,
.vmode = FB_VMODE_NONINTERLACED
};
+static struct fb_videomode fsl_diu_mode_1280_720 = {
+ .name = "1280x720-60",
+ .refresh = 60,
+ .xres = 1280,
+ .yres = 720,
+ .pixclock = 13426,
+ .left_margin = 192,
+ .right_margin = 64,
+ .upper_margin = 22,
+ .lower_margin = 1,
+ .hsync_len = 136,
+ .vsync_len = 3,
+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
+static struct fb_videomode fsl_diu_mode_1920_1080 = {
+ .name = "1920x1080-60",
+ .refresh = 60,
+ .xres = 1920,
+ .yres = 1080,
+ .pixclock = 5787,
+ .left_margin = 328,
+ .right_margin = 120,
+ .upper_margin = 34,
+ .lower_margin = 1,
+ .hsync_len = 208,
+ .vsync_len = 3,
+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
/*
* These are the fields of area descriptor(in DDR memory) for every plane
*/
* point to the framebuffer memory. Memory is aligned as needed.
*/
static struct diu_ad *allocate_fb(unsigned int xres, unsigned int yres,
- unsigned int depth, void **fb)
+ unsigned int depth, char **fb)
{
unsigned long size = xres * yres * depth;
struct diu_addr addr;
return ad;
}
-int fsl_diu_init(int xres, u32 pixel_format, int gamma_fix)
+int fsl_diu_init(u16 xres, u16 yres, u32 pixel_format, int gamma_fix)
{
struct fb_videomode *fsl_diu_mode_db;
struct diu_ad *ad;
struct diu *hw = (struct diu *)CONFIG_SYS_DIU_ADDR;
u8 *gamma_table_base;
unsigned int i, j;
- struct diu_ad *dummy_ad;
struct diu_addr gamma;
struct diu_addr cursor;
- switch (xres) {
- case 800:
- fsl_diu_mode_db = &fsl_diu_mode_800;
+/* Convert the X,Y resolution pair into a single number */
+#define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
+
+ switch (RESOLUTION(xres, yres)) {
+ case RESOLUTION(800, 480):
+ fsl_diu_mode_db = &fsl_diu_mode_800_480;
+ break;
+ case RESOLUTION(800, 600):
+ fsl_diu_mode_db = &fsl_diu_mode_800_600;
+ break;
+ case RESOLUTION(1024, 768):
+ fsl_diu_mode_db = &fsl_diu_mode_1024_768;
break;
- case 1280:
- fsl_diu_mode_db = &fsl_diu_mode_1280;
+ case RESOLUTION(1280, 1024):
+ fsl_diu_mode_db = &fsl_diu_mode_1280_1024;
+ break;
+ case RESOLUTION(1280, 720):
+ fsl_diu_mode_db = &fsl_diu_mode_1280_720;
+ break;
+ case RESOLUTION(1920, 1080):
+ fsl_diu_mode_db = &fsl_diu_mode_1920_1080;
break;
default:
- fsl_diu_mode_db = &fsl_diu_mode_1024;
- }
-
- /* The AD struct for the dummy framebuffer and the FB itself */
- dummy_ad = allocate_fb(2, 4, 4, NULL);
- if (!dummy_ad) {
- printf("DIU: Out of memory\n");
+ printf("DIU: Unsupported resolution %ux%u\n", xres, yres);
return -1;
}
- dummy_ad->pix_fmt = 0x88883316;
/* read mode info */
info.var.xres = fsl_diu_mode_db->xres;
info.var.vsync_len = fsl_diu_mode_db->vsync_len;
info.var.sync = fsl_diu_mode_db->sync;
info.var.vmode = fsl_diu_mode_db->vmode;
- info.line_length = info.var.xres * info.var.bits_per_pixel / 8;
+ info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
/* Memory allocation for framebuffer */
- info.smem_len =
+ info.screen_size =
info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
ad = allocate_fb(info.var.xres, info.var.yres,
info.var.bits_per_pixel / 8, &info.screen_base);
out_be32(&hw->gamma, gamma.paddr);
out_be32(&hw->cursor, cursor.paddr);
out_be32(&hw->bgnd, 0x007F7F7F);
- out_be32(&hw->bgnd_wb, 0);
out_be32(&hw->disp_size, info.var.yres << 16 | info.var.xres);
- out_be32(&hw->wb_size, 0);
- out_be32(&hw->wb_mem_addr, 0);
out_be32(&hw->hsyn_para, info.var.left_margin << 22 |
info.var.hsync_len << 11 |
info.var.right_margin);
info.var.vsync_len << 11 |
info.var.lower_margin);
- out_be32(&hw->syn_pol, 0);
- out_be32(&hw->thresholds, 0x00037800);
- out_be32(&hw->int_status, 0);
- out_be32(&hw->int_mask, 0);
- out_be32(&hw->plut, 0x01F5F666);
/* Pixel Clock configuration */
diu_set_pixel_clock(info.var.pixclock);
/* Set the frame buffers */
out_be32(&hw->desc[0], virt_to_phys(ad));
- out_be32(&hw->desc[1], virt_to_phys(dummy_ad));
- out_be32(&hw->desc[2], virt_to_phys(dummy_ad));
+ out_be32(&hw->desc[1], 0);
+ out_be32(&hw->desc[2], 0);
/* Enable the DIU, set display to all three planes */
out_be32(&hw->diu_mode, 1);