#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_frame;			// Visible size of one frame buffer
  uint32 fb_bytes_per_buffer;			// Allocated 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_BACKLIGHT			2	// Has a backlight 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
#define FBCAP_DPMS		       64	// Supports power management

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

struct framebuffer_output {
  int fo_width;					// Output width.
  int fo_height;				// Output height.
  int fo_bpp;					// Color depth.
  int fo_hz;					// Frame refresh frequency.
};

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

struct framebuffer_origin {
  uint x;
  uint y;
};

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

struct framebuffer_watch {
  uint32 offset;
  uint32 count;
};

/****************************************************************************************************************/
//
// Display states
//
#define FBSTATE_DPMS_OFF		0		// Display is off
#define FBSTATE_DPMS_SUSPEND		1		//
#define FBSTATE_DPMS_STANDBY		2		//
#define FBSTATE_DPMS_NORMAL		3		// Display is on
#define FBSTATE_DPMS_MASK	      3

#define FBSTATE_CONNECTED		4		// Display is plugged in
#define FBSTATE_POWERED			8		// Display is plugged in and has power (but might still be off)
#define FBSTATE_ACTIVE			16		// Graphics controller is enabled

#define FBSTATE_BACKPLANE_CONNECTED	32		// Backplane controller detected and online

#define FBSTATE_REMAPPED		(1<<30)		// Application needs to remap framebuffer
#define FBSTATE_CHANGED			(1<<31)		// Display state has changed since last call to FBDEV_GET_STATE

/****************************************************************************************************************/
//
// 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.
//
// This call does NOT change the resolution of the VIEWPORT.
//
// 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.)
//
// This call may cause the current mmap()ping of the framebuffer to become detached from the display.
// Before calling this munmap() the old framebuffer, then mmap() the new one.
// 
#define FBDEV_SETUP_FRAMEBUFFER	0x4602
#define FBDEV_SETUP		FBDEV_SETUP_FRAMEBUFFER // Deprecated

//
// 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

//
// Blocked: 0x4605, 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

/****************************************************************************************************************
 *
 * Access display output parameters.
 *
 * These parameters directly affect the signals that are sent to the display.
 *
 */

//
// Get current display output configuration
// Takes a "struct framebuffer_output" and returns currently configured values.
// If no display is connected, all structure fields are returned as -1
//
#define FBDEV_GET_VIEWPORT	0x4610

//
// Change current display output configuration
// Takes a "struct framebuffer_output" and sets up what is sent to the display.
// Any field in the structure that is set to -1 will be replaced by preferred default values for the display.
// Call fails if values are not supported by display.
// Obviously, if no display is connected then nothing is supported and the call fails, too.
//
// This call may cause the current mmap()ping of the framebuffer to become detached from the display.
// Before calling this munmap() the old framebuffer, then mmap() the new one.
//
#define FBDEV_SET_VIEWPORT	0x4611

//
// Get current display output configuration
// Takes a "struct fbdev_modeline" and returns currently configured values.
// If no display is connected, structure is filled with zeroes.
//
#define FBDEV_GET_MODELINE	0x4612

//
// Change current display output configuration
// Takes a "struct fbdev_modeline" and sets up what is sent to the display.
// Call fails if values are not supported by display.
// Obviously, if no display is connected then nothing is supported and the call fails, too.
//
// This call may cause the current mmap()ping of the framebuffer to become detached from the display.
// Before calling this munmap() the old framebuffer, then mmap() the new one.
//
#define FBDEV_SET_MODELINE	0x4613

//
// Get current display status
// Takes a pointer to an unsigned int. Returns a set of FBSTATE_... flags.
// FBSTATE_CHANGED and FBSTATE_REMAPPED are cleared after the call.
//
#define FBDEV_GET_STATE		0x4614

//
// Change display status
// Takes a pointer to an unsigned int with a set of FBSTATE_... flags.
// Only the power management states can be changed.
//
#define FBDEV_SET_STATE		0x4615

//
// Get edid data from current display.
// Takes a "struct fbdev_edid" and returns decoded values.
// If no display is connected, structure is filled with zeroes.
//
// The field structure_size of the passed "struct fbdev_edid" must be set to the size of the structure.
//
#define FBDEV_GET_EDID		0x4616

//
// Get raw edid data from current display. This is the raw data as it was read from the eeprom.
// Pass a "struct iovec" that is properly filled to point to a buffer of at least 128 bytes.
//
#define FBDEV_GET_EDID_RAW	0x4617

//
// Get backplane version data from current display.
// Takes a "struct fbdev_backplane_version" and returns decoded values.
// If no display is connected or the display does not have a backplane processor, structure is filled with zeroes.
//
// The field structure_size of the passed "struct fbdev_backplane_version" must be set to the size of the structure.
//
#define FBDEV_GET_BACKPLANE	0x4618

//
// Get default orientation as stored in kernel config.
// Avoids having to deal with /dev/kconfig just to read this value.
// Read C4S_GENERAL -> C4T_GEN_DISPLAY_ORIENTATION
//
#define FBDEV_GET_DEFAULT_ORIENTATION	0x461B

//
// Query list of 1kB pages inside the framebuffer that have changed since last call.
// Takes a pointer to a struct framebuffer_watch.
// Call will fail unless framebuffer watch data buffer has been mmap()ed already.
// The call rearms change detection.
//
#define FBDEV_WATCH		0x461C

//
// Enable/disable vertical blank signalling.
// Takes a pointer to an unsigned int containing mode value.
//
#define FBDEV_GET_VERTICAL_BLANK    0x461D
#define FBDEV_SET_VERTICAL_BLANK    0x461E

#define FBDEV_VERTICAL_BLANK_OFF    0 // Disabled
#define FBDEV_VERTICAL_BLANK_ON     1 // Enabled

//
// Enable/disable double buffering
// Takes a pointer to an unsigned int containing mode value.
// When enabled, kernel allocates two framebuffers of equal size.
// Buffer can be switched with FBDEV_SET_DOUBLE_BUFFER_INDEX
//
#define FBDEV_GET_DOUBLE_BUFFER_MODE     0x4620
#define FBDEV_SET_DOUBLE_BUFFER_MODE     0x4621

// Query current selected buffer when double buffering is enabled.
// Takes pointer to integer that will receive the index.
#define FBDEV_GET_DOUBLE_BUFFER_INDEX    0x4622

// Set current selected buffer when double buffering is enabled.
// Takes pointer to integer that must contain the index.
// On return, the integer will contain the number of elapsed microseconds since last buffer switch.
#define FBDEV_SET_DOUBLE_BUFFER_INDEX    0x4623

/****************************************************************************************************************
 *
 * 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.
 *
 */
#define FBDEV_CONTROL_BACKLIGHT	  0
#define FBDEV_CONTROL_CONTRAST	  1
#define FBDEV_CONTROL_BRIGHTNESS  2
#define FBDEV_CONTROL_DESKEW      3
#define FBDEV_CONTROL_TFP410_TEST 15

struct fbdev_control {
  unsigned int control;
  int value;
};

#define FBDEV_SETCONTROL	0x4619
#define FBDEV_GETCONTROL	0x461A

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