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:
parent
8edff9d295
commit
dbf286472b
4
Kconfig
4
Kconfig
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
18
video/Kconfig
Normal 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
80
video/Makefile
Normal 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
12
video/edid/Kconfig
Normal 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
48
video/edid/Make.defs
Normal 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
610
video/edid/edid_parse.c
Normal 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
201
video/edid/edid_videomode.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user