X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fvideo%2Fmxc_ipuv3_fb.c;h=6a147d5186af55d5a0cbccdff9cfd5c772154d7b;hb=778c3cbd857f4abe54773f399204dd86ffe6516c;hp=a66981c27c9f86bedaf3d719aedc4ad8352f120d;hpb=73bb4c72407aca3c2f461708bb872a23f2b1bf5a;p=karo-tx-uboot.git diff --git a/drivers/video/mxc_ipuv3_fb.c b/drivers/video/mxc_ipuv3_fb.c index a66981c27c..6a147d5186 100644 --- a/drivers/video/mxc_ipuv3_fb.c +++ b/drivers/video/mxc_ipuv3_fb.c @@ -4,27 +4,11 @@ * (C) Copyright 2010 * Stefano Babic, DENX Software Engineering, sbabic@denx.de * - * MX51 Linux framebuffer: + * IPUv3 Linux framebuffer: * - * (C) Copyright 2004-2010 Freescale Semiconductor, Inc. + * (C) Copyright 2004-2011 Freescale Semiconductor, Inc. * - * 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 + * SPDX-License-Identifier: GPL-2.0+ */ /* #define DEBUG */ @@ -36,24 +20,13 @@ #include #include #include +#include +#include +#include #include "videomodes.h" -#include "ipu.h" -#include "mxcfb.h" DECLARE_GLOBAL_DATA_PTR; -void *lcd_base; /* Start of framebuffer memory */ -void *lcd_console_address; /* Start of console buffer */ - -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; - -short console_col; -short console_row; - -vidinfo_t panel_info; - static int mxcfb_map_video_memory(struct fb_info *fbi); static int mxcfb_unmap_video_memory(struct fb_info *fbi); @@ -65,15 +38,7 @@ void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) { } -void lcd_disable(void) -{ -} - -void lcd_panel_disable(void) -{ -} - -void fb_videomode_to_var(struct fb_var_screeninfo *var, +static void fb_videomode_to_var(struct fb_var_screeninfo *var, const struct fb_videomode *mode) { var->xres = mode->xres; @@ -145,6 +110,8 @@ static uint32_t bpp_to_pixfmt(struct fb_info *fbi) case 16: pixfmt = IPU_PIX_FMT_RGB565; break; + case 8: + pixfmt = IPU_PIX_FMT_GENERIC; } return pixfmt; } @@ -173,7 +140,7 @@ static int mxcfb_set_fix(struct fb_info *info) static int setup_disp_channel1(struct fb_info *fbi) { ipu_channel_params_t params; - struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par; + struct mxcfb_info *mxc_fbi = fbi->par; memset(¶ms, 0, sizeof(params)); params.mem_dp_bg_sync.di = mxc_fbi->ipu_di; @@ -208,7 +175,7 @@ static int setup_disp_channel1(struct fb_info *fbi) static int setup_disp_channel2(struct fb_info *fbi) { int retval = 0; - struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par; + struct mxcfb_info *mxc_fbi = fbi->par; mxc_fbi->cur_ipu_buf = 1; if (mxc_fbi->alpha_chan_en) @@ -216,7 +183,7 @@ static int setup_disp_channel2(struct fb_info *fbi) fbi->var.xoffset = fbi->var.yoffset = 0; - debug("%s: %x %d %d %d %lx %lx\n", + debug("%s: ch: %08x xres: %d yres: %d line_length: %d mem: %08lx .. %08lx\n", __func__, mxc_fbi->ipu_ch, fbi->var.xres, @@ -224,7 +191,7 @@ static int setup_disp_channel2(struct fb_info *fbi) fbi->fix.line_length, fbi->fix.smem_start, fbi->fix.smem_start + - (fbi->fix.line_length * fbi->var.yres)); + (fbi->fix.line_length * fbi->var.yres) - 1); retval = ipu_init_channel_buffer(mxc_fbi->ipu_ch, IPU_INPUT_BUFFER, bpp_to_pixfmt(fbi), @@ -250,7 +217,7 @@ static int mxcfb_set_par(struct fb_info *fbi) int retval = 0; u32 mem_len; ipu_di_signal_cfg_t sig_cfg; - struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par; + struct mxcfb_info *mxc_fbi = fbi->par; uint32_t out_pixel_fmt; ipu_disable_channel(mxc_fbi->ipu_ch); @@ -295,10 +262,11 @@ static int mxcfb_set_par(struct fb_info *fbi) if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN) sig_cfg.clkidle_en = 1; - debug("pixclock = %ul Hz\n", - (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL)); + debug("pixclock = %lu.%03lu MHz\n", + PICOS2KHZ(fbi->var.pixclock) / 1000, + PICOS2KHZ(fbi->var.pixclock) % 1000); - if (ipu_init_sync_panel(mxc_fbi->ipu_di, + retval = ipu_init_sync_panel(mxc_fbi->ipu_di, (PICOS2KHZ(fbi->var.pixclock)) * 1000UL, fbi->var.xres, fbi->var.yres, out_pixel_fmt, @@ -308,9 +276,10 @@ static int mxcfb_set_par(struct fb_info *fbi) fbi->var.upper_margin, fbi->var.vsync_len, fbi->var.lower_margin, - 0, sig_cfg) != 0) { - puts("mxcfb: Error initializing panel.\n"); - return -EINVAL; + 0, sig_cfg); + if (retval != 0) { + printf("mxc_ipuv3_fb: Error %d initializing panel\n", retval); + return retval; } retval = setup_disp_channel2(fbi); @@ -439,24 +408,22 @@ static int mxcfb_map_video_memory(struct fb_info *fbi) fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length; } - - fbi->screen_base = (char *)lcd_base; - fbi->fix.smem_start = (unsigned long)lcd_base; - if (fbi->screen_base == 0) { + if (gd->fb_base) + fbi->screen_base = (void *)gd->fb_base; + else + fbi->screen_base = malloc(fbi->fix.smem_len); + if (fbi->screen_base == NULL) { puts("Unable to allocate framebuffer memory\n"); fbi->fix.smem_len = 0; - fbi->fix.smem_start = 0; return -EBUSY; } + fbi->fix.smem_start = (unsigned long)fbi->screen_base; debug("allocated fb @ paddr=0x%08X, size=%d.\n", (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len); fbi->screen_size = fbi->fix.smem_len; - /* Clear the screen */ - memset((char *)fbi->screen_base, 0, fbi->fix.smem_len); - return 0; } @@ -479,17 +446,14 @@ static int mxcfb_unmap_video_memory(struct fb_info *fbi) */ static struct fb_info *mxcfb_init_fbinfo(void) { -#define BYTES_PER_LONG 4 -#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG)) struct fb_info *fbi; struct mxcfb_info *mxcfbi; - char *p; - int size = sizeof(struct mxcfb_info) + PADDING + + void *p; + int size = ALIGN(sizeof(struct mxcfb_info), sizeof(long)) + sizeof(struct fb_info); - debug("%s: %d %d %d %d\n", + debug("%s: %d %d %d\n", __func__, - PADDING, size, sizeof(struct mxcfb_info), sizeof(struct fb_info)); @@ -503,12 +467,12 @@ static struct fb_info *mxcfb_init_fbinfo(void) memset(p, 0, size); - fbi = (struct fb_info *)p; - fbi->par = p + sizeof(struct fb_info) + PADDING; + fbi = p; + fbi->par = p + ALIGN(sizeof(struct fb_info), sizeof(long)); - mxcfbi = (struct mxcfb_info *)fbi->par; - debug("Framebuffer structures at: fbi=0x%x mxcfbi=0x%x\n", - (unsigned int)fbi, (unsigned int)mxcfbi); + mxcfbi = fbi->par; + debug("Framebuffer structures at: fbi=%p mxcfbi=%p\n", + fbi, mxcfbi); fbi->var.activate = FB_ACTIVATE_NOW; @@ -526,21 +490,19 @@ static struct fb_info *mxcfb_init_fbinfo(void) * * @return Appropriate error code to the kernel common code */ -static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) +static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode, int di) { struct fb_info *fbi; struct mxcfb_info *mxcfbi; - int ret = 0; /* * Initialize FB structures */ fbi = mxcfb_init_fbinfo(); - if (!fbi) { - ret = -ENOMEM; - goto err0; - } - mxcfbi = (struct mxcfb_info *)fbi->par; + if (!fbi) + return -ENOMEM; + + mxcfbi = fbi->par; if (!g_dp_in_use) { mxcfbi->ipu_ch = MEM_BG_SYNC; @@ -550,7 +512,7 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) mxcfbi->blank = FB_BLANK_POWERDOWN; } - mxcfbi->ipu_di = 0; + mxcfbi->ipu_di = di; ipu_disp_set_global_alpha(mxcfbi->ipu_ch, 1, 0x80); ipu_disp_set_color_key(mxcfbi->ipu_ch, 0, 0); @@ -561,12 +523,14 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) mxcfb_info[mxcfbi->ipu_di] = fbi; /* Need dummy values until real panel is configured */ - fbi->var.xres = 640; - fbi->var.yres = 480; - fbi->var.bits_per_pixel = 16; + fbi->var.xres = panel_info.vl_col; + fbi->var.yres = panel_info.vl_row; mxcfbi->ipu_di_pix_fmt = interface_pix_fmt; fb_videomode_to_var(&fbi->var, mode); + fbi->var.bits_per_pixel = NBITS(panel_info.vl_bpix); + fbi->fix.line_length = fbi->var.xres * (fbi->var.bits_per_pixel / 8); + fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length; mxcfb_check_var(&fbi->var, fbi); @@ -575,18 +539,12 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) mxcfb_set_fix(fbi); - /* alocate fb first */ + /* allocate fb first */ if (mxcfb_map_video_memory(fbi) < 0) return -ENOMEM; mxcfb_set_par(fbi); - /* Setting panel_info for lcd */ - panel_info.cmap = NULL; - panel_info.vl_col = fbi->var.xres; - panel_info.vl_row = fbi->var.yres; - panel_info.vl_bpix = LCD_BPP; - lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; debug("MXC IPUV3 configured\n" @@ -598,45 +556,26 @@ static int mxcfb_probe(u32 interface_pix_fmt, struct fb_videomode *mode) ipu_dump_registers(); return 0; - -err0: - return ret; } -int overwrite_console(void) +ulong calc_fbsize(void) { - /* Keep stdout / stderr on serial, our LCD is for splashscreen only */ - return 1; + return (panel_info.vl_col * panel_info.vl_row * + NBITS(panel_info.vl_bpix)) / 8; } -void lcd_ctrl_init(void *lcdbase) -{ - u32 mem_len = panel_info.vl_col * - panel_info.vl_row * - NBITS(panel_info.vl_bpix) / 8; - - /* - * We rely on lcdbase being a physical address, i.e., either MMU off, - * or 1-to-1 mapping. Might want to add some virt2phys here. - */ - if (!lcdbase) - return; - - memset(lcdbase, 0, mem_len); -} - -int mx51_fb_init(struct fb_videomode *mode) +int ipuv3_fb_init(struct fb_videomode *mode, int di, unsigned int interface_pix_fmt, + ipu_di_clk_parent_t di_clk_parent, unsigned long di_clk_val, int bpp) { int ret; - ret = ipu_probe(); - if (ret) - puts("Error initializing IPU\n"); - - lcd_base += 56; + default_bpp = bpp; - debug("Framebuffer at 0x%x\n", (unsigned int)lcd_base); - ret = mxcfb_probe(IPU_PIX_FMT_RGB666, mode); + ret = ipu_probe(di, di_clk_parent, di_clk_val); + if (ret) { + printf("Error initializing IPU\n"); + return ret; + } - return ret; + return mxcfb_probe(interface_pix_fmt, mode, di); }