#ifndef _CORE_FBDEV_H_
#define _CORE_FBDEV_H_

#include <core/types.h>

/****************************************************************************************************************
 *
 * FRAMEBUFFER INTERFACE
 *
 * Note the distinction between VIEWPORT and FRAMEBUFFER.
 *
 * The size of the VIEWPORT is the size of the actual display hardware.
 * The FRAMEBUFFER size might be bigger than this.
 *
 * If FRAMEBUFFER is bigger than VIEWPORT, then the display hardware will show a rectangular area
 * of the whole FRAMEBUFFER, starting at the ORIGIN position.
 *
 ****************************************************************************************************************/

struct framebuffer {
  uint   fb_width;				// Geometry
  uint   fb_height;
  uint   fb_x_step;				// Granularity of possible VIEWPORT origins.
  uint   fb_y_step;
  uint32 fb_bytes_per_line;			// Bytes used by a single line
  uint32 fb_bytes_per_screen;			// Size of whole data buffer
  uint16 fb_palette_size;			// Size of palette (0 = direct color)
  uint8  fb_bpp;				// Bits per pixel
  uint8  fb_format;				// Pixel format (see below)
};

/****************************************************************************************************************/

struct framebuffer_capabilities {
  uint fc_width;				// Geometry of actual hardware
  uint fc_height;
  uint fc_max_bpp;				// Maximum supported bits per pixel
  uint fc_flags;				// Misc flags
  char fc_name[64];				// Name of the display
};

#define FBCAP_TOUCH			1	// Has a touch screen attached
#define FBCAP_BRIGHTNESS		2	// Has a brightness control
#define FBCAP_CONTRAST			4	// Has a contrast control
#define FBCAP_XFLIP			8	// Can mirror display in X direction
#define FBCAP_YFLIP		       16	// Can mirror display in Y direction
#define FBCAP_REVERSE		       32	// Default background is black

/****************************************************************************************************************/

struct framebuffer_origin {
  uint x;
  uint y;
};

/****************************************************************************************************************/
//
// Pixel format
//
#define FBRGB_STRAIGHT		0x00		// Pixel values map directly to 24-bit RGB values

#define FBRGB_16BPP_ATMEL_BGR	0x01		// 16 bits per pixel, 565, BGR
#define FBRGB_24BPP_ATMEL_BGR	0x02		// 24 bits per pixel, Red and blue values swapped
#define FBRGB_16BPP_ATMEL_RGB	0x03		// 16 bits per pixel, 565, RGB

#define FBRGB_18BPP_SHIFTED	0x04		// 18 bits per pixel, 666, use bits 0..5 per byte

#define FBRGB_1BPP_MONO		0x81		// 1 bit per pixel
#define FBRGB_2BPP_MONO		0x82		// 2 bits per pixel grayscale
#define FBRGB_4BPP_MONO		0x83		// 4 bits per pixel grayscale

#define FBRGB_MONOCHROME	0x80		// Bit mask to detect monochrome format

/****************************************************************************************************************
 *
 * Work with framebuffer and screen geometries.
 *
 */

//
// Get capabilities of display hardware.
// Fills a "struct framebuffer_capabilities"
//
#define FBDEV_GETCAPS		0x4600

//
// Get geometry of framebuffer
// Takes a "struct framebuffer" and returns currently configured values.
//
#define FBDEV_GETGEO		0x4601

//
// Change geometry of full FRAMEBUFFER.
// Takes a "struct framebuffer" and updates the hardware.
// 
// Only the fields fb_width, fb_height and fb_bpp are used.
// On success, the other fields are filled in with the actual values.
// 
// - Initializes hardware
// - Resets origin to 0,0
// - Resets palette to default colors (if used)
// - Clears screen to default color
//    - Black on color displays
//    - 0 on monochrome displays (What that means depends on the display hardware.)
//
// Before calling this munmap() the old framebuffer, then mmap() the new one.
// 
#define FBDEV_SETUP		0x4602

//
// Set origin of VIEWPORT inside FRAMEBUFFER
// Takes a "struct framebuffer_origin" and updates the hardware.
//
// Actual hardware may have some constraints on possible values.
// (E.g. set some values only in steps of 8 or such).
// This call will do a best effort and will update the passed structure with the values actually chosen.
//
#define FBDEV_SETORG		0x4603

//
// Set origin of VIEWPORT inside FRAMEBUFFER
// Fills a "struct framebuffer_origin"
//
#define FBDEV_GETORG		0x4604

//
// (Forcefully) select type of display attached
// Takes a single integer with the display type identifier.
//
#define FBDEV_SELECT		0x460F

/****************************************************************************************************************
 *
 * Update contrast and brightness
 *
 * On get, if a value is -1, hardware does not support it.
 * On set, if a value is -1, the control is not changed.
 *
 */
struct fbdev_control {
  int brightness;
  int contrast;
  int spare[14];
};

#define FBDEV_SETCONTR		0x4605		// Brightness, Contrast, ...
#define FBDEV_GETCONTR		0x4606

/****************************************************************************************************************
 *
 * For speed reasons, the framebuffer is fully cached inside the CPU.
 * Unfortunately, this means that the cache needs to be flushed to make sure everything drawn appears on screen.
 *
 * Invoke this ioctl after doing major screen updates and whenever you are waiting for user input.
 * Media players must call this after each frame has been drawn.
 *
 */
#define FBDEV_SYNC		0x460A		// Flushes data cache of framebuffer

/****************************************************************************************************************
 *
 * Access the palette, when the framebuffer runs in paletted mode.
 *
 * ioctls take a pointer to an array of 32-bit integers, with the color values in standard 24-bit RGB format.
 *
 * The size of the array depends on the palette size value from the framebuffer geometry.
 *
 */
#define FBDEV_SETPALETTE	0x460B
#define FBDEV_GETPALETTE	0x460C

/****************************************************************************************************************
 *
 * Set and get control flags
 *
 * Takes a pointer to an integer.
 *
 */
#define FBFLAG_XFLIP			8	// Enable mirror display in X direction
#define FBFLAG_YFLIP		       16	// Enable mirror display in Y direction

#define FBDEV_SETFLAGS		0x460D
#define FBDEV_GETFLAGS		0x460E

/****************************************************************************************************************/
#endif
