Commit a3671bd8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fbdev-for-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev

Pull fbdev fixes from Helge Deller:
 "The majority of lines changed is due to a code style cleanup in the
  pnmtologo helper program.

  Arnd removed the omap1 osk driver and the SIS fb driver is now
  orphaned.

  Other than that it's the usual bunch of small fixes and cleanups, e.g.
  prevent possible divide-by-zero in various fb drivers if the pixclock
  is zero and various conversions to devm_platform*() and of_property*()
  functions:

   - Drop omap1 osk driver

   - Various potential divide by zero pixclock fixes

   - Add pixelclock and fb_check_var() to stifb

   - Code style cleanups and indenting fixes"

* tag 'fbdev-for-6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev:
  fbdev: Use of_property_present() for testing DT property presence
  fbdev: au1200fb: Fix potential divide by zero
  fbdev: lxfb: Fix potential divide by zero
  fbdev: intelfb: Fix potential divide by zero
  fbdev: nvidia: Fix potential divide by zero
  fbdev: stifb: Provide valid pixelclock and add fb_check_var() checks
  fbdev: omapfb: remove omap1 osk driver
  fbdev: xilinxfb: Use devm_platform_get_and_ioremap_resource()
  fbdev: wm8505fb: Use devm_platform_ioremap_resource()
  fbdev: pxa3xx-gcu: Use devm_platform_get_and_ioremap_resource()
  fbdev: Use of_property_read_bool() for boolean properties
  fbdev: clps711x-fb: Use devm_platform_get_and_ioremap_resource()
  fbdev: tgafb: Fix potential divide by zero
  MAINTAINERS: orphan SIS FRAMEBUFFER DRIVER
  fbdev: omapfb: cleanup inconsistent indentation
  drivers: video: logo: add SPDX comment, remove GPL notice in pnmtologo.c
  drivers: video: logo: fix code style issues in pnmtologo.c
parents 53429336 29413f05
...@@ -19150,9 +19150,7 @@ W: http://www.brownhat.org/sis900.html ...@@ -19150,9 +19150,7 @@ W: http://www.brownhat.org/sis900.html
F: drivers/net/ethernet/sis/sis900.* F: drivers/net/ethernet/sis/sis900.*
SIS FRAMEBUFFER DRIVER SIS FRAMEBUFFER DRIVER
M: Thomas Winischhofer <thomas@winischhofer.net> S: Orphan
S: Maintained
W: http://www.winischhofer.net/linuxsisvga.shtml
F: Documentation/fb/sisfb.rst F: Documentation/fb/sisfb.rst
F: drivers/video/fbdev/sis/ F: drivers/video/fbdev/sis/
F: include/video/sisfb.h F: include/video/sisfb.h
......
...@@ -854,7 +854,7 @@ static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev) ...@@ -854,7 +854,7 @@ static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
board->caps = CLCD_CAP_ALL; board->caps = CLCD_CAP_ALL;
board->check = clcdfb_check; board->check = clcdfb_check;
board->decode = clcdfb_decode; board->decode = clcdfb_decode;
if (of_find_property(node, "memory-region", NULL)) { if (of_property_present(node, "memory-region")) {
board->setup = clcdfb_of_vram_setup; board->setup = clcdfb_of_vram_setup;
board->mmap = clcdfb_of_vram_mmap; board->mmap = clcdfb_of_vram_mmap;
board->remove = clcdfb_of_vram_remove; board->remove = clcdfb_of_vram_remove;
......
...@@ -1040,6 +1040,9 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, ...@@ -1040,6 +1040,9 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
u32 pixclock; u32 pixclock;
int screen_size, plane; int screen_size, plane;
if (!var->pixclock)
return -EINVAL;
plane = fbdev->plane; plane = fbdev->plane;
/* Make sure that the mode respect all LCD controller and /* Make sure that the mode respect all LCD controller and
......
...@@ -306,7 +306,7 @@ static int bw2_probe(struct platform_device *op) ...@@ -306,7 +306,7 @@ static int bw2_probe(struct platform_device *op)
if (!par->regs) if (!par->regs)
goto out_release_fb; goto out_release_fb;
if (!of_find_property(dp, "width", NULL)) { if (!of_property_present(dp, "width")) {
err = bw2_do_default_mode(par, info, &linebytes); err = bw2_do_default_mode(par, info, &linebytes);
if (err) if (err)
goto out_unmap_regs; goto out_unmap_regs;
......
...@@ -393,7 +393,7 @@ static int cg3_probe(struct platform_device *op) ...@@ -393,7 +393,7 @@ static int cg3_probe(struct platform_device *op)
cg3_blank(FB_BLANK_UNBLANK, info); cg3_blank(FB_BLANK_UNBLANK, info);
if (!of_find_property(dp, "width", NULL)) { if (!of_property_present(dp, "width")) {
err = cg3_do_default_mode(par); err = cg3_do_default_mode(par);
if (err) if (err)
goto out_unmap_screen; goto out_unmap_screen;
......
...@@ -238,8 +238,7 @@ static int clps711x_fb_probe(struct platform_device *pdev) ...@@ -238,8 +238,7 @@ static int clps711x_fb_probe(struct platform_device *pdev)
info->fix.mmio_start = res->start; info->fix.mmio_start = res->start;
info->fix.mmio_len = resource_size(res); info->fix.mmio_len = resource_size(res);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); info->screen_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
info->screen_base = devm_ioremap_resource(dev, res);
if (IS_ERR(info->screen_base)) { if (IS_ERR(info->screen_base)) {
ret = PTR_ERR(info->screen_base); ret = PTR_ERR(info->screen_base);
goto out_fb_release; goto out_fb_release;
......
...@@ -235,6 +235,9 @@ static void get_modedb(struct fb_videomode **modedb, unsigned int *size) ...@@ -235,6 +235,9 @@ static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{ {
if (!var->pixclock)
return -EINVAL;
if (var->xres > 1920 || var->yres > 1440) if (var->xres > 1920 || var->yres > 1440)
return -EINVAL; return -EINVAL;
......
...@@ -1222,6 +1222,9 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, ...@@ -1222,6 +1222,9 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
dinfo = GET_DINFO(info); dinfo = GET_DINFO(info);
if (!var->pixclock)
return -EINVAL;
/* update the pitch */ /* update the pitch */
if (intelfbhw_validate_mode(dinfo, var) != 0) if (intelfbhw_validate_mode(dinfo, var) != 0)
return -EINVAL; return -EINVAL;
......
...@@ -764,6 +764,8 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var, ...@@ -764,6 +764,8 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var,
int pitch, err = 0; int pitch, err = 0;
NVTRACE_ENTER(); NVTRACE_ENTER();
if (!var->pixclock)
return -EINVAL;
var->transp.offset = 0; var->transp.offset = 0;
var->transp.length = 0; var->transp.length = 0;
......
...@@ -549,10 +549,10 @@ static void offb_init_nodriver(struct platform_device *parent, struct device_nod ...@@ -549,10 +549,10 @@ static void offb_init_nodriver(struct platform_device *parent, struct device_nod
int foreign_endian = 0; int foreign_endian = 0;
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
if (of_get_property(dp, "little-endian", NULL)) if (of_property_read_bool(dp, "little-endian"))
foreign_endian = FBINFO_FOREIGN_ENDIAN; foreign_endian = FBINFO_FOREIGN_ENDIAN;
#else #else
if (of_get_property(dp, "big-endian", NULL)) if (of_property_read_bool(dp, "big-endian"))
foreign_endian = FBINFO_FOREIGN_ENDIAN; foreign_endian = FBINFO_FOREIGN_ENDIAN;
#endif #endif
......
...@@ -18,7 +18,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o ...@@ -18,7 +18,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
lcds-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o lcds-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
lcds-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o lcds-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
lcds-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
lcds-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o lcds-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* LCD panel support for the TI OMAP OSK board
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
* Adapted for OSK by <dirk.behme@de.bosch.com>
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/soc/ti/omap1-io.h>
#include <linux/soc/ti/omap1-mux.h>
#include "omapfb.h"
static int osk_panel_enable(struct lcd_panel *panel)
{
/* configure PWL pin */
omap_cfg_reg(PWL);
/* Enable PWL unit */
omap_writeb(0x01, OMAP_PWL_CLK_ENABLE);
/* Set PWL level */
omap_writeb(0xFF, OMAP_PWL_ENABLE);
/* set GPIO2 high (lcd power enabled) */
gpio_set_value(2, 1);
return 0;
}
static void osk_panel_disable(struct lcd_panel *panel)
{
/* Set PWL level to zero */
omap_writeb(0x00, OMAP_PWL_ENABLE);
/* Disable PWL unit */
omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
/* set GPIO2 low */
gpio_set_value(2, 0);
}
static struct lcd_panel osk_panel = {
.name = "osk",
.config = OMAP_LCDC_PANEL_TFT,
.bpp = 16,
.data_lines = 16,
.x_res = 240,
.y_res = 320,
.pixel_clock = 12500,
.hsw = 40,
.hfp = 40,
.hbp = 72,
.vsw = 1,
.vfp = 1,
.vbp = 0,
.pcd = 12,
.enable = osk_panel_enable,
.disable = osk_panel_disable,
};
static int osk_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&osk_panel);
return 0;
}
static struct platform_driver osk_panel_driver = {
.probe = osk_panel_probe,
.driver = {
.name = "lcd_osk",
},
};
module_platform_driver(osk_panel_driver);
MODULE_AUTHOR("Imre Deak");
MODULE_DESCRIPTION("LCD panel support for the TI OMAP OSK board");
MODULE_LICENSE("GPL");
...@@ -544,19 +544,25 @@ static int set_fb_var(struct fb_info *fbi, ...@@ -544,19 +544,25 @@ static int set_fb_var(struct fb_info *fbi,
var->yoffset = var->yres_virtual - var->yres; var->yoffset = var->yres_virtual - var->yres;
if (plane->color_mode == OMAPFB_COLOR_RGB444) { if (plane->color_mode == OMAPFB_COLOR_RGB444) {
var->red.offset = 8; var->red.length = 4; var->red.offset = 8;
var->red.msb_right = 0; var->red.length = 4;
var->green.offset = 4; var->green.length = 4; var->red.msb_right = 0;
var->green.msb_right = 0; var->green.offset = 4;
var->blue.offset = 0; var->blue.length = 4; var->green.length = 4;
var->blue.msb_right = 0; var->green.msb_right = 0;
var->blue.offset = 0;
var->blue.length = 4;
var->blue.msb_right = 0;
} else { } else {
var->red.offset = 11; var->red.length = 5; var->red.offset = 11;
var->red.msb_right = 0; var->red.length = 5;
var->green.offset = 5; var->green.length = 6; var->red.msb_right = 0;
var->green.msb_right = 0; var->green.offset = 5;
var->blue.offset = 0; var->blue.length = 5; var->green.length = 6;
var->blue.msb_right = 0; var->green.msb_right = 0;
var->blue.offset = 0;
var->blue.length = 5;
var->blue.msb_right = 0;
} }
var->height = -1; var->height = -1;
......
...@@ -192,7 +192,7 @@ static int __init omapdss_boot_init(void) ...@@ -192,7 +192,7 @@ static int __init omapdss_boot_init(void)
omapdss_walk_device(dss, true); omapdss_walk_device(dss, true);
for_each_available_child_of_node(dss, child) { for_each_available_child_of_node(dss, child) {
if (!of_find_property(child, "compatible", NULL)) if (!of_property_present(child, "compatible"))
continue; continue;
omapdss_walk_device(child, true); omapdss_walk_device(child, true);
......
...@@ -599,8 +599,7 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev) ...@@ -599,8 +599,7 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev)
priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops; priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops;
/* handle IO resources */ /* handle IO resources */
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
priv->mmio_base = devm_ioremap_resource(dev, r);
if (IS_ERR(priv->mmio_base)) if (IS_ERR(priv->mmio_base))
return PTR_ERR(priv->mmio_base); return PTR_ERR(priv->mmio_base);
......
...@@ -1737,10 +1737,10 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head, ...@@ -1737,10 +1737,10 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head,
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
if (of_get_property(info->dev->parent->of_node, "little-endian", NULL)) if (of_property_read_bool(info->dev->parent->of_node, "little-endian"))
fb->flags |= FBINFO_FOREIGN_ENDIAN; fb->flags |= FBINFO_FOREIGN_ENDIAN;
#else #else
if (of_get_property(info->dev->parent->of_node, "big-endian", NULL)) if (of_property_read_bool(info->dev->parent->of_node, "big-endian"))
fb->flags |= FBINFO_FOREIGN_ENDIAN; fb->flags |= FBINFO_FOREIGN_ENDIAN;
#endif #endif
#endif #endif
......
...@@ -921,6 +921,28 @@ SETUP_HCRX(struct stifb_info *fb) ...@@ -921,6 +921,28 @@ SETUP_HCRX(struct stifb_info *fb)
/* ------------------- driver specific functions --------------------------- */ /* ------------------- driver specific functions --------------------------- */
static int
stifb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct stifb_info *fb = container_of(info, struct stifb_info, info);
if (var->xres != fb->info.var.xres ||
var->yres != fb->info.var.yres ||
var->bits_per_pixel != fb->info.var.bits_per_pixel)
return -EINVAL;
var->xres_virtual = var->xres;
var->yres_virtual = var->yres;
var->xoffset = 0;
var->yoffset = 0;
var->grayscale = fb->info.var.grayscale;
var->red.length = fb->info.var.red.length;
var->green.length = fb->info.var.green.length;
var->blue.length = fb->info.var.blue.length;
return 0;
}
static int static int
stifb_setcolreg(u_int regno, u_int red, u_int green, stifb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp, struct fb_info *info) u_int blue, u_int transp, struct fb_info *info)
...@@ -1145,6 +1167,7 @@ stifb_init_display(struct stifb_info *fb) ...@@ -1145,6 +1167,7 @@ stifb_init_display(struct stifb_info *fb)
static const struct fb_ops stifb_ops = { static const struct fb_ops stifb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_check_var = stifb_check_var,
.fb_setcolreg = stifb_setcolreg, .fb_setcolreg = stifb_setcolreg,
.fb_blank = stifb_blank, .fb_blank = stifb_blank,
.fb_fillrect = stifb_fillrect, .fb_fillrect = stifb_fillrect,
...@@ -1164,6 +1187,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) ...@@ -1164,6 +1187,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
struct stifb_info *fb; struct stifb_info *fb;
struct fb_info *info; struct fb_info *info;
unsigned long sti_rom_address; unsigned long sti_rom_address;
char modestr[32];
char *dev_name; char *dev_name;
int bpp, xres, yres; int bpp, xres, yres;
...@@ -1342,6 +1366,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) ...@@ -1342,6 +1366,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
info->flags = FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; info->flags = FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
info->pseudo_palette = &fb->pseudo_palette; info->pseudo_palette = &fb->pseudo_palette;
scnprintf(modestr, sizeof(modestr), "%dx%d-%d", xres, yres, bpp);
fb_find_mode(&info->var, info, modestr, NULL, 0, NULL, bpp);
/* This has to be done !!! */ /* This has to be done !!! */
if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0)) if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0))
goto out_err1; goto out_err1;
......
...@@ -379,8 +379,7 @@ static int tcx_probe(struct platform_device *op) ...@@ -379,8 +379,7 @@ static int tcx_probe(struct platform_device *op)
spin_lock_init(&par->lock); spin_lock_init(&par->lock);
par->lowdepth = par->lowdepth = of_property_read_bool(dp, "tcx-8-bit");
(of_find_property(dp, "tcx-8-bit", NULL) != NULL);
sbusfb_fill_var(&info->var, dp, 8); sbusfb_fill_var(&info->var, dp, 8);
info->var.red.length = 8; info->var.red.length = 8;
......
...@@ -173,6 +173,9 @@ tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -173,6 +173,9 @@ tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{ {
struct tga_par *par = (struct tga_par *)info->par; struct tga_par *par = (struct tga_par *)info->par;
if (!var->pixclock)
return -EINVAL;
if (par->tga_type == TGA_TYPE_8PLANE) { if (par->tga_type == TGA_TYPE_8PLANE) {
if (var->bits_per_pixel != 8) if (var->bits_per_pixel != 8)
return -EINVAL; return -EINVAL;
......
...@@ -261,7 +261,6 @@ static const struct fb_ops wm8505fb_ops = { ...@@ -261,7 +261,6 @@ static const struct fb_ops wm8505fb_ops = {
static int wm8505fb_probe(struct platform_device *pdev) static int wm8505fb_probe(struct platform_device *pdev)
{ {
struct wm8505fb_info *fbi; struct wm8505fb_info *fbi;
struct resource *res;
struct display_timings *disp_timing; struct display_timings *disp_timing;
void *addr; void *addr;
int ret; int ret;
...@@ -299,8 +298,7 @@ static int wm8505fb_probe(struct platform_device *pdev) ...@@ -299,8 +298,7 @@ static int wm8505fb_probe(struct platform_device *pdev)
addr = addr + sizeof(struct wm8505fb_info); addr = addr + sizeof(struct wm8505fb_info);
fbi->fb.pseudo_palette = addr; fbi->fb.pseudo_palette = addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); fbi->regbase = devm_platform_ioremap_resource(pdev, 0);
fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(fbi->regbase)) if (IS_ERR(fbi->regbase))
return PTR_ERR(fbi->regbase); return PTR_ERR(fbi->regbase);
......
...@@ -273,8 +273,7 @@ static int xilinxfb_assign(struct platform_device *pdev, ...@@ -273,8 +273,7 @@ static int xilinxfb_assign(struct platform_device *pdev,
if (drvdata->flags & BUS_ACCESS_FLAG) { if (drvdata->flags & BUS_ACCESS_FLAG) {
struct resource *res; struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); drvdata->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
drvdata->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(drvdata->regs)) if (IS_ERR(drvdata->regs))
return PTR_ERR(drvdata->regs); return PTR_ERR(drvdata->regs);
...@@ -469,8 +468,7 @@ static int xilinxfb_of_probe(struct platform_device *pdev) ...@@ -469,8 +468,7 @@ static int xilinxfb_of_probe(struct platform_device *pdev)
pdata.yvirt = prop[1]; pdata.yvirt = prop[1];
} }
if (of_find_property(pdev->dev.of_node, "rotate-display", NULL)) pdata.rotate_screen = of_property_read_bool(pdev->dev.of_node, "rotate-display");
pdata.rotate_screen = 1;
platform_set_drvdata(pdev, drvdata); platform_set_drvdata(pdev, drvdata);
return xilinxfb_assign(pdev, drvdata, &pdata); return xilinxfb_assign(pdev, drvdata, &pdata);
......
// SPDX-License-Identifier: GPL-2.0-only
/* /*
* Convert a logo in ASCII PNM format to C source suitable for inclusion in * Convert a logo in ASCII PNM format to C source suitable for inclusion in
* the Linux kernel * the Linux kernel
* *
* (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org> * (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
*
* --------------------------------------------------------------------------
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the Linux
* distribution for more details.
*/ */
#include <ctype.h> #include <ctype.h>
...@@ -34,37 +28,37 @@ static FILE *out; ...@@ -34,37 +28,37 @@ static FILE *out;
#define LINUX_LOGO_GRAY256 4 /* 256 levels grayscale */ #define LINUX_LOGO_GRAY256 4 /* 256 levels grayscale */
static const char *logo_types[LINUX_LOGO_GRAY256+1] = { static const char *logo_types[LINUX_LOGO_GRAY256+1] = {
[LINUX_LOGO_MONO] = "LINUX_LOGO_MONO", [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
[LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16", [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
[LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224", [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
[LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256" [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256"
}; };
#define MAX_LINUX_LOGO_COLORS 224 #define MAX_LINUX_LOGO_COLORS 224
struct color { struct color {
unsigned char red; unsigned char red;
unsigned char green; unsigned char green;
unsigned char blue; unsigned char blue;
}; };
static const struct color clut_vga16[16] = { static const struct color clut_vga16[16] = {
{ 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0xaa }, { 0x00, 0x00, 0xaa },
{ 0x00, 0xaa, 0x00 }, { 0x00, 0xaa, 0x00 },
{ 0x00, 0xaa, 0xaa }, { 0x00, 0xaa, 0xaa },
{ 0xaa, 0x00, 0x00 }, { 0xaa, 0x00, 0x00 },
{ 0xaa, 0x00, 0xaa }, { 0xaa, 0x00, 0xaa },
{ 0xaa, 0x55, 0x00 }, { 0xaa, 0x55, 0x00 },
{ 0xaa, 0xaa, 0xaa }, { 0xaa, 0xaa, 0xaa },
{ 0x55, 0x55, 0x55 }, { 0x55, 0x55, 0x55 },
{ 0x55, 0x55, 0xff }, { 0x55, 0x55, 0xff },
{ 0x55, 0xff, 0x55 }, { 0x55, 0xff, 0x55 },
{ 0x55, 0xff, 0xff }, { 0x55, 0xff, 0xff },
{ 0xff, 0x55, 0x55 }, { 0xff, 0x55, 0x55 },
{ 0xff, 0x55, 0xff }, { 0xff, 0x55, 0xff },
{ 0xff, 0xff, 0x55 }, { 0xff, 0xff, 0x55 },
{ 0xff, 0xff, 0xff }, { 0xff, 0xff, 0xff },
}; };
...@@ -77,438 +71,440 @@ static unsigned int logo_clutsize; ...@@ -77,438 +71,440 @@ static unsigned int logo_clutsize;
static int is_plain_pbm = 0; static int is_plain_pbm = 0;
static void die(const char *fmt, ...) static void die(const char *fmt, ...)
__attribute__ ((noreturn)) __attribute ((format (printf, 1, 2))); __attribute__((noreturn)) __attribute((format (printf, 1, 2)));
static void usage(void) __attribute ((noreturn)); static void usage(void) __attribute((noreturn));
static unsigned int get_number(FILE *fp) static unsigned int get_number(FILE *fp)
{ {
int c, val; int c, val;
/* Skip leading whitespace */ /* Skip leading whitespace */
do { do {
c = fgetc(fp);
if (c == EOF)
die("%s: end of file\n", filename);
if (c == '#') {
/* Ignore comments 'till end of line */
do {
c = fgetc(fp); c = fgetc(fp);
if (c == EOF) if (c == EOF)
die("%s: end of file\n", filename); die("%s: end of file\n", filename);
} while (c != '\n'); if (c == '#') {
/* Ignore comments 'till end of line */
do {
c = fgetc(fp);
if (c == EOF)
die("%s: end of file\n", filename);
} while (c != '\n');
}
} while (isspace(c));
/* Parse decimal number */
val = 0;
while (isdigit(c)) {
val = 10*val+c-'0';
/* some PBM are 'broken'; GiMP for example exports a PBM without space
* between the digits. This is Ok cause we know a PBM can only have a '1'
* or a '0' for the digit.
*/
if (is_plain_pbm)
break;
c = fgetc(fp);
if (c == EOF)
die("%s: end of file\n", filename);
} }
} while (isspace(c)); return val;
/* Parse decimal number */
val = 0;
while (isdigit(c)) {
val = 10*val+c-'0';
/* some PBM are 'broken'; GiMP for example exports a PBM without space
* between the digits. This is Ok cause we know a PBM can only have a '1'
* or a '0' for the digit. */
if (is_plain_pbm)
break;
c = fgetc(fp);
if (c == EOF)
die("%s: end of file\n", filename);
}
return val;
} }
static unsigned int get_number255(FILE *fp, unsigned int maxval) static unsigned int get_number255(FILE *fp, unsigned int maxval)
{ {
unsigned int val = get_number(fp); unsigned int val = get_number(fp);
return (255*val+maxval/2)/maxval;
return (255*val+maxval/2)/maxval;
} }
static void read_image(void) static void read_image(void)
{ {
FILE *fp; FILE *fp;
unsigned int i, j; unsigned int i, j;
int magic; int magic;
unsigned int maxval; unsigned int maxval;
/* open image file */ /* open image file */
fp = fopen(filename, "r"); fp = fopen(filename, "r");
if (!fp) if (!fp)
die("Cannot open file %s: %s\n", filename, strerror(errno)); die("Cannot open file %s: %s\n", filename, strerror(errno));
/* check file type and read file header */ /* check file type and read file header */
magic = fgetc(fp); magic = fgetc(fp);
if (magic != 'P') if (magic != 'P')
die("%s is not a PNM file\n", filename); die("%s is not a PNM file\n", filename);
magic = fgetc(fp); magic = fgetc(fp);
switch (magic) { switch (magic) {
case '1': case '1':
case '2': case '2':
case '3': case '3':
/* Plain PBM/PGM/PPM */ /* Plain PBM/PGM/PPM */
break; break;
case '4': case '4':
case '5': case '5':
case '6': case '6':
/* Binary PBM/PGM/PPM */ /* Binary PBM/PGM/PPM */
die("%s: Binary PNM is not supported\n" die("%s: Binary PNM is not supported\n"
"Use pnmnoraw(1) to convert it to ASCII PNM\n", filename); "Use pnmnoraw(1) to convert it to ASCII PNM\n", filename);
default: default:
die("%s is not a PNM file\n", filename); die("%s is not a PNM file\n", filename);
} }
logo_width = get_number(fp); logo_width = get_number(fp);
logo_height = get_number(fp); logo_height = get_number(fp);
/* allocate image data */ /* allocate image data */
logo_data = (struct color **)malloc(logo_height*sizeof(struct color *)); logo_data = (struct color **)malloc(logo_height*sizeof(struct color *));
if (!logo_data) if (!logo_data)
die("%s\n", strerror(errno)); die("%s\n", strerror(errno));
for (i = 0; i < logo_height; i++) { for (i = 0; i < logo_height; i++) {
logo_data[i] = malloc(logo_width*sizeof(struct color)); logo_data[i] = malloc(logo_width*sizeof(struct color));
if (!logo_data[i]) if (!logo_data[i])
die("%s\n", strerror(errno)); die("%s\n", strerror(errno));
} }
/* read image data */ /* read image data */
switch (magic) { switch (magic) {
case '1': case '1':
/* Plain PBM */ /* Plain PBM */
is_plain_pbm = 1; is_plain_pbm = 1;
for (i = 0; i < logo_height; i++) for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) for (j = 0; j < logo_width; j++)
logo_data[i][j].red = logo_data[i][j].green = logo_data[i][j].red = logo_data[i][j].green =
logo_data[i][j].blue = 255*(1-get_number(fp)); logo_data[i][j].blue = 255*(1-get_number(fp));
break; break;
case '2': case '2':
/* Plain PGM */ /* Plain PGM */
maxval = get_number(fp); maxval = get_number(fp);
for (i = 0; i < logo_height; i++) for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) for (j = 0; j < logo_width; j++)
logo_data[i][j].red = logo_data[i][j].green = logo_data[i][j].red = logo_data[i][j].green =
logo_data[i][j].blue = get_number255(fp, maxval); logo_data[i][j].blue = get_number255(fp, maxval);
break; break;
case '3': case '3':
/* Plain PPM */ /* Plain PPM */
maxval = get_number(fp); maxval = get_number(fp);
for (i = 0; i < logo_height; i++) for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) { for (j = 0; j < logo_width; j++) {
logo_data[i][j].red = get_number255(fp, maxval); logo_data[i][j].red = get_number255(fp, maxval);
logo_data[i][j].green = get_number255(fp, maxval); logo_data[i][j].green = get_number255(fp, maxval);
logo_data[i][j].blue = get_number255(fp, maxval); logo_data[i][j].blue = get_number255(fp, maxval);
} }
break; break;
} }
/* close file */ /* close file */
fclose(fp); fclose(fp);
} }
static inline int is_black(struct color c) static inline int is_black(struct color c)
{ {
return c.red == 0 && c.green == 0 && c.blue == 0; return c.red == 0 && c.green == 0 && c.blue == 0;
} }
static inline int is_white(struct color c) static inline int is_white(struct color c)
{ {
return c.red == 255 && c.green == 255 && c.blue == 255; return c.red == 255 && c.green == 255 && c.blue == 255;
} }
static inline int is_gray(struct color c) static inline int is_gray(struct color c)
{ {
return c.red == c.green && c.red == c.blue; return c.red == c.green && c.red == c.blue;
} }
static inline int is_equal(struct color c1, struct color c2) static inline int is_equal(struct color c1, struct color c2)
{ {
return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue; return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
} }
static void write_header(void) static void write_header(void)
{ {
/* open logo file */ /* open logo file */
if (outputname) { if (outputname) {
out = fopen(outputname, "w"); out = fopen(outputname, "w");
if (!out) if (!out)
die("Cannot create file %s: %s\n", outputname, strerror(errno)); die("Cannot create file %s: %s\n", outputname, strerror(errno));
} else { } else {
out = stdout; out = stdout;
} }
fputs("/*\n", out); fputs("/*\n", out);
fputs(" * DO NOT EDIT THIS FILE!\n", out); fputs(" * DO NOT EDIT THIS FILE!\n", out);
fputs(" *\n", out); fputs(" *\n", out);
fprintf(out, " * It was automatically generated from %s\n", filename); fprintf(out, " * It was automatically generated from %s\n", filename);
fputs(" *\n", out); fputs(" *\n", out);
fprintf(out, " * Linux logo %s\n", logoname); fprintf(out, " * Linux logo %s\n", logoname);
fputs(" */\n\n", out); fputs(" */\n\n", out);
fputs("#include <linux/linux_logo.h>\n\n", out); fputs("#include <linux/linux_logo.h>\n\n", out);
fprintf(out, "static unsigned char %s_data[] __initdata = {\n", fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
logoname); logoname);
} }
static void write_footer(void) static void write_footer(void)
{ {
fputs("\n};\n\n", out); fputs("\n};\n\n", out);
fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname); fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]); fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
fprintf(out, "\t.width\t\t= %d,\n", logo_width); fprintf(out, "\t.width\t\t= %d,\n", logo_width);
fprintf(out, "\t.height\t\t= %d,\n", logo_height); fprintf(out, "\t.height\t\t= %d,\n", logo_height);
if (logo_type == LINUX_LOGO_CLUT224) { if (logo_type == LINUX_LOGO_CLUT224) {
fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize); fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize);
fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname); fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname);
} }
fprintf(out, "\t.data\t\t= %s_data\n", logoname); fprintf(out, "\t.data\t\t= %s_data\n", logoname);
fputs("};\n\n", out); fputs("};\n\n", out);
/* close logo file */ /* close logo file */
if (outputname) if (outputname)
fclose(out); fclose(out);
} }
static int write_hex_cnt; static int write_hex_cnt;
static void write_hex(unsigned char byte) static void write_hex(unsigned char byte)
{ {
if (write_hex_cnt % 12) if (write_hex_cnt % 12)
fprintf(out, ", 0x%02x", byte); fprintf(out, ", 0x%02x", byte);
else if (write_hex_cnt) else if (write_hex_cnt)
fprintf(out, ",\n\t0x%02x", byte); fprintf(out, ",\n\t0x%02x", byte);
else else
fprintf(out, "\t0x%02x", byte); fprintf(out, "\t0x%02x", byte);
write_hex_cnt++; write_hex_cnt++;
} }
static void write_logo_mono(void) static void write_logo_mono(void)
{ {
unsigned int i, j; unsigned int i, j;
unsigned char val, bit; unsigned char val, bit;
/* validate image */ /* validate image */
for (i = 0; i < logo_height; i++) for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) for (j = 0; j < logo_width; j++)
if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j])) if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j]))
die("Image must be monochrome\n"); die("Image must be monochrome\n");
/* write file header */ /* write file header */
write_header(); write_header();
/* write logo data */ /* write logo data */
for (i = 0; i < logo_height; i++) { for (i = 0; i < logo_height; i++) {
for (j = 0; j < logo_width;) { for (j = 0; j < logo_width;) {
for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1) for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1)
if (logo_data[i][j].red) if (logo_data[i][j].red)
val |= bit; val |= bit;
write_hex(val); write_hex(val);
}
} }
}
/* write logo structure and file footer */ /* write logo structure and file footer */
write_footer(); write_footer();
} }
static void write_logo_vga16(void) static void write_logo_vga16(void)
{ {
unsigned int i, j, k; unsigned int i, j, k;
unsigned char val; unsigned char val;
/* validate image */
for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) {
for (k = 0; k < 16; k++)
if (is_equal(logo_data[i][j], clut_vga16[k]))
break;
if (k == 16)
die("Image must use the 16 console colors only\n"
"Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
"of colors\n");
}
/* write file header */ /* validate image */
write_header(); for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) {
/* write logo data */ for (k = 0; k < 16; k++)
for (i = 0; i < logo_height; i++) if (is_equal(logo_data[i][j], clut_vga16[k]))
for (j = 0; j < logo_width; j++) { break;
for (k = 0; k < 16; k++) if (k == 16)
if (is_equal(logo_data[i][j], clut_vga16[k])) die("Image must use the 16 console colors only\n"
break; "Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
val = k<<4; "of colors\n");
if (++j < logo_width) { }
for (k = 0; k < 16; k++)
if (is_equal(logo_data[i][j], clut_vga16[k]))
break;
val |= k;
}
write_hex(val);
}
/* write logo structure and file footer */ /* write file header */
write_footer(); write_header();
/* write logo data */
for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) {
for (k = 0; k < 16; k++)
if (is_equal(logo_data[i][j], clut_vga16[k]))
break;
val = k<<4;
if (++j < logo_width) {
for (k = 0; k < 16; k++)
if (is_equal(logo_data[i][j], clut_vga16[k]))
break;
val |= k;
}
write_hex(val);
}
/* write logo structure and file footer */
write_footer();
} }
static void write_logo_clut224(void) static void write_logo_clut224(void)
{ {
unsigned int i, j, k; unsigned int i, j, k;
/* validate image */
for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) {
for (k = 0; k < logo_clutsize; k++)
if (is_equal(logo_data[i][j], logo_clut[k]))
break;
if (k == logo_clutsize) {
if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
die("Image has more than %d colors\n"
"Use ppmquant(1) to reduce the number of colors\n",
MAX_LINUX_LOGO_COLORS);
logo_clut[logo_clutsize++] = logo_data[i][j];
}
}
/* write file header */ /* validate image */
write_header(); for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) {
for (k = 0; k < logo_clutsize; k++)
if (is_equal(logo_data[i][j], logo_clut[k]))
break;
if (k == logo_clutsize) {
if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
die("Image has more than %d colors\n"
"Use ppmquant(1) to reduce the number of colors\n",
MAX_LINUX_LOGO_COLORS);
logo_clut[logo_clutsize++] = logo_data[i][j];
}
}
/* write logo data */ /* write file header */
for (i = 0; i < logo_height; i++) write_header();
for (j = 0; j < logo_width; j++) {
for (k = 0; k < logo_clutsize; k++) /* write logo data */
if (is_equal(logo_data[i][j], logo_clut[k])) for (i = 0; i < logo_height; i++)
break; for (j = 0; j < logo_width; j++) {
write_hex(k+32); for (k = 0; k < logo_clutsize; k++)
if (is_equal(logo_data[i][j], logo_clut[k]))
break;
write_hex(k+32);
}
fputs("\n};\n\n", out);
/* write logo clut */
fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
logoname);
write_hex_cnt = 0;
for (i = 0; i < logo_clutsize; i++) {
write_hex(logo_clut[i].red);
write_hex(logo_clut[i].green);
write_hex(logo_clut[i].blue);
} }
fputs("\n};\n\n", out);
/* write logo structure and file footer */
/* write logo clut */ write_footer();
fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
logoname);
write_hex_cnt = 0;
for (i = 0; i < logo_clutsize; i++) {
write_hex(logo_clut[i].red);
write_hex(logo_clut[i].green);
write_hex(logo_clut[i].blue);
}
/* write logo structure and file footer */
write_footer();
} }
static void write_logo_gray256(void) static void write_logo_gray256(void)
{ {
unsigned int i, j; unsigned int i, j;
/* validate image */ /* validate image */
for (i = 0; i < logo_height; i++) for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) for (j = 0; j < logo_width; j++)
if (!is_gray(logo_data[i][j])) if (!is_gray(logo_data[i][j]))
die("Image must be grayscale\n"); die("Image must be grayscale\n");
/* write file header */ /* write file header */
write_header(); write_header();
/* write logo data */ /* write logo data */
for (i = 0; i < logo_height; i++) for (i = 0; i < logo_height; i++)
for (j = 0; j < logo_width; j++) for (j = 0; j < logo_width; j++)
write_hex(logo_data[i][j].red); write_hex(logo_data[i][j].red);
/* write logo structure and file footer */ /* write logo structure and file footer */
write_footer(); write_footer();
} }
static void die(const char *fmt, ...) static void die(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
va_end(ap); va_end(ap);
exit(1); exit(1);
} }
static void usage(void) static void usage(void)
{ {
die("\n" die("\n"
"Usage: %s [options] <filename>\n" "Usage: %s [options] <filename>\n"
"\n" "\n"
"Valid options:\n" "Valid options:\n"
" -h : display this usage information\n" " -h : display this usage information\n"
" -n <name> : specify logo name (default: linux_logo)\n" " -n <name> : specify logo name (default: linux_logo)\n"
" -o <output> : output to file <output> instead of stdout\n" " -o <output> : output to file <output> instead of stdout\n"
" -t <type> : specify logo type, one of\n" " -t <type> : specify logo type, one of\n"
" mono : monochrome black/white\n" " mono : monochrome black/white\n"
" vga16 : 16 colors VGA text palette\n" " vga16 : 16 colors VGA text palette\n"
" clut224 : 224 colors (default)\n" " clut224 : 224 colors (default)\n"
" gray256 : 256 levels grayscale\n" " gray256 : 256 levels grayscale\n"
"\n", programname); "\n", programname);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int opt; int opt;
programname = argv[0]; programname = argv[0];
opterr = 0; opterr = 0;
while (1) { while (1) {
opt = getopt(argc, argv, "hn:o:t:"); opt = getopt(argc, argv, "hn:o:t:");
if (opt == -1) if (opt == -1)
break; break;
switch (opt) { switch (opt) {
case 'h': case 'h':
usage(); usage();
break; break;
case 'n': case 'n':
logoname = optarg; logoname = optarg;
break; break;
case 'o': case 'o':
outputname = optarg; outputname = optarg;
break; break;
case 't': case 't':
if (!strcmp(optarg, "mono")) if (!strcmp(optarg, "mono"))
logo_type = LINUX_LOGO_MONO; logo_type = LINUX_LOGO_MONO;
else if (!strcmp(optarg, "vga16")) else if (!strcmp(optarg, "vga16"))
logo_type = LINUX_LOGO_VGA16; logo_type = LINUX_LOGO_VGA16;
else if (!strcmp(optarg, "clut224")) else if (!strcmp(optarg, "clut224"))
logo_type = LINUX_LOGO_CLUT224; logo_type = LINUX_LOGO_CLUT224;
else if (!strcmp(optarg, "gray256")) else if (!strcmp(optarg, "gray256"))
logo_type = LINUX_LOGO_GRAY256; logo_type = LINUX_LOGO_GRAY256;
else else
usage(); usage();
break; break;
default: default:
usage(); usage();
break; break;
}
} }
} if (optind != argc-1)
if (optind != argc-1) usage();
usage();
filename = argv[optind]; filename = argv[optind];
read_image(); read_image();
switch (logo_type) { switch (logo_type) {
case LINUX_LOGO_MONO: case LINUX_LOGO_MONO:
write_logo_mono(); write_logo_mono();
break; break;
case LINUX_LOGO_VGA16: case LINUX_LOGO_VGA16:
write_logo_vga16(); write_logo_vga16();
break; break;
case LINUX_LOGO_CLUT224: case LINUX_LOGO_CLUT224:
write_logo_clut224(); write_logo_clut224();
break; break;
case LINUX_LOGO_GRAY256: case LINUX_LOGO_GRAY256:
write_logo_gray256(); write_logo_gray256();
break; break;
} }
exit(0); exit(0);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment