Squashed commit of the following:

video/edid:  Add some initial EDID logic ported from FreeBSD.
    video/:  Add basic configure and build support for a video subsystem.
This commit is contained in:
Gregory Nutt 2019-07-07 16:40:24 -06:00
parent 8edff9d295
commit dbf286472b
13 changed files with 1230 additions and 98 deletions

View File

@ -1684,6 +1684,10 @@ menu "Audio Support"
source audio/Kconfig
endmenu
menu "Video Support"
source video/Kconfig
endmenu
menu "Wireless Support"
source wireless/Kconfig
endmenu

View File

@ -49,6 +49,8 @@
* Included Files
********************************************************************************************/
#include <stdint.h>
/********************************************************************************************
* Pre-processor Definitions
********************************************************************************************/
@ -58,91 +60,95 @@
/* EDID data offsets ************************************************************************/
/* Bytes 0-7: Header Information */
#define EDID_HEADER_MAGIC 0 /* Fixed header pattern: 00 FF FF FF FF FF FF 00 */
#define EDID_HEADER_MAGIC_SIZE 8
#define EDID_HEADER_MAGIC_OFFSET 0 /* Fixed header pattern: 00 FF FF FF FF FF FF 00 */
#define EDID_HEADER_MAGIC_SIZE 8
/* Bytes 8-17: Vendor Information */
#define EDID_VENDOR_MANUFACTURER 8 /* Encoded 3-character manufacture ID */
#define EDID_VENDOR_MANUFACTURER_SIZE 2 /* 16-bit, big endian value */
#define EDID_VENDOR_MANUFACTURER_OFFSET 8 /* Encoded 3-character manufacture ID */
#define EDID_VENDOR_MANUFACTURER_SIZE 2 /* 16-bit, big endian value */
#define EDID_VENDOR_PRODUCTCODE 10 /* Product code. 16-bit, little endian value */
#define EDID_VENDOR_PRODUCTCODE_SIZE 2
#define EDID_VENDOR_PRODUCTCODE_OFFSET 10 /* Product code. 16-bit, little endian value */
#define EDID_VENDOR_PRODUCTCODE_SIZE 2
#define EDID_VENDOR_SERIALNO 12 /* Serial number: 32-bit, little endian value */
#define EDID_VENDOR_SERIALNO_SIZE 4
#define EDID_VENDOR_SERIALNO_OFFSET 12 /* Serial number: 32-bit, little endian value */
#define EDID_VENDOR_SERIALNO_SIZE 4
#define EDID_VENDOR_WEEK 16 /* Week of manufacture or model year flag */
#define EDID_VENDOR_YEAR 17 /* Year of manufacture (minus 1990) */
#define EDID_VENDOR_WEEK_OFFSET 16 /* Week of manufacture or model year flag */
#define EDID_VENDOR_YEAR_OFFSET 17 /* Year of manufacture (minus 1990) */
/* Bytes 18-19: EDID Version */
#define EDID_VERSION_MAJOR 18 /* EDID version, usually 1 (for 1.3) */
#define EDID_VERSION_MINOR 19 /* EDID revision, usually 3 (for 1.3) */
#define EDID_VERSION_MAJOR_OFFSET 18 /* EDID version, usually 1 (for 1.3) */
#define EDID_VERSION_MINOR_OFFSET 19 /* EDID revision, usually 3 (for 1.3) */
/* Bytes 20-44: Display Information */
#define EDID_DISPLAY_INPUT 20 /* Video input parameters bitmap */
#define EDID_DISPLAY_HSIZE 21 /* Horizontal screen size, in centimetres */
#define EDID_DISPLAY_VSIZE 22 /* Vertical screen size, in centimetres */
#define EDID_DISPLAY_GAMMA 23 /* Display gamma, factory default */
#define EDID_DISPLAY_FEATURES 24 /* Support features bitmap */
#define EDID_DISPLAY_INPUT_OFFSET 20 /* Video input parameters bitmap */
#define EDID_DISPLAY_HSIZE_OFFSET 21 /* Horizontal screen size, in centimetres */
#define EDID_DISPLAY_VSIZE_OFFSET 22 /* Vertical screen size, in centimetres */
#define EDID_DISPLAY_GAMMA_OFFSET 23 /* Display gamma, factory default */
#define EDID_DISPLAY_FEATURES_OFFSET 24 /* Support features bitmap */
/* Bytes 25-34: Chromaticity */
#define EDID_CHROMA_RG_LOW 25 /* Red and green least-significant bits (2^9, 2^10) */
#define EDID_CHROMA_BW_LOW 26 /* Blue and white least-significant 2 bits */
#define EDID_CHROMA_REDX 27 /* Red x value most significant 8 bits (2^1,...,2^8) */
#define EDID_CHROMA_REDY 28 /* Red y value most significant 8 bits */
#define EDID_CHROMA_GREENX 29 /* Green x value most significant 8 bits */
#define EDID_CHROMA_GREENY 30 /* Green y value most significant 8 bits */
#define EDID_CHROMA_BLUEX 31 /* Blue x value most significant 8 bits */
#define EDID_CHROMA_BLUEY 32 /* Blue y value most significant 8 bits */
#define EDID_CHROMA_WHITEX 33 /* Default white point x value most significant 8 bits */
#define EDID_CHROMA_WHITEY 34 /* Default white point y value most significant 8 bits */
#define EDID_CHROMA_RG_LOW_OFFSET 25 /* Red and green least-significant bits (2^9, 2^10) */
#define EDID_CHROMA_BW_LOW_OFFSET 26 /* Blue and white least-significant 2 bits */
#define EDID_CHROMA_REDX_OFFSET 27 /* Red x value most significant 8 bits (2^1,...,2^8) */
#define EDID_CHROMA_REDY_OFFSET 28 /* Red y value most significant 8 bits */
#define EDID_CHROMA_GREENX_OFFSET 29 /* Green x value most significant 8 bits */
#define EDID_CHROMA_GREENY_OFFSET 30 /* Green y value most significant 8 bits */
#define EDID_CHROMA_BLUEX_OFFSET 31 /* Blue x value most significant 8 bits */
#define EDID_CHROMA_BLUEY_OFFSET 32 /* Blue y value most significant 8 bits */
#define EDID_CHROMA_WHITEX_OFFSET 33 /* Default white point x value most significant 8 bits */
#define EDID_CHROMA_WHITEY_OFFSET 34 /* Default white point y value most significant 8 bits */
/* Bytes 35-37: Established timing bitmap */
#define EDID_TIMING_1 35
#define EDID_TIMING_2 36
#define EDID_TIMING_3 37
#define EDID_TIMING_OFFSET_1 35
#define EDID_TIMING_OFFSET_2 36
#define EDID_TIMING_OFFSET_3 37
/* Bytes 38-53: Standard Timing Information */
#define EDID_STDTIMING_1 38 /* Each is size two bytes. */
#define EDID_STDTIMING_2 40
#define EDID_STDTIMING_3 42
#define EDID_STDTIMING_4 44
#define EDID_STDTIMING_5 45
#define EDID_STDTIMING_6 48
#define EDID_STDTIMING_7 50
#define EDID_STDTIMING_8 52
#define EDID_STDTIMING_OFFSET 38 /* Each is size two bytes. */
#define EDID_STDTIMING_OFFSET_1 38
#define EDID_STDTIMING_OFFSET_2 40
#define EDID_STDTIMING_OFFSET_3 42
#define EDID_STDTIMING_OFFSET_4 44
#define EDID_STDTIMING_OFFSET_5 45
#define EDID_STDTIMING_OFFSET_6 48
#define EDID_STDTIMING_OFFSET_7 50
#define EDID_STDTIMING_OFFSET_8 52
#define EDID_STDTIMING_NUMBER 8
#define EDID_STDTIMING_SIZE 2
#define EDID_STDTIMING_NUMBER 8
#define EDID_STDTIMING_SIZE 2
/* Bytes 54-125: Descriptor Blocks */
#define EDID_DESCRIPTOR_1 54 /* Each is size 18 bytes */
#define EDID_DESCRIPTOR_2 72
#define EDID_DESCRIPTOR_3 90
#define EDID_DESCRIPTOR_4 108
#define EDID_DESCRIPTOR_OFFSET 54 /* Each is size 18 bytes */
#define EDID_DESCRIPTOR_OFFSET_1 54
#define EDID_DESCRIPTOR_OFFSET_2 72
#define EDID_DESCRIPTOR_OFFSET_3 90
#define EDID_DESCRIPTOR_OFFSET_4 108
#define EDID_DESCRIPTOR_NUMBER 4
#define EDID_DESCRIPTOR_SIZE 18
#define EDID_DESCRIPTOR_NUMBER 4
#define EDID_DESCRIPTOR_SIZE 18
/* Bits 126-127: Trailer */
#define EDID_TRAILER_NEXTENSIONS 126 /* Number of extensions to follow */
#define EDID_TRAILER_CHECKSUM 127 /* Checksum. Sum of all 128 bytes should equal 0 */
#define EDID_TRAILER_NEXTENSIONS_OFFSET 126 /* Number of extensions to follow */
#define EDID_TRAILER_CHECKSUM_OFFSET 127 /* Checksum. Sum of all 128 bytes should equal 0 */
/* EDID Bitfield Definitions ****************************************************************/
#define EDID_MAGIC {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0}
/* Vendor Section: Manufacturer ID */
#define EDID_VENDOR_MANUFACTURER_1(n) (((n) >> 10) & 0x3f) + 'A')
#define EDID_VENDOR_MANUFACTURER_2(n) (((n) >> 5) & 0x3f) + 'A')
#define EDID_VENDOR_MANUFACTURER_3(n) ( (n) >> 0 & 0x3f) + 'A')
#define EDID_VENDOR_MANUFACTURER_1(n) ((((n) >> 10) & 0x1f) + '@')
#define EDID_VENDOR_MANUFACTURER_2(n) ((((n) >> 5) & 0x1f) + '@')
#define EDID_VENDOR_MANUFACTURER_3(n) ((((n) >> 0) & 0x1f) + '@')
/* Display Section: Display Input */
@ -213,6 +219,45 @@
#define EDID_CHROMA_RG_LOW_RED_X_SHIFT (6) /* Bits 6-7: Red x value least-significant 2 bits */
#define EDID_CHROMA_RG_LOW_RED_X_MASK (3 << EDID_CHROMA_RG_LOW_RED_X_SHIFT)
#define EDID_CHROMA_BW_LOW_WHITE_Y_SHIFT (0) /* Bits 0-1: White y value least-significant 2 bits */
#define EDID_CHROMA_BW_LOW_WHITE_Y_MASK (3 << EDID_CHROMA_BW_LOW_WHITE_Y_SHIFT)
#define EDID_CHROMA_BW_LOW_WHITE_X_SHIFT (2) /* Bits 2-3: White x value least-significant 2 bits */
#define EDID_CHROMA_BW_LOW_WHITE_X_MASK (3 << EDID_CHROMA_BW_LOW_WHITE_X_SHIFT)
#define EDID_CHROMA_BW_LOW_BLUE_Y_SHIFT (4) /* Bits 4-5: Blue y value least-significant 2 bits */
#define EDID_CHROMA_BW_LOW_BLUE_Y_MASK (3 << EDID_CHROMA_BW_LOW_BLUE_Y_SHIFT)
#define EDID_CHROMA_BW_LOW_BLUE_X_SHIFT (6) /* Bits 6-7: Blue x value least-significant 2 bits */
#define EDID_CHROMA_BW_LOW_BLUE_X_MASK (3 << EDID_CHROMA_RG_LOW_RED_X_SHIFT)
#define _CHLO(b,s) (((b) >> (s)) & 0x3)
#define _CHHI(b) ((b) << 2)
#define _CHHILO(p,l,s,h) (_CHLO((p)[l], s) | _CHHI((p)[h]))
#define _CHROMA(p,l,s,h) ((_CHHILO(p,l,s,h) * 1000) / 1024)
#define EDID_CHROMA_RED_X(p) \
(_CHROMA(p, EDID_CHROMA_RG_LOW_OFFSET, EDID_CHROMA_RG_LOW_RED_X_SHIFT, \
EDID_CHROMA_REDX_OFFSET))
#define EDID_CHROMA_RED_Y(p) \
(_CHROMA(p, EDID_CHROMA_RG_LOW_OFFSET, EDID_CHROMA_RG_LOW_RED_Y_SHIFT, \
EDID_CHROMA_REDY_OFFSET))
#define EDID_CHROMA_GREEN_X(p) \
(_CHROMA(p, EDID_CHROMA_RG_LOW_OFFSET, EDID_CHROMA_RG_LOW_GREEN_X_SHIFT, \
EDID_CHROMA_GREENX_OFFSET))
#define EDID_CHROMA_GREEN_Y(p) \
(_CHROMA(p, EDID_CHROMA_RG_LOW_OFFSET, EDID_CHROMA_RG_LOW_GREEN_Y_SHIFT, \
EDID_CHROMA_GREENY_OFFSET))
#define EDID_CHROMA_BLUE_X(p) \
(_CHROMA(p, EDID_CHROMA_BW_LOW_OFFSET, EDID_CHROMA_BW_LOW_BLUE_X_SHIFT, \
EDID_CHROMA_BLUEX_OFFSET))
#define EDID_CHROMA_BLUE_Y(p) \
(_CHROMA(p, EDID_CHROMA_BW_LOW_OFFSET, EDID_CHROMA_BW_LOW_BLUE_Y_SHIFT, \
EDID_CHROMA_BLUEY_OFFSET))
#define EDID_CHROMA_WHITE_X(p) \
(_CHROMA(p, EDID_CHROMA_BW_LOW_OFFSET, EDID_CHROMA_BW_LOW_WHITE_X_SHIFT, \
EDID_CHROMA_WHITEX_OFFSET))
#define EDID_CHROMA_WHITE_Y(p) \
(_CHROMA(p, EDID_CHROMA_BW_LOW_OFFSET, EDID_CHROMA_BW_LOW_WHITE_Y_SHIFT, \
EDID_CHROMA_WHITEY_OFFSET))
/* Bytes 35-37: Established timing bitmap */
#define EDID_TIMING_1_800x600_60Hz (1 << 0)
@ -245,12 +290,17 @@
#define ASPECT_RATIO_16_9 3 /* Aspect ratio: 16:9 */
#define EDID_STDTIMING_XRES_OFFSET (0) /* Byte 0: X resolution, divided by 8, less 31 */
#define EDID_STDTIMING_INFO_OFFSET (1) /* Byte 1: Image Aspect Ratio / Vertical Frequency */
# define EDID_STDTIMING_ASPECT_SHIFT (6) /* Bits 6-7: Image aspect ratio */
# define EDID_STDTIMING_ASPECT_MASK (3 << EDID_STDTIMING_ASPECT_SHIFT)
# define EDID_STDTIMING_ASPECT_16_10 (ASPECT_RATIO_16_10 << EDID_STDTIMING_ASPECT_SHIFT)
# define EDID_STDTIMING_ASPECT_4_3 (ASPECT_RATIO_4_3 << EDID_STDTIMING_ASPECT_SHIFT)
# define EDID_STDTIMING_ASPECT_5_4 (ASPECT_RATIO_5_4 << EDID_STDTIMING_ASPECT_SHIFT)
# define EDID_STDTIMING_ASPECT_16_9 (ASPECT_RATIO_16_9 << EDID_STDTIMING_ASPECT_SHIFT)
# define EDID_STDTIMING_VFREQ_SHIFT (0) /* Bits 0-5: Vertical frequency, less 60 */
# define EDID_STDTIMING_VFREQ_MASK (0x3f << EDID_STDTIMING_VFREQ_SHIFT)
#define EDID_STDTIMING_INFO_OFFSET (1) /* Byte 1: Image Aspect Ratio / Vertical Frequency */
/* Display Descriptor: EDID Detailed Timing Descriptor */
#define EDID_STEROMODE_FIELDSEQ_RIGHT 1 /* Field sequential, sync=1 during right (bit0=0) */
@ -261,29 +311,29 @@
#define EDID_STEROMODE_LEFT 2 /* Left image on even lines (bit0=1) */
#define EDID_STEROMODE_SIDEBYSIDE 3 /* Side-by-side (bit0=1) */
#define EDID_DESC_PIXCLOCK 0 /* Bytes 0-1: Pixel clock in 10 kHz units */
#define EDID_DESC_HPIXELS_LSBITS 2 /* Byte 2: Horizontal active pixels 8 LS bits */
#define EDID_DESC_HBLANK_LSBITS 3 /* Byte 3: Horizontal blanking pixels 8 LS bits */
#define EDID_DESC_HMSBITS 4 /* Byte 4: Horizontal MS bits */
#define EDID_DESC_PIXCLOCK_OFFSET 0 /* Bytes 0-1: Pixel clock in 10 kHz units */
#define EDID_DESC_HPIXELS_LSBITS_OFFSET 2 /* Byte 2: Horizontal active pixels 8 LS bits */
#define EDID_DESC_HBLANK_LSBITS_OFFSET 3 /* Byte 3: Horizontal blanking pixels 8 LS bits */
#define EDID_DESC_HMSBITS_OFFSET 4 /* Byte 4: Horizontal MS bits */
# define EDID_DESC_HBLANK_MSBITS_SHIFT (0) /* Bits 0-3: Horizontal blanking pixels 4 MS bits */
# define EDID_DESC_HBLANK_MSBITS_MASK (15 << EDID_DESC_HPIXELS_MSBITS_SHIFT)
# define EDID_DESC_HBLANK_MSBITS_MASK (15 << EDID_DESC_HBLANK_MSBITS_SHIFT)
# define EDID_DESC_HPIXELS_MSBITS_SHIFT (4) /* Bits 4-7: Horizontal active pixels 4 MS bits */
# define EDID_DESC_HPIXELS_MSBITS_MASK (15 << EDID_DESC_HPIXELS_MSBITS_SHIFT)
#define EDID_DESC_VLINES_LSBITS 5 /* Byte 5: Vertical active lines 8 LS bits */
#define EDID_DESC_VBLANK_LSBITS 6 /* Byte 6: Vertical blanking lines 8 LS bits */
#define EDID_DESC_VMSBITS 7 /* Byte 7: Vertical MS bits */
#define EDID_DESC_VLINES_LSBITS_OFFSET 5 /* Byte 5: Vertical active lines 8 LS bits */
#define EDID_DESC_VBLANK_LSBITS_OFFSET 6 /* Byte 6: Vertical blanking lines 8 LS bits */
#define EDID_DESC_VMSBITS_OFFSET 7 /* Byte 7: Vertical MS bits */
# define EDID_DESC_VBLANK_MSBITS_SHIFT (0) /* Bits 0-3: Vertical blanking lines 4 MS bits */
# define EDID_DESC_VBLANK_MSBITS_MASK (15 << EDID_DESC_VBLANK_MSBITS_SHIFT)
# define EDID_DESC_VLINES_MSBITS_SHIFT (4) /* Bits 4-7: Vertical active lines 4 MS bits */
# define EDID_DESC_VLINES_MSBITS_MASK (15 << EDID_DESC_VLINES_MSBITS_SHIFT)
#define EDID_DESC_HPORCH_LSBITS 8 /* Byte 8: Horizontal front porch pixels 8 LS bits */
#define EDID_DESC_HPW_LSBITS 9 /* Byte 9: Horizontal sync pulse width pixels 8 LS bits */
#define EDID_DESC_VPORCH_LSBITS 10 /* Byte 10: Vertical front porch and pulsewidth LS bits */
#define EDID_DESC_HPORCH_LSBITS_OFFSET 8 /* Byte 8: Horizontal front porch pixels 8 LS bits */
#define EDID_DESC_HPW_LSBITS_OFFSET 9 /* Byte 9: Horizontal sync pulse width pixels 8 LS bits */
#define EDID_DESC_VPORCH_LSBITS_OFFSET 10 /* Byte 10: Vertical front porch and pulsewidth LS bits */
# define EDID_DESC_VPW_LSBITS_SHIFT (0) /* Bits 0-3: Vertical sync pulsewidth 4 LS bits */
# define EDID_DESC_VPW_LSBITS_MASK (15 << EDID_DESC_VPW_LSBITS_SHIFT)
# define EDID_DESC_VPORCH_LSBITS_SHIFT (4) /* Bits 4-7: Vertical front portch 4 LS bits */
# define EDID_DESC_VPORCH_LSBITS_MASK (15 << EDID_DESC_VPORCH_LSBITS_SHIFT)
#define EDID_DESC_PORCH_MSBITS 11 /* Byte 7: Vertical MS bits */
#define EDID_DESC_PORCH_MSBITS_OFFSET 11 /* Byte 11: Vertical MS bits */
# define EDID_DESC_VPW_MSBITS_SHIFT (0) /* Bits 0-1: Vertical sync pulsewidth lines 2 MS bits */
# define EDID_DESC_VPW_MSBITS_MASK (3 << EDID_DESC_VPW_MSBITS_SHIFT)
# define EDID_DESC_VPORCH_MSBITS_SHIFT (2) /* Bits 2-3: Vertical front porch lines 2 MS bits */
@ -292,16 +342,16 @@
# define EDID_DESC_HPW_MSBITS_MASK (3 << EDID_DESC_HPW_MSBITS_SHIFT)
# define EDID_DESC_HPORCH_MSBITS_SHIFT (6) /* Bits 6-7: Horizontal front porch pixels 2 MS bits */
# define EDID_DESC_HPORCH_MSBITS_MASK (3 << EDID_DESC_HPORCH_MSBITS_SHIFT)
#define EDID_DESC_HSIZE_LSBITS 12 /* Byte 12: Horizontal image size, mm, 8 LS bits */
#define EDID_DESC_VSIZE_LSBITS 13 /* Byte 13: Vertical image size, mm, 8 LS bits */
#define EDID_DESC_SIZE_MSBITS 14 /* Byte 14: Image size MS bits */
#define EDID_DESC_HSIZE_LSBITS_OFFSET 12 /* Byte 12: Horizontal image size, mm, 8 LS bits */
#define EDID_DESC_VSIZE_LSBITS_OFFSET 13 /* Byte 13: Vertical image size, mm, 8 LS bits */
#define EDID_DESC_SIZE_MSBITS_OFFSET 14 /* Byte 14: Image size MS bits */
# define EDID_DESC_VSIZE_MSBITS_SHIFT (0) /* Bits 0-3: Vertical image size, mm, 4 MS bits */
# define EDID_DESC_VSIZE_MSBITS_MASK (15 << EDID_DESC_VSIZE_MSBITS_SHIFT)
# define EDID_DESC_HSIZE_MSBITS_SHIFT (4) /* Bits 4-7: Horizontal image size, mm, 4 MS bits */
# define EDID_DESC_HSIZE_MSBITS_MASK (15 << EDID_DESC_HSIZE_MSBITS_SHIFT)
#define EDID_DESC_HBORDER 15 /* Byte 15: Horizontal border pixels (one side) */
#define EDID_DESC_VBORDER 16 /* Byte 16: Vertical border lines (one side) */
#define EDID_DESC_FEATURES 17 /* Byte 17: Features bitmap */
#define EDID_DESC_HBORDER_OFFSET 15 /* Byte 15: Horizontal border pixels (one side) */
#define EDID_DESC_VBORDER_OFFSET 16 /* Byte 16: Vertical border lines (one side) */
#define EDID_DESC_FEATURES_OFFSET 17 /* Byte 17: Features bitmap */
/* If bits 5-6=00: */
# define EDID_DESC_STEREO_INTERLEAVE (1 << 0) /* Bit 0: 2-way line-interleaved or side-by-side
* interleaved stereo */
@ -320,8 +370,50 @@
# define EDID_DESC_STEREO_MASK (3 << EDID_DESC_STEREO_SHIFT)
# define EDID_DESC_INTERLACED (1 << 7) /* Bit 7: Interlaced */
/* Descriptor helpers */
#define _VACT_LO(p) ((p)[EDID_DESC_VLINES_LSBITS_OFFSET])
#define _VBLK_LO(p) ((p)[EDID_DESC_VBLANK_LSBITS_OFFSET])
#define _VACT_HI(p) (((p)[EDID_DESC_VMSBITS_OFFSET] & EDID_DESC_VLINES_MSBITS_MASK) << 4)
#define _VBLK_HI(p) (((p)[EDID_DESC_VMSBITS_OFFSET] & EDID_DESC_VBLANK_MSBITS_MASK) << 8)
#define EDID_DESC_VACTIVE(p) (_VACT_LO(p) | _VACT_HI(p))
#define EDID_DESC_VBLANK(p) (_VBLK_LO(p) | _VBLK_HI(p))
#define _HACT_LO(p) ((p)[EDID_DESC_HPIXELS_LSBITS_OFFSET])
#define _HBLK_LO(p) ((p)[EDID_DESC_HBLANK_LSBITS_OFFSET])
#define _HACT_HI(p) (((p)[EDID_DESC_HMSBITS_OFFSET] & EDID_DESC_HPIXELS_MSBITS_SHIFT) << 4)
#define _HBLK_HI(p) (((p)[EDID_DESC_HMSBITS_OFFSET] & EDID_DESC_HBLANK_MSBITS_SHIFT) << 8)
#define EDID_DESC_HACTIVE(p) (_HACT_LO(p) | _HACT_HI(p))
#define EDID_DESC_HBLANK(p) (_HBLK_LO(p) | _HBLK_HI(p))
#define _HOFF_LO(p) ((p)[EDID_DESC_HPORCH_LSBITS_OFFSET])
#define _HWID_LO(p) ((p)[EDID_DESC_HPW_LSBITS_OFFSET])
#define _VOFF_LO(p) ((p)[EDID_DESC_VPORCH_LSBITS_OFFSET] >> EDID_DESC_VPORCH_LSBITS_SHIFT)
#define _VWID_LO(p) ((p)[EDID_DESC_VPORCH_LSBITS_OFFSET] & EDID_DESC_VPW_LSBITS_MASK)
#define _HOFF_HI(p) (((p)[EDID_DESC_PORCH_MSBITS_OFFSET] & EDID_DESC_HPORCH_MSBITS_MASK) << 2)
#define _HWID_HI(p) (((p)[EDID_DESC_PORCH_MSBITS_OFFSET] & EDID_DESC_HPW_MSBITS_MASK) << 4)
#define _VOFF_HI(p) (((p)[EDID_DESC_PORCH_MSBITS_OFFSET] & EDID_DESC_VPORCH_MSBITS_MASK) << 2)
#define _VWID_HI(p) (((p)[EDID_DESC_PORCH_MSBITS_OFFSET] & EDID_DESC_VPW_MSBITS_MASK) << 4)
#define EDID_DESC_HSYNC_OFFSET(p) (_HOFF_LO(p) | _HOFF_HI(p))
#define EDID_DESC_HSYNC_WIDTH(p) (_HWID_LO(p) | _HWID_HI(p))
#define EDID_DESC_VSYNC_OFFSET(p) (_VOFF_LO(p) | _VOFF_HI(p))
#define EDID_DESC_VSYNC_WIDTH(p) (_VWID_LO(p) | _VWID_HI(p))
#define _HSZ_LO(p) ((p)[EDID_DESC_HSIZE_LSBITS_OFFSET])
#define _VSZ_LO(p) ((p)[EDID_DESC_VSIZE_LSBITS_OFFSET])
#define _HSZ_HI(p) (((p)[EDID_DESC_SIZE_MSBITS_OFFSET] & EDID_DESC_HSIZE_MSBITS_MASK) << 4)
#define _VSZ_HI(p) (((p)[EDID_DESC_SIZE_MSBITS_OFFSET] & EDID_DESC_VSIZE_MSBITS_MASK) << 8)
#define EDID_DESC_HSIZE(p) (_HSZ_LO(p) | _HSZ_HI(p))
#define EDID_DESC_VSIZE(p) (_VSZ_LO(p) | _VSZ_HI(p))
/* Display Descriptor: EDID Other Monitor Descriptors */
#define EDID_DESC_ZERO_1 0 /* Bytes 0-1: Zero=not a detailed timing descriptor */
#define EDID_DESC_ZERO_2 2 /* Byte 2: Zero */
#define EDID_DESC_DESCTYPE 3 /* Byte 3: Descriptor type */
#define EDID_DESC_ZERO_3 4 /* Byte 4: Zero */
#define EDID_DESC_INFO 5 /* Bytes 5-17: Determined by descriptor type */
/* 0x00-0x0f: Manufacturer reserved descriptors */
#define EDID_DESCTYPE_DUMMY 0x10 /* Dummy identifier */
#define EDID_DESCTYPE_STDTIMING 0xf7 /* Additional standard timing 3 */
@ -334,11 +426,35 @@
#define EDID_DESCTYPE_TEXT 0xfe /* Unspecified text (ASCII text) */
#define EDID_DESCTYPE_SERIALNO 0xff /* Display serial number (ASCII text) */
#define EDID_DESC_ZERO_1 0 /* Bytes 0-1: Zero=not a detailed timing descriptor */
#define EDID_DESC_ZERO_2 2 /* Byte 2: Zero */
#define EDID_DESC_DESCTYPE 3 /* Byte 3: Descriptor type */
#define EDID_DESC_ZERO_3 4 /* Byte 4: Zero */
#define EDID_DESC_INFO 5 /* Bytes 5-17: Determined by descriptor type */
/* Used for descriptors 0xff, 0xfe, and 0xfc */
#define EDID_DESC_ASCII_DATA_OFFSET 5
#define EDID_DESC_ASCII_DATA_LEN 13
#define EDID_DESC_RANGE_MIN_VFREQ(p) ((p)[5]) /* Hz */
#define EDID_DESC_RANGE_MAX_VFREQ(p) ((p)[6]) /* Hz */
#define EDID_DESC_RANGE_MIN_HFREQ(p) ((p)[7]) /* kHz */
#define EDID_DESC_RANGE_MAX_HFREQ(p) ((p)[8]) /* kHz */
#define EDID_DESC_RANGE_MAX_CLOCK(p) (((p)[9]) * 10) /* MHz */
#define EDID_DESC_RANGE_HAVE_GTF2(p) (((p)[10]) == 0x02)
#define EDID_DESC_RANGE_GTF2_HFREQ(p) (((p)[12]) * 2)
#define EDID_DESC_RANGE_GTF2_C(p) (((p)[13]) / 2)
#define EDID_DESC_RANGE_GTF2_M(p) ((p)[14] + ((p)[15] << 8))
#define EDID_DESC_RANGE_GTF2_K(p) ((p)[16])
#define EDID_DESC_RANGE_GTF2_J(p) ((p)[17] / 2)
#define EDID_DESC_COLOR_WHITEX(p)
#define EDID_DESC_COLOR_WHITE_INDEX_1(p) ((p)[5])
#define EDID_DESC_COLOR_WHITEX_1(p) _CHROMA(p, 6, 2, 7)
#define EDID_DESC_COLOR_WHITEY_1(p) _CHROMA(p, 6, 0, 8)
#define EDID_DESC_COLOR_GAMMA_1(p) _GAMMA(p[9])
#define EDID_DESC_COLOR_WHITE_INDEX_2(p) ((p)[10])
#define EDID_DESC_COLOR_WHITEX_2(p) _CHROMA(p, 11, 2, 12)
#define EDID_DESC_COLOR_WHITEY_2(p) _CHROMA(p, 11, 0, 13)
#define EDID_DESC_COLOR_GAMMA_2(p) _GAMMA(p[14])
#define EDID_DESC_STD_TIMING_START_OFFSET 5
#define EDID_DESC_STD_TIMING_COUNT_OFFSET 6
/* Extended EDID data offsets ****************************************************************/
/* To be provided */
@ -388,16 +504,16 @@
struct edid_videomode_s
{
int dotclock; /* Dot clock frequency in kHz. */
int hdisplay;
int hsync_start;
int hsync_end;
int htotal;
int vdisplay;
int vsync_start;
int vsync_end;
int vtotal;
int flags; /* Video mode flags; see above. */
uint32_t dotclock; /* Dot clock frequency in kHz. */
uint16_t flags; /* Video mode flags; see above. */
uint16_t hdisplay;
uint16_t hsync_start;
uint16_t hsync_end;
uint16_t htotal;
uint16_t vdisplay;
uint16_t vsync_start;
uint16_t vsync_end;
uint16_t vtotal;
FAR const char *name;
int hskew;
};
@ -433,22 +549,19 @@ struct edid_range_s
struct edid_info_s
{
uint8_t edid_vendor[4];
char edid_vendorname[16];
char edid_productname[16];
char edid_comment[16];
char edid_serial[16];
uint16_t edid_product;
uint8_t edid_manufacturer[4];
uint8_t edid_version;
uint8_t edid_revision;
int edid_year;
int edid_week;
uint8_t edid_video_input;
uint8_t edid_max_hsize; /* in cm */
uint8_t edid_max_vsize; /* in cm */
uint8_t edid_gamma;
uint8_t edid_features;
uint8_t edid_ext_block_count;
uint16_t edid_product;
uint32_t edid_serial;
int edid_year;
int edid_week;
int edid_have_range;
struct edid_range_s edid_range;
@ -475,8 +588,11 @@ struct edid_info_s
* Input Parameters:
* data - A reference to the raw EDID data
* edid - The location to return the digested EDID data.
*
*
*
* Returned Value:
* Zero (OK) is returned on success; otherwise a negated errno value is returned to
* indicate the nature of the failure.
*
********************************************************************************************/
int edid_parse(FAR const uint8_t *data, FAR struct edid_info_s *edid);
@ -494,9 +610,22 @@ int edid_parse(FAR const uint8_t *data, FAR struct edid_info_s *edid);
* preferred - A pointer to the pointer to the preferred mode in the list
* nmodes - The number of modes in the list
*
* Returned Value:
* None
*
********************************************************************************************/
int edid_sort_modes(FAR struct edid_videomode_s *modes,
FAR struct edid_videomode_s **preferred, unsigned int nmodes);
void edid_sort_modes(FAR struct edid_videomode_s *modes,
FAR struct edid_videomode_s **preferred, unsigned int nmodes);
/********************************************************************************************
* Name: edid_mode_lookup
*
* Description:
* Find the video mode in a look-up table
*
********************************************************************************************/
FAR const struct edid_videomode_s *edid_mode_lookup(FAR const char *name);
#endif /* __INCLUDE_NUTTX_LCD_EDID_H */

View File

@ -142,6 +142,12 @@ else
OTHERDIRS += audio
endif
ifeq ($(CONFIG_VIDEO),y)
NONFSDIRS += video
else
OTHERDIRS += video
endif
ifeq ($(CONFIG_WIRELESS),y)
NONFSDIRS += wireless
else

View File

@ -118,6 +118,12 @@ ifeq ($(CONFIG_AUDIO),y)
NUTTXLIBS += staging$(DELIM)libaudio$(LIBEXT)
endif
# Add libraries for the Video sub-system
ifeq ($(CONFIG_VIDEO),y)
NUTTXLIBS += staging$(DELIM)libvideo$(LIBEXT)
endif
# Add libraries for the Wireless sub-system
ifeq ($(CONFIG_WIRELESS),y)

View File

@ -112,6 +112,12 @@ ifeq ($(CONFIG_AUDIO),y)
NUTTXLIBS += staging$(DELIM)libaudio$(LIBEXT)
endif
# Add libraries for the Video sub-system
ifeq ($(CONFIG_VIDEO),y)
NUTTXLIBS += staging$(DELIM)libvideo$(LIBEXT)
endif
# Add libraries for the Wireless sub-system
ifeq ($(CONFIG_WIRELESS),y)

View File

@ -124,6 +124,12 @@ audio$(DELIM)libaudio$(LIBEXT): context
staging$(DELIM)libaudio$(LIBEXT): audio$(DELIM)libaudio$(LIBEXT)
$(Q) $(call INSTALL_LIB,$<,$@)
video$(DELIM)libvideo$(LIBEXT): context
$(Q) $(MAKE) -C video TOPDIR="$(TOPDIR)" libvideo$(LIBEXT) KERNEL=y EXTRADEFINES=$(KDEFINE)
staging$(DELIM)libvideo$(LIBEXT): video$(DELIM)libvideo$(LIBEXT)
$(Q) $(call INSTALL_LIB,$<,$@)
wireless$(DELIM)libwireless$(LIBEXT): context
$(Q) $(MAKE) -C wireless TOPDIR="$(TOPDIR)" libwireless$(LIBEXT) KERNEL=y EXTRADEFINES=$(KDEFINE)

View File

@ -119,6 +119,12 @@ ifeq ($(CONFIG_AUDIO),y)
NUTTXLIBS += staging$(DELIM)libaudio$(LIBEXT)
endif
# Add libraries for the Video sub-system
ifeq ($(CONFIG_VIDEO),y)
NUTTXLIBS += staging$(DELIM)libvideo$(LIBEXT)
endif
# Add libraries for the Wireless sub-system
ifeq ($(CONFIG_WIRELESS),y)

18
video/Kconfig Normal file
View File

@ -0,0 +1,18 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
comment "Video subsystem"
config VIDEO
bool "Video Support"
default n
---help---
Enables overall support for Video library.
if VIDEO
source video/edid/Kconfig
endif # VIDEO

80
video/Makefile Normal file
View File

@ -0,0 +1,80 @@
############################################################################
# video/Makefile
#
# Copyright (C) 2019 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
-include $(TOPDIR)/Make.defs
ASRCS =
CSRCS =
DEPPATH = --dep-path .
VPATH = .
include edid/Make.defs
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
BIN = libvideo$(LIBEXT)
all: $(BIN)
.PHONY: depend clean distclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
$(COBJS): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
$(BIN): $(OBJS)
$(call ARCHIVE, $@, $(OBJS))
.depend: Makefile $(SRCS)
$(Q) $(MKDEP) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@
depend: .depend
clean:
$(call DELFILE, $(BIN))
$(call CLEAN)
distclean: clean
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
-include Make.dep

12
video/edid/Kconfig Normal file
View File

@ -0,0 +1,12 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config VIDEO_EDID
bool "EDID Support"
default n
---help---
Enable support for managing EDID data EDID (Extended Display
Identification Data).

48
video/edid/Make.defs Normal file
View File

@ -0,0 +1,48 @@
############################################################################
# video/edid/Make.defs
#
# Copyright (C) 2019 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name Nuttx nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
ifeq ($(CONFIG_VIDEO_EDID),y)
# Files required for EDID support
ASRCS +=
CSRCS += edid_parse.c edid_videomode.c # edid_sort.c
# Include EDID build support
DEPPATH += --dep-path edid
VPATH += :edid
endif

610
video/edid/edid_parse.c Normal file
View File

@ -0,0 +1,610 @@
/****************************************************************************
* video/edid/edid_parse.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derives from logic in FreeBSD which has an equivalent 3-clause BSD
* license:
*
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <nuttx/lcd/edid.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DIVIDE(x,y) (((x) + ((y) / 2)) / (y))
/****************************************************************************
* Private Data
****************************************************************************/
/* These are reversed established timing order */
static FAR const char *g_edid_modes[] =
{
"1280x1024x75",
"1024x768x75",
"1024x768x70",
"1024x768x60",
"1024x768x87i",
"832x624x74", /* Rounding error, 74.55 Hz aka "832x624x75" */
"800x600x75",
"800x600x72",
"800x600x60",
"800x600x56",
"640x480x75",
"640x480x72",
"640x480x67",
"640x480x60",
"720x400x87", /* Rounding error, 87.85 Hz aka "720x400x88" */
"720x400x70",
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: edid_valid
*
* Description:
* Return true if the EDID is valid
*
****************************************************************************/
static bool edid_valid(FAR const uint8_t *data)
{
static const uint8_t magic[8] = EDID_MAGIC;
int sum = 0;
int i;
/* Verify the EDID magic number */
if (memcmp(data, magic, 8) != 0)
{
return false;
}
/* Verify the EDID checksum */
for (i = 0; i < 128; i++)
{
sum += data[i];
}
if ((sum & 0xff) != 0)
{
return false;
}
return true;
}
/****************************************************************************
* Name: edid_std_timing
*
* Description:
* Parse STD timing entry
*
****************************************************************************/
static bool edid_std_timing(FAR const uint8_t *stdtim,
FAR struct edid_videomode_s *mode)
{
FAR const struct edid_videomode_s *lookup;
char name[80];
unsigned x;
unsigned y;
unsigned f;
if ((stdtim[0] == 1 && stdtim[1] == 1) ||
(stdtim[0] == 0 && stdtim[1] == 0) ||
(stdtim[0] == 0x20 && stdtim[1] == 0x20))
{
return false;
}
x = stdtim[EDID_STDTIMING_XRES_OFFSET];
switch (x & EDID_STDTIMING_ASPECT_MASK)
{
case EDID_STDTIMING_ASPECT_16_10:
y = x * 10 / 16;
break;
case EDID_STDTIMING_ASPECT_4_3:
y = x * 3 / 4;
break;
case EDID_STDTIMING_ASPECT_5_4:
y = x * 4 / 5;
break;
case EDID_STDTIMING_ASPECT_16_9:
default:
y = x * 9 / 16;
break;
}
f = stdtim[EDID_STDTIMING_INFO_OFFSET];
/* First try to lookup the mode as a DMT timing */
snprintf(name, sizeof(name), "%dx%dx%d", x, y, f);
if ((lookup = edid_mode_lookup(name)) != NULL)
{
*mode = *lookup;
}
else
{
#if 0 /* Not implemented */
/* Failing that, calculate it using gtf
*
* Hmm. I'm not using alternate GTF timings, which
* could, in theory, be present.
*/
vesagtf_mode(x, y, f, mode);
#endif
# warning REVISIT: Missing logic
return false;
}
return true;
}
/****************************************************************************
* Name: edid_search_mode
*
* Description:
* Check if for duplicate video modes.
*
****************************************************************************/
static struct edid_videomode_s *
edid_search_mode(FAR struct edid_info_s *edid,
FAR const struct edid_videomode_s *mode)
{
int refresh;
int i;
refresh = DIVIDE(DIVIDE(mode->dotclock * 1000, mode->htotal),
mode->vtotal);
for (i = 0; i < edid->edid_nmodes; i++)
{
if (mode->hdisplay == edid->edid_modes[i].hdisplay &&
mode->vdisplay == edid->edid_modes[i].vdisplay &&
refresh == DIVIDE(DIVIDE(edid->edid_modes[i].dotclock * 1000,
edid->edid_modes[i].htotal),
edid->edid_modes[i].vtotal))
{
return &edid->edid_modes[i];
}
}
return NULL;
}
/****************************************************************************
* Name: edid_desc_timing
*
* Description:
*
****************************************************************************/
static bool edid_desc_timing(FAR const uint8_t *desc,
FAR struct edid_videomode_s *mode)
{
uint16_t hactive;
unsigned int hblank;
unsigned int hsyncwid;
unsigned int hsyncoff;
unsigned int vactive;
unsigned int vblank;
unsigned int vsyncwid;
unsigned int vsyncoff;
uint8_t flags;
flags = desc[EDID_DESC_FEATURES_OFFSET];
/* We don't support stereo modes (for now) */
if (flags & (EDID_DESC_STEREO_MASK | EDID_DESC_STEREO_INTERLEAVE))
{
return false;
}
mode->dotclock = (uint16_t)desc[EDID_DESC_PIXCLOCK_OFFSET] |
((uint16_t)desc[EDID_DESC_PIXCLOCK_OFFSET + 1] << 8);
hactive = EDID_DESC_HACTIVE(desc);
hblank = EDID_DESC_HBLANK(desc);
hsyncwid = EDID_DESC_HSYNC_WIDTH(desc);
hsyncoff = EDID_DESC_HSYNC_OFFSET(desc);
vactive = EDID_DESC_VACTIVE(desc);
vblank = EDID_DESC_VBLANK(desc);
vsyncwid = EDID_DESC_VSYNC_WIDTH(desc);
vsyncoff = EDID_DESC_VSYNC_OFFSET(desc);
/* Borders are contained within the blank areas. */
mode->hdisplay = hactive;
mode->htotal = hactive + hblank;
mode->hsync_start = hactive + hsyncoff;
mode->hsync_end = mode->hsync_start + hsyncwid;
mode->vdisplay = vactive;
mode->vtotal = vactive + vblank;
mode->vsync_start = vactive + vsyncoff;
mode->vsync_end = mode->vsync_start + vsyncwid;
mode->flags = 0;
if ((flags & EDID_DESC_INTERLACED) != 0)
{
mode->flags |= VID_INTERLACE;
}
if ((flags & EDID_DESC_DIGITAL_HPOLARITY) != 0)
{
mode->flags |= VID_PHSYNC;
}
else
{
mode->flags |= VID_NHSYNC;
}
if ((flags & EDID_DESC_DIGITAL_VSERRATION) != 0)
{
mode->flags |= VID_PVSYNC;
}
else
{
mode->flags |= VID_NVSYNC;
}
return true;
}
/****************************************************************************
* Name: edid_block
*
* Description:
* Parse an EDID descriptor block.
*
****************************************************************************/
static void edid_block(FAR struct edid_info_s *edid, FAR const uint8_t *desc)
{
struct edid_videomode_s mode;
FAR struct edid_videomode_s *exist_mode;
uint16_t pixclk;
int i;
/* A detailed timing descriptor with have a nonzero pixel clock */
pixclk = ((uint16_t)desc[EDID_DESC_PIXCLOCK_OFFSET] << 8) |
(uint16_t)desc[EDID_DESC_PIXCLOCK_OFFSET + 1];
if (pixclk > 0)
{
if (!edid_desc_timing(desc, &mode))
{
return;
}
/* Does this mode already exist? */
exist_mode = edid_search_mode(edid, &mode);
if (exist_mode != NULL)
{
*exist_mode = mode;
if (edid->edid_preferred_mode == NULL)
{
edid->edid_preferred_mode = exist_mode;
}
}
else
{
edid->edid_modes[edid->edid_nmodes] = mode;
if (edid->edid_preferred_mode == NULL)
{
edid->edid_preferred_mode = &edid->edid_modes[edid->edid_nmodes];}
edid->edid_nmodes++;
}
return;
}
/* Not a detailed timing descriptor */
switch (desc[EDID_DESC_DESCTYPE])
{
case EDID_DESCTYPE_SERIALNO:
#if 0 /* Not implemented */
memcpy(edid->edid_serstr, desc + EDID_DESC_ASCII_DATA_OFFSET,
EDID_DESC_ASCII_DATA_LEN);
edid->edid_serstr[sizeof(edid->edid_serial) - 1] = 0;
#endif
break;
case EDID_DESCTYPE_TEXT:
#if 0 /* Not implemented */
memcpy(edid->edid_comment, desc + EDID_DESC_ASCII_DATA_OFFSET,
EDID_DESC_ASCII_DATA_LEN);
edid->edid_comment[sizeof(edid->edid_comment) - 1] = 0;
#endif
break;
case EDID_DESCTYPE_LIMITS:
edid->edid_have_range = 1;
edid->edid_range.er_min_vfreq = EDID_DESC_RANGE_MIN_VFREQ(desc);
edid->edid_range.er_max_vfreq = EDID_DESC_RANGE_MAX_VFREQ(desc);
edid->edid_range.er_min_hfreq = EDID_DESC_RANGE_MIN_HFREQ(desc);
edid->edid_range.er_max_hfreq = EDID_DESC_RANGE_MAX_HFREQ(desc);
edid->edid_range.er_max_clock = EDID_DESC_RANGE_MAX_CLOCK(desc);
if (!EDID_DESC_RANGE_HAVE_GTF2(desc))
{
break;
}
edid->edid_range.er_have_gtf2 = 1;
edid->edid_range.er_gtf2_hfreq = EDID_DESC_RANGE_GTF2_HFREQ(desc);
edid->edid_range.er_gtf2_c = EDID_DESC_RANGE_GTF2_C(desc);
edid->edid_range.er_gtf2_m = EDID_DESC_RANGE_GTF2_M(desc);
edid->edid_range.er_gtf2_j = EDID_DESC_RANGE_GTF2_J(desc);
edid->edid_range.er_gtf2_k = EDID_DESC_RANGE_GTF2_K(desc);
break;
case EDID_DESCTYPE_NAME:
#if 0 /* Not implemented */
/* Copy the product name into place */
memcpy(edid->edid_productname,
desc + EDID_DESC_ASCII_DATA_OFFSET, EDID_DESC_ASCII_DATA_LEN);
#endif
break;
case EDID_DESCTYPE_STDTIMING_ID:
desc += EDID_DESC_STD_TIMING_START_OFFSET;
for (i = 0; i < EDID_DESC_STD_TIMING_COUNT_OFFSET; i++)
{
if (edid_std_timing(desc, &mode))
{
/* Does this mode already exist? */
exist_mode = edid_search_mode(edid, &mode);
if (exist_mode == NULL)
{
edid->edid_modes[edid->edid_nmodes] = mode;
edid->edid_nmodes++;
}
}
desc += 2;
}
break;
case EDID_DESCTYPE_WHITEPOINT:
/* XXX: not implemented yet */
break;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: edid_parse
*
* Description:
* Given a block of raw EDID data, parse the data and convert it to the
* 'digested' form of struct edid_info_s.
*
* Input Parameters:
* data - A reference to the raw EDID data
* edid - The location to return the digested EDID data.
*
* Returned Value:
* Zero (OK) is returned on success; otherwise a negated errno value is returned to
* indicate the nature of the failure.
*
****************************************************************************/
int edid_parse(FAR const uint8_t *data, FAR struct edid_info_s *edid)
{
FAR const struct edid_videomode_s *mode;
uint16_t manufacturer;
uint16_t estmodes;
uint8_t gamma;
int i;
int max_dotclock = 0;
int mhz;
if (!edid_valid(&data[EDID_HEADER_MAGIC_OFFSET]))
{
return -EINVAL;
}
/* Get product identification */
manufacturer = (uint16_t)data[EDID_VENDOR_MANUFACTURER_OFFSET] |
((uint16_t)data[EDID_VENDOR_MANUFACTURER_OFFSET + 1] << 8);
edid->edid_manufacturer[0] = EDID_VENDOR_MANUFACTURER_1(manufacturer);
edid->edid_manufacturer[1] = EDID_VENDOR_MANUFACTURER_2(manufacturer);
edid->edid_manufacturer[2] = EDID_VENDOR_MANUFACTURER_3(manufacturer);
edid->edid_manufacturer[3] = 0; /* NUL terminate for convenience */
edid->edid_product = (uint16_t)data[EDID_VENDOR_PRODUCTCODE_OFFSET] |
((uint16_t)data[EDID_VENDOR_PRODUCTCODE_OFFSET + 1] << 8);
edid->edid_serial = ((uint32_t)data[EDID_VENDOR_SERIALNO_OFFSET] << 24) |
((uint32_t)data[EDID_VENDOR_SERIALNO_OFFSET + 1] << 16) |
((uint32_t)data[EDID_VENDOR_SERIALNO_OFFSET + 2] << 8) |
(uint32_t)data[EDID_VENDOR_SERIALNO_OFFSET + 3];
edid->edid_week = data[EDID_VENDOR_WEEK_OFFSET];
edid->edid_year = data[EDID_VENDOR_YEAR_OFFSET] + 1990;
/* Get EDID revision */
edid->edid_version = data[EDID_VERSION_MAJOR_OFFSET];
edid->edid_revision = data[EDID_VERSION_MINOR_OFFSET];
edid->edid_video_input = data[EDID_DISPLAY_INPUT_OFFSET];
edid->edid_max_hsize = data[EDID_DISPLAY_HSIZE_OFFSET];
edid->edid_max_vsize = data[EDID_DISPLAY_VSIZE_OFFSET];
gamma = data[EDID_DISPLAY_GAMMA_OFFSET];
edid->edid_gamma = gamma == 0xff ? 100 : gamma + 100;
edid->edid_features = data[EDID_DISPLAY_FEATURES_OFFSET];
edid->edid_chroma.ec_redx = EDID_CHROMA_RED_X(data);
edid->edid_chroma.ec_redy = EDID_CHROMA_RED_X(data);
edid->edid_chroma.ec_greenx = EDID_CHROMA_GREEN_X(data);
edid->edid_chroma.ec_greeny = EDID_CHROMA_GREEN_Y(data);
edid->edid_chroma.ec_bluex = EDID_CHROMA_BLUE_X(data);
edid->edid_chroma.ec_bluey = EDID_CHROMA_BLUE_Y(data);
edid->edid_chroma.ec_whitex = EDID_CHROMA_WHITE_X(data);
edid->edid_chroma.ec_whitey = EDID_CHROMA_WHITE_Y(data);
edid->edid_ext_block_count = data[EDID_TRAILER_NEXTENSIONS_OFFSET];
/* Lookup established modes */
edid->edid_nmodes = 0;
edid->edid_preferred_mode = NULL;
estmodes = ((uint16_t)data[EDID_TIMING_OFFSET_1] << 8) |
(uint16_t)data[EDID_TIMING_OFFSET_2];
/* Iterate in established timing order */
for (i = 15; i >= 0; i--)
{
if (estmodes & (1 << i))
{
mode = edid_mode_lookup(g_edid_modes[i]);
if (mode != NULL)
{
edid->edid_modes[edid->edid_nmodes] = *mode;
edid->edid_nmodes++;
}
else
{
lcdwarn("WARNING: No data for est. mode %s\n",
g_edid_modes[i]);
}
}
}
/* Do standard timing section */
for (i = 0; i < EDID_STDTIMING_NUMBER; i++)
{
struct edid_videomode_s stdmode;
FAR struct edid_videomode_s *exist_mode;
if (edid_std_timing(data + EDID_STDTIMING_OFFSET + i * 2, &stdmode))
{
/* Does this mode already exist? */
exist_mode = edid_search_mode(edid, &stdmode);
if (exist_mode == NULL)
{
edid->edid_modes[edid->edid_nmodes] = stdmode;
edid->edid_nmodes++;
}
}
}
/* Do detailed timings and descriptors */
for (i = 0; i < EDID_DESCRIPTOR_NUMBER; i++)
{
edid_block(edid, data + EDID_DESCRIPTOR_OFFSET + i * EDID_DESCRIPTOR_SIZE);
}
/* Some monitors lie about their maximum supported dot clock
* by claiming to support modes which need a higher dot clock
* than the stated maximum.
*
* For sanity's sake we bump it to the highest dot clock we find
* in the list of supported modes
*/
for (i = 0; i < edid->edid_nmodes; i++)
{
if (edid->edid_modes[i].dotclock > max_dotclock)
{
max_dotclock = edid->edid_modes[i].dotclock;
}
}
lcdinfo("max_dotclock according to supported modes: %d\n",
max_dotclock);
mhz = (max_dotclock + 999) / 1000;
if (edid->edid_have_range)
{
if (mhz > edid->edid_range.er_max_clock)
{
edid->edid_range.er_max_clock = mhz;
}
}
else
{
edid->edid_range.er_max_clock = mhz;
}
return OK;
}

201
video/edid/edid_videomode.c Normal file
View File

@ -0,0 +1,201 @@
/****************************************************************************
* video/edid/edid_parse.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derives from logic in FreeBSD which has an equivalent 3-clause BSD
* license:
*
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <string.h>
#include <nuttx/lcd/edid.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* These macros help the mode lines below fit on one line. */
#define HP VID_PHSYNC
#define HN VID_NHSYNC
#define VP VID_PVSYNC
#define VN VID_NVSYNC
#define I VID_INTERLACE
#define DS VID_DBLSCAN
#define M(nm,hr,vr,clk,hs,he,ht,vs,ve,vt,f) \
{ \
clk, hr, hs, he, ht, vr, vs, ve, vt, f, nm, 0 \
}
/****************************************************************************
* Private Data
****************************************************************************/
static const struct edid_videomode_s g_videomodes[] =
{
M("640x350x85", 640, 350, 31500, 672, 736, 832, 382, 385, 445, HP|VN),
M("640x400x85", 640, 400, 31500, 672, 736, 832, 401, 404, 445, HN|VP),
M("720x400x70", 720, 400, 28320, 738, 846, 900, 412, 414, 449, HN|VP),
M("720x400x85", 720, 400, 35500, 756, 828, 936, 401, 404, 446, HN|VP),
M("720x400x87", 720, 400, 35500, 738, 846, 900, 421, 423, 449, HN|VN),
M("640x480x60", 640, 480, 25175, 656, 752, 800, 490, 492, 525, HN|VN),
M("640x480x72", 640, 480, 31500, 664, 704, 832, 489, 492, 520, HN|VN),
M("640x480x75", 640, 480, 31500, 656, 720, 840, 481, 484, 500, HN|VN),
M("640x480x85", 640, 480, 36000, 696, 752, 832, 481, 484, 509, HN|VN),
M("800x600x56", 800, 600, 36000, 824, 896, 1024, 601, 603, 625, HP|VP),
M("800x600x60", 800, 600, 40000, 840, 968, 1056, 601, 605, 628, HP|VP),
M("800x600x72", 800, 600, 50000, 856, 976, 1040, 637, 643, 666, HP|VP),
M("800x600x75", 800, 600, 49500, 816, 896, 1056, 601, 604, 625, HP|VP),
M("800x600x85", 800, 600, 56250, 832, 896, 1048, 601, 604, 631, HP|VP),
M("1024x768x87i", 1024, 768, 44900, 1032, 1208, 1264, 768, 776, 817, HP|VP|I),
M("1024x768x60", 1024, 768, 65000, 1048, 1184, 1344, 771, 777, 806, HN|VN),
M("1024x768x70", 1024, 768, 75000, 1048, 1184, 1328, 771, 777, 806, HN|VN),
M("1024x768x75", 1024, 768, 78750, 1040, 1136, 1312, 769, 772, 800, HP|VP),
M("1024x768x85", 1024, 768, 94500, 1072, 1168, 1376, 769, 772, 808, HP|VP),
M("1024x768x89", 1024, 768, 100000, 1108, 1280, 1408, 768, 780, 796, HP|VP),
M("1152x864x75", 1152, 864, 108000, 1216, 1344, 1600, 865, 868, 900, HP|VP),
M("1280x768x75", 1280, 768, 105640, 1312, 1712, 1744, 782, 792, 807, HN|VP),
M("1280x960x60", 1280, 960, 108000, 1376, 1488, 1800, 961, 964, 1000, HP|VP),
M("1280x960x85", 1280, 960, 148500, 1344, 1504, 1728, 961, 964, 1011, HP|VP),
M("1280x1024x60", 1280, 1024, 108000, 1328, 1440, 1688, 1025, 1028, 1066, HP|VP),
M("1280x1024x70", 1280, 1024, 126000, 1328, 1440, 1688, 1025, 1028, 1066, HP|VP),
M("1280x1024x75", 1280, 1024, 135000, 1296, 1440, 1688, 1025, 1028, 1066, HP|VP),
M("1280x1024x85", 1280, 1024, 157500, 1344, 1504, 1728, 1025, 1028, 1072, HP|VP),
M("1600x1200x60", 1600, 1200, 162000, 1664, 1856, 2160, 1201, 1204, 1250, HP|VP),
M("1600x1200x65", 1600, 1200, 175500, 1664, 1856, 2160, 1201, 1204, 1250, HP|VP),
M("1600x1200x70", 1600, 1200, 189000, 1664, 1856, 2160, 1201, 1204, 1250, HP|VP),
M("1600x1200x75", 1600, 1200, 202500, 1664, 1856, 2160, 1201, 1204, 1250, HP|VP),
M("1600x1200x85", 1600, 1200, 229500, 1664, 1856, 2160, 1201, 1204, 1250, HP|VP),
M("1680x1050x60", 1680, 1050, 147140, 1784, 1968, 2256, 1051, 1054, 1087, HP|VP),
M("1792x1344x60", 1792, 1344, 204800, 1920, 2120, 2448, 1345, 1348, 1394, HN|VP),
M("1792x1344x75", 1792, 1344, 261000, 1888, 2104, 2456, 1345, 1348, 1417, HN|VP),
M("1856x1392x60", 1856, 1392, 218300, 1952, 2176, 2528, 1393, 1396, 1439, HN|VP),
M("1856x1392x75", 1856, 1392, 288000, 1984, 2208, 2560, 1393, 1396, 1500, HN|VP),
M("1920x1440x60", 1920, 1440, 234000, 2048, 2256, 2600, 1441, 1444, 1500, HN|VP),
M("1920x1440x75", 1920, 1440, 297000, 2064, 2288, 2640, 1441, 1444, 1500, HN|VP),
M("832x624x74", 832, 624, 57284, 864, 928, 1152, 625, 628, 667, HN|VN),
M("1152x768x54", 1152, 768, 64995, 1178, 1314, 1472, 771, 777, 806, HP|VP),
M("1400x1050x60", 1400, 1050, 122000, 1488, 1640, 1880, 1052, 1064, 1082, HP|VP),
M("1400x1050x74", 1400, 1050, 155800, 1464, 1784, 1912, 1052, 1064, 1090, HP|VP),
M("1152x900x66", 1152, 900, 94500, 1192, 1320, 1528, 902, 906, 937, HN|VN),
M("1152x900x76", 1152, 900, 105560, 1168, 1280, 1472, 902, 906, 943, HN|VN),
/* Derived Double Scan Modes */
M("320x175x85", 320, 175, 15750, 336, 368, 416, 191, 192, 222, HP|VN|DS),
M("320x200x85", 320, 200, 15750, 336, 368, 416, 200, 202, 222, HN|VP|DS),
M("360x200x70", 360, 200, 14160, 369, 423, 450, 206, 207, 224, HN|VP|DS),
M("360x200x85", 360, 200, 17750, 378, 414, 468, 200, 202, 223, HN|VP|DS),
M("360x200x87", 360, 200, 17750, 369, 423, 450, 210, 211, 224, HN|VN|DS),
M("320x240x60", 320, 240, 12587, 328, 376, 400, 245, 246, 262, HN|VN|DS),
M("320x240x72", 320, 240, 15750, 332, 352, 416, 244, 246, 260, HN|VN|DS),
M("320x240x75", 320, 240, 15750, 328, 360, 420, 240, 242, 250, HN|VN|DS),
M("320x240x85", 320, 240, 18000, 348, 376, 416, 240, 242, 254, HN|VN|DS),
M("400x300x56", 400, 300, 18000, 412, 448, 512, 300, 301, 312, HP|VP|DS),
M("400x300x60", 400, 300, 20000, 420, 484, 528, 300, 302, 314, HP|VP|DS),
M("400x300x72", 400, 300, 25000, 428, 488, 520, 318, 321, 333, HP|VP|DS),
M("400x300x75", 400, 300, 24750, 408, 448, 528, 300, 302, 312, HP|VP|DS),
M("400x300x85", 400, 300, 28125, 416, 448, 524, 300, 302, 315, HP|VP|DS),
M("512x384x87i", 512, 384, 22450, 516, 604, 632, 384, 388, 408, HP|VP|DS|I),
M("512x384x60", 512, 384, 32500, 524, 592, 672, 385, 388, 403, HN|VN|DS),
M("512x384x70", 512, 384, 37500, 524, 592, 664, 385, 388, 403, HN|VN|DS),
M("512x384x75", 512, 384, 39375, 520, 568, 656, 384, 386, 400, HP|VP|DS),
M("512x384x85", 512, 384, 47250, 536, 584, 688, 384, 386, 404, HP|VP|DS),
M("512x384x89", 512, 384, 50000, 554, 640, 704, 384, 390, 398, HP|VP|DS),
M("576x432x75", 576, 432, 54000, 608, 672, 800, 432, 434, 450, HP|VP|DS),
M("640x384x75", 640, 384, 52820, 656, 856, 872, 391, 396, 403, HN|VP|DS),
M("640x480x60", 640, 480, 54000, 688, 744, 900, 480, 482, 500, HP|VP|DS),
M("640x480x85", 640, 480, 74250, 672, 752, 864, 480, 482, 505, HP|VP|DS),
M("640x512x60", 640, 512, 54000, 664, 720, 844, 512, 514, 533, HP|VP|DS),
M("640x512x70", 640, 512, 63000, 664, 720, 844, 512, 514, 533, HP|VP|DS),
M("640x512x75", 640, 512, 67500, 648, 720, 844, 512, 514, 533, HP|VP|DS),
M("640x512x85", 640, 512, 78750, 672, 752, 864, 512, 514, 536, HP|VP|DS),
M("800x600x60", 800, 600, 81000, 832, 928, 1080, 600, 602, 625, HP|VP|DS),
M("800x600x65", 800, 600, 87750, 832, 928, 1080, 600, 602, 625, HP|VP|DS),
M("800x600x70", 800, 600, 94500, 832, 928, 1080, 600, 602, 625, HP|VP|DS),
M("800x600x75", 800, 600, 101250, 832, 928, 1080, 600, 602, 625, HP|VP|DS),
M("800x600x85", 800, 600, 114750, 832, 928, 1080, 600, 602, 625, HP|VP|DS),
M("840x525x60", 840, 525, 73570, 892, 984, 1128, 525, 527, 543, HP|VP|DS),
M("896x672x60", 896, 672, 102400, 960, 1060, 1224, 672, 674, 697, HN|VP|DS),
M("896x672x75", 896, 672, 130500, 944, 1052, 1228, 672, 674, 708, HN|VP|DS),
M("928x696x60", 928, 696, 109150, 976, 1088, 1264, 696, 698, 719, HN|VP|DS),
M("928x696x75", 928, 696, 144000, 992, 1104, 1280, 696, 698, 750, HN|VP|DS),
M("960x720x60", 960, 720, 117000, 1024, 1128, 1300, 720, 722, 750, HN|VP|DS),
M("960x720x75", 960, 720, 148500, 1032, 1144, 1320, 720, 722, 750, HN|VP|DS),
M("416x312x74", 416, 312, 28642, 432, 464, 576, 312, 314, 333, HN|VN|DS),
M("576x384x54", 576, 384, 32497, 589, 657, 736, 385, 388, 403, HP|VP|DS),
M("700x525x60", 700, 525, 61000, 744, 820, 940, 526, 532, 541, HP|VP|DS),
M("700x525x74", 700, 525, 77900, 732, 892, 956, 526, 532, 545, HP|VP|DS),
M("576x450x66", 576, 450, 47250, 596, 660, 764, 451, 453, 468, HN|VN|DS),
M("576x450x76", 576, 450, 52780, 584, 640, 736, 451, 453, 471, HN|VN|DS),
};
static const int g_nvideomodes = 46;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: edid_mode_lookup
*
* Description:
* Find the video mode in a look-up table
*
****************************************************************************/
FAR const struct edid_videomode_s *edid_mode_lookup(FAR const char *name)
{
int i;
for (i = 0; i < g_nvideomodes; i++)
{
if (strcmp(name, g_videomodes[i].name) == 0)
{
return &g_videomodes[i];
}
}
return NULL;
}