[Armadeus-commitlog] armadeus branch, master, updated. release-3.4-176-g63748f8
Brought to you by:
sszy
|
From: Julien B a. A. <ar...@us...> - 2011-06-14 17:42:06
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "armadeus".
The branch, master has been updated
via 63748f87b60a24b4453bcba8c859c5485fc2643a (commit)
via 0230f7073cdb774daf98d8ef622472547d3435f4 (commit)
via 1e22c3a852d1e5f6f200a04b56547ba0f8143ee2 (commit)
via 5bf26360316e4f06b16d7bede6ddc8b308bf6366 (commit)
from 345fafc242dc64c28098aa9a967473fb25a1aa61 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 63748f87b60a24b4453bcba8c859c5485fc2643a
Merge: 0230f7073cdb774daf98d8ef622472547d3435f4 345fafc242dc64c28098aa9a967473fb25a1aa61
Author: Julien Boibessot <jul...@ar...>
Date: Tue Jun 14 19:40:40 2011 +0200
Merge branch 'master' of ssh://artemys@armadeus.git.sourceforge.net/gitroot/armadeus/armadeus
commit 0230f7073cdb774daf98d8ef622472547d3435f4
Author: Julien Boibessot <jul...@ar...>
Date: Tue Jun 14 19:39:10 2011 +0200
[TOOLS] Cleanup tfp410ctrl and add it the possibility to read EDID infos from monitor
commit 1e22c3a852d1e5f6f200a04b56547ba0f8143ee2
Merge: 5bf26360316e4f06b16d7bede6ddc8b308bf6366 7aa47bbb81ee77c992a8b55b33299fcbb9543689
Author: Julien Boibessot <jul...@ar...>
Date: Fri Jun 10 16:04:38 2011 +0200
Merge branch 'master' of ssh://artemys@armadeus.git.sourceforge.net/gitroot/armadeus/armadeus
commit 5bf26360316e4f06b16d7bede6ddc8b308bf6366
Author: Julien Boibessot <jul...@ar...>
Date: Wed Jun 8 10:49:05 2011 +0200
Indentation
-----------------------------------------------------------------------
Summary of changes:
target/packages/tfp410ctrl/Makefile | 63 +---
target/packages/tfp410ctrl/README | 4 +
target/packages/tfp410ctrl/drm_edid.h | 212 +++++++++++
target/packages/tfp410ctrl/parse-edid.c | 622 +++++++++++++++++++++++++++++++
target/packages/tfp410ctrl/parse-edid.h | 6 +
target/packages/tfp410ctrl/tfp410ctrl.c | 234 +++++++-----
target/packages/tfp410ctrl/tfp410ctrl.h | 17 +-
7 files changed, 1009 insertions(+), 149 deletions(-)
create mode 100644 target/packages/tfp410ctrl/README
create mode 100644 target/packages/tfp410ctrl/drm_edid.h
create mode 100644 target/packages/tfp410ctrl/parse-edid.c
create mode 100644 target/packages/tfp410ctrl/parse-edid.h
diff --git a/target/packages/tfp410ctrl/Makefile b/target/packages/tfp410ctrl/Makefile
index 51569b1..b811fd5 100644
--- a/target/packages/tfp410ctrl/Makefile
+++ b/target/packages/tfp410ctrl/Makefile
@@ -1,59 +1,34 @@
#
-# Makefile for the Armadeus HDMI/DVI controler TFP410
+# Makefile for the APF51 HDMI/DVI controler (TFP410) utility
#
-CFLAGS = -Wall -O
-
+CC = arm-linux-gcc
+CFLAGS = -Wall -O
INCLUDES =
-PWD := $(shell pwd)
-
-#HEADERS =
-
-SOURCES = tfp410ctrl.c
-OBJECTS = tfp410ctrl.o
-
-TARGET = tfp410ctrl
-
-
-####### Implicit rules
-
-.SUFFIXES: .cpp .cxx .cc .C .c
-
-.cpp.o:
- $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $<
+PWD := $(shell pwd)
-.cxx.o:
- $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $<
+SOURCES = $(wildcard *.c)
+OBJS = $(SOURCES:.c=.o)
-.cc.o:
- $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $<
+EXE = tfp410ctrl
-.C.o:
- $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $<
-
-.c.o:
- $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $<
-
-
-####### Build rules
-
-
-$(TARGET): $(OBJECTS) Makefile $(HEADERS)
+$(EXE): $(OBJS)
@echo
- @echo "Building tfp410ctrl control programm..."
- $(CC) $(OBJECTS) $(CFLAGS) $(INCLUDES) -o $(TARGET)
-
+ @echo "Building $(EXE) control program..."
+ $(CC) $(OBJS) $(LDFLAGS) -o $(EXE)
-all: $(TARGET)
+all: $(EXE)
clean:
- -rm -f $(TARGET)
- -rm -f *.o *~ core
+ rm -f $(EXE)
+ rm -f *.o *~ core
+ rm -f parse_edid
-tfp410ctrl.o: tfp410ctrl.c tfp410ctrl.h Makefile
+tfp410ctrl.o: tfp410ctrl.c tfp410ctrl.h
@echo
- $(CC) -c $(CFLAGS) $(INCLUDES) tfp410ctrl.c
-
-
+ $(CC) -c $(CFLAGS) $(INCLUDES) $<
+parse_edid: parse-edid.o
+ @echo "Building standalone parse_edid program..."
+ $(CC) $< $(LDFLAGS) -o $@
diff --git a/target/packages/tfp410ctrl/README b/target/packages/tfp410ctrl/README
new file mode 100644
index 0000000..3d9604b
--- /dev/null
+++ b/target/packages/tfp410ctrl/README
@@ -0,0 +1,4 @@
+* Compile parse_edid as standalone (PC):
+ $ make clean; make parse_edid CC=gcc CFLAGS=-DSTANDALONE
+* Cross-compile (ARM): be sure that arm-linux-gcc is in your PATH
+ $ make
diff --git a/target/packages/tfp410ctrl/drm_edid.h b/target/packages/tfp410ctrl/drm_edid.h
new file mode 100644
index 0000000..cb9150d
--- /dev/null
+++ b/target/packages/tfp410ctrl/drm_edid.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright © 2007-2008 Intel Corporation
+ * Jesse Barnes <jes...@in...>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __DRM_EDID_H__
+#define __DRM_EDID_H__
+
+#include <linux/types.h>
+#define u8 unsigned char
+#define u32 unsigned int
+
+#define EDID_LENGTH 128
+#define DDC_ADDR 0x50
+
+#define CEA_EXT 0x02
+#define VTB_EXT 0x10
+#define DI_EXT 0x40
+#define LS_EXT 0x50
+#define MI_EXT 0x60
+
+struct est_timings {
+ u8 t1;
+ u8 t2;
+ u8 mfg_rsvd;
+} __attribute__((packed));
+
+/* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
+#define EDID_TIMING_ASPECT_SHIFT 6
+#define EDID_TIMING_ASPECT_MASK (0x3 << EDID_TIMING_ASPECT_SHIFT)
+
+/* need to add 60 */
+#define EDID_TIMING_VFREQ_SHIFT 0
+#define EDID_TIMING_VFREQ_MASK (0x3f << EDID_TIMING_VFREQ_SHIFT)
+
+struct std_timing {
+ u8 hsize; /* need to multiply by 8 then add 248 */
+ u8 vfreq_aspect;
+} __attribute__((packed));
+
+#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
+#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
+#define DRM_EDID_PT_SEPARATE_SYNC (3 << 3)
+#define DRM_EDID_PT_STEREO (1 << 5)
+#define DRM_EDID_PT_INTERLACED (1 << 7)
+
+/* If detailed data is pixel timing */
+struct detailed_pixel_timing {
+ u8 hactive_lo;
+ u8 hblank_lo;
+ u8 hactive_hblank_hi;
+ u8 vactive_lo;
+ u8 vblank_lo;
+ u8 vactive_vblank_hi;
+ u8 hsync_offset_lo;
+ u8 hsync_pulse_width_lo;
+ u8 vsync_offset_pulse_width_lo;
+ u8 hsync_vsync_offset_pulse_width_hi;
+ u8 width_mm_lo;
+ u8 height_mm_lo;
+ u8 width_height_mm_hi;
+ u8 hborder;
+ u8 vborder;
+ u8 misc;
+} __attribute__((packed));
+
+/* If it's not pixel timing, it'll be one of the below */
+struct detailed_data_string {
+ u8 str[13];
+} __attribute__((packed));
+
+struct detailed_data_monitor_range {
+ u8 min_vfreq;
+ u8 max_vfreq;
+ u8 min_hfreq_khz;
+ u8 max_hfreq_khz;
+ u8 pixel_clock_mhz; /* need to multiply by 10 */
+ __le16 sec_gtf_toggle; /* A000=use above, 20=use below */
+ u8 hfreq_start_khz; /* need to multiply by 2 */
+ u8 c; /* need to divide by 2 */
+ __le16 m;
+ u8 k;
+ u8 j; /* need to divide by 2 */
+} __attribute__((packed));
+
+struct detailed_data_wpindex {
+ u8 white_yx_lo; /* Lower 2 bits each */
+ u8 white_x_hi;
+ u8 white_y_hi;
+ u8 gamma; /* need to divide by 100 then add 1 */
+} __attribute__((packed));
+
+struct detailed_data_color_point {
+ u8 windex1;
+ u8 wpindex1[3];
+ u8 windex2;
+ u8 wpindex2[3];
+} __attribute__((packed));
+
+struct cvt_timing {
+ u8 code[3];
+} __attribute__((packed));
+
+struct detailed_non_pixel {
+ u8 pad1;
+ u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
+ fb=color point data, fa=standard timing data,
+ f9=undefined, f8=mfg. reserved */
+ u8 pad2;
+ union {
+ struct detailed_data_string str;
+ struct detailed_data_monitor_range range;
+ struct detailed_data_wpindex color;
+ struct std_timing timings[6];
+ struct cvt_timing cvt[4];
+ } data;
+} __attribute__((packed));
+
+#define EDID_DETAIL_EST_TIMINGS 0xf7
+#define EDID_DETAIL_CVT_3BYTE 0xf8
+#define EDID_DETAIL_COLOR_MGMT_DATA 0xf9
+#define EDID_DETAIL_STD_MODES 0xfa
+#define EDID_DETAIL_MONITOR_CPDATA 0xfb
+#define EDID_DETAIL_MONITOR_NAME 0xfc
+#define EDID_DETAIL_MONITOR_RANGE 0xfd
+#define EDID_DETAIL_MONITOR_STRING 0xfe
+#define EDID_DETAIL_MONITOR_SERIAL 0xff
+
+struct detailed_timing {
+ __le16 pixel_clock; /* need to multiply by 10 KHz */
+ union {
+ struct detailed_pixel_timing pixel_data;
+ struct detailed_non_pixel other_data;
+ } data;
+} __attribute__((packed));
+
+#define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0)
+#define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 1)
+#define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 2)
+#define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3)
+#define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 4)
+#define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 5)
+#define DRM_EDID_INPUT_DIGITAL (1 << 7) /* bits below must be zero if set */
+
+#define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0)
+#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1)
+#define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2)
+#define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
+#define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 5)
+#define DRM_EDID_FEATURE_PM_SUSPEND (1 << 6)
+#define DRM_EDID_FEATURE_PM_STANDBY (1 << 7)
+
+struct edid {
+ u8 header[8];
+ /* Vendor & product info */
+ u8 mfg_id[2];
+ u8 prod_code[2];
+ u32 serial; /* FIXME: byte order */
+ u8 mfg_week;
+ u8 mfg_year;
+ /* EDID version */
+ u8 version;
+ u8 revision;
+ /* Display info: */
+ u8 input;
+ u8 width_cm;
+ u8 height_cm;
+ u8 gamma;
+ u8 features;
+ /* Color characteristics */
+ u8 red_green_lo;
+ u8 black_white_lo;
+ u8 red_x;
+ u8 red_y;
+ u8 green_x;
+ u8 green_y;
+ u8 blue_x;
+ u8 blue_y;
+ u8 white_x;
+ u8 white_y;
+ /* Est. timings and mfg rsvd timings*/
+ struct est_timings established_timings;
+ /* Standard timings 1-8*/
+ struct std_timing standard_timings[8];
+ /* Detailing timings 1-4 */
+ struct detailed_timing detailed_timings[4];
+ /* Number of 128 byte ext. blocks */
+ u8 extensions;
+ /* Checksum */
+ u8 checksum;
+} __attribute__((packed));
+
+#define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
+
+#endif /* __DRM_EDID_H__ */
diff --git a/target/packages/tfp410ctrl/parse-edid.c b/target/packages/tfp410ctrl/parse-edid.c
new file mode 100644
index 0000000..fcde1f3
--- /dev/null
+++ b/target/packages/tfp410ctrl/parse-edid.c
@@ -0,0 +1,622 @@
+/* Code taken from parse_edid tool from read-edid-1.4.2 suite which was
+ * written by:
+ * John Fremlin <vi...@us...>
+ * Martin Kavalec <xk...@vs...>
+ *
+ * Source is released under the:
+ * GNU GENERAL PUBLIC LICENSE
+ * Version 2, June 1991
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "parse-edid.h"
+#include "drm_edid.h"
+
+// TODO: rewrite
+// FIXME: cleanup 'static' variables
+
+//typedef unsigned char byte;
+#define byte unsigned char
+#define u8 unsigned char
+typedef unsigned int bool;
+#define true 1
+#define false 0
+
+/* byte must be 8 bits */
+
+/* int must be at least 16 bits */
+
+/* long must be at least 32 bits */
+
+#define DIE_MSG( x ) \
+ { MSG( x ); exit( 1 ); }
+
+#define UPPER_NIBBLE( x ) \
+ (((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE( x ) \
+ ((1|2|4|8) & (x))
+
+#define COMBINE_HI_8LO( hi, lo ) \
+ ( (((unsigned)hi) << 8) | (unsigned)lo )
+
+#define COMBINE_HI_4LO( hi, lo ) \
+ ( (((unsigned)hi) << 4) | (unsigned)lo )
+
+const char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00
+};
+
+const char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
+
+static char* edid_est_modes[] = {
+ "800x600@60Hz",
+ "800x600@56Hz",
+ "640x480@75Hz",
+ "640x480@72Hz",
+ "640x480@67Hz",
+ "640x480@60Hz",
+ "720x400@88Hz",
+ "720x400@70Hz",
+ "1280x1024@75Hz",
+ "1024x768@75Hz",
+ "1024x768@70Hz",
+ "1024x768@60Hz",
+ "1024x768@43Hz",
+ "832x624@75Hz",
+ "800x600@75Hz",
+ "800x600@72Hz",
+ "1152x864@75Hz",
+};
+
+enum {
+ EST_800x600_60 = 0,
+ EST_640x480_60 = 5,
+ EST_1024x768_60 = 11,
+};
+
+//#define EDID_LENGTH 0x80
+
+#define EDID_HEADER 0x00
+#define EDID_HEADER_END 0x07
+
+#define ID_MANUFACTURER_NAME 0x08
+#define ID_MANUFACTURER_NAME_END 0x09
+#define ID_MODEL 0x0a
+
+#define ID_SERIAL_NUMBER 0x0c
+
+#define MANUFACTURE_WEEK 0x10
+#define MANUFACTURE_YEAR 0x11
+
+#define EDID_STRUCT_VERSION 0x12
+#define EDID_STRUCT_REVISION 0x13
+
+#define DPMS_FLAGS 0x18
+#define ESTABLISHED_TIMING_1 0x23
+#define ESTABLISHED_TIMING_2 0x24
+#define MANUFACTURERS_TIMINGS 0x25
+
+#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE 18
+#define NO_DETAILED_TIMING_DESCRIPTIONS 4
+
+#define DETAILED_TIMING_DESCRIPTION_1 0x36
+#define DETAILED_TIMING_DESCRIPTION_2 0x48
+#define DETAILED_TIMING_DESCRIPTION_3 0x5a
+#define DETAILED_TIMING_DESCRIPTION_4 0x6c
+
+#define PIXEL_CLOCK_LO (unsigned)dtd[ 0 ]
+#define PIXEL_CLOCK_HI (unsigned)dtd[ 1 ]
+#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
+
+#define H_ACTIVE_LO (unsigned)dtd[ 2 ]
+
+#define H_BLANKING_LO (unsigned)dtd[ 3 ]
+
+#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)dtd[ 4 ] )
+
+#define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
+
+#define H_BLANKING_HI LOWER_NIBBLE( (unsigned)dtd[ 4 ] )
+
+#define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
+
+#define V_ACTIVE_LO (unsigned)dtd[ 5 ]
+
+#define V_BLANKING_LO (unsigned)dtd[ 6 ]
+
+#define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)dtd[ 7 ] )
+
+#define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
+
+#define V_BLANKING_HI LOWER_NIBBLE( (unsigned)dtd[ 7 ] )
+
+#define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
+
+#define H_SYNC_OFFSET_LO (unsigned)dtd[ 8 ]
+#define H_SYNC_WIDTH_LO (unsigned)dtd[ 9 ]
+
+#define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)dtd[ 10 ] )
+#define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)dtd[ 10 ] )
+
+#define V_SYNC_WIDTH_HI ((unsigned)dtd[ 11 ] & (1|2))
+#define V_SYNC_OFFSET_HI (((unsigned)dtd[ 11 ] & (4|8)) >> 2)
+
+#define H_SYNC_WIDTH_HI (((unsigned)dtd[ 11 ] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI (((unsigned)dtd[ 11 ] & (64|128)) >> 6)
+
+#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
+#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
+
+#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
+#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
+
+#define H_SIZE_LO (unsigned)dtd[ 12 ]
+#define V_SIZE_LO (unsigned)dtd[ 13 ]
+
+#define H_SIZE_HI UPPER_NIBBLE( (unsigned)dtd[ 14 ] )
+#define V_SIZE_HI LOWER_NIBBLE( (unsigned)dtd[ 14 ] )
+
+#define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
+#define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
+
+#define H_BORDER (unsigned)dtd[ 15 ]
+#define V_BORDER (unsigned)dtd[ 16 ]
+
+#define FLAGS (unsigned)dtd[ 17 ]
+
+#define INTERLACED (FLAGS&128)
+#define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */
+#define SYNC_SEPARATE (3<<3)
+#define HSYNC_POSITIVE (FLAGS & 4)
+#define VSYNC_POSITIVE (FLAGS & 2)
+
+#define MONITOR_NAME 0xfc
+#define MONITOR_LIMITS 0xfd
+#define UNKNOWN_DESCRIPTOR -1
+#define DETAILED_TIMING_BLOCK -2
+
+#define DESCRIPTOR_DATA 5
+#define V_MIN_RATE block[ 5 ]
+#define V_MAX_RATE block[ 6 ]
+#define H_MIN_RATE block[ 7 ]
+#define H_MAX_RATE block[ 8 ]
+
+#define MAX_PIXEL_CLOCK (((int)block[ 9 ]) * 10)
+#define GTF_SUPPORT block[10]
+
+#define DPMS_ACTIVE_OFF (1 << 5)
+#define DPMS_SUSPEND (1 << 6)
+#define DPMS_STANDBY (1 << 7)
+
+char *myname;
+
+void MSG(const char *x)
+{
+ fprintf(stderr, "%s: %s\n", myname, x);
+}
+
+int parse_timing_description(byte * dtd);
+
+int parse_monitor_limits(byte * block);
+
+int block_type(byte * block);
+
+char *get_monitor_name(byte const *block);
+
+char *get_vendor_sign(byte const *block);
+
+int parse_dpms_capabilities(byte flags);
+
+bool drm_detect_hdmi_monitor(struct edid * edid);
+bool drm_detect_monitor_audio(struct edid * edid);
+static int check_established_modes(struct edid *edid);
+
+#ifdef STANDALONE
+int main(int argc, char **argv)
+{
+ byte edid[EDID_LENGTH];
+ FILE *edid_file;
+
+ myname = argv[0];
+ fprintf(stderr, "%s: parse-edid (version 1.4)\n", myname);
+
+ if (argc > 2) {
+ DIE_MSG("syntax: [input EDID file]");
+ } else {
+ if (argc == 2) {
+ edid_file = fopen(argv[1], "rb");
+ if (!edid_file)
+ DIE_MSG("unable to open file for input");
+ }
+
+ else
+ edid_file = stdin;
+ }
+
+ if (fread(edid, sizeof(byte), EDID_LENGTH, edid_file)
+ != EDID_LENGTH) {
+ DIE_MSG("IO error reading EDID");
+ }
+
+ fclose(edid_file);
+
+ return parse_edid(edid);
+}
+#endif
+
+int parse_edid(byte * edid)
+{
+ unsigned i;
+ byte *block;
+ char *monitor_name = NULL;
+ char monitor_alt_name[100];
+ byte checksum = 0;
+ char *vendor_sign;
+ int ret = 0;
+
+ for (i = 0; i < EDID_LENGTH; i++)
+ checksum += edid[i];
+
+ if (checksum != 0) {
+ MSG("EDID checksum failed - data is corrupt. Continuing anyway.");
+ ret = 1;
+ } else
+ MSG("EDID checksum passed.");
+
+ if (strncmp
+ ((char *)edid + EDID_HEADER, edid_v1_header, EDID_HEADER_END + 1)) {
+ MSG("first bytes don't match EDID version 1 header");
+ MSG("do not trust output (if any).");
+ ret = 1;
+ }
+
+ printf("\n\t# EDID version %d revision %d\n",
+ (int)edid[EDID_STRUCT_VERSION], (int)edid[EDID_STRUCT_REVISION]);
+
+ vendor_sign = get_vendor_sign(edid + ID_MANUFACTURER_NAME);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+ for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
+ block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+
+ if (block_type(block) == MONITOR_NAME) {
+ monitor_name = get_monitor_name(block);
+ break;
+ }
+ }
+
+ if (!monitor_name) {
+ /* Stupid djgpp hasn't snprintf so we have to hack something together */
+ if (strlen(vendor_sign) + 10 > sizeof(monitor_alt_name))
+ vendor_sign[3] = 0;
+
+ sprintf(monitor_alt_name, "%s:%02x%02x",
+ vendor_sign, edid[ID_MODEL], edid[ID_MODEL + 1]);
+ monitor_name = monitor_alt_name;
+ }
+
+ printf("\tVendor Name \"%s\"\n", vendor_sign);
+ printf("\tModel Name \"%s\"\n", monitor_name);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+ for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
+ block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+
+ if (block_type(block) == MONITOR_LIMITS)
+ parse_monitor_limits(block);
+ }
+
+ parse_dpms_capabilities(edid[DPMS_FLAGS]);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+ for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
+ block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+
+ if (block_type(block) == DETAILED_TIMING_BLOCK)
+ parse_timing_description(block);
+ }
+
+ printf("\n");
+
+ if (drm_detect_hdmi_monitor((struct edid *) edid)) {
+ printf("It's an HDMI monitor\n");
+ } else {
+ printf("It's NOT an HDMI monitor\n");
+ }
+
+ if (!drm_detect_monitor_audio((struct edid *) edid)) {
+ printf("Monitor has NO audio\n");
+ }
+
+ check_established_modes((struct edid *) edid);
+
+ return ret;
+}
+
+int parse_timing_description(byte * dtd)
+{
+ int htotal, vtotal;
+ htotal = H_ACTIVE + H_BLANKING;
+ vtotal = V_ACTIVE + V_BLANKING;
+
+ printf("\tMode \t\"%dx%d\"", H_ACTIVE, V_ACTIVE);
+ printf("\t# vfreq %3.3fHz, hfreq %6.3fkHz\n",
+ (double)PIXEL_CLOCK / ((double)vtotal * (double)htotal),
+ (double)PIXEL_CLOCK / (double)(htotal * 1000));
+
+ printf("\t\tDotClock\t%f\n", (double)PIXEL_CLOCK / 1000000.0);
+
+ printf("\t\tHTimings\t%u %u %u %u\n", H_ACTIVE,
+ H_ACTIVE + H_SYNC_OFFSET,
+ H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, htotal);
+
+ printf("\t\tVTimings\t%u %u %u %u\n", V_ACTIVE,
+ V_ACTIVE + V_SYNC_OFFSET,
+ V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, vtotal);
+
+ if (INTERLACED || (SYNC_TYPE == SYNC_SEPARATE)) {
+ printf("\t\tFlags\t%s\"%sHSync\" \"%sVSync\"\n",
+ INTERLACED ? "\"Interlace\" " : "",
+ HSYNC_POSITIVE ? "+" : "-", VSYNC_POSITIVE ? "+" : "-");
+ }
+
+ printf("\tEndMode\n");
+
+ return 0;
+}
+
+int block_type(byte * block)
+{
+ if (!strncmp(edid_v1_descriptor_flag, (char *)block, 2)) {
+ /* printf("\t# Block type: 2:%x 3:%x\n", block[2], block[3]); */
+
+ /* descriptor */
+
+ if (block[2] != 0)
+ return UNKNOWN_DESCRIPTOR;
+
+ return block[3];
+ } else {
+
+ /* detailed timing block */
+
+ return DETAILED_TIMING_BLOCK;
+ }
+}
+
+char *get_monitor_name(byte const *block)
+{
+ static char name[13];
+ unsigned i;
+ byte const *ptr = block + DESCRIPTOR_DATA;
+
+ for (i = 0; i < 13; i++, ptr++) {
+
+ if (*ptr == 0xa) {
+ name[i] = 0;
+ return name;
+ }
+
+ name[i] = *ptr;
+ }
+
+ return name;
+}
+
+char *get_vendor_sign(byte const *block)
+{
+ static char sign[4];
+ unsigned short h;
+
+ /*
+ 08h WORD big-endian manufacturer ID (see #00136)
+ bits 14-10: first letter (01h='A', 02h='B', etc.)
+ bits 9-5: second letter
+ bits 4-0: third letter
+ */
+ h = COMBINE_HI_8LO(block[0], block[1]);
+ sign[0] = ((h >> 10) & 0x1f) + 'A' - 1;
+ sign[1] = ((h >> 5) & 0x1f) + 'A' - 1;
+ sign[2] = (h & 0x1f) + 'A' - 1;
+ sign[3] = 0;
+ return sign;
+}
+
+int parse_monitor_limits(byte * block)
+{
+ printf("\tHorizSync %u-%u\n", H_MIN_RATE, H_MAX_RATE);
+ printf("\tVertRefresh %u-%u\n", V_MIN_RATE, V_MAX_RATE);
+ if (MAX_PIXEL_CLOCK == 10 * 0xff)
+ printf("\t# Max dot clock not given\n");
+ else
+ printf("\t# Max dot clock (video bandwidth) %u MHz\n",
+ (int)MAX_PIXEL_CLOCK);
+
+ if (GTF_SUPPORT) {
+ printf("\t# EDID version 3 GTF given: contact author\n");
+ }
+
+ return 0;
+}
+
+int parse_dpms_capabilities(byte flags)
+{
+ printf
+ ("\t# DPMS capabilities: Active off:%s Suspend:%s Standby:%s\n\n",
+ (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
+ (flags & DPMS_SUSPEND) ? "yes" : "no",
+ (flags & DPMS_STANDBY) ? "yes" : "no");
+ return 0;
+}
+
+/* Following functions are taken from Linux sources (drivers/gpu/drm/drm_edid.c)
+ * and are:
+ * Copyright (c) 2007-2008 Intel Corporation
+ * Jesse Barnes <jes...@in...>
+ * Copyright 2010 Red Hat, Inc.
+ */
+
+#define DRM_DEBUG_KMS printf
+
+#define EDID_EST_TIMINGS 16
+#define EDID_STD_TIMINGS 8
+#define EDID_DETAILED_TIMINGS 4
+
+#define HDMI_IDENTIFIER 0x000C03
+#define AUDIO_BLOCK 0x01
+#define VENDOR_BLOCK 0x03
+#define EDID_BASIC_AUDIO (1 << 6)
+
+/**
+ * Search EDID for CEA extension block.
+ */
+u8 *drm_find_cea_extension(struct edid * edid)
+{
+ u8 *edid_ext = NULL;
+ int i;
+
+ /* No EDID or EDID extensions */
+ if (edid == NULL || edid->extensions == 0) {
+ printf("NO CEA extension\n");
+ return NULL;
+ }
+
+ /* Find CEA extension */
+ for (i = 0; i < edid->extensions; i++) {
+ edid_ext = (u8 *) edid + EDID_LENGTH * (i + 1);
+ if (edid_ext[0] == CEA_EXT)
+ break;
+ }
+ if (i == edid->extensions)
+ return NULL;
+
+ return edid_ext;
+}
+
+/**
+ * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
+ * @edid: monitor EDID information
+ *
+ * Parse the CEA extension according to CEA-861-B.
+ * Return true if HDMI, false if not or unknown.
+ */
+bool drm_detect_hdmi_monitor(struct edid * edid)
+{
+ u8 *edid_ext;
+ int i, hdmi_id;
+ int start_offset, end_offset;
+ bool is_hdmi = false;
+
+ edid_ext = drm_find_cea_extension(edid);
+ if (!edid_ext)
+ goto end;
+
+ /* Data block offset in CEA extension block */
+ start_offset = 4;
+ end_offset = edid_ext[2];
+
+ /*
+ * Because HDMI identifier is in Vendor Specific Block,
+ * search it from all data blocks of CEA extension.
+ */
+ for (i = start_offset; i < end_offset;
+ /* Increased by data block len */
+ i += ((edid_ext[i] & 0x1f) + 1)) {
+ /* Find vendor specific block */
+ if ((edid_ext[i] >> 5) == VENDOR_BLOCK) {
+ hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) |
+ edid_ext[i + 3] << 16;
+ /* Find HDMI identifier */
+ if (hdmi_id == HDMI_IDENTIFIER)
+ is_hdmi = true;
+ break;
+ }
+ }
+
+end:
+ return is_hdmi;
+}
+
+ /**
+ * drm_detect_monitor_audio - check monitor audio capability
+ *
+ * Monitor should have CEA extension block.
+ * If monitor has 'basic audio', but no CEA audio blocks, it's 'basic
+ * audio' only. If there is any audio extension block and supported
+ * audio format, assume at least 'basic audio' support, even if 'basic
+ * audio' is not defined in EDID.
+ *
+ */
+bool drm_detect_monitor_audio(struct edid * edid)
+{
+ u8 *edid_ext;
+ int i, j;
+ bool has_audio = false;
+ int start_offset, end_offset;
+
+ edid_ext = drm_find_cea_extension(edid);
+ if (!edid_ext)
+ goto end;
+
+ has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0);
+
+ if (has_audio) {
+ DRM_DEBUG_KMS("Monitor has basic audio support\n");
+ goto end;
+ }
+
+ /* Data block offset in CEA extension block */
+ start_offset = 4;
+ end_offset = edid_ext[2];
+
+ for (i = start_offset; i < end_offset; i += ((edid_ext[i] & 0x1f) + 1)) {
+ if ((edid_ext[i] >> 5) == AUDIO_BLOCK) {
+ has_audio = true;
+ for (j = 1; j < (edid_ext[i] & 0x1f); j += 3)
+ DRM_DEBUG_KMS("CEA audio format %d\n",
+ (edid_ext[i + j] >> 3) & 0xf);
+ goto end;
+ }
+ }
+end:
+ return has_audio;
+}
+
+/**
+ * add_established_modes - get est. modes from EDID and add them
+ * @edid: EDID block to scan
+ *
+ * Each EDID block contains a bitmap of the supported "established modes" list
+ * (defined above). Tease them out and add them to the global modes list.
+ */
+static int
+check_established_modes(struct edid *edid)
+{
+ unsigned long est_bits = edid->established_timings.t1 |
+ (edid->established_timings.t2 << 8) |
+ ((edid->established_timings.mfg_rsvd & 0x80) << 9);
+ int i, modes = 0;
+
+ for (i = 0; i <= EDID_EST_TIMINGS; i++) {
+ if (est_bits & (1<<i)) {
+ if ((i == EST_800x600_60) || (i == EST_640x480_60) || (i == EST_1024x768_60))
+ printf("%s is supported\n", edid_est_modes[i]);
+ modes++;
+ }
+ }
+
+/* if (version_greater(edid, 1, 0))
+ drm_for_each_detailed_block((u8 *)edid,
+ do_established_modes, &closure);
+*/
+ return modes;
+}
+
diff --git a/target/packages/tfp410ctrl/parse-edid.h b/target/packages/tfp410ctrl/parse-edid.h
new file mode 100644
index 0000000..5852112
--- /dev/null
+++ b/target/packages/tfp410ctrl/parse-edid.h
@@ -0,0 +1,6 @@
+#ifndef __PARSE_EDID_H__
+#define __PARSE_EDID_H__
+
+int parse_edid(unsigned char* edid);
+
+#endif /* __PARSE_EDID_H__ */
diff --git a/target/packages/tfp410ctrl/tfp410ctrl.c b/target/packages/tfp410ctrl/tfp410ctrl.c
index bb062c6..25ad25e 100644
--- a/target/packages/tfp410ctrl/tfp410ctrl.c
+++ b/target/packages/tfp410ctrl/tfp410ctrl.c
@@ -1,7 +1,8 @@
/*
-** ARMADEUS Systems
+** tfp410ctrl: manage the TFP410 Video controller
**
-** Copyright (C) 2011 The source forge armadeus systems team
+** Copyright (C) 2011 ARMadeus Systems
+** authors: th...@us...
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -17,11 +18,7 @@
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
-** tfp410ctrl: manage the TFP410 Video controller
-**
-** authors: th...@us...
-*/
-
+*/
#include <stdio.h>
#include <fcntl.h>
@@ -30,17 +27,20 @@
#include <stdlib.h>
#include <string.h>
-#include <linux/i2c.h>
+#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-
+
#include <sys/ioctl.h>
+
#include "tfp410ctrl.h"
-#define DEBUG_TFP410 1
+#include "parse-edid.h"
-#define VERSION "0.2alpha"
+
+#define VERSION "0.3alpha"
#define CONF_FILE "tfp410.conf"
+#define EDID_FILE "edid.bin"
#define MAX_DUMP_LINE 100
-/****************************************************************************************************************************/
+
/* MENU */
void usage()
@@ -51,6 +51,7 @@ void usage()
printf("d: dump tfp410 registers\n");
printf("s: save\n");
printf("l: load\n");
+ printf("e: get EDID from monitor\n");
printf("other: this menu\n");
}
@@ -67,9 +68,8 @@ void registerMenu()
printf("\n9. DE_LIN\n");
}
-
-static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
- int size, union i2c_smbus_data *data)
+static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
+ int size, union i2c_smbus_data *data)
{
struct i2c_smbus_ioctl_data args;
@@ -100,7 +100,7 @@ int read_byte(int fd, unsigned char dev, unsigned char reg, unsigned char *buf)
}
if (i2c_smbus_access(fd, I2C_SMBUS_READ, reg,
- I2C_SMBUS_BYTE_DATA, &data)) {
+ I2C_SMBUS_BYTE_DATA, &data)) {
printf("Read error\n");
return -1;
} else {
@@ -120,7 +120,7 @@ int read_word(int fd, unsigned char dev, unsigned char reg, unsigned short *buf)
}
if (i2c_smbus_access(fd, I2C_SMBUS_READ, reg,
- I2C_SMBUS_WORD_DATA, &data)) {
+ I2C_SMBUS_WORD_DATA, &data)) {
printf("Read error\n");
return -1;
} else {
@@ -129,7 +129,6 @@ int read_word(int fd, unsigned char dev, unsigned char reg, unsigned short *buf)
}
}
-
/* Write a byte on the I2C bus
@param fd: file descriptor of the device
@param dev: address of the device on I2C bus
@@ -137,7 +136,8 @@ int read_word(int fd, unsigned char dev, unsigned char reg, unsigned short *buf)
@param value: value to write
@return : -1 in case of error otherwise 0
*/
-int write_byte(int fd, unsigned char dev, unsigned char reg, unsigned char value)
+int write_byte(int fd, unsigned char dev, unsigned char reg,
+ unsigned char value)
{
union i2c_smbus_data data;
data.byte = value;
@@ -149,12 +149,13 @@ int write_byte(int fd, unsigned char dev, unsigned char reg, unsigned char value
}
return i2c_smbus_access(fd, I2C_SMBUS_WRITE, reg,
- I2C_SMBUS_BYTE_DATA, &data);
+ I2C_SMBUS_BYTE_DATA, &data);
- return 0;
+ return 0;
}
-int write_word(int fd, unsigned char dev, unsigned char reg, unsigned short value)
+int write_word(int fd, unsigned char dev, unsigned char reg,
+ unsigned short value)
{
union i2c_smbus_data data;
data.word = value;
@@ -166,14 +167,14 @@ int write_word(int fd, unsigned char dev, unsigned char reg, unsigned short valu
}
return i2c_smbus_access(fd, I2C_SMBUS_WRITE, reg,
- I2C_SMBUS_WORD_DATA, &data);
+ I2C_SMBUS_WORD_DATA, &data);
- return 0;
+ return 0;
}
/* dump the register values on the screen if destFile is NULL or in a file
*/
-void dumpReg(int fd, int regAddr, char* info, FILE* destFile)
+void dump_reg(int fd, int regAddr, char *info, FILE *destFile)
{
unsigned short buf = 0;
char dumpString[MAX_DUMP_LINE];
@@ -181,14 +182,15 @@ void dumpReg(int fd, int regAddr, char* info, FILE* destFile)
if (regAddr > DE_TOP_REG)
read_word(fd, TFP410_I2C_SLAVE_ADDR, regAddr, &buf);
else
- read_byte(fd, TFP410_I2C_SLAVE_ADDR, regAddr, (unsigned char*)&buf);
+ read_byte(fd, TFP410_I2C_SLAVE_ADDR, regAddr,
+ (unsigned char *)&buf);
- if (destFile == NULL){
+ if (destFile == NULL) {
sprintf(dumpString, "%s %02X:%04X\t", info, regAddr, buf);
printf("%s\n", dumpString);
} else {
sprintf(dumpString, "%02X:%04X\t", regAddr, buf);
- fprintf(destFile, "%s\n", dumpString);
+ fprintf(destFile, "%s\n", dumpString);
}
}
@@ -196,30 +198,29 @@ void dumpReg(int fd, int regAddr, char* info, FILE* destFile)
@param fd: file descriptor of the TFP410
@param destFile: file in which to write if used otherwise ""
*/
-void dump(int fd, FILE* destFile)
+void dump(int fd, FILE *destFile)
{
-
if (destFile == NULL)
printf("\t\t Ad:Va\n");
- dumpReg(fd, CTL_1_MODE_REG, "CTL_1_MODE:\t", destFile);
- dumpReg(fd, CTL_2_MODE_REG, "CTL_2_MODE:\t", destFile);
- dumpReg(fd, CTL_3_MODE_REG, "CTL_3_MODE:\t", destFile);
- dumpReg(fd, CFG_REG, "CFG:\t\t", destFile);
- dumpReg(fd, DE_DLY_REG, "DE_DLY:\t\t", destFile);
- dumpReg(fd, DE_CTL_REG, "DE_CTL:\t\t", destFile);
- dumpReg(fd, DE_TOP_REG, "DE_TOP:\t\t", destFile);
- dumpReg(fd, DE_CNT_REG, "DE_CNT:\t\t", destFile);
- dumpReg(fd, DE_LIN_REG, "DE_LIN:\t\t", destFile);
- dumpReg(fd, H_RES_REG, "H_RES:\t\t", destFile);
- dumpReg(fd, V_RES_REG, "V_RES:\t\t", destFile);
+ dump_reg(fd, CTL_1_MODE_REG, "CTL_1_MODE:\t", destFile);
+ dump_reg(fd, CTL_2_MODE_REG, "CTL_2_MODE:\t", destFile);
+ dump_reg(fd, CTL_3_MODE_REG, "CTL_3_MODE:\t", destFile);
+ dump_reg(fd, CFG_REG, "CFG:\t\t", destFile);
+ dump_reg(fd, DE_DLY_REG, "DE_DLY:\t\t", destFile);
+ dump_reg(fd, DE_CTL_REG, "DE_CTL:\t\t", destFile);
+ dump_reg(fd, DE_TOP_REG, "DE_TOP:\t\t", destFile);
+ dump_reg(fd, DE_CNT_REG, "DE_CNT:\t\t", destFile);
+ dump_reg(fd, DE_LIN_REG, "DE_LIN:\t\t", destFile);
+ dump_reg(fd, H_RES_REG, "H_RES:\t\t", destFile);
+ dump_reg(fd, V_RES_REG, "V_RES:\t\t", destFile);
}
/* load the TFP410 registers with the values contained in the given file
@param fd: file descriptor of the TFP410
@param fileName: file containing the values. If "" then the name has to be entered
*/
-void load(int fd, char* fileName)
+void load(int fd, char *fileName)
{
char line[MAX_DUMP_LINE];
char tempFileName[MAX_DUMP_LINE];
@@ -229,78 +230,97 @@ void load(int fd, char* fileName)
if (strlen(fileName) == 0) {
printf("Enter file name: ");
fgets(tempFileName, sizeof(tempFileName), stdin);
- tempFileName[strlen(tempFileName)-1] = '\0'; /* suppress \n */
- }
- else {
+ tempFileName[strlen(tempFileName) - 1] = '\0'; /* suppress \n */
+ } else {
strcpy(tempFileName, fileName);
}
if ((fd_conf = fopen(tempFileName, "r")) == NULL) {
perror("Open error: ");
- exit (1);
+ exit(1);
}
while (fgets(line, MAX_DUMP_LINE, fd_conf) != NULL) {
- sscanf(line,"%2X%*c%4X", ®Addr, &val);
+ sscanf(line, "%2X%*c%4X", ®Addr, &val);
printf("reg %02x, value %04x\n", regAddr, val);
if (regAddr > DE_TOP_REG)
write_word(fd, TFP410_I2C_SLAVE_ADDR, regAddr, val);
else
write_byte(fd, TFP410_I2C_SLAVE_ADDR, regAddr, val);
- }
+ }
if (fd_conf != NULL)
- fclose(fd_conf);
+ fclose(fd_conf);
}
-void modifyRegister(int fd, int regAddr)
+static void modify_register(int fd, int regAddr)
{
int regValue;
- char string[10]; // user input string
+ char string[10]; /* user input string */
printf("Reg value:");
fgets(string, sizeof(string), stdin);
if ((regAddr == DE_CNT_REG) || (regAddr == DE_LIN_REG)) {
sscanf(string, "%4x", ®Value);
- write_word(fd, TFP410_I2C_SLAVE_ADDR, regAddr, regValue);
+ write_word(fd, TFP410_I2C_SLAVE_ADDR, regAddr, regValue);
} else {
sscanf(string, "%2x", ®Value);
write_byte(fd, TFP410_I2C_SLAVE_ADDR, regAddr, regValue);
}
}
-void tfp410_init( int fd )
+unsigned char EDID[256];
+static int get_edid_infos(int fd, unsigned char *buf)
+{
+ int i;
+ int res;
+
+ for (i = 0; i < sizeof(EDID); i++) {
+ res = read_byte(fd, 0x50, i, buf);
+ /* printf("%02x ", *buf); */
+ if (res < 0) {
+ fprintf(stderr, "Error while getting EDID infos, "
+ "please check your monitor is connected\n");
+ return -ENODEV;
+ }
+ buf++;
+ }
+ return 0;
+}
+
+void tfp410_init(int fd)
{
/* exit power down mode */
write_byte(fd, TFP410_I2C_SLAVE_ADDR, CTL_1_MODE_REG, 0xBD);
- /* configure MSEN/PO1 as hotplug detect pin */
+ /* configure MSEN/PO1 as hotplug detect pin */
write_byte(fd, TFP410_I2C_SLAVE_ADDR, CTL_2_MODE_REG, 0x32);
-
}
int main(int argc, char *argv[])
{
- int fd; // TFP410 file descriptor
- FILE *fd_conf = NULL; // config file
- char string[10]; // user input string
- unsigned short buf; // buf to store I2C command/data
- char* bus = "/dev/i2c-1";
-
- if (argc > 2) { /* too many args */
+ int fd; /* TFP410 file descriptor */
+ FILE *fd_conf = NULL; /* config file */
+ FILE *edid_file = NULL;
+ char string[10]; /* user input string */
+ unsigned short buf; /* buf to store I2C command/data */
+ char *bus = "/dev/i2c-1";
+ int res;
+
+ if (argc > 2) { /* too many args */
usage();
exit(1);
- } else if (argc == 2) { /* i2c bus */
+ } else if (argc == 2) { /* i2c bus */
bus = argv[1];
}
/* open I2C /dev */
if ((fd = open(bus, O_RDWR)) < 0) {
perror("Open error: ");
- exit (1);
+ exit(1);
}
-
+
/* configure I2C_SLAVE */
if (ioctl(fd, I2C_SLAVE, TFP410_I2C_SLAVE_ADDR) < 0) {
perror("Ioctl error: ");
- exit (1);
+ exit(1);
}
/* check TFP410 presence */
@@ -314,55 +334,83 @@ int main(int argc, char *argv[])
printf("TFP410 not found. Exiting\n");
exit(1);
}
-
+
tfp410_init(fd);
usage();
- while(1) {
+ while (1) {
+ printf(" > ");
fgets(string, sizeof(string), stdin);
- if (string[0] == 'q') { /* Exit */
+ if (string[0] == 'q') { /* Exit */
exit(0);
- }
- else if (string[0] == 'm') { /* Modify registers */
+ } else if (string[0] == 'm') { /* Modify registers */
registerMenu();
fgets(string, sizeof(string), stdin);
- switch (string[0]){
- case '1': modifyRegister(fd, CTL_1_MODE_REG); break;
- case '2': modifyRegister(fd, CTL_2_MODE_REG); break;
- case '3': modifyRegister(fd, CTL_3_MODE_REG); break;
- case '4': modifyRegister(fd, CFG_REG); break;
- case '5': modifyRegister(fd, DE_DLY_REG); break;
- case '6': modifyRegister(fd, DE_CTL_REG); break;
- case '7': modifyRegister(fd, DE_TOP_REG); break;
- case '8': modifyRegister(fd, DE_CNT_REG); break;
- case '9': modifyRegister(fd, DE_LIN_REG); break;
- default: printf("invalid selection\n"); break;
+ switch (string[0]) {
+ case '1':
+ modify_register(fd, CTL_1_MODE_REG);
+ break;
+ case '2':
+ modify_register(fd, CTL_2_MODE_REG);
+ break;
+ case '3':
+ modify_register(fd, CTL_3_MODE_REG);
+ break;
+ case '4':
+ modify_register(fd, CFG_REG);
+ break;
+ case '5':
+ modify_register(fd, DE_DLY_REG);
+ break;
+ case '6':
+ modify_register(fd, DE_CTL_REG);
+ break;
+ case '7':
+ modify_register(fd, DE_TOP_REG);
+ break;
+ case '8':
+ modify_register(fd, DE_CNT_REG);
+ break;
+ case '9':
+ modify_register(fd, DE_LIN_REG);
+ break;
+ default:
+ printf("invalid selection\n");
+ break;
}
- }
- else if (string[0] == 'd') { /* Dump to screen */
+ } else if (string[0] == 'd') { /* Dump to screen */
dump(fd, fd_conf);
- }
- else if (string[0] == 's') { /* Save to file */
+ } else if (string[0] == 's') { /* Save to file */
if ((fd_conf = fopen(CONF_FILE, "w")) < 0) {
perror("Open error: ");
- exit (1);
+ exit(1);
}
dump(fd, fd_conf);
if (fd_conf != NULL) {
fclose(fd_conf);
}
printf("Data saved to conf file\n");
- }
- else if (string[0] == 'l') { /* load from file */
+ } else if (string[0] == 'l') { /* load from file */
load(fd, "");
+ } else if (string[0] == 'e') { /* EDID */
+ res = get_edid_infos(fd, EDID);
+ if (!res) {
+ edid_file = fopen(EDID_FILE, "wb");
+ if (edid_file) {
+ fwrite(EDID, sizeof(EDID), 1, edid_file);
+ fclose(edid_file);
+ } else {
+ fprintf(stderr, "Failed to open %s\n", EDID_FILE);
+ }
+ parse_edid(EDID);
+ }
} else {
usage();
}
};
-
+
if (fd >= 0) {
close(fd);
}
-
- exit (0);
-}
+ exit(0);
+}
diff --git a/target/packages/tfp410ctrl/tfp410ctrl.h b/target/packages/tfp410ctrl/tfp410ctrl.h
index 617348b..9155b33 100644
--- a/target/packages/tfp410ctrl/tfp410ctrl.h
+++ b/target/packages/tfp410ctrl/tfp410ctrl.h
@@ -1,7 +1,8 @@
/*
-** ARMADEUS Systems
+** tfp410ctrl: manage the TFP410 Video controller
**
-** Copyright (C) 2011 year The source forge armadeus systems team
+** Copyright (C) 2011 ARMadeus Systems
+** authors: th...@us...
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -17,23 +18,17 @@
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
-** File : tfp410ctrl.h
-**
-** authors: th...@us...
*/
-// I2C slave Adresses
-
+/* I2C slave address */
#define TFP410_I2C_SLAVE_ADDR 0x38
-
-// main registers address
+/* main registers address */
#define VEN_ID 0x014C
#define DEV_ID 0x410
#define REV_ID 0x0000
-
#define VEN_ID_REG 0x00
#define DEV_ID_REG 0x02
#define REV_ID_REG 0x04
@@ -49,5 +44,3 @@
#define H_RES_REG 0x3A
#define V_RES_REG 0x3C
-
-
hooks/post-receive
--
armadeus
|