fb: introduce framebuffer support to Minix
This patch introduces a framebuffer to Minix. It's written for the ARM port of Minix, but has an architectural split that separates the hardware dependent part from the non-hardware dependent part. Futhermore, this driver was developed using a screen that has a native resolution of 1024x600 pixels and having lack of support for obtaining EDID from the screen. Consequently, it uses a hardcoded resolution of 1024x600. The driver uses an interface based on the Linux ioctl API, but supports only a very limited subset.
This commit is contained in:
		
							parent
							
								
									2aa82a9c7b
								
							
						
					
					
						commit
						ba49a155b5
					
				@ -23,13 +23,14 @@ case $#:$1 in
 | 
			
		||||
	ttypa ttypb ttypc ttypd ttype ttypf \
 | 
			
		||||
	ttyq0 ttyq1 ttyq2 ttyq3 ttyq4 ttyq5 ttyq6 ttyq7 ttyq8 ttyq9 \
 | 
			
		||||
	ttyqa ttyqb ttyqc ttyqd ttyqe ttyqf \
 | 
			
		||||
	eth klog random uds filter fbd hello
 | 
			
		||||
	eth klog random uds filter fbd hello fb0
 | 
			
		||||
    ;;
 | 
			
		||||
0:|1:-\?)
 | 
			
		||||
    cat >&2 <<EOF
 | 
			
		||||
Usage:	$0 [-n] key ...
 | 
			
		||||
Where key is one of the following:
 | 
			
		||||
  ram mem kmem null boot zero	  # One of these makes all these memory devices
 | 
			
		||||
  fb0			  # Make /dev/fb0
 | 
			
		||||
  fd0 fd1 ...		  # Floppy devices for drive 0, 1, ...
 | 
			
		||||
  fd0p0 fd1p0 ...	  # Make floppy partitions fd0p[0-3], fd1p[0-3], ...
 | 
			
		||||
  c0d0 c0d1 ...		  # Make disks c0d0, c0d1, ...
 | 
			
		||||
@ -254,7 +255,7 @@ do
 | 
			
		||||
	;;
 | 
			
		||||
    uds)
 | 
			
		||||
	# unix domain sockets device
 | 
			
		||||
	$e mknod uds c 18 0;	$e chmod 644 random
 | 
			
		||||
	$e mknod uds c 18 0;
 | 
			
		||||
	$e chgrp operator uds
 | 
			
		||||
	$e chmod 666 uds
 | 
			
		||||
	;;
 | 
			
		||||
@ -278,6 +279,11 @@ do
 | 
			
		||||
	$e mknod hello c 17 0
 | 
			
		||||
	$e chmod 644 hello
 | 
			
		||||
	;;
 | 
			
		||||
    fb0)
 | 
			
		||||
	# framebuffer driver
 | 
			
		||||
	$e mknod fb0 c 19 0
 | 
			
		||||
	$e chmod 644 fb0
 | 
			
		||||
	;;
 | 
			
		||||
    *)
 | 
			
		||||
	echo "$0: don't know about $dev" >&2
 | 
			
		||||
	ex=1
 | 
			
		||||
 | 
			
		||||
@ -38,5 +38,4 @@ SUBDIR+=	atnormalize dosread fdisk loadfont \
 | 
			
		||||
	autopart part partition playwave  \
 | 
			
		||||
	recwave repartition screendump
 | 
			
		||||
.endif
 | 
			
		||||
 | 
			
		||||
.include <bsd.subdir.mk>
 | 
			
		||||
 | 
			
		||||
@ -95,5 +95,6 @@
 | 
			
		||||
./usr/lib/libpadconf.a			minix-sys
 | 
			
		||||
./usr/lib/libpadconf_pic.a		minix-sys
 | 
			
		||||
./usr/mdec				minix-sys
 | 
			
		||||
./usr/sbin/fb				minix-sys
 | 
			
		||||
./usr/sbin/gpio				minix-sys
 | 
			
		||||
./usr/sbin/random			minix-sys
 | 
			
		||||
 | 
			
		||||
@ -576,6 +576,7 @@
 | 
			
		||||
./usr/include/minix/drvlib.h		minix-sys
 | 
			
		||||
./usr/include/minix/ds.h		minix-sys
 | 
			
		||||
./usr/include/minix/endpoint.h		minix-sys
 | 
			
		||||
./usr/include/minix/fb.h		minix-sys
 | 
			
		||||
./usr/include/minix/fslib.h		minix-sys
 | 
			
		||||
./usr/include/minix/gcov.h		minix-sys
 | 
			
		||||
./usr/include/minix/gpio.h		minix-sys
 | 
			
		||||
@ -792,6 +793,7 @@
 | 
			
		||||
./usr/include/sys/ioc_block.h		minix-sys
 | 
			
		||||
./usr/include/sys/ioccom.h		minix-sys
 | 
			
		||||
./usr/include/sys/ioc_disk.h		minix-sys
 | 
			
		||||
./usr/include/sys/ioc_fb.h		minix-sys
 | 
			
		||||
./usr/include/sys/ioc_fbd.h		minix-sys
 | 
			
		||||
./usr/include/sys/ioc_file.h		minix-sys
 | 
			
		||||
./usr/include/sys/ioc_memory.h		minix-sys
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ SUBDIR= ahci amddev atl2 at_wini audio dec21140A dp8390 dpeth \
 | 
			
		||||
.endif
 | 
			
		||||
 | 
			
		||||
.if ${MACHINE_ARCH} == "earm"
 | 
			
		||||
SUBDIR=  gpio mmc log tty random
 | 
			
		||||
SUBDIR=  fb gpio mmc log tty random
 | 
			
		||||
.endif
 | 
			
		||||
 | 
			
		||||
.endif # ${MKIMAGEONLY} != "yes"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								drivers/fb/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								drivers/fb/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
# Makefile for the framebuffer driver.
 | 
			
		||||
PROG=	fb
 | 
			
		||||
 | 
			
		||||
.include "arch/${MACHINE_ARCH}/Makefile.inc"
 | 
			
		||||
 | 
			
		||||
SRCS+=	fb.c
 | 
			
		||||
 | 
			
		||||
DPADD+=	${LIBCHARDRIVER} ${LIBSYS}
 | 
			
		||||
LDADD+=	-lchardriver -lsys
 | 
			
		||||
 | 
			
		||||
MAN=
 | 
			
		||||
 | 
			
		||||
BINDIR?= /usr/sbin
 | 
			
		||||
 | 
			
		||||
.include <minix.service.mk>
 | 
			
		||||
							
								
								
									
										7
									
								
								drivers/fb/arch/earm/Makefile.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								drivers/fb/arch/earm/Makefile.inc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
# Makefile for arch-dependent framebuffer code
 | 
			
		||||
.include <bsd.own.mk>
 | 
			
		||||
 | 
			
		||||
HERE=${.CURDIR}/arch/${MACHINE_ARCH}
 | 
			
		||||
.PATH:  ${HERE}
 | 
			
		||||
 | 
			
		||||
SRCS +=	fb_arch.c
 | 
			
		||||
							
								
								
									
										65
									
								
								drivers/fb/arch/earm/dss.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								drivers/fb/arch/earm/dss.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
#ifndef __DSS_H__
 | 
			
		||||
#define __DSS_H__ 
 | 
			
		||||
 | 
			
		||||
/* DSS Base Registers */
 | 
			
		||||
#define OMAP3_DSS_BASE			0x48050000
 | 
			
		||||
#define OMAP3_DISPC_BASE		0x48050400
 | 
			
		||||
#define OMAP3_VENC_BASE			0x48050C00
 | 
			
		||||
 | 
			
		||||
#define OMAP3_DSS_SYSCONFIG(b)		(b + 0x10)
 | 
			
		||||
#define OMAP3_DSS_SYSSTATUS(b)		(b + 0x14)
 | 
			
		||||
 | 
			
		||||
#define OMAP3_DISPC_IRQSTATUS(b)	(b + 0x18)
 | 
			
		||||
#define OMAP3_DISPC_CONTROL(b)		(b + 0x40)
 | 
			
		||||
#define OMAP3_DISPC_CONFIG(b)		(b + 0x44)
 | 
			
		||||
#define OMAP3_DISPC_DEFAULT_COLOR0(b)	(b + 0x4c)
 | 
			
		||||
#define OMAP3_DISPC_DEFAULT_COLOR1(b)	(b + 0x50)
 | 
			
		||||
#define OMAP3_DISPC_TIMINGH(b)		(b + 0x64)
 | 
			
		||||
#define OMAP3_DISPC_TIMINGV(b)		(b + 0x68)
 | 
			
		||||
#define OMAP3_DISPC_POL_FREQ(b)		(b + 0x6c)
 | 
			
		||||
#define OMAP3_DISPC_DIVISOR(b)		(b + 0x70)
 | 
			
		||||
#define OMAP3_DISPC_SIZE_DIG(b)		(b + 0x78)
 | 
			
		||||
#define OMAP3_DISPC_SIZE_LCD(b)		(b + 0x7c)
 | 
			
		||||
#define OMAP3_DISPC_GFX_BA0(b)		(b + 0x80)
 | 
			
		||||
#define OMAP3_DISPC_GFX_BA1(b)		(b + 0x84)
 | 
			
		||||
#define OMAP3_DISPC_GFX_SIZE(b)		(b + 0x8c)
 | 
			
		||||
#define OMAP3_DISPC_GFX_ATTRIBUTES(b)	(b + 0xa0)
 | 
			
		||||
#define OMAP3_DISPC_GFX_ROW_INC(b)	(b + 0xac)
 | 
			
		||||
#define OMAP3_DISPC_GFX_PIXEL_INC(b)	(b + 0xb0)
 | 
			
		||||
 | 
			
		||||
#define LOADMODE_SHIFT		1
 | 
			
		||||
#define TFTSTN_SHIFT		3
 | 
			
		||||
#define DATALINES_SHIFT		8
 | 
			
		||||
#define GFXFORMAT_SHIFT		1
 | 
			
		||||
#define GFXBURSTSIZE_SHIFT	6
 | 
			
		||||
 | 
			
		||||
#define DSS_SOFTRESET			(1 << 1)
 | 
			
		||||
#define DSS_RESETDONE			(1 << 0)
 | 
			
		||||
 | 
			
		||||
#define DISPC_LCDENABLE			(1 << 0)
 | 
			
		||||
#define DISPC_DIGITALENABLE		(1 << 1)
 | 
			
		||||
#define DISPC_GOLCD			(1 << 5)
 | 
			
		||||
#define DISPC_GODIGITAL			(1 << 6)
 | 
			
		||||
#define DISPC_GPIN0			(1 << 13)
 | 
			
		||||
#define DISPC_GPIN1			(1 << 14)
 | 
			
		||||
#define DISPC_GPOUT0			(1 << 15)
 | 
			
		||||
#define DISPC_GPOUT1			(1 << 16)
 | 
			
		||||
#define DISPC_ENABLESIGNAL		(1 << 28)
 | 
			
		||||
#define DISPC_FRAMEDONE			(1 << 0)
 | 
			
		||||
#define DISPC_GFXENABLE			(1 << 0)
 | 
			
		||||
#define DISPC_GFXFORMAT_BMP1		0x0
 | 
			
		||||
#define DISPC_GFXFORMAT_BMP2		0x1
 | 
			
		||||
#define DISPC_GFXFORMAT_BMP4		0x2
 | 
			
		||||
#define DISPC_GFXFORMAT_BMP8		0x3
 | 
			
		||||
#define DISPC_GFXFORMAT_RGB12		0x4
 | 
			
		||||
#define DISPC_GFXFORMAT_ARGB16		0x5
 | 
			
		||||
#define DISPC_GFXFORMAT_RGB16		0x6
 | 
			
		||||
#define DISPC_GFXFORMAT_RGB24		0x8
 | 
			
		||||
#define DISPC_GFXFORMAT_RGB24P		0x9
 | 
			
		||||
#define DISPC_GFXFORMAT_ARGB32		0xC
 | 
			
		||||
#define DISPC_GFXFORMAT_RGBA32		0xD
 | 
			
		||||
#define DISPC_GFXFORMAT_RGBx		0xE
 | 
			
		||||
#define DISPC_GFXBURSTSIZE_4		0x0
 | 
			
		||||
#define DISPC_GFXBURSTSIZE_8		0x1
 | 
			
		||||
#define DISPC_GFXBURSTSIZE_16		0x2
 | 
			
		||||
#endif /* __DSS_H__ */
 | 
			
		||||
							
								
								
									
										271
									
								
								drivers/fb/arch/earm/fb_arch.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								drivers/fb/arch/earm/fb_arch.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,271 @@
 | 
			
		||||
/* Architecture dependent part for the framebuffer on the OMAP3. Since we don't
 | 
			
		||||
 * have support for EDID (which requires support for i2c, also something we
 | 
			
		||||
 * don't have, yet), but we do have a screen with 1024*600 resolution for our
 | 
			
		||||
 * testing purposes, we hardcode that resolution here. There's obvious room for
 | 
			
		||||
 * improvement. */
 | 
			
		||||
 | 
			
		||||
#include <minix/chardriver.h>
 | 
			
		||||
#include <minix/drivers.h>
 | 
			
		||||
#include <minix/fb.h>
 | 
			
		||||
#include <minix/type.h>
 | 
			
		||||
#include <minix/vm.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "dss.h"
 | 
			
		||||
#define SCREEN_WIDTH 1024
 | 
			
		||||
#define SCREEN_HEIGHT 600
 | 
			
		||||
#define PAGES_NR 2
 | 
			
		||||
 | 
			
		||||
static vir_bytes dss_phys_base;		/* Address of dss phys memory map */
 | 
			
		||||
static vir_bytes dispc_phys_base;	/* Address of dispc phys memory map */
 | 
			
		||||
static vir_bytes fb_vir;
 | 
			
		||||
static phys_bytes fb_phys;
 | 
			
		||||
static size_t fb_size;
 | 
			
		||||
static int initialized = 0;
 | 
			
		||||
 | 
			
		||||
struct panel_config {
 | 
			
		||||
        u32_t timing_h;
 | 
			
		||||
        u32_t timing_v;
 | 
			
		||||
        u32_t pol_freq;
 | 
			
		||||
        u32_t divisor;
 | 
			
		||||
        u32_t lcd_size;
 | 
			
		||||
        u32_t panel_type;
 | 
			
		||||
        u32_t data_lines;
 | 
			
		||||
        u32_t load_mode;
 | 
			
		||||
        u32_t panel_color;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct panel_config default_cfg = {
 | 
			
		||||
	/* See OMAP TRM section 15.7 for the register values/encoding */
 | 
			
		||||
        .timing_h       = 0x1a4024c9,	/* Horizontal timing */
 | 
			
		||||
        .timing_v       = 0x02c00509,	/* Vertical timing */
 | 
			
		||||
        .pol_freq       = 0x00007028,	/* Pol Freq */
 | 
			
		||||
        .divisor        = 0x00010001,	/* 96MHz Pixel Clock */
 | 
			
		||||
	.lcd_size	= ((SCREEN_HEIGHT - 1) << 16 | (SCREEN_WIDTH - 1)),
 | 
			
		||||
        .panel_type     = 0x01,		/* TFT */
 | 
			
		||||
        .data_lines     = 0x03,		/* 24 Bit RGB */
 | 
			
		||||
        .load_mode      = 0x02,		/* Frame Mode */
 | 
			
		||||
        .panel_color    = 0xFFFFFF	/* WHITE */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct fb_fix_screeninfo fbfs = {
 | 
			
		||||
	.xpanstep	= 0,
 | 
			
		||||
	.ypanstep	= 0,
 | 
			
		||||
	.ywrapstep	= 0,
 | 
			
		||||
	.line_length	= SCREEN_WIDTH * 4,
 | 
			
		||||
	.mmio_start	= 0,	/* Not implemented for char. special, so */
 | 
			
		||||
	.mmio_len	= 0	/* these are set to 0 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct fb_var_screeninfo fbvs = {
 | 
			
		||||
	.xres		= SCREEN_WIDTH,
 | 
			
		||||
	.yres		= SCREEN_HEIGHT,
 | 
			
		||||
	.xres_virtual	= SCREEN_WIDTH,
 | 
			
		||||
	.yres_virtual	= SCREEN_HEIGHT*2,
 | 
			
		||||
	.xoffset	= 0,
 | 
			
		||||
	.yoffset	= 0,
 | 
			
		||||
	.bits_per_pixel = 32,
 | 
			
		||||
	.red =	{
 | 
			
		||||
		.offset = 16,
 | 
			
		||||
		.length = 8,
 | 
			
		||||
		.msb_right = 0
 | 
			
		||||
		},
 | 
			
		||||
	.green = {
 | 
			
		||||
		.offset = 8,
 | 
			
		||||
		.length = 8,
 | 
			
		||||
		.msb_right = 0
 | 
			
		||||
		},
 | 
			
		||||
	.blue =	{
 | 
			
		||||
		.offset = 0,
 | 
			
		||||
		.length = 8,
 | 
			
		||||
		.msb_right = 0
 | 
			
		||||
		},
 | 
			
		||||
	.transp = {
 | 
			
		||||
		.offset = 24,
 | 
			
		||||
		.length = 8,
 | 
			
		||||
		.msb_right = 0
 | 
			
		||||
		}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline u32_t
 | 
			
		||||
readw(vir_bytes addr)
 | 
			
		||||
{
 | 
			
		||||
        return *((volatile u32_t *) addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
writew(vir_bytes addr, u32_t val)
 | 
			
		||||
{
 | 
			
		||||
        *((volatile u32_t *) addr) = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
arch_configure_display(int minor)
 | 
			
		||||
{
 | 
			
		||||
/* Tell hardware where frame buffer is and turn display on */
 | 
			
		||||
	u32_t off, rdispc;
 | 
			
		||||
 | 
			
		||||
	if (!initialized) return;
 | 
			
		||||
	if (minor != 0) return;
 | 
			
		||||
 | 
			
		||||
	off = fbvs.yoffset * fbvs.xres_virtual * (fbvs.bits_per_pixel/8);
 | 
			
		||||
 | 
			
		||||
	writew((vir_bytes) OMAP3_DISPC_GFX_BA0(dispc_phys_base),
 | 
			
		||||
		fb_phys + (phys_bytes) off);
 | 
			
		||||
	rdispc = readw((vir_bytes) OMAP3_DISPC_CONTROL(dispc_phys_base));
 | 
			
		||||
	rdispc |= DISPC_LCDENABLE | DISPC_DIGITALENABLE | DISPC_GOLCD |
 | 
			
		||||
				DISPC_GODIGITAL | DISPC_GPOUT0 | DISPC_GPOUT1;
 | 
			
		||||
	writew((vir_bytes) OMAP3_DISPC_CONTROL(dispc_phys_base), rdispc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
arch_get_device(int minor, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	if (!initialized) return ENXIO;
 | 
			
		||||
	if (minor != 0) return ENXIO;
 | 
			
		||||
	dev->dv_base = fb_vir;
 | 
			
		||||
	dev->dv_size = fb_size;
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
arch_get_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp)
 | 
			
		||||
{
 | 
			
		||||
	if (!initialized) return ENXIO;
 | 
			
		||||
	if (minor != 0) return ENXIO;
 | 
			
		||||
 | 
			
		||||
	*fbvsp = fbvs;
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
arch_put_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp)
 | 
			
		||||
{
 | 
			
		||||
	int r = OK;
 | 
			
		||||
	
 | 
			
		||||
	assert(fbvsp != NULL);
 | 
			
		||||
 | 
			
		||||
	if (!initialized) return ENXIO;
 | 
			
		||||
	if (minor != 0)	return ENXIO;
 | 
			
		||||
 | 
			
		||||
	/* For now we only allow to play with the yoffset setting */
 | 
			
		||||
	if (fbvsp->yoffset != fbvs.yoffset) {
 | 
			
		||||
		if (fbvsp->yoffset < 0 || fbvsp->yoffset > fbvs.yres) {
 | 
			
		||||
			return EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fbvs.yoffset = fbvsp->yoffset;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Now update hardware with new settings */
 | 
			
		||||
	arch_configure_display(minor);
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
arch_get_fixscreeninfo(int minor, struct fb_fix_screeninfo *fbfsp)
 | 
			
		||||
{
 | 
			
		||||
	if (!initialized) return ENXIO;
 | 
			
		||||
	if (minor != 0) return ENXIO;
 | 
			
		||||
 | 
			
		||||
	*fbfsp = fbfs;
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
arch_pan_display(int minor, struct fb_var_screeninfo *fbvsp)
 | 
			
		||||
{
 | 
			
		||||
	return arch_put_varscreeninfo(minor, fbvsp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
arch_fb_init(int minor, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	u32_t rdispc;
 | 
			
		||||
	struct minix_mem_range mr;
 | 
			
		||||
 | 
			
		||||
	const struct panel_config *panel_cfg = &default_cfg;
 | 
			
		||||
 | 
			
		||||
	assert(dev != NULL);
 | 
			
		||||
	if (minor != 0) return ENXIO;	/* We support only one minor */
 | 
			
		||||
 | 
			
		||||
	if (initialized) {
 | 
			
		||||
		dev->dv_base = fb_vir;
 | 
			
		||||
		dev->dv_size = fb_size;
 | 
			
		||||
		return OK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	initialized = 1;
 | 
			
		||||
 | 
			
		||||
        /* Configure DSS memory access */
 | 
			
		||||
        mr.mr_base = OMAP3_DSS_BASE;
 | 
			
		||||
        mr.mr_limit = mr.mr_base + 0x60;
 | 
			
		||||
        if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) {
 | 
			
		||||
                panic("Unable to request access to DSS(1) memory");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dss_phys_base = (vir_bytes) vm_map_phys(SELF, (void *) OMAP3_DSS_BASE,
 | 
			
		||||
						0x60);
 | 
			
		||||
 | 
			
		||||
        if (dss_phys_base == (vir_bytes) MAP_FAILED) {
 | 
			
		||||
                panic("Unable to request access to DSS(2) memory");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Configure DISPC memory access */
 | 
			
		||||
        mr.mr_base = OMAP3_DISPC_BASE;
 | 
			
		||||
        mr.mr_limit = mr.mr_base + 0x430;
 | 
			
		||||
        if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) {
 | 
			
		||||
                panic("Unable to request access to DISPC(1) memory");
 | 
			
		||||
        }
 | 
			
		||||
        dispc_phys_base = (vir_bytes) vm_map_phys(SELF,
 | 
			
		||||
						  (void *) OMAP3_DISPC_BASE,
 | 
			
		||||
						  0x430);
 | 
			
		||||
 | 
			
		||||
        if (dispc_phys_base == (vir_bytes) MAP_FAILED) {
 | 
			
		||||
                panic("Unable to request access to DISPC(2) memory");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	/* Set timings, screen mode, screen size, etc. */
 | 
			
		||||
	writew(OMAP3_DISPC_TIMINGH(dispc_phys_base), panel_cfg->timing_h);
 | 
			
		||||
	writew(OMAP3_DISPC_TIMINGV(dispc_phys_base), panel_cfg->timing_v);
 | 
			
		||||
	writew(OMAP3_DISPC_POL_FREQ(dispc_phys_base), panel_cfg->pol_freq);
 | 
			
		||||
	writew(OMAP3_DISPC_DIVISOR(dispc_phys_base), panel_cfg->divisor);
 | 
			
		||||
	writew(OMAP3_DISPC_CONFIG(dispc_phys_base),
 | 
			
		||||
				panel_cfg->load_mode << LOADMODE_SHIFT);
 | 
			
		||||
	writew(OMAP3_DISPC_CONTROL(dispc_phys_base),
 | 
			
		||||
				panel_cfg->panel_type << TFTSTN_SHIFT |
 | 
			
		||||
				panel_cfg->data_lines << DATALINES_SHIFT);
 | 
			
		||||
	
 | 
			
		||||
	writew((vir_bytes) OMAP3_DISPC_SIZE_LCD(dispc_phys_base),
 | 
			
		||||
				panel_cfg->lcd_size);
 | 
			
		||||
	writew((vir_bytes) OMAP3_DISPC_GFX_SIZE(dispc_phys_base),
 | 
			
		||||
				panel_cfg->lcd_size);
 | 
			
		||||
	writew(OMAP3_DISPC_DEFAULT_COLOR0(dispc_phys_base),
 | 
			
		||||
				panel_cfg->panel_color);
 | 
			
		||||
 | 
			
		||||
	/* Enable gfx engine */
 | 
			
		||||
        writew(OMAP3_DISPC_GFX_ATTRIBUTES(dispc_phys_base),
 | 
			
		||||
				(DISPC_GFXBURSTSIZE_16 << GFXBURSTSIZE_SHIFT) |
 | 
			
		||||
				(DISPC_GFXFORMAT_RGB24 << GFXFORMAT_SHIFT) |
 | 
			
		||||
				(DISPC_GFXENABLE));
 | 
			
		||||
	writew(OMAP3_DISPC_GFX_ROW_INC(dispc_phys_base), 1);
 | 
			
		||||
	writew(OMAP3_DISPC_GFX_PIXEL_INC(dispc_phys_base), 1);
 | 
			
		||||
 | 
			
		||||
	/* Allocate contiguous physical memory for the display buffer */
 | 
			
		||||
	fb_size = fbvs.yres_virtual * fbvs.xres_virtual *
 | 
			
		||||
				(fbvs.bits_per_pixel / 8);
 | 
			
		||||
	fb_vir = (vir_bytes) alloc_contig(fb_size, 0, &fb_phys);
 | 
			
		||||
	if (fb_vir == (vir_bytes) MAP_FAILED) {
 | 
			
		||||
		panic("Unable to allocate contiguous memory\n");
 | 
			
		||||
	} 
 | 
			
		||||
	dev->dv_base = fb_vir;
 | 
			
		||||
	dev->dv_size = fb_size;
 | 
			
		||||
 | 
			
		||||
	/* Configure buffer settings and turn on LCD/Digital */
 | 
			
		||||
	arch_configure_display(minor);
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										426
									
								
								drivers/fb/fb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										426
									
								
								drivers/fb/fb.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,426 @@
 | 
			
		||||
#include <minix/fb.h>
 | 
			
		||||
#include <minix/chardriver.h>
 | 
			
		||||
#include <minix/drivers.h>
 | 
			
		||||
#include <minix/ds.h>
 | 
			
		||||
#include <minix/type.h>
 | 
			
		||||
#include <minix/vm.h>
 | 
			
		||||
#include <sys/ioc_fb.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "logos.h"
 | 
			
		||||
#include "fb.h"
 | 
			
		||||
 | 
			
		||||
#define FB_DEV_NR	1
 | 
			
		||||
/*
 | 
			
		||||
 * Function prototypes for the fb driver.
 | 
			
		||||
 */
 | 
			
		||||
static int fb_open(message *m);
 | 
			
		||||
static int fb_close(message *m);
 | 
			
		||||
static struct device * fb_prepare(dev_t device);
 | 
			
		||||
static int fb_transfer(endpoint_t endpt, int opcode, u64_t position,
 | 
			
		||||
	iovec_t *iov, unsigned int nr_req, endpoint_t user_endpt, unsigned int
 | 
			
		||||
	flags);
 | 
			
		||||
static int fb_do_read(endpoint_t ep, iovec_t *iov, int minor, u64_t pos,
 | 
			
		||||
	size_t *io_bytes);
 | 
			
		||||
static int fb_do_write(endpoint_t ep, iovec_t *iov, int minor, u64_t pos,
 | 
			
		||||
	size_t *io_bytes);
 | 
			
		||||
static int fb_ioctl(message *m);
 | 
			
		||||
static void paint_bootlogo(int minor);
 | 
			
		||||
static void paint_restartlogo(int minor);
 | 
			
		||||
static void paint_centered(int minor, char *data, int width, int height);
 | 
			
		||||
static int do_get_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid);
 | 
			
		||||
static int do_put_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid);
 | 
			
		||||
static int do_get_fixscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid);
 | 
			
		||||
static int do_pan_display(int minor, endpoint_t ep, cp_grant_id_t gid);
 | 
			
		||||
 | 
			
		||||
/* SEF functions and variables. */
 | 
			
		||||
static void sef_local_startup(void);
 | 
			
		||||
static int sef_cb_init(int type, sef_init_info_t *info);
 | 
			
		||||
static int sef_cb_lu_state_save(int);
 | 
			
		||||
static int lu_state_restore(void);
 | 
			
		||||
 | 
			
		||||
/* Entry points to the fb driver. */
 | 
			
		||||
static struct chardriver fb_tab =
 | 
			
		||||
{
 | 
			
		||||
	fb_open,
 | 
			
		||||
	fb_close,
 | 
			
		||||
	fb_ioctl,
 | 
			
		||||
	fb_prepare,
 | 
			
		||||
	fb_transfer,
 | 
			
		||||
	nop_cleanup,
 | 
			
		||||
	nop_alarm,
 | 
			
		||||
	nop_cancel,
 | 
			
		||||
	nop_select,
 | 
			
		||||
	NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Represents the /dev/fb device. */
 | 
			
		||||
static struct device fb_device[FB_DEV_NR];
 | 
			
		||||
static int fb_minor, has_restarted = 0;
 | 
			
		||||
 | 
			
		||||
static int open_counter[FB_DEV_NR];		/* Open count */
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
fb_open(message *m)
 | 
			
		||||
{
 | 
			
		||||
	static int initialized = 0;
 | 
			
		||||
 | 
			
		||||
	if (m->DEVICE < 0 || m->DEVICE >= FB_DEV_NR) return ENXIO;
 | 
			
		||||
 | 
			
		||||
	if (arch_fb_init(m->DEVICE, &fb_device[m->DEVICE]) == OK) {
 | 
			
		||||
		open_counter[m->DEVICE]++;
 | 
			
		||||
		if (!initialized) {
 | 
			
		||||
			if (has_restarted) {
 | 
			
		||||
				paint_restartlogo(m->DEVICE);
 | 
			
		||||
				has_restarted = 0;
 | 
			
		||||
			} else {
 | 
			
		||||
				paint_bootlogo(m->DEVICE);
 | 
			
		||||
			}
 | 
			
		||||
			initialized = 1;
 | 
			
		||||
		}
 | 
			
		||||
		return OK;
 | 
			
		||||
	}
 | 
			
		||||
	return ENXIO ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
fb_close(message *m)
 | 
			
		||||
{
 | 
			
		||||
	if (m->DEVICE < 0 || m->DEVICE >= FB_DEV_NR) return ENXIO;
 | 
			
		||||
	assert(open_counter[m->DEVICE] > 0);
 | 
			
		||||
	open_counter[m->DEVICE]--;
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct device *
 | 
			
		||||
fb_prepare(dev_t dev)
 | 
			
		||||
{
 | 
			
		||||
	if (dev < 0 || dev >= FB_DEV_NR) return NULL;
 | 
			
		||||
	assert(open_counter[dev] > 0);
 | 
			
		||||
	fb_minor = dev;
 | 
			
		||||
	return &fb_device[dev];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
fb_transfer(endpoint_t endpt, int opcode, u64_t position,
 | 
			
		||||
    iovec_t *iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
 | 
			
		||||
    unsigned int UNUSED(flags))
 | 
			
		||||
{
 | 
			
		||||
	size_t io_bytes = 0, ret;
 | 
			
		||||
 | 
			
		||||
	if (nr_req != 1) {
 | 
			
		||||
		/* This should never trigger for char drivers at the moment. */
 | 
			
		||||
		printf("fb: vectored transfer, using first element only\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (opcode) {
 | 
			
		||||
	case DEV_GATHER_S:
 | 
			
		||||
	    /* Userland read operation */
 | 
			
		||||
	    ret = fb_do_read(endpt, iov, fb_minor, position, &io_bytes);
 | 
			
		||||
	    iov->iov_size -= io_bytes;
 | 
			
		||||
            break;
 | 
			
		||||
	case DEV_SCATTER_S:
 | 
			
		||||
	    /* Userland write operation */
 | 
			
		||||
	    ret = fb_do_write(endpt, iov, fb_minor, position, &io_bytes);
 | 
			
		||||
	    iov->iov_size -= io_bytes;
 | 
			
		||||
	    break;
 | 
			
		||||
	default:
 | 
			
		||||
	    return EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
fb_do_read(endpoint_t ep, iovec_t *iov, int minor, u64_t pos, size_t *io_bytes)
 | 
			
		||||
{
 | 
			
		||||
	struct device dev;
 | 
			
		||||
 | 
			
		||||
	arch_get_device(minor, &dev);
 | 
			
		||||
 | 
			
		||||
	if (pos >= dev.dv_size) return EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (dev.dv_size - pos < iov->iov_size) {
 | 
			
		||||
		*io_bytes = dev.dv_size - pos;
 | 
			
		||||
	} else {
 | 
			
		||||
		*io_bytes = iov->iov_size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (*io_bytes <= 0) {
 | 
			
		||||
                return OK;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	return sys_safecopyto(ep, (cp_grant_id_t) iov->iov_addr, 0,
 | 
			
		||||
				(vir_bytes) (dev.dv_base + ex64lo(pos)),
 | 
			
		||||
				*io_bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
fb_ioctl(message *m)
 | 
			
		||||
{
 | 
			
		||||
/* Process I/O control requests */
 | 
			
		||||
	endpoint_t ep;
 | 
			
		||||
	cp_grant_id_t gid;
 | 
			
		||||
	int minor;
 | 
			
		||||
	unsigned int request;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	minor = m->DEVICE;
 | 
			
		||||
	request = m->COUNT;
 | 
			
		||||
	ep = (endpoint_t) m->USER_ENDPT;
 | 
			
		||||
	gid = (cp_grant_id_t) m->IO_GRANT;
 | 
			
		||||
 | 
			
		||||
	if (minor != 0) return EINVAL;
 | 
			
		||||
 | 
			
		||||
	switch(request) {
 | 
			
		||||
	case FBIOGET_VSCREENINFO:
 | 
			
		||||
		r = do_get_varscreeninfo(minor, ep, gid);
 | 
			
		||||
		return r;
 | 
			
		||||
	case FBIOPUT_VSCREENINFO:
 | 
			
		||||
		r = do_put_varscreeninfo(minor, ep, gid);
 | 
			
		||||
		return r;
 | 
			
		||||
	case FBIOGET_FSCREENINFO:
 | 
			
		||||
		r = do_get_fixscreeninfo(minor, ep, gid);
 | 
			
		||||
		return r;
 | 
			
		||||
	case FBIOPAN_DISPLAY:
 | 
			
		||||
		r = do_pan_display(minor, ep, gid);
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
do_get_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct fb_var_screeninfo fbvs;
 | 
			
		||||
 | 
			
		||||
	if ((r = arch_get_varscreeninfo(minor, &fbvs)) == OK) {
 | 
			
		||||
		r = sys_safecopyto(ep, gid, 0, (vir_bytes) &fbvs, sizeof(fbvs));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
do_put_varscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
	struct fb_var_screeninfo fbvs_copy;
 | 
			
		||||
 | 
			
		||||
	if ((r = sys_safecopyfrom(ep, gid, 0, (vir_bytes) &fbvs_copy,
 | 
			
		||||
	    sizeof(fbvs_copy))) != OK) {
 | 
			
		||||
		return r;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return arch_put_varscreeninfo(minor, &fbvs_copy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
do_pan_display(int minor, endpoint_t ep, cp_grant_id_t gid)
 | 
			
		||||
{
 | 
			
		||||
	int r;
 | 
			
		||||
        struct fb_var_screeninfo fbvs_copy;
 | 
			
		||||
 | 
			
		||||
        if ((r = sys_safecopyfrom(ep, gid, 0, (vir_bytes) &fbvs_copy,
 | 
			
		||||
            sizeof(fbvs_copy))) != OK) {
 | 
			
		||||
                return r;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return arch_pan_display(minor, &fbvs_copy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
do_get_fixscreeninfo(int minor, endpoint_t ep, cp_grant_id_t gid)
 | 
			
		||||
{
 | 
			
		||||
        int r;
 | 
			
		||||
        struct fb_fix_screeninfo fbfs;
 | 
			
		||||
 | 
			
		||||
        if ((r = arch_get_fixscreeninfo(minor, &fbfs)) == OK) {
 | 
			
		||||
                r = sys_safecopyto(ep, gid, 0, (vir_bytes) &fbfs, sizeof(fbfs));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
fb_do_write(endpoint_t ep, iovec_t *iov, int minor, u64_t pos, size_t *io_bytes)
 | 
			
		||||
{
 | 
			
		||||
	struct device dev;
 | 
			
		||||
 | 
			
		||||
	arch_get_device(minor, &dev);
 | 
			
		||||
 | 
			
		||||
	if (pos >= dev.dv_size) {
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev.dv_size - pos < iov->iov_size) {
 | 
			
		||||
		*io_bytes = dev.dv_size - pos;
 | 
			
		||||
	} else {
 | 
			
		||||
		*io_bytes = iov->iov_size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (*io_bytes <= 0) {
 | 
			
		||||
                return OK;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	return sys_safecopyfrom(ep, (cp_grant_id_t) iov->iov_addr, 0,
 | 
			
		||||
				(vir_bytes) (dev.dv_base + ex64lo(pos)),
 | 
			
		||||
				*io_bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
sef_cb_lu_state_save(int UNUSED(state)) {
 | 
			
		||||
/* Save the state. */
 | 
			
		||||
	ds_publish_u32("open_counter", open_counter[0], DSF_OVERWRITE);
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
lu_state_restore() {
 | 
			
		||||
/* Restore the state. */
 | 
			
		||||
	u32_t value;
 | 
			
		||||
 | 
			
		||||
	ds_retrieve_u32("open_counter", &value);
 | 
			
		||||
	ds_delete_u32("open_counter");
 | 
			
		||||
	open_counter[0] = (int) value;
 | 
			
		||||
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sef_local_startup()
 | 
			
		||||
{
 | 
			
		||||
	/* Register init callbacks. Use the same function for all event types */
 | 
			
		||||
	sef_setcb_init_fresh(sef_cb_init);
 | 
			
		||||
	sef_setcb_init_lu(sef_cb_init);
 | 
			
		||||
	sef_setcb_init_restart(sef_cb_init);
 | 
			
		||||
 | 
			
		||||
	/* Register live update callbacks  */
 | 
			
		||||
	/* - Agree to update immediately when LU is requested in a valid state*/
 | 
			
		||||
	sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
 | 
			
		||||
	/* - Support live update starting from any standard state */
 | 
			
		||||
	sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
 | 
			
		||||
	/* - Register a custom routine to save the state. */
 | 
			
		||||
	sef_setcb_lu_state_save(sef_cb_lu_state_save);
 | 
			
		||||
 | 
			
		||||
	/* Let SEF perform startup. */
 | 
			
		||||
	sef_startup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
sef_cb_init(int type, sef_init_info_t *UNUSED(info))
 | 
			
		||||
{
 | 
			
		||||
/* Initialize the fb driver. */
 | 
			
		||||
	int do_announce_driver = TRUE;
 | 
			
		||||
 | 
			
		||||
	open_counter[0] = 0;
 | 
			
		||||
	switch(type) {
 | 
			
		||||
	case SEF_INIT_FRESH:
 | 
			
		||||
	    printf("framebuffer fresh: pid %d\n", getpid());
 | 
			
		||||
	    break;
 | 
			
		||||
 | 
			
		||||
	case SEF_INIT_LU:
 | 
			
		||||
	    /* Restore the state. */
 | 
			
		||||
	    lu_state_restore();
 | 
			
		||||
	    do_announce_driver = FALSE;
 | 
			
		||||
 | 
			
		||||
	    printf("framebuffer: I'm a new version!\n");
 | 
			
		||||
	    break;
 | 
			
		||||
 | 
			
		||||
	case SEF_INIT_RESTART:
 | 
			
		||||
	    printf("framebuffer restarted: pid %d\n", getpid());
 | 
			
		||||
	    has_restarted = 1;
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Announce we are up when necessary. */
 | 
			
		||||
	if (do_announce_driver) {
 | 
			
		||||
		chardriver_announce();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Initialization completed successfully. */
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(void)
 | 
			
		||||
{
 | 
			
		||||
	sef_local_startup();
 | 
			
		||||
	chardriver_task(&fb_tab, CHARDRIVER_SYNC);
 | 
			
		||||
	return OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
paint_bootlogo(int minor)
 | 
			
		||||
{
 | 
			
		||||
	paint_centered(minor, bootlogo_data, bootlogo_width, bootlogo_height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
paint_restartlogo(int minor)
 | 
			
		||||
{
 | 
			
		||||
	paint_centered(minor, restartlogo_data, restartlogo_width,
 | 
			
		||||
			restartlogo_height);
 | 
			
		||||
	micro_delay(1 * 1000000);	/* 1 second */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
paint_centered(int minor, char *data, int width, int height)
 | 
			
		||||
{
 | 
			
		||||
	u8_t pixel[3];
 | 
			
		||||
	u32_t i, min_x, min_y, max_x, max_y, x_painted = 0, rows = 0;
 | 
			
		||||
	int r, bytespp;
 | 
			
		||||
	struct device dev;
 | 
			
		||||
	struct fb_var_screeninfo fbvs;
 | 
			
		||||
 | 
			
		||||
	/* Put display in a known state to simplify positioning code below */
 | 
			
		||||
	if ((r = arch_get_varscreeninfo(minor, &fbvs)) != OK) {
 | 
			
		||||
		printf("fb: unable to get screen info: %d\n", r);
 | 
			
		||||
	}
 | 
			
		||||
	fbvs.yoffset = 0;
 | 
			
		||||
	if ((r = arch_pan_display(minor, &fbvs)) != OK) {
 | 
			
		||||
		printf("fb: unable to pan display: %d\n", r);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arch_get_device(minor, &dev);
 | 
			
		||||
 | 
			
		||||
	/* Paint on a white canvas */
 | 
			
		||||
	bytespp = fbvs.bits_per_pixel / 8;
 | 
			
		||||
	for (i = 0; i < fbvs.xres * fbvs.yres * bytespp; i+= bytespp)
 | 
			
		||||
		*((u32_t *)((u32_t) dev.dv_base + i)) = 0x00FFFFFF;
 | 
			
		||||
 | 
			
		||||
	/* First seek to start */
 | 
			
		||||
	min_x = fbvs.xres / 2 - width / 2;
 | 
			
		||||
	max_x = fbvs.xres / 2 + width / 2;
 | 
			
		||||
	min_y = fbvs.yres / 2 - height / 2;
 | 
			
		||||
	max_y = fbvs.yres / 2 + height / 2;
 | 
			
		||||
	i = min_x * fbvs.xres + min_y;
 | 
			
		||||
 | 
			
		||||
	/* Add the image data */
 | 
			
		||||
	for (i = ((min_y * fbvs.xres) + min_x) * bytespp; rows < height;) {
 | 
			
		||||
		GET_PIXEL(data, pixel);
 | 
			
		||||
 | 
			
		||||
		((unsigned char *)((u32_t) dev.dv_base + i))[0] = pixel[2];
 | 
			
		||||
		((unsigned char *)((u32_t) dev.dv_base + i))[1] = pixel[1];
 | 
			
		||||
                ((unsigned char *)((u32_t) dev.dv_base + i))[2] = pixel[0];
 | 
			
		||||
		((unsigned char *)((u32_t) dev.dv_base + i))[3] = 0;
 | 
			
		||||
 | 
			
		||||
		x_painted++;/* Keep tab of how many row pixels we've painted */
 | 
			
		||||
		if (x_painted == width) {
 | 
			
		||||
			/* We've reached the end of the row, carriage return
 | 
			
		||||
			 * and go to next line.
 | 
			
		||||
			 */
 | 
			
		||||
			x_painted = 0;
 | 
			
		||||
			rows++;
 | 
			
		||||
			i = (((min_y + rows) * fbvs.xres) + min_x) * 4;
 | 
			
		||||
		} else {
 | 
			
		||||
			i += 4;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								drivers/fb/fb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								drivers/fb/fb.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
#ifndef __FB_H__
 | 
			
		||||
#define __FB_H__
 | 
			
		||||
 | 
			
		||||
int arch_fb_init(int minor, struct device *dev);
 | 
			
		||||
int arch_get_device(int minor, struct device *dev);
 | 
			
		||||
int arch_get_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp);
 | 
			
		||||
int arch_put_varscreeninfo(int minor, struct fb_var_screeninfo *fbvs_copy);
 | 
			
		||||
int arch_get_fixscreeninfo(int minor, struct fb_fix_screeninfo *fbfsp);
 | 
			
		||||
int arch_pan_display(int minor, struct fb_var_screeninfo *fbvs_copy);
 | 
			
		||||
 | 
			
		||||
#define FB_MESSAGE "Hello, world! From framebuffer!\n"
 | 
			
		||||
 | 
			
		||||
#endif /* __FB_H__ */
 | 
			
		||||
							
								
								
									
										3054
									
								
								drivers/fb/logos.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3054
									
								
								drivers/fb/logos.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -57,7 +57,7 @@ PROG_DRIVERS+=	acpi
 | 
			
		||||
 | 
			
		||||
.if ${MACHINE_ARCH} == "earm"
 | 
			
		||||
EXTRA+=		rc.arm mylogin.sh ttys
 | 
			
		||||
PROG_DRIVERS+=	mmc tty gpio
 | 
			
		||||
PROG_DRIVERS+=	fb mmc tty gpio
 | 
			
		||||
PROG_COMMANDS+=	cp dd getty time sleep stty umount
 | 
			
		||||
PROG_BIN+=	cat ls rm sync
 | 
			
		||||
PROTO=		proto.arm.small
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ d--755 0 0
 | 
			
		||||
		fsck.mfs ---755 0 0 fsck.mfs
 | 
			
		||||
	$
 | 
			
		||||
	sbin d--755 0 0
 | 
			
		||||
		fb ---755 0 0 fb
 | 
			
		||||
		mmc ---755 0 0 mmc
 | 
			
		||||
		mfs ---755 0 0 mfs
 | 
			
		||||
		gpio ---755 0 0 gpio
 | 
			
		||||
 | 
			
		||||
@ -336,6 +336,7 @@
 | 
			
		||||
		c1d7p3s2 b--600 0 0 8 254 
 | 
			
		||||
		c1d7p3s3 b--600 0 0 8 255 
 | 
			
		||||
		console c--600 0 4 4 0 
 | 
			
		||||
		fb0 c--644 0 0 19 0
 | 
			
		||||
		fbd b--600 0 0 14 0 
 | 
			
		||||
		fd0 b--666 0 0 2 0 
 | 
			
		||||
		filter b--644 0 0 11 0 
 | 
			
		||||
 | 
			
		||||
@ -14,5 +14,5 @@ exec </dev/null
 | 
			
		||||
#/bin/mount  /dev/c0d0p1 /mnt
 | 
			
		||||
#gpio
 | 
			
		||||
#mount -t gpio none /gpio
 | 
			
		||||
 | 
			
		||||
#service up /sbin/fb -dev /dev/fb0 -period 2HZ
 | 
			
		||||
exit
 | 
			
		||||
 | 
			
		||||
@ -554,6 +554,18 @@ service mmc
 | 
			
		||||
	irq	83;		# IRQ 83 allowed
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
service fb 
 | 
			
		||||
{
 | 
			
		||||
	system
 | 
			
		||||
		UMAP		# 14
 | 
			
		||||
                DEVIO           # 21
 | 
			
		||||
		PRIVCTL		#  4
 | 
			
		||||
        ;
 | 
			
		||||
	ipc
 | 
			
		||||
                SYSTEM pm rs ds vm vfs
 | 
			
		||||
	;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
service gpio
 | 
			
		||||
{
 | 
			
		||||
	system
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ INCS+=	acpi.h audio_fw.h bitmap.h \
 | 
			
		||||
	config.h const.h cpufeature.h crtso.h \
 | 
			
		||||
	debug.h devio.h devman.h dmap.h \
 | 
			
		||||
	driver.h drivers.h drvlib.h ds.h \
 | 
			
		||||
	endpoint.h fslib.h gpio.h gcov.h hash.h \
 | 
			
		||||
	endpoint.h fb.h fslib.h gpio.h gcov.h hash.h \
 | 
			
		||||
	hgfs.h ioctl.h input.h ipc.h ipcconst.h \
 | 
			
		||||
	keymap.h limits.h log.h mmio.h mount.h mthread.h minlib.h \
 | 
			
		||||
	netdriver.h optset.h padconf.h partition.h portio.h \
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@ enum dev_style { STYLE_NDEV, STYLE_DEV, STYLE_DEVA, STYLE_TTY, STYLE_CTTY,
 | 
			
		||||
#define RANDOM_MAJOR		  16	/* 16 = /dev/random (random driver)   */
 | 
			
		||||
#define HELLO_MAJOR		  17	/* 17 = /dev/hello  (hello driver)    */
 | 
			
		||||
#define UDS_MAJOR		  18	/* 18 = /dev/uds    (pfs)             */
 | 
			
		||||
#define FB_MAJOR		  19	/* 18 = /dev/fb0    (fb driver)       */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Minor device numbers for memory driver. */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								include/minix/fb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								include/minix/fb.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
#ifndef __MINIX_FB_H_
 | 
			
		||||
#define __MINIX_FB_H_
 | 
			
		||||
 | 
			
		||||
#include <minix/type.h>
 | 
			
		||||
 | 
			
		||||
struct fb_fix_screeninfo {
 | 
			
		||||
	char id[16];		/* Identification string */
 | 
			
		||||
	u16_t xpanstep;
 | 
			
		||||
	u16_t ypanstep;
 | 
			
		||||
	u16_t ywrapstep;
 | 
			
		||||
	u32_t line_length;
 | 
			
		||||
	phys_bytes mmio_start;
 | 
			
		||||
	size_t mmio_len;
 | 
			
		||||
	u16_t reserved[15];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fb_bitfield {
 | 
			
		||||
	u32_t offset;
 | 
			
		||||
	u32_t length;
 | 
			
		||||
	u32_t msb_right;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fb_var_screeninfo {
 | 
			
		||||
	u32_t xres;		/* visible resolution */
 | 
			
		||||
	u32_t yres;
 | 
			
		||||
	u32_t xres_virtual;	/* virtual resolution */
 | 
			
		||||
	u32_t yres_virtual;
 | 
			
		||||
	u32_t xoffset;		/* offset from virtual to visible */
 | 
			
		||||
	u32_t yoffset;
 | 
			
		||||
	u32_t bits_per_pixel;
 | 
			
		||||
	struct fb_bitfield red;	/* bitfield in fb mem if true color */
 | 
			
		||||
	struct fb_bitfield green;
 | 
			
		||||
	struct fb_bitfield blue;
 | 
			
		||||
	struct fb_bitfield transp;	/* transparency */
 | 
			
		||||
	u16_t reserved[10];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* __MINIX_FB_H_ */
 | 
			
		||||
@ -3,8 +3,8 @@ INCSDIR= /usr/include/sys
 | 
			
		||||
 | 
			
		||||
# Minix specific system headers
 | 
			
		||||
INCS=	elf64.h elf_common.h elf_core.h elf_generic.h \
 | 
			
		||||
	ioc_block.h ioc_disk.h ioc_fbd.h ioc_file.h ioc_memory.h ioc_net.h \
 | 
			
		||||
	ioc_sound.h ioc_tape.h ioc_tty.h \
 | 
			
		||||
	ioc_block.h ioc_disk.h ioc_fb.h ioc_fbd.h ioc_file.h ioc_memory.h \
 | 
			
		||||
	ioc_net.h ioc_sound.h ioc_tape.h ioc_tty.h \
 | 
			
		||||
	kbdio.h \
 | 
			
		||||
	procfs.h statfs.h svrctl.h video.h vm.h 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								include/sys/ioc_fb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								include/sys/ioc_fb.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
/*	sys/ioc_fb.h - Framebuffer command codes
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _S_I_FB_H
 | 
			
		||||
#define _S_I_FB_H
 | 
			
		||||
 | 
			
		||||
/* The I/O control requests. */
 | 
			
		||||
#define FBIOGET_VSCREENINFO	_IOR('V', 1, struct fb_var_screeninfo)
 | 
			
		||||
#define FBIOPUT_VSCREENINFO     _IOW('V', 2, struct fb_var_screeninfo)
 | 
			
		||||
#define FBIOGET_FSCREENINFO     _IOR('V', 3, struct fb_fix_screeninfo)
 | 
			
		||||
#define FBIOPAN_DISPLAY	_IOW('V', 4, struct fb_var_screeninfo)
 | 
			
		||||
 | 
			
		||||
#endif /* _S_I_FB_H */
 | 
			
		||||
@ -20,6 +20,7 @@
 | 
			
		||||
#include <sys/ioc_memory.h>	/* 'm'			*/
 | 
			
		||||
#include <sys/ioc_tape.h>	/* 'M'			*/
 | 
			
		||||
#include <sys/ioc_sound.h>	/* 's'			*/
 | 
			
		||||
#include <sys/ioc_fb.h>		/* 'F'			*/
 | 
			
		||||
 | 
			
		||||
#if defined(_NETBSD_SOURCE)
 | 
			
		||||
#define		TIOCDRAIN 	TCDRAIN
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user