~jkaivo/freeonebook

888154172ac00710a5f792a56c7b8e82377160ad — Jakob Kaivo 3 years ago 72386a1
further progress
1 files changed, 88 insertions(+), 59 deletions(-)

M fb.c
M fb.c => fb.c +88 -59
@@ 1,65 1,73 @@
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

#include <linux/fb.h>
#include <linux/mxcfb.h>
#include <sys/ioctl.h>

#include "fb.h"
#include "gpio.h"

struct imx_epdc_fb_mode {
	struct fb_videomode *vmode;
	int vscan_holdoff;
	int sdoed_width;
	int sdoed_delay;
	int sdoez_width;
	int sdoez_delay;
	int gdclk_hp_offs;
	int gdsp_offs;
	int gdoe_offs;
	int gdclk_offs;
	int num_ce;
};

static unsigned char *fbaddr;
static struct fb_fix_screeninfo fsi;
static struct fb_var_screeninfo vsi;

static void dumpvsi(const char *ctl, int io)
static struct {
	int fd;
	unsigned char *addr;
	struct fb_fix_screeninfo fsi;
	struct fb_var_screeninfo vsi;
	size_t size;
} fb;

static void fb_update(int x, int y, int w, int h)
{
	printf("- %s\n", ctl);
	printf("\tioctl returned %d\n", io);
	printf("\txres: %d\n", vsi.xres);
	printf("\tyres: %d\n", vsi.yres);
	printf("\txres_virtual: %d\n", vsi.xres_virtual);
	printf("\tyres_virtual: %d\n", vsi.yres_virtual);
	printf("\txoffset: %d\n", vsi.xoffset);
	printf("\tyoffset: %d\n", vsi.yoffset);
	printf("\tbits_per_pixel: %d\n", vsi.bits_per_pixel);
	printf("\tgrayscale: %d\n", vsi.grayscale);
	static int marker = 0;
	marker++;

	struct mxcfb_update_data data = {
		.update_mode = UPDATE_MODE_PARTIAL,
		.waveform_mode = WAVEFORM_MODE_AUTO, /* DU? */
		.update_region.left = x,
		.update_region.top = y,
		.update_region.width = w,
		.update_region.height = h,
		.update_marker = marker,
		.temp = TEMP_USE_AMBIENT,
		.flags = 0,
	};
	ioctl(fb.fd, MXCFB_SEND_UPDATE, &data);

	struct mxcfb_update_marker_data md = {
		.update_marker = marker,
	};

	ioctl(fb.fd, MXCFB_WAIT_FOR_UPDATE_COMPLETE, &md);
}

static void dumpfsi(const char *ctl, int io)
static void fb_blank(void)
{
	printf("- %s\n", ctl);
	printf("\tioctl returned %d\n", io);
	printf("\tid: %16s\n", fsi.id);
	printf("\tsmem_len: %d\n", fsi.smem_len);
	printf("\ttype: %d\n", fsi.type);
	printf("\ttype_aux: %d\n", fsi.type_aux);
	printf("\tvisual: %d\n", fsi.visual);
	printf("\txpanstep: %d\n", fsi.xpanstep);
	printf("\typanstep: %d\n", fsi.ypanstep);
	printf("\tywrapstep: %d\n", fsi.ywrapstep);
	printf("\tline_length: %d\n", fsi.line_length);
	printf("\tmmio_start: %lu\n", fsi.mmio_start);
	printf("\tmmio_len: %d\n", fsi.mmio_len);
	printf("\taccel: %d\n", fsi.accel);
	printf("\tcapabilities: %d\n", fsi.capabilities);
	memset(fb.addr, 0xff, fb.size);
	fb_update(0, 0, fb.vsi.xres, fb.vsi.yres);
}

static void fb_loadimage(const char *path)
{
	int fd = open(path, O_RDONLY);
	if (fd == -1) {
		return;
	}

	char *img = mmap(NULL, fb.size, PROT_READ, MAP_PRIVATE, fd, 0);
	if (img == MAP_FAILED) {
		return;
	}

	memcpy(fb.addr, img, fb.size);
	munmap(img, fb.size);
	close(fd);

	fb_update(0, 0, fb.vsi.xres, fb.vsi.yres);
}

void fb_init(void)


@@ 73,23 81,44 @@ void fb_init(void)

	printf("mapping framebuffer...\n");
	
	int fbfd = open("/dev/fb0", O_RDWR);
	fb.fd = open("/dev/fb0", O_RDWR);

	ioctl(fb.fd, FBIOGET_FSCREENINFO, &fb.fsi);

	ioctl(fb.fd, FBIOGET_VSCREENINFO, &fb.vsi);

	fb.vsi.bits_per_pixel = 8;
	fb.vsi.grayscale = GRAYSCALE_8BIT_INVERTED;
	fb.vsi.activate = FB_ACTIVATE_FORCE;

	int io = ioctl(fbfd, FBIOGET_FSCREENINFO, &fsi);
	dumpfsi("FBIOGET_FSCREENINFO", io);
	ioctl(fb.fd, FBIOPUT_VSCREENINFO, &fb.vsi);

	io = ioctl(fbfd, FBIOGET_VSCREENINFO, &vsi);
	dumpvsi("FBIOEGET_VSCREENINFO", io);
	fb.size = fb.vsi.xres_virtual * fb.vsi.yres_virtual;
	fb.addr = mmap(NULL, fb.size, PROT_READ | PROT_WRITE, MAP_SHARED, fb.fd, 0);

	vsi.bits_per_pixel = 8;
	vsi.grayscale = 1;
	vsi.activate = FB_ACTIVATE_FORCE;
	printf("at %p\n", fb.addr);

	io = ioctl(fbfd, FBIOPUT_VSCREENINFO, &vsi); 
	dumpvsi("FBIOPUT_VSCREENINFO", io);
	int updatemode = AUTO_UPDATE_MODE_REGION_MODE;
	ioctl(fb.fd, MXCFB_SET_AUTO_UPDATE_MODE, &updatemode);

	fbaddr = mmap(NULL, fsi.smem_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fbfd, 0);
	/*
	struct mxcfb_waveform_modes wave = {
		.mode_init = WAVEFORM_MODE_INIT,
		.mode_du = WAVEFORM_MODE_DU,
		.mode_gc4 = WAVEFORM_MODE_GC4,
		.mode_gc8 = WAVEFORM_MODE_GC16,
		.mode_gc16 = WAVEFORM_MODE_GC16,
		.mode_gc32 = WAVEFORM_MODE_GC16,
	};
	ioctl(fb.fd, MXCFB_SET_WAVEFORM_MODES, &wave);

	int scheme = UPDATE_SCHEME_QUEUE_AND_MERGE;
	ioctl(fb.fd, MXCFB_SET_UPDATE_SCHEME, &scheme);

	int powerdelay = 0;
	ioctl(fb.fd, MXCFB_SET_PWRDOWN_DELAY, &powerdelay);
	*/

	close(fbfd);
	printf("at %p\n", fbaddr);
	fb_blank();
	//fb_loadimage("/run/media/mmcblk0p1/left-screen.dat");
}