2019-12-01 18:53:54 -07:00
|
|
|
#include <stddef.h>
|
2019-12-01 19:39:14 -07:00
|
|
|
#include <string.h>
|
2019-12-01 18:53:54 -07:00
|
|
|
#include <fcntl.h>
|
2019-12-01 19:20:04 -07:00
|
|
|
#include <unistd.h>
|
2019-12-01 18:53:54 -07:00
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/ioctl.h>
|
2019-12-01 19:39:14 -07:00
|
|
|
#include <sys/mman.h>
|
2019-12-01 18:53:54 -07:00
|
|
|
#include <linux/fb.h>
|
2019-12-06 22:06:05 -07:00
|
|
|
#include "config.h"
|
2019-12-01 18:53:54 -07:00
|
|
|
#include "log.h"
|
|
|
|
#include "fbinit.h"
|
2019-12-05 18:21:37 -07:00
|
|
|
#include "scode.h"
|
2019-12-01 18:53:54 -07:00
|
|
|
|
2019-12-06 20:41:26 -07:00
|
|
|
/* references to splash screen data in splash.o/splash.bin */
|
2019-12-06 20:51:41 -07:00
|
|
|
extern uint8_t _binary_splash_bin_start[];
|
|
|
|
extern uint8_t _binary_splash_bin_end;
|
|
|
|
extern uint8_t _binary_splash_bin_size;
|
2019-12-06 20:41:26 -07:00
|
|
|
|
2019-12-07 13:07:59 -07:00
|
|
|
static int fb_fd = -1; /* framebuffer file descriptor */
|
2019-12-01 18:53:54 -07:00
|
|
|
|
2019-12-07 13:07:59 -07:00
|
|
|
/* frame buffer information */
|
2019-12-01 19:39:14 -07:00
|
|
|
static FBINFO local_info;
|
|
|
|
PCFBINFO Fb_Info = &local_info;
|
2019-12-01 18:53:54 -07:00
|
|
|
|
2019-12-07 13:07:59 -07:00
|
|
|
UINT16 *Fb_Ptr = NULL; /* pointer to memory-mapped frame buffer */
|
2019-12-01 19:39:14 -07:00
|
|
|
|
2019-12-05 18:21:37 -07:00
|
|
|
inline static UINT16 makemask(unsigned offset, unsigned length)
|
2019-12-01 18:53:54 -07:00
|
|
|
{
|
2019-12-05 18:21:37 -07:00
|
|
|
return (UINT16)(((1 << length) - 1) << offset);
|
2019-12-01 18:53:54 -07:00
|
|
|
}
|
|
|
|
|
2019-12-06 22:06:05 -07:00
|
|
|
static void do_cleanup(void)
|
|
|
|
{
|
2019-12-07 13:07:59 -07:00
|
|
|
/* black out the display */
|
2019-12-06 22:06:05 -07:00
|
|
|
memset(Fb_Ptr, 0, local_info.screenbytes);
|
|
|
|
|
2019-12-07 13:07:59 -07:00
|
|
|
munmap((void *)Fb_Ptr, local_info.screenbytes);
|
|
|
|
Fb_Ptr = NULL;
|
2019-12-06 22:06:05 -07:00
|
|
|
close(fb_fd);
|
|
|
|
fb_fd = -1;
|
|
|
|
}
|
|
|
|
|
2019-12-05 18:21:37 -07:00
|
|
|
HRESULT Fb_setup(void)
|
2019-12-01 18:53:54 -07:00
|
|
|
{
|
2019-12-05 18:21:37 -07:00
|
|
|
HRESULT hr = S_OK;
|
2019-12-01 18:53:54 -07:00
|
|
|
struct fb_fix_screeninfo fixed;
|
|
|
|
struct fb_var_screeninfo var;
|
|
|
|
|
2019-12-06 22:06:05 -07:00
|
|
|
fb_fd = open(Gconfig.framebuffer_device, O_RDWR);
|
2019-12-01 18:53:54 -07:00
|
|
|
if (fb_fd == -1)
|
|
|
|
{
|
2019-12-05 18:21:37 -07:00
|
|
|
hr = ERRNO_AS_SCODE;
|
2019-12-07 13:07:59 -07:00
|
|
|
Log(LFATAL, "Unable to open framebuffer device %s (%08X)", Gconfig.framebuffer_device, hr);
|
2019-12-05 18:21:37 -07:00
|
|
|
return hr;
|
2019-12-01 18:53:54 -07:00
|
|
|
}
|
|
|
|
|
2019-12-07 13:07:59 -07:00
|
|
|
/* fixed info is needed to get the memory parameters for the display */
|
2019-12-01 18:53:54 -07:00
|
|
|
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fixed))
|
|
|
|
{
|
2019-12-05 18:21:37 -07:00
|
|
|
hr = ERRNO_AS_SCODE;
|
|
|
|
Log(LFATAL, "Could not get fixed screen info (%08X)", hr);
|
|
|
|
return hr;
|
2019-12-01 18:53:54 -07:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:39:14 -07:00
|
|
|
local_info.linebytes = fixed.line_length;
|
|
|
|
local_info.screenbytes = fixed.smem_len;
|
2019-12-01 18:53:54 -07:00
|
|
|
|
2019-12-07 13:07:59 -07:00
|
|
|
/* variable info is used to get scren geometry and color info */
|
2019-12-01 18:53:54 -07:00
|
|
|
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
|
|
|
|
{
|
2019-12-05 18:21:37 -07:00
|
|
|
hr = ERRNO_AS_SCODE;
|
|
|
|
Log(LFATAL, "Could not get variable screen info (%08X)", hr);
|
|
|
|
return hr;
|
2019-12-01 18:53:54 -07:00
|
|
|
}
|
|
|
|
|
2019-12-01 19:39:14 -07:00
|
|
|
local_info.width = var.xres;
|
|
|
|
local_info.height = var.yres;
|
|
|
|
local_info.virtual_width = var.xres_virtual;
|
|
|
|
local_info.virtual_height = var.yres_virtual;
|
|
|
|
local_info.bpp = var.bits_per_pixel;
|
|
|
|
local_info.red_offset = var.red.offset;
|
|
|
|
local_info.red_length = var.red.length;
|
|
|
|
local_info.red_mask = makemask(var.red.offset, var.red.length);
|
|
|
|
local_info.green_offset = var.green.offset;
|
|
|
|
local_info.green_length = var.green.length;
|
|
|
|
local_info.green_mask = makemask(var.green.offset, var.green.length);
|
|
|
|
local_info.blue_offset = var.blue.offset;
|
|
|
|
local_info.blue_length = var.blue.length;
|
|
|
|
local_info.blue_mask = makemask(var.blue.offset, var.blue.length);
|
|
|
|
|
2019-12-05 18:21:37 -07:00
|
|
|
Fb_Ptr = (UINT16 *)mmap(0, fixed.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
|
2019-12-01 19:39:14 -07:00
|
|
|
if ((int)Fb_Ptr == -1)
|
|
|
|
{
|
2019-12-05 18:21:37 -07:00
|
|
|
hr = ERRNO_AS_SCODE;
|
|
|
|
Log(LFATAL, "Unable to memmap framebuffer (%08X)", hr);
|
2019-12-01 19:39:14 -07:00
|
|
|
Fb_Ptr = NULL;
|
|
|
|
close(fb_fd);
|
|
|
|
fb_fd = -1;
|
2019-12-05 18:21:37 -07:00
|
|
|
return hr;
|
2019-12-01 19:39:14 -07:00
|
|
|
}
|
2019-12-01 18:53:54 -07:00
|
|
|
|
2019-12-06 20:57:44 -07:00
|
|
|
/* display the splash screen */
|
2019-12-06 21:15:44 -07:00
|
|
|
memcpy(Fb_Ptr, _binary_splash_bin_start, (size_t)(&_binary_splash_bin_size));
|
2019-12-06 20:57:44 -07:00
|
|
|
|
2019-12-06 22:06:05 -07:00
|
|
|
hr = Config_exitfunc(do_cleanup);
|
|
|
|
if (FAILED(hr))
|
|
|
|
do_cleanup();
|
2019-12-05 18:21:37 -07:00
|
|
|
return hr;
|
2019-12-01 18:53:54 -07:00
|
|
|
}
|
|
|
|
|
2019-12-06 20:57:44 -07:00
|
|
|
void Fb_clear(void)
|
|
|
|
{
|
|
|
|
memset(Fb_Ptr, 0, local_info.screenbytes);
|
|
|
|
}
|