- dcu and imx7 DM_VIDEO conversion

- lb070wv8 compatible in simple_panel driver
 - bmp_logo improvements for DM_VIDEO
 - EDID updates to filter supported modes
 - meson_dw_hdmi: support EDID mode filtering
 - dw_hdmi: support ddc-i2c-bus phandle for external I2C masters
 - fix rpi crash when firmware doesn't report connected display
 -----BEGIN PGP SIGNATURE-----
 
 iGwEABECACwWIQSC4hxrSoIUVfFO0kRM6ATMmsalXAUCXT6z3g4cYWd1c3RAZGVu
 eC5kZQAKCRBM6ATMmsalXNhfAJ9r0ewu4sKAiLZl7fcOoYYjgz30TACeIrchuxwH
 x9SiZYFntOLL0trK/O0=
 =ZsD5
 -----END PGP SIGNATURE-----

Merge tag 'video-for-2019.10' of https://gitlab.denx.de/u-boot/custodians/u-boot-video

- dcu and imx7 DM_VIDEO conversion
- lb070wv8 compatible in simple_panel driver
- bmp_logo improvements for DM_VIDEO
- EDID updates to filter supported modes
- meson_dw_hdmi: support EDID mode filtering
- dw_hdmi: support ddc-i2c-bus phandle for external I2C masters
- fix rpi crash when firmware doesn't report connected display
This commit is contained in:
Tom Rini 2019-07-29 09:02:46 -04:00
commit ad4a699cfe
32 changed files with 453 additions and 130 deletions

View File

@ -12,8 +12,10 @@
compatible = "toradex,colibri-imx6ull", "fsl,imx6ull"; compatible = "toradex,colibri-imx6ull", "fsl,imx6ull";
aliases { aliases {
u-boot,dm-pre-reloc;
mmc0 = &usdhc1; mmc0 = &usdhc1;
usb0 = &usbotg1; /* required for ums */ usb0 = &usbotg1; /* required for ums */
display0 = &lcdif;
}; };
chosen { chosen {
@ -156,6 +158,36 @@
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif_dat pinctrl-0 = <&pinctrl_lcdif_dat
&pinctrl_lcdif_ctrl>; &pinctrl_lcdif_ctrl>;
status = "okay";
display = <&display0>;
u-boot,dm-pre-reloc;
display0: display0 {
bits-per-pixel = <18>;
bus-width = <24>;
status = "okay";
display-timings {
native-mode = <&timing_vga>;
timing_vga: 640x480 {
u-boot,dm-pre-reloc;
clock-frequency = <25175000>;
hactive = <640>;
vactive = <480>;
hback-porch = <48>;
hfront-porch = <16>;
vback-porch = <33>;
vfront-porch = <10>;
hsync-len = <96>;
vsync-len = <2>;
de-active = <1>;
hsync-active = <0>;
vsync-active = <0>;
pixelclk-active = <0>;
};
};
};
}; };
/* PWM <A> */ /* PWM <A> */

View File

@ -113,29 +113,34 @@
}; };
&lcdif { &lcdif {
u-boot,dm-pre-reloc;
status = "okay"; status = "okay";
display = <&display0>;
u-boot,dm-pre-reloc;
display-timings { display0: display0 {
native-mode = <&timing_vga>; bits-per-pixel = <18>;
bus-width = <24>;
status = "okay";
/* Standard VGA timing */ display-timings {
timing_vga: 640x480 { native-mode = <&timing_vga>;
u-boot,dm-pre-reloc; timing_vga: 640x480 {
clock-frequency = <25175000>; u-boot,dm-pre-reloc;
hactive = <640>; clock-frequency = <25175000>;
vactive = <480>; hactive = <640>;
hback-porch = <48>; vactive = <480>;
hfront-porch = <16>; hback-porch = <48>;
vback-porch = <33>; hfront-porch = <16>;
vfront-porch = <10>; vback-porch = <33>;
hsync-len = <96>; vfront-porch = <10>;
vsync-len = <2>; hsync-len = <96>;
vsync-len = <2>;
de-active = <1>; de-active = <1>;
hsync-active = <0>; hsync-active = <0>;
vsync-active = <0>; vsync-active = <0>;
pixelclk-active = <0>; pixelclk-active = <0>;
};
}; };
}; };
}; };

View File

@ -21,3 +21,7 @@
&uart0 { &uart0 {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
&dcu0 {
u-boot,dm-pre-reloc;
};

View File

@ -14,6 +14,7 @@
aliases { aliases {
usb0 = &ehci0; /* required for ums */ usb0 = &ehci0; /* required for ums */
display1 = &dcu0;
}; };
reg_usbh_vbus: regulator-usbh-vbus { reg_usbh_vbus: regulator-usbh-vbus {
@ -241,3 +242,7 @@
pinctrl-0 = <&pinctrl_uart0>; pinctrl-0 = <&pinctrl_uart0>;
status = "okay"; status = "okay";
}; };
&dcu0 {
status = "okay";
};

View File

@ -145,6 +145,12 @@
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
dcu0: dcu@40058000 {
compatible = "fsl,vf610-dcu";
reg = <0x40058000 0x1200>;
status = "disabled";
};
ehci0: ehci@40034000 { ehci0: ehci@40034000 {
compatible = "fsl,vf610-usb"; compatible = "fsl,vf610-usb";
reg = <0x40034000 0x800>; reg = <0x40034000 0x800>;

View File

@ -554,7 +554,7 @@ const struct boot_mode soc_boot_modes[] = {
void reset_misc(void) void reset_misc(void)
{ {
#ifndef CONFIG_SPL_BUILD #ifndef CONFIG_SPL_BUILD
#ifdef CONFIG_VIDEO_MXS #if defined(CONFIG_VIDEO_MXS) && !defined(CONFIG_DM_VIDEO)
lcdif_power_down(); lcdif_power_down();
#endif #endif
#endif #endif

View File

@ -23,9 +23,10 @@ unsigned int dcu_set_pixel_clock(unsigned int pixclock)
return div; return div;
} }
int platform_dcu_init(unsigned int xres, unsigned int yres, int platform_dcu_init(struct fb_info *fbinfo,
const char *port, unsigned int xres, unsigned int yres,
struct fb_videomode *dcu_fb_videomode) const char *port,
struct fb_videomode *dcu_fb_videomode)
{ {
const char *name; const char *name;
unsigned int pixel_format; unsigned int pixel_format;
@ -40,7 +41,7 @@ int platform_dcu_init(unsigned int xres, unsigned int yres,
printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres); printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres);
pixel_format = 32; pixel_format = 32;
fsl_dcu_init(xres, yres, pixel_format); fsl_dcu_init(fbinfo, xres, yres, pixel_format);
return 0; return 0;
} }

View File

@ -39,7 +39,9 @@ unsigned int dcu_set_pixel_clock(unsigned int pixclock)
return div; return div;
} }
int platform_dcu_init(unsigned int xres, unsigned int yres, int platform_dcu_init(struct fb_info *fbinfo,
unsigned int xres,
unsigned int yres,
const char *port, const char *port,
struct fb_videomode *dcu_fb_videomode) struct fb_videomode *dcu_fb_videomode)
{ {
@ -85,7 +87,7 @@ int platform_dcu_init(unsigned int xres, unsigned int yres,
printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres); printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres);
pixel_format = 32; pixel_format = 32;
fsl_dcu_init(xres, yres, pixel_format); fsl_dcu_init(fbinfo, xres, yres, pixel_format);
return 0; return 0;
} }

View File

@ -23,7 +23,8 @@ unsigned int dcu_set_pixel_clock(unsigned int pixclock)
return div; return div;
} }
int platform_dcu_init(unsigned int xres, unsigned int yres, int platform_dcu_init(struct fb_info *fbinfo,
unsigned int xres, unsigned int yres,
const char *port, const char *port,
struct fb_videomode *dcu_fb_videomode) struct fb_videomode *dcu_fb_videomode)
{ {
@ -40,7 +41,7 @@ int platform_dcu_init(unsigned int xres, unsigned int yres,
printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres); printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres);
pixel_format = 32; pixel_format = 32;
fsl_dcu_init(xres, yres, pixel_format); fsl_dcu_init(fbinfo, xres, yres, pixel_format);
return 0; return 0;
} }

View File

@ -430,7 +430,9 @@ int checkboard(void)
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
int ft_board_setup(void *blob, bd_t *bd) int ft_board_setup(void *blob, bd_t *bd)
{ {
#ifndef CONFIG_DM_VIDEO
int ret = 0; int ret = 0;
#endif
#ifdef CONFIG_FDT_FIXUP_PARTITIONS #ifdef CONFIG_FDT_FIXUP_PARTITIONS
static const struct node_info nodes[] = { static const struct node_info nodes[] = {
{ "fsl,vf610-nfc", MTD_DEV_TYPE_NAND, }, /* NAND flash */ { "fsl,vf610-nfc", MTD_DEV_TYPE_NAND, }, /* NAND flash */
@ -440,7 +442,7 @@ int ft_board_setup(void *blob, bd_t *bd)
puts(" Updating MTD partitions...\n"); puts(" Updating MTD partitions...\n");
fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
#endif #endif
#ifdef CONFIG_VIDEO_FSL_DCU_FB #if defined(CONFIG_VIDEO_FSL_DCU_FB) && !defined(CONFIG_DM_VIDEO)
ret = fsl_dcu_fixedfb_setup(blob); ret = fsl_dcu_fixedfb_setup(blob);
if (ret) if (ret)
return ret; return ret;

View File

@ -26,11 +26,13 @@ unsigned int dcu_set_pixel_clock(unsigned int pixclock)
return div; return div;
} }
int platform_dcu_init(unsigned int xres, unsigned int yres, int platform_dcu_init(struct fb_info *fbinfo,
unsigned int xres,
unsigned int yres,
const char *port, const char *port,
struct fb_videomode *dcu_fb_videomode) struct fb_videomode *dcu_fb_videomode)
{ {
fsl_dcu_init(xres, yres, 32); fsl_dcu_init(fbinfo, xres, yres, 32);
return 0; return 0;
} }

View File

@ -168,8 +168,12 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info)
return false; return false;
} }
int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, int edid_get_timing_validate(u8 *buf, int buf_size,
int *panel_bits_per_colourp) struct display_timing *timing,
int *panel_bits_per_colourp,
bool (*mode_valid)(void *priv,
const struct display_timing *timing),
void *mode_valid_priv)
{ {
struct edid1_info *edid = (struct edid1_info *)buf; struct edid1_info *edid = (struct edid1_info *)buf;
bool timing_done; bool timing_done;
@ -193,7 +197,11 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
desc = &edid->monitor_details.descriptor[i]; desc = &edid->monitor_details.descriptor[i];
if (desc->zero_flag_1 != 0) { if (desc->zero_flag_1 != 0) {
decode_timing((u8 *)desc, timing); decode_timing((u8 *)desc, timing);
timing_done = true; if (mode_valid)
timing_done = mode_valid(mode_valid_priv,
timing);
else
timing_done = true;
break; break;
} }
} }
@ -225,6 +233,14 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
return 0; return 0;
} }
int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
int *panel_bits_per_colourp)
{
return edid_get_timing_validate(buf, buf_size, timing,
panel_bits_per_colourp, NULL, NULL);
}
/** /**
* Snip the tailing whitespace/return of a string. * Snip the tailing whitespace/return of a string.
* *

View File

@ -78,6 +78,6 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
CONFIG_USB_GADGET_PRODUCT_NUM=0x4000 CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
CONFIG_CI_UDC=y CONFIG_CI_UDC=y
CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_VIDEO=y CONFIG_DM_VIDEO=y
CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_FDT_FIXUP_PARTITIONS=y CONFIG_FDT_FIXUP_PARTITIONS=y

View File

@ -74,6 +74,6 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
CONFIG_USB_GADGET_PRODUCT_NUM=0x4000 CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
CONFIG_CI_UDC=y CONFIG_CI_UDC=y
CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_VIDEO=y CONFIG_DM_VIDEO=y
CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_FDT_FIXUP_PARTITIONS=y CONFIG_FDT_FIXUP_PARTITIONS=y

View File

@ -89,7 +89,7 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
CONFIG_CI_UDC=y CONFIG_CI_UDC=y
CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_VIDEO_FSL_DCU_FB=y CONFIG_VIDEO_FSL_DCU_FB=y
CONFIG_VIDEO=y CONFIG_DM_VIDEO=y
CONFIG_SYS_CONSOLE_FG_COL=0x00 CONFIG_SYS_CONSOLE_FG_COL=0x00
CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_FDT_FIXUP_PARTITIONS=y CONFIG_FDT_FIXUP_PARTITIONS=y

View File

@ -484,7 +484,7 @@ config VIDEO_IVYBRIDGE_IGD
config VIDEO_FSL_DCU_FB config VIDEO_FSL_DCU_FB
bool "Enable Freescale Display Control Unit" bool "Enable Freescale Display Control Unit"
depends on VIDEO depends on VIDEO || DM_VIDEO
help help
This enables support for Freescale Display Control Unit (DCU4) This enables support for Freescale Display Control Unit (DCU4)
module found on Freescale Vybrid and QorIQ family of SoCs. module found on Freescale Vybrid and QorIQ family of SoCs.

View File

@ -19,13 +19,15 @@ static int bcm2835_video_probe(struct udevice *dev)
debug("bcm2835: Query resolution...\n"); debug("bcm2835: Query resolution...\n");
ret = bcm2835_get_video_size(&w, &h); ret = bcm2835_get_video_size(&w, &h);
if (ret) if (ret || w == 0 || h == 0)
return -EIO; return -EIO;
debug("bcm2835: Setting up display for %d x %d\n", w, h); debug("bcm2835: Setting up display for %d x %d\n", w, h);
ret = bcm2835_set_video_params(&w, &h, 32, BCM2835_MBOX_PIXEL_ORDER_RGB, ret = bcm2835_set_video_params(&w, &h, 32, BCM2835_MBOX_PIXEL_ORDER_RGB,
BCM2835_MBOX_ALPHA_MODE_IGNORED, BCM2835_MBOX_ALPHA_MODE_IGNORED,
&fb_base, &fb_size, &pitch); &fb_base, &fb_size, &pitch);
if (ret)
return -EIO;
debug("bcm2835: Final resolution is %d x %d\n", w, h); debug("bcm2835: Final resolution is %d x %d\n", w, h);

View File

@ -37,6 +37,17 @@ int display_enable(struct udevice *dev, int panel_bpp,
return 0; return 0;
} }
static bool display_mode_valid(void *priv, const struct display_timing *timing)
{
struct udevice *dev = priv;
struct dm_display_ops *ops = display_get_ops(dev);
if (ops && ops->mode_valid)
return ops->mode_valid(dev, timing);
return true;
}
int display_read_timing(struct udevice *dev, struct display_timing *timing) int display_read_timing(struct udevice *dev, struct display_timing *timing)
{ {
struct dm_display_ops *ops = display_get_ops(dev); struct dm_display_ops *ops = display_get_ops(dev);
@ -53,7 +64,9 @@ int display_read_timing(struct udevice *dev, struct display_timing *timing)
if (ret < 0) if (ret < 0)
return ret; return ret;
return edid_get_timing(buf, ret, timing, &panel_bits_per_colour); return edid_get_timing_validate(buf, ret, timing,
&panel_bits_per_colour,
display_mode_valid, dev);
} }
bool display_in_use(struct udevice *dev) bool display_in_use(struct udevice *dev)

View File

@ -8,6 +8,7 @@
#include <common.h> #include <common.h>
#include <fdtdec.h> #include <fdtdec.h>
#include <asm/io.h> #include <asm/io.h>
#include <i2c.h>
#include <media_bus_format.h> #include <media_bus_format.h>
#include "dw_hdmi.h" #include "dw_hdmi.h"
@ -812,6 +813,18 @@ static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
u32 trytime = 5; u32 trytime = 5;
u32 n; u32 n;
if (CONFIG_IS_ENABLED(DM_I2C) && hdmi->ddc_bus) {
struct udevice *chip;
edid_read_err = i2c_get_chip(hdmi->ddc_bus,
HDMI_I2CM_SLAVE_DDC_ADDR,
1, &chip);
if (edid_read_err)
return edid_read_err;
return dm_i2c_read(chip, shift, buff, HDMI_EDID_BLOCK_SIZE);
}
/* set ddc i2c clk which devided from ddc_clk to 100khz */ /* set ddc i2c clk which devided from ddc_clk to 100khz */
hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR); hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR); hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);

View File

@ -1,16 +1,19 @@
// SPDX-License-Identifier: GPL-2.0+ // SPDX-License-Identifier: GPL-2.0+
/* /*
* Copyright 2014 Freescale Semiconductor, Inc. * Copyright 2014 Freescale Semiconductor, Inc.
* Copyright 2019 Toradex AG
* *
* FSL DCU Framebuffer driver * FSL DCU Framebuffer driver
*/ */
#include <asm/io.h> #include <asm/io.h>
#include <common.h> #include <common.h>
#include <dm.h>
#include <fdt_support.h> #include <fdt_support.h>
#include <fsl_dcu_fb.h> #include <fsl_dcu_fb.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <malloc.h> #include <malloc.h>
#include <video.h>
#include <video_fb.h> #include <video_fb.h>
#include "videomodes.h" #include "videomodes.h"
@ -218,8 +221,6 @@ struct dcu_reg {
u32 ctrldescl[DCU_LAYER_MAX_NUM][16]; u32 ctrldescl[DCU_LAYER_MAX_NUM][16];
}; };
static struct fb_info info;
static void reset_total_layers(void) static void reset_total_layers(void)
{ {
struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR; struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
@ -240,20 +241,22 @@ static void reset_total_layers(void)
} }
} }
static int layer_ctrldesc_init(int index, u32 pixel_format) static int layer_ctrldesc_init(struct fb_info fbinfo,
int index, u32 pixel_format)
{ {
struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR; struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
unsigned int bpp = BPP_24_RGB888; unsigned int bpp = BPP_24_RGB888;
dcu_write32(&regs->ctrldescl[index][0], dcu_write32(&regs->ctrldescl[index][0],
DCU_CTRLDESCLN_1_HEIGHT(info.var.yres) | DCU_CTRLDESCLN_1_HEIGHT(fbinfo.var.yres) |
DCU_CTRLDESCLN_1_WIDTH(info.var.xres)); DCU_CTRLDESCLN_1_WIDTH(fbinfo.var.xres));
dcu_write32(&regs->ctrldescl[index][1], dcu_write32(&regs->ctrldescl[index][1],
DCU_CTRLDESCLN_2_POSY(0) | DCU_CTRLDESCLN_2_POSY(0) |
DCU_CTRLDESCLN_2_POSX(0)); DCU_CTRLDESCLN_2_POSX(0));
dcu_write32(&regs->ctrldescl[index][2], (unsigned int)info.screen_base); dcu_write32(&regs->ctrldescl[index][2],
(unsigned int)fbinfo.screen_base);
switch (pixel_format) { switch (pixel_format) {
case 16: case 16:
@ -294,42 +297,46 @@ static int layer_ctrldesc_init(int index, u32 pixel_format)
return 0; return 0;
} }
int fsl_dcu_init(unsigned int xres, unsigned int yres, int fsl_dcu_init(struct fb_info *fbinfo, unsigned int xres,
unsigned int pixel_format) unsigned int yres, unsigned int pixel_format)
{ {
struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR; struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
unsigned int div, mode; unsigned int div, mode;
/*
* When DM_VIDEO is enabled reservation of framebuffer is done
* in advance during bind() call.
*/
#if !CONFIG_IS_ENABLED(DM_VIDEO)
fbinfo->screen_size = fbinfo->var.xres * fbinfo->var.yres *
(fbinfo->var.bits_per_pixel / 8);
info.screen_size = if (fbinfo->screen_size > CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB) {
info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8); fbinfo->screen_size = 0;
if (info.screen_size > CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB) {
info.screen_size = 0;
return -ENOMEM; return -ENOMEM;
} }
/* Reserve framebuffer at the end of memory */ /* Reserve framebuffer at the end of memory */
gd->fb_base = gd->bd->bi_dram[0].start + gd->fb_base = gd->bd->bi_dram[0].start +
gd->bd->bi_dram[0].size - info.screen_size; gd->bd->bi_dram[0].size - fbinfo->screen_size;
info.screen_base = (char *)gd->fb_base; fbinfo->screen_base = (char *)gd->fb_base;
memset(info.screen_base, 0, info.screen_size); memset(fbinfo->screen_base, 0, fbinfo->screen_size);
#endif
reset_total_layers(); reset_total_layers();
dcu_write32(&regs->disp_size, dcu_write32(&regs->disp_size,
DCU_DISP_SIZE_DELTA_Y(info.var.yres) | DCU_DISP_SIZE_DELTA_Y(fbinfo->var.yres) |
DCU_DISP_SIZE_DELTA_X(info.var.xres / 16)); DCU_DISP_SIZE_DELTA_X(fbinfo->var.xres / 16));
dcu_write32(&regs->hsyn_para, dcu_write32(&regs->hsyn_para,
DCU_HSYN_PARA_BP(info.var.left_margin) | DCU_HSYN_PARA_BP(fbinfo->var.left_margin) |
DCU_HSYN_PARA_PW(info.var.hsync_len) | DCU_HSYN_PARA_PW(fbinfo->var.hsync_len) |
DCU_HSYN_PARA_FP(info.var.right_margin)); DCU_HSYN_PARA_FP(fbinfo->var.right_margin));
dcu_write32(&regs->vsyn_para, dcu_write32(&regs->vsyn_para,
DCU_VSYN_PARA_BP(info.var.upper_margin) | DCU_VSYN_PARA_BP(fbinfo->var.upper_margin) |
DCU_VSYN_PARA_PW(info.var.vsync_len) | DCU_VSYN_PARA_PW(fbinfo->var.vsync_len) |
DCU_VSYN_PARA_FP(info.var.lower_margin)); DCU_VSYN_PARA_FP(fbinfo->var.lower_margin));
dcu_write32(&regs->synpol, dcu_write32(&regs->synpol,
DCU_SYN_POL_INV_PXCK_FALL | DCU_SYN_POL_INV_PXCK_FALL |
@ -352,9 +359,9 @@ int fsl_dcu_init(unsigned int xres, unsigned int yres,
mode = dcu_read32(&regs->mode); mode = dcu_read32(&regs->mode);
dcu_write32(&regs->mode, mode | DCU_MODE_NORMAL); dcu_write32(&regs->mode, mode | DCU_MODE_NORMAL);
layer_ctrldesc_init(0, pixel_format); layer_ctrldesc_init(*fbinfo, 0, pixel_format);
div = dcu_set_pixel_clock(info.var.pixclock); div = dcu_set_pixel_clock(fbinfo->var.pixclock);
dcu_write32(&regs->div_ratio, (div - 1)); dcu_write32(&regs->div_ratio, (div - 1));
dcu_write32(&regs->update_mode, DCU_UPDATE_MODE_READREG); dcu_write32(&regs->update_mode, DCU_UPDATE_MODE_READREG);
@ -367,24 +374,26 @@ ulong board_get_usable_ram_top(ulong total_size)
return gd->ram_top - CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB; return gd->ram_top - CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB;
} }
void *video_hw_init(void) int fsl_probe_common(struct fb_info *fbinfo, unsigned int *win_x,
unsigned int *win_y)
{ {
static GraphicDevice ctfb;
const char *options; const char *options;
unsigned int depth = 0, freq = 0; unsigned int depth = 0, freq = 0;
struct fb_videomode *fsl_dcu_mode_db = &fsl_dcu_mode_480_272; struct fb_videomode *fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq, if (!video_get_video_mode(win_x, win_y, &depth, &freq,
&options)) &options))
return NULL; return -EINVAL;
/* Find the monitor port, which is a required option */ /* Find the monitor port, which is a required option */
if (!options) if (!options)
return NULL; return -EINVAL;
if (strncmp(options, "monitor=", 8) != 0)
return NULL;
switch (RESOLUTION(ctfb.winSizeX, ctfb.winSizeY)) { if (strncmp(options, "monitor=", 8) != 0)
return -EINVAL;
switch (RESOLUTION(*win_x, *win_y)) {
case RESOLUTION(480, 272): case RESOLUTION(480, 272):
fsl_dcu_mode_db = &fsl_dcu_mode_480_272; fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
break; break;
@ -402,39 +411,31 @@ void *video_hw_init(void)
break; break;
default: default:
printf("unsupported resolution %ux%u\n", printf("unsupported resolution %ux%u\n",
ctfb.winSizeX, ctfb.winSizeY); *win_x, *win_y);
} }
info.var.xres = fsl_dcu_mode_db->xres; fbinfo->var.xres = fsl_dcu_mode_db->xres;
info.var.yres = fsl_dcu_mode_db->yres; fbinfo->var.yres = fsl_dcu_mode_db->yres;
info.var.bits_per_pixel = 32; fbinfo->var.bits_per_pixel = 32;
info.var.pixclock = fsl_dcu_mode_db->pixclock; fbinfo->var.pixclock = fsl_dcu_mode_db->pixclock;
info.var.left_margin = fsl_dcu_mode_db->left_margin; fbinfo->var.left_margin = fsl_dcu_mode_db->left_margin;
info.var.right_margin = fsl_dcu_mode_db->right_margin; fbinfo->var.right_margin = fsl_dcu_mode_db->right_margin;
info.var.upper_margin = fsl_dcu_mode_db->upper_margin; fbinfo->var.upper_margin = fsl_dcu_mode_db->upper_margin;
info.var.lower_margin = fsl_dcu_mode_db->lower_margin; fbinfo->var.lower_margin = fsl_dcu_mode_db->lower_margin;
info.var.hsync_len = fsl_dcu_mode_db->hsync_len; fbinfo->var.hsync_len = fsl_dcu_mode_db->hsync_len;
info.var.vsync_len = fsl_dcu_mode_db->vsync_len; fbinfo->var.vsync_len = fsl_dcu_mode_db->vsync_len;
info.var.sync = fsl_dcu_mode_db->sync; fbinfo->var.sync = fsl_dcu_mode_db->sync;
info.var.vmode = fsl_dcu_mode_db->vmode; fbinfo->var.vmode = fsl_dcu_mode_db->vmode;
info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8; fbinfo->fix.line_length = fbinfo->var.xres *
fbinfo->var.bits_per_pixel / 8;
if (platform_dcu_init(ctfb.winSizeX, ctfb.winSizeY, return platform_dcu_init(fbinfo, *win_x, *win_y,
options + 8, fsl_dcu_mode_db) < 0) options + 8, fsl_dcu_mode_db);
return NULL;
ctfb.frameAdrs = (unsigned int)info.screen_base;
ctfb.plnSizeX = ctfb.winSizeX;
ctfb.plnSizeY = ctfb.winSizeY;
ctfb.gdfBytesPP = 4;
ctfb.gdfIndex = GDF_32BIT_X888RGB;
ctfb.memSize = info.screen_size;
return &ctfb;
} }
#ifndef CONFIG_DM_VIDEO
static struct fb_info info;
#if defined(CONFIG_OF_BOARD_SETUP) #if defined(CONFIG_OF_BOARD_SETUP)
int fsl_dcu_fixedfb_setup(void *blob) int fsl_dcu_fixedfb_setup(void *blob)
{ {
@ -457,3 +458,89 @@ int fsl_dcu_fixedfb_setup(void *blob)
return 0; return 0;
} }
#endif #endif
void *video_hw_init(void)
{
static GraphicDevice ctfb;
if (fsl_probe_common(&info, &ctfb.winSizeX, &ctfb.winSizeY) < 0)
return NULL;
ctfb.frameAdrs = (unsigned int)info.screen_base;
ctfb.plnSizeX = ctfb.winSizeX;
ctfb.plnSizeY = ctfb.winSizeY;
ctfb.gdfBytesPP = 4;
ctfb.gdfIndex = GDF_32BIT_X888RGB;
ctfb.memSize = info.screen_size;
return &ctfb;
}
#else /* ifndef CONFIG_DM_VIDEO */
static int fsl_dcu_video_probe(struct udevice *dev)
{
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
struct fb_info fbinfo = { 0 };
unsigned int win_x;
unsigned int win_y;
u32 fb_start, fb_end;
int ret = 0;
fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
fb_end = plat->base + plat->size;
fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
fbinfo.screen_base = (char *)fb_start;
fbinfo.screen_size = plat->size;
ret = fsl_probe_common(&fbinfo, &win_x, &win_y);
if (ret < 0)
return ret;
uc_priv->bpix = VIDEO_BPP32;
uc_priv->xsize = win_x;
uc_priv->ysize = win_y;
/* Enable dcache for the frame buffer */
mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
DCACHE_WRITEBACK);
video_set_flush_dcache(dev, true);
return ret;
}
static int fsl_dcu_video_bind(struct udevice *dev)
{
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
unsigned int win_x;
unsigned int win_y;
unsigned int depth = 0, freq = 0;
const char *options;
int ret = 0;
ret = video_get_video_mode(&win_x, &win_y, &depth, &freq, &options);
if (ret < 0)
return ret;
plat->size = win_x * win_y * 32;
return 0;
}
static const struct udevice_id fsl_dcu_video_ids[] = {
{ .compatible = "fsl,vf610-dcu" },
{ /* sentinel */ }
};
U_BOOT_DRIVER(fsl_dcu_video) = {
.name = "fsl_dcu_video",
.id = UCLASS_VIDEO,
.of_match = fsl_dcu_video_ids,
.bind = fsl_dcu_video_bind,
.probe = fsl_dcu_video_probe,
.flags = DM_FLAG_PRE_RELOC,
};
#endif /* ifndef CONFIG_DM_VIDEO */

View File

@ -375,6 +375,9 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
} }
#endif #endif
uclass_get_device_by_phandle(UCLASS_I2C, dev, "ddc-i2c-bus",
&priv->hdmi.ddc_bus);
ret = reset_get_bulk(dev, &resets); ret = reset_get_bulk(dev, &resets);
if (ret) if (ret)
return ret; return ret;
@ -426,9 +429,16 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
return ret; return ret;
} }
static bool meson_dw_hdmi_mode_valid(struct udevice *dev,
const struct display_timing *timing)
{
return meson_venc_hdmi_supported_mode(timing);
}
static const struct dm_display_ops meson_dw_hdmi_ops = { static const struct dm_display_ops meson_dw_hdmi_ops = {
.read_edid = meson_dw_hdmi_read_edid, .read_edid = meson_dw_hdmi_read_edid,
.enable = meson_dw_hdmi_enable, .enable = meson_dw_hdmi_enable,
.mode_valid = meson_dw_hdmi_mode_valid,
}; };
static const struct udevice_id meson_dw_hdmi_ids[] = { static const struct udevice_id meson_dw_hdmi_ids[] = {

View File

@ -271,6 +271,42 @@ dealloc_fb:
} }
#else /* ifndef CONFIG_DM_VIDEO */ #else /* ifndef CONFIG_DM_VIDEO */
static int mxs_of_get_timings(struct udevice *dev,
struct display_timing *timings,
u32 *bpp)
{
int ret = 0;
u32 display_phandle;
ofnode display_node;
ret = ofnode_read_u32(dev_ofnode(dev), "display", &display_phandle);
if (ret) {
dev_err(dev, "required display property isn't provided\n");
return -EINVAL;
}
display_node = ofnode_get_by_phandle(display_phandle);
if (!ofnode_valid(display_node)) {
dev_err(dev, "failed to find display subnode\n");
return -EINVAL;
}
ret = ofnode_read_u32(display_node, "bits-per-pixel", bpp);
if (ret) {
dev_err(dev,
"required bits-per-pixel property isn't provided\n");
return -EINVAL;
}
ret = ofnode_decode_display_timing(display_node, 0, timings);
if (ret) {
dev_err(dev, "failed to get any display timings\n");
return -EINVAL;
}
return ret;
}
static int mxs_video_probe(struct udevice *dev) static int mxs_video_probe(struct udevice *dev)
{ {
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
@ -278,18 +314,16 @@ static int mxs_video_probe(struct udevice *dev)
struct ctfb_res_modes mode; struct ctfb_res_modes mode;
struct display_timing timings; struct display_timing timings;
int bpp = -1; u32 bpp = 0;
u32 fb_start, fb_end; u32 fb_start, fb_end;
int ret; int ret;
debug("%s() plat: base 0x%lx, size 0x%x\n", debug("%s() plat: base 0x%lx, size 0x%x\n",
__func__, plat->base, plat->size); __func__, plat->base, plat->size);
ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, &timings); ret = mxs_of_get_timings(dev, &timings, &bpp);
if (ret) { if (ret)
dev_err(dev, "failed to get any display timings\n"); return ret;
return -EINVAL;
}
mode.xres = timings.hactive.typ; mode.xres = timings.hactive.typ;
mode.yres = timings.vactive.typ; mode.yres = timings.vactive.typ;
@ -301,13 +335,12 @@ static int mxs_video_probe(struct udevice *dev)
mode.vsync_len = timings.vsync_len.typ; mode.vsync_len = timings.vsync_len.typ;
mode.pixclock = HZ2PS(timings.pixelclock.typ); mode.pixclock = HZ2PS(timings.pixelclock.typ);
bpp = BITS_PP;
ret = mxs_probe_common(&mode, bpp, plat->base); ret = mxs_probe_common(&mode, bpp, plat->base);
if (ret) if (ret)
return ret; return ret;
switch (bpp) { switch (bpp) {
case 32:
case 24: case 24:
case 18: case 18:
uc_priv->bpix = VIDEO_BPP32; uc_priv->bpix = VIDEO_BPP32;
@ -341,15 +374,32 @@ static int mxs_video_bind(struct udevice *dev)
{ {
struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
struct display_timing timings; struct display_timing timings;
u32 bpp = 0;
u32 bytes_pp = 0;
int ret; int ret;
ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, &timings); ret = mxs_of_get_timings(dev, &timings, &bpp);
if (ret) { if (ret)
dev_err(dev, "failed to get any display timings\n"); return ret;
switch (bpp) {
case 32:
case 24:
case 18:
bytes_pp = 4;
break;
case 16:
bytes_pp = 2;
break;
case 8:
bytes_pp = 1;
break;
default:
dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp);
return -EINVAL; return -EINVAL;
} }
plat->size = timings.hactive.typ * timings.vactive.typ * BYTES_PP; plat->size = timings.hactive.typ * timings.vactive.typ * bytes_pp;
return 0; return 0;
} }

View File

@ -93,6 +93,9 @@ int rk_hdmi_ofdata_to_platdata(struct udevice *dev)
priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
uclass_get_device_by_phandle(UCLASS_I2C, dev, "ddc-i2c-bus",
&hdmi->ddc_bus);
return 0; return 0;
} }

View File

@ -105,6 +105,7 @@ static const struct udevice_id simple_panel_ids[] = {
{ .compatible = "auo,b133xtn01" }, { .compatible = "auo,b133xtn01" },
{ .compatible = "auo,b116xw03" }, { .compatible = "auo,b116xw03" },
{ .compatible = "auo,b133htn01" }, { .compatible = "auo,b133htn01" },
{ .compatible = "lg,lb070wv8" },
{ } { }
}; };

View File

@ -373,6 +373,9 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
priv->hdmi.phy_set = sunxi_dw_hdmi_phy_cfg; priv->hdmi.phy_set = sunxi_dw_hdmi_phy_cfg;
priv->mux = uc_plat->source_id; priv->mux = uc_plat->source_id;
uclass_get_device_by_phandle(UCLASS_I2C, dev, "ddc-i2c-bus",
&priv->hdmi.ddc_bus);
dw_hdmi_init(&priv->hdmi); dw_hdmi_init(&priv->hdmi);
return 0; return 0;

View File

@ -170,7 +170,7 @@
#define CONFIG_SYS_DFU_DATA_BUF_SIZE SZ_16M #define CONFIG_SYS_DFU_DATA_BUF_SIZE SZ_16M
#define DFU_DEFAULT_POLL_TIMEOUT 300 #define DFU_DEFAULT_POLL_TIMEOUT 300
#ifdef CONFIG_VIDEO #if defined(CONFIG_VIDEO) || defined(CONFIG_DM_VIDEO)
#define CONFIG_VIDEO_MXS #define CONFIG_VIDEO_MXS
#define MXS_LCDIF_BASE MX6UL_LCDIF1_BASE_ADDR #define MXS_LCDIF_BASE MX6UL_LCDIF1_BASE_ADDR
#define CONFIG_VIDEO_LOGO #define CONFIG_VIDEO_LOGO

View File

@ -80,6 +80,16 @@ struct dm_display_ops {
*/ */
int (*enable)(struct udevice *dev, int panel_bpp, int (*enable)(struct udevice *dev, int panel_bpp,
const struct display_timing *timing); const struct display_timing *timing);
/**
* mode_valid() - Check if mode is supported
*
* @dev: Device to enable
* @timing: Display timings
* @return true if supported, false if not
*/
bool (*mode_valid)(struct udevice *dev,
const struct display_timing *timing);
}; };
#define display_get_ops(dev) ((struct dm_display_ops *)(dev)->driver->ops) #define display_get_ops(dev) ((struct dm_display_ops *)(dev)->driver->ops)

View File

@ -542,6 +542,7 @@ struct dw_hdmi {
u8 i2c_clk_low; u8 i2c_clk_low;
u8 reg_io_width; u8 reg_io_width;
struct hdmi_data_info hdmi_data; struct hdmi_data_info hdmi_data;
struct udevice *ddc_bus;
int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock); int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
void (*write_reg)(struct dw_hdmi *hdmi, u8 val, int offset); void (*write_reg)(struct dw_hdmi *hdmi, u8 val, int offset);

View File

@ -306,6 +306,28 @@ int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin,
struct display_timing; struct display_timing;
/**
* edid_get_timing_validate() - Get basic digital display parameters with
* mode selection callback
*
* @param buf Buffer containing EDID data
* @param buf_size Size of buffer in bytes
* @param timing Place to put preferring timing information
* @param panel_bits_per_colourp Place to put the number of bits per
* colour supported by the panel. This will be set to
* -1 if not available
* @param mode_valid Callback validating mode, returning true is mode is
* supported, false otherwise.
* @parem valid_priv Pointer to private data for mode_valid callback
* @return 0 if timings are OK, -ve on error
*/
int edid_get_timing_validate(u8 *buf, int buf_size,
struct display_timing *timing,
int *panel_bits_per_colourp,
bool (*mode_valid)(void *priv,
const struct display_timing *timing),
void *mode_valid_priv);
/** /**
* edid_get_timing() - Get basic digital display parameters * edid_get_timing() - Get basic digital display parameters
* *

View File

@ -6,11 +6,17 @@
*/ */
#include <linux/fb.h> #include <linux/fb.h>
int fsl_dcu_init(unsigned int xres, unsigned int yres, int fsl_dcu_init(struct fb_info *fbinfo,
unsigned int xres,
unsigned int yres,
unsigned int pixel_format); unsigned int pixel_format);
int fsl_dcu_fixedfb_setup(void *blob); int fsl_dcu_fixedfb_setup(void *blob);
/* Prototypes for external board-specific functions */ /* Prototypes for external board-specific functions */
int platform_dcu_init(unsigned int xres, unsigned int yres, int platform_dcu_init(struct fb_info *fbinfo,
const char *port, struct fb_videomode *dcu_fb_videomode); unsigned int xres,
unsigned int yres,
const char *port,
struct fb_videomode *dcu_fb_videomode);
unsigned int dcu_set_pixel_clock(unsigned int pixclock); unsigned int dcu_set_pixel_clock(unsigned int pixclock);

View File

@ -269,8 +269,14 @@ __build: $(LOGO-y)
$(LOGO_H): $(obj)/bmp_logo $(LOGO_BMP) $(LOGO_H): $(obj)/bmp_logo $(LOGO_BMP)
$(obj)/bmp_logo --gen-info $(LOGO_BMP) > $@ $(obj)/bmp_logo --gen-info $(LOGO_BMP) > $@
ifeq ($(CONFIG_DM_VIDEO),y)
$(LOGO_DATA_H): $(obj)/bmp_logo $(LOGO_BMP)
$(obj)/bmp_logo --gen-bmp $(LOGO_BMP) > $@
else
$(LOGO_DATA_H): $(obj)/bmp_logo $(LOGO_BMP) $(LOGO_DATA_H): $(obj)/bmp_logo $(LOGO_BMP)
$(obj)/bmp_logo --gen-data $(LOGO_BMP) > $@ $(obj)/bmp_logo --gen-data $(LOGO_BMP) > $@
#endif
endif
# Let clean descend into subdirs # Let clean descend into subdirs
subdir- += env subdir- += env

View File

@ -2,7 +2,8 @@
enum { enum {
MODE_GEN_INFO, MODE_GEN_INFO,
MODE_GEN_DATA MODE_GEN_DATA,
MODE_GEN_BMP
}; };
typedef struct bitmap_s { /* bitmap description */ typedef struct bitmap_s { /* bitmap description */
@ -16,7 +17,8 @@ typedef struct bitmap_s { /* bitmap description */
void usage(const char *prog) void usage(const char *prog)
{ {
fprintf(stderr, "Usage: %s [--gen-info|--gen-data] file\n", prog); fprintf(stderr, "Usage: %s [--gen-info|--gen-data|--gen-bmp] file\n",
prog);
} }
/* /*
@ -73,6 +75,7 @@ void gen_info(bitmap_t *b, uint16_t n_colors)
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
int mode, i, x; int mode, i, x;
int size;
FILE *fp; FILE *fp;
bitmap_t bmp; bitmap_t bmp;
bitmap_t *b = &bmp; bitmap_t *b = &bmp;
@ -87,6 +90,8 @@ int main (int argc, char *argv[])
mode = MODE_GEN_INFO; mode = MODE_GEN_INFO;
else if (!strcmp(argv[1], "--gen-data")) else if (!strcmp(argv[1], "--gen-data"))
mode = MODE_GEN_DATA; mode = MODE_GEN_DATA;
else if (!strcmp(argv[1], "--gen-bmp"))
mode = MODE_GEN_BMP;
else { else {
usage(argv[0]); usage(argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -131,6 +136,7 @@ int main (int argc, char *argv[])
b->width = le_short(b->width); b->width = le_short(b->width);
b->height = le_short(b->height); b->height = le_short(b->height);
n_colors = le_short(n_colors); n_colors = le_short(n_colors);
size = b->width * b->height;
/* assume we are working with an 8-bit file */ /* assume we are working with an 8-bit file */
if ((n_colors == 0) || (n_colors > 256 - DEFAULT_CMAP_SIZE)) { if ((n_colors == 0) || (n_colors > 256 - DEFAULT_CMAP_SIZE)) {
@ -152,10 +158,6 @@ int main (int argc, char *argv[])
"#ifndef __BMP_LOGO_DATA_H__\n" "#ifndef __BMP_LOGO_DATA_H__\n"
"#define __BMP_LOGO_DATA_H__\n\n"); "#define __BMP_LOGO_DATA_H__\n\n");
/* allocate memory */
if ((b->data = (uint8_t *)malloc(b->width * b->height)) == NULL)
error ("Error allocating memory for file", fp);
/* read and print the palette information */ /* read and print the palette information */
printf("unsigned short bmp_logo_palette[] = {\n"); printf("unsigned short bmp_logo_palette[] = {\n");
@ -175,21 +177,39 @@ int main (int argc, char *argv[])
} }
/* seek to offset indicated by file header */ /* seek to offset indicated by file header */
fseek(fp, (long)data_offset, SEEK_SET); if (mode == MODE_GEN_BMP) {
/* copy full bmp file */
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
} else {
fseek(fp, (long)data_offset, SEEK_SET);
}
/* allocate memory */
b->data = (uint8_t *)malloc(size);
if (!b->data)
error("Error allocating memory for file", fp);
/* read the bitmap; leave room for default color map */ /* read the bitmap; leave room for default color map */
printf ("\n"); printf ("\n");
printf ("};\n"); printf ("};\n");
printf ("\n"); printf ("\n");
printf("unsigned char bmp_logo_bitmap[] = {\n"); printf("unsigned char bmp_logo_bitmap[] = {\n");
for (i=(b->height-1)*b->width; i>=0; i-=b->width) { if (mode == MODE_GEN_BMP) {
for (x = 0; x < b->width; x++) { /* write full bmp */
b->data[i + x] = (uint8_t) fgetc(fp) for (i = 0; i < size; i++)
b->data[i] = (uint8_t)fgetc(fp);
} else {
for (i = (b->height - 1) * b->width; i >= 0; i -= b->width) {
for (x = 0; x < b->width; x++) {
b->data[i + x] = (uint8_t)fgetc(fp)
+ DEFAULT_CMAP_SIZE; + DEFAULT_CMAP_SIZE;
}
} }
} }
for (i=0; i<(b->height*b->width); ++i) { for (i = 0; i < size; ++i) {
if ((i%8) == 0) if ((i%8) == 0)
putchar ('\t'); putchar ('\t');
printf ("0x%02X,%c", printf ("0x%02X,%c",