]> Zhao Yanbai Git Server - minix.git/commitdiff
fb: auto-configure with EDID 34/734/2
authorThomas Cort <tcort@minix3.org>
Mon, 29 Jul 2013 17:01:38 +0000 (13:01 -0400)
committerGerrit Code Review <gerrit@gerrit>
Sun, 11 Aug 2013 18:37:16 +0000 (20:37 +0200)
Use EDID when available to configure the frame buffer driver with
good settings for the attached display.

Change-Id: I69a78155a93e55ffa1ca3ff6621a879a56cdbceb

drivers/fb/Makefile
drivers/fb/README.txt [new file with mode: 0644]
drivers/fb/arch/earm/fb_arch.c
drivers/fb/fb.c
drivers/fb/fb.h
drivers/fb/fb_edid.c [new file with mode: 0644]
drivers/fb/fb_edid.h [new file with mode: 0644]
etc/system.conf
etc/usr/rc

index 2744ccfdb3b1655c09bf023141b8fb768b422ba3..493892fb490e0065731f21a46f5778e1e8c82cf7 100644 (file)
@@ -3,7 +3,14 @@ PROG=  fb
 
 .include "arch/${MACHINE_ARCH}/Makefile.inc"
 
-SRCS+= fb.c
+SRCS+= fb_edid.c fb.c
+
+# re-use EDID parsing/validation code from NetBSD.
+.PATH: ${NETBSDSRCDIR}/sys/dev/videomode
+SRCS+= edid.c pickmode.c videomode.c vesagtf.c
+
+# Put this dir and the EDID headers (dev/videomode/*.h) in the search path.
+CPPFLAGS+= -I${.CURDIR} -I${NETBSDSRCDIR}/sys
 
 DPADD+=        ${LIBCHARDRIVER} ${LIBSYS}
 LDADD+=        -lchardriver -lsys
diff --git a/drivers/fb/README.txt b/drivers/fb/README.txt
new file mode 100644 (file)
index 0000000..838901b
--- /dev/null
@@ -0,0 +1,24 @@
+Frame Buffer Driver
+===================
+
+Overview
+--------
+
+This is the driver for the frame buffer. Currently it only supports the
+DM37XX (BeagleBoard-xM).
+
+Testing the Code
+----------------
+
+Starting up an instance:
+
+service up /usr/sbin/fb -dev /dev/fb0 -args edid.0=cat24c256.3.50
+
+The arguments take the following form:
+
+       edid.X=L where X is the frame buffer device (usually 0) and L is
+       the service label of the service to perform the EDID reading. In
+       the example above, it's the EEPROM with slave address 0x50 on
+       the 3rd I2C bus. If you want to use the defaults and skip EDID
+       reading, you may omit the arguments.
+
index 5dbf7340ff1ecaf0c73903d410cfe273eb8818a4..d324ed16af73cce55a818dc2bc255a098d609da2 100644 (file)
@@ -1,23 +1,50 @@
-/* Architecture dependent part for the framebuffer on the OMAP3. Since we don't
- * have support for EDID (which requires support for i2c, also something we
- * don't have, yet), but we do have a screen with 1024*600 resolution for our
- * testing purposes, we hardcode that resolution here. There's obvious room for
- * improvement. */
+/* Architecture dependent part for the framebuffer on the OMAP3.
+ * There's obvious room for improvement.
+ */
 
 #include <minix/chardriver.h>
 #include <minix/drivers.h>
 #include <minix/fb.h>
 #include <minix/type.h>
 #include <minix/vm.h>
+#include <minix/log.h>
 #include <assert.h>
 #include <sys/mman.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <dev/videomode/videomode.h>
+#include <dev/videomode/edidvar.h>
+#include <dev/videomode/edidreg.h>
 #include "dss.h"
+#include "fb.h"
+
+/* default / fallback resolution if EDID reading fails */
 #define SCREEN_WIDTH 1024
 #define SCREEN_HEIGHT 600
 #define PAGES_NR 2
 
+#define NSUPPORTED_MODES (4)
+
+/* List of valid modes from TRM 7.1
+ * Other modes might work (like the default 1024x600), but no guarantees.
+ */
+struct supported_modes {
+       int hdisplay;
+       int vdisplay;
+} omap_supported_modes[NSUPPORTED_MODES] = {
+       { .hdisplay = 1024, .vdisplay = 768 }, /* XGA */
+       { .hdisplay = 1280, .vdisplay = 800 }, /* WXGA */
+       { .hdisplay = 1400, .vdisplay = 1050 }, /* SXGA+ */
+       { .hdisplay = 1280, .vdisplay = 720 } /* HD 720p */
+};
+
+/* local function prototypes */
+static struct videomode *choose_mode(struct edid_info *info);
+static void configure_with_defaults(int minor);
+static int configure_with_edid(int minor, struct edid_info *info);
+
+/* globals */
 static vir_bytes dss_phys_base;                /* Address of dss phys memory map */
 static vir_bytes dispc_phys_base;      /* Address of dispc phys memory map */
 static vir_bytes fb_vir;
@@ -50,7 +77,9 @@ static const struct panel_config default_cfg = {
         .panel_color    = 0xFFFFFF     /* WHITE */
 };
 
-static const struct fb_fix_screeninfo fbfs = {
+static struct panel_config omap_cfg[FB_DEV_NR];
+
+static const struct fb_fix_screeninfo default_fbfs = {
        .xpanstep       = 0,
        .ypanstep       = 0,
        .ywrapstep      = 0,
@@ -59,7 +88,9 @@ static const struct fb_fix_screeninfo fbfs = {
        .mmio_len       = 0     /* these are set to 0 */
 };
 
-static struct fb_var_screeninfo fbvs = {
+static struct fb_fix_screeninfo omap_fbfs[FB_DEV_NR];
+
+static const struct fb_var_screeninfo default_fbvs = {
        .xres           = SCREEN_WIDTH,
        .yres           = SCREEN_HEIGHT,
        .xres_virtual   = SCREEN_WIDTH,
@@ -89,6 +120,15 @@ static struct fb_var_screeninfo fbvs = {
                }
 };
 
+static struct fb_var_screeninfo omap_fbvs[FB_DEV_NR];
+
+/* logging - use with log_warn(), log_info(), log_debug(), log_trace() */
+static struct log log = {
+       .name = "fb",
+       .log_level = LEVEL_INFO,
+       .log_func = default_log
+};
+
 static inline u32_t
 readw(vir_bytes addr)
 {
@@ -101,6 +141,97 @@ writew(vir_bytes addr, u32_t val)
         *((volatile u32_t *) addr) = val;
 }
 
+static struct videomode *
+choose_mode(struct edid_info *info)
+{
+       int i, j;
+
+       /* choose the highest resolution supported by both the SoC and screen */
+       for (i = info->edid_nmodes - 1; i >= 0; i--) {
+               for (j = NSUPPORTED_MODES - 1; j >= 0; j--) {
+
+                       if (info->edid_modes[i].hdisplay ==
+                               omap_supported_modes[j].hdisplay &&
+                               info->edid_modes[i].vdisplay ==
+                               omap_supported_modes[j].vdisplay) {
+
+                               return &(info->edid_modes[i]);
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+static int
+configure_with_edid(int minor, struct edid_info *info)
+{
+       struct videomode *mode;
+
+       if (info == NULL || minor < 0 || minor >= FB_DEV_NR) {
+               log_warn(&log, "Invalid minor #%d or info == NULL\n", minor);
+               return -1;
+       }
+
+       /* If debugging or tracing, print the contents of info */
+       if (log.log_level >= LEVEL_DEBUG) {
+               log_debug(&log, "--- EDID - START ---\n");
+               edid_print(info);
+               log_debug(&log, "--- EDID - END ---\n");
+       }
+
+       /* Choose the preferred mode. */
+       mode = choose_mode(info);
+       if (mode == NULL) {
+               log_warn(&log, "Couldn't find a supported resolution.\n");
+               return -1;
+       }
+
+       /*
+        * apply the default settings since we don't overwrite every field
+        */
+       configure_with_defaults(minor);
+
+       /*
+        * apply the settings corresponding to the given EDID
+        */
+
+       /* panel_config */
+       omap_cfg[minor].lcd_size    = ((mode->vdisplay - 1) << 16 | (mode->hdisplay - 1));
+
+       if (EDID_FEATURES_DISP_TYPE(info->edid_features) ==
+                       EDID_FEATURES_DISP_TYPE_MONO) {
+               omap_cfg[minor].panel_type  = 0x00;             /* Mono */
+       } else {
+               omap_cfg[minor].panel_type  = 0x01;             /* RGB/Color */
+       }
+
+       /* fb_fix_screeninfo */
+       omap_fbfs[minor].line_length = mode->hdisplay * 4;
+
+       /* fb_var_screeninfo */
+       omap_fbvs[minor].xres           = mode->hdisplay;
+       omap_fbvs[minor].yres           = mode->vdisplay;
+       omap_fbvs[minor].xres_virtual   = mode->hdisplay;
+       omap_fbvs[minor].yres_virtual   = mode->vdisplay*2;
+
+       return OK;
+}
+
+static void
+configure_with_defaults(int minor)
+{
+       if (minor < 0 || minor >= FB_DEV_NR) {
+               log_warn(&log, "Invalid minor #%d\n", minor);
+               return;
+       }
+
+       /* copy the default values into this minor's configuration */
+       memcpy(&omap_cfg[minor], &default_cfg, sizeof(struct panel_config));
+       memcpy(&omap_fbfs[minor], &default_fbfs, sizeof(struct fb_fix_screeninfo));
+       memcpy(&omap_fbvs[minor], &default_fbvs, sizeof(struct fb_var_screeninfo));
+}
+
 static void
 arch_configure_display(int minor)
 {
@@ -110,7 +241,7 @@ arch_configure_display(int minor)
        if (!initialized) return;
        if (minor != 0) return;
 
-       off = fbvs.yoffset * fbvs.xres_virtual * (fbvs.bits_per_pixel/8);
+       off = omap_fbvs[minor].yoffset * omap_fbvs[minor].xres_virtual * (omap_fbvs[minor].bits_per_pixel/8);
 
        writew((vir_bytes) OMAP3_DISPC_GFX_BA0(dispc_phys_base),
                fb_phys + (phys_bytes) off);
@@ -136,7 +267,7 @@ arch_get_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp)
        if (!initialized) return ENXIO;
        if (minor != 0) return ENXIO;
 
-       *fbvsp = fbvs;
+       *fbvsp = omap_fbvs[minor];
        return OK;
 }
 
@@ -151,12 +282,12 @@ arch_put_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp)
        if (minor != 0) return ENXIO;
 
        /* For now we only allow to play with the yoffset setting */
-       if (fbvsp->yoffset != fbvs.yoffset) {
-               if (fbvsp->yoffset < 0 || fbvsp->yoffset > fbvs.yres) {
+       if (fbvsp->yoffset != omap_fbvs[minor].yoffset) {
+               if (fbvsp->yoffset < 0 || fbvsp->yoffset > omap_fbvs[minor].yres) {
                        return EINVAL;
                }
 
-               fbvs.yoffset = fbvsp->yoffset;
+               omap_fbvs[minor].yoffset = fbvsp->yoffset;
        }
        
        /* Now update hardware with new settings */
@@ -170,7 +301,7 @@ arch_get_fixscreeninfo(int minor, struct fb_fix_screeninfo *fbfsp)
        if (!initialized) return ENXIO;
        if (minor != 0) return ENXIO;
 
-       *fbfsp = fbfs;
+       *fbfsp = omap_fbfs[minor];
        return OK;
 }
 
@@ -181,20 +312,32 @@ arch_pan_display(int minor, struct fb_var_screeninfo *fbvsp)
 }
 
 int
-arch_fb_init(int minor, struct device *dev)
+arch_fb_init(int minor, struct device *dev, struct edid_info *info)
 {
+       int r;
        u32_t rdispc;
        struct minix_mem_range mr;
 
-       const struct panel_config *panel_cfg = &default_cfg;
+       const struct panel_config *panel_cfg = &omap_cfg[minor];
 
        assert(dev != NULL);
        if (minor != 0) return ENXIO;   /* We support only one minor */
 
+
        if (initialized) {
                dev->dv_base = fb_vir;
                dev->dv_size = fb_size;
                return OK;
+       } else if (info != NULL) {
+               log_debug(&log, "Configuring Settings based on EDID...\n");
+               r = configure_with_edid(minor, info);
+               if (r != OK) {
+                       log_warn(&log, "EDID config failed. Using defaults.\n");
+                       configure_with_defaults(minor);
+               }
+       } else {
+               log_debug(&log, "Loading Default Settings...\n");
+               configure_with_defaults(minor);
        }
 
        initialized = 1;
@@ -254,8 +397,8 @@ arch_fb_init(int minor, struct device *dev)
        writew(OMAP3_DISPC_GFX_PIXEL_INC(dispc_phys_base), 1);
 
        /* Allocate contiguous physical memory for the display buffer */
-       fb_size = fbvs.yres_virtual * fbvs.xres_virtual *
-                               (fbvs.bits_per_pixel / 8);
+       fb_size = omap_fbvs[minor].yres_virtual * omap_fbvs[minor].xres_virtual *
+                               (omap_fbvs[minor].bits_per_pixel / 8);
        fb_vir = (vir_bytes) alloc_contig(fb_size, 0, &fb_phys);
        if (fb_vir == (vir_bytes) MAP_FAILED) {
                panic("Unable to allocate contiguous memory\n");
index b3103de970fbfabeec7ec64a7a619618062dc64c..52c08fce79e7d1f4beaef469c96a681efb7c0a7e 100644 (file)
 #include <sys/mman.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <dev/videomode/videomode.h>
+#include <dev/videomode/edidvar.h>
+#include <dev/videomode/edidreg.h>
+
 #include "logos.h"
+#include "fb_edid.h"
 #include "fb.h"
 
-#define FB_DEV_NR      1
 /*
  * Function prototypes for the fb driver.
  */
@@ -69,11 +74,19 @@ static int open_counter[FB_DEV_NR];         /* Open count */
 static int
 fb_open(message *m)
 {
+       int r;
        static int initialized = 0;
+       static struct edid_info info;
+       static struct edid_info *infop = NULL;
 
        if (m->DEVICE < 0 || m->DEVICE >= FB_DEV_NR) return ENXIO;
 
-       if (arch_fb_init(m->DEVICE, &fb_device[m->DEVICE]) == OK) {
+       if (!initialized) {
+               r = fb_edid_read(m->DEVICE, &info);
+               infop = (r == 0) ? &info : NULL;
+       }
+
+       if (arch_fb_init(m->DEVICE, &fb_device[m->DEVICE], infop) == OK) {
                open_counter[m->DEVICE]++;
                if (!initialized) {
                        if (has_restarted) {
@@ -363,8 +376,11 @@ sef_cb_init(int type, sef_init_info_t *UNUSED(info))
 }
 
 int
-main(void)
+main(int argc, char *argv[])
 {
+       env_setargs(argc, argv);
+       fb_edid_args_parse();
+
        sef_local_startup();
        chardriver_task(&fb_tab, CHARDRIVER_SYNC);
        return OK;
index 2784ef6d50f1ccaba688a13ca724fa08fa6cec33..cf9da112d11f30978fff663e1d40675fecb01372 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef __FB_H__
 #define __FB_H__
 
-int arch_fb_init(int minor, struct device *dev);
+#include <minix/fb.h>
+
+int arch_fb_init(int minor, struct device *dev, struct edid_info *info);
 int arch_get_device(int minor, struct device *dev);
 int arch_get_varscreeninfo(int minor, struct fb_var_screeninfo *fbvsp);
 int arch_put_varscreeninfo(int minor, struct fb_var_screeninfo *fbvs_copy);
@@ -9,5 +11,6 @@ int arch_get_fixscreeninfo(int minor, struct fb_fix_screeninfo *fbfsp);
 int arch_pan_display(int minor, struct fb_var_screeninfo *fbvs_copy);
 
 #define FB_MESSAGE "Hello, world! From framebuffer!\n"
+#define FB_DEV_NR 1
 
 #endif /* __FB_H__ */
diff --git a/drivers/fb/fb_edid.c b/drivers/fb/fb_edid.c
new file mode 100644 (file)
index 0000000..116b644
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Handle reading the EDID information, validating it, and parsing it into
+ * a struct edid_info. EDID reads are done using the Block Device Protocol
+ * as it's already supported by the cat24c256 driver and there is no need
+ * to add yet another message format/type.
+ */
+
+#include <minix/fb.h>
+#include <minix/chardriver.h>
+#include <minix/drivers.h>
+#include <minix/ds.h>
+#include <minix/rs.h>
+#include <minix/log.h>
+#include <minix/sysutil.h>
+#include <minix/type.h>
+#include <minix/vm.h>
+#include <sys/ioc_fb.h>
+#include <assert.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <dev/videomode/videomode.h>
+#include <dev/videomode/edidvar.h>
+#include <dev/videomode/edidreg.h>
+
+#include "fb_edid.h"
+#include "fb.h"
+
+static int do_read(endpoint_t endpt, uint8_t *buf, size_t bufsize);
+
+/* logging - use with log_warn(), log_info(), log_debug(), log_trace() */
+static struct log log = {
+       .name = "edid",
+       .log_level = LEVEL_INFO,
+       .log_func = default_log
+};
+
+/*
+ * Labels corresponding to drivers which provide EDID.
+ */
+static char edid_providers[FB_DEV_NR][RS_MAX_LABEL_LEN+1];
+
+/*
+ * Populate edid_providers from command line arguments. The service command
+ * should get EDID providers like this: "-args edid.0=tda19988.1.3470" where
+ * 0 is the minor number of the frame buffer, tda19988 is the device driver,
+ * 1 is the i2c bus and 3470 is the slave address (the TDA19988 has 2 slave
+ * addresses 0x34 and 0x70).
+ */
+int
+fb_edid_args_parse(void)
+{
+       int i;
+       int r;
+       char key[32];
+
+       for (i = 0; i < FB_DEV_NR; i++) {
+
+               memset(key, '\0', 32);
+               snprintf(key, 32, "edid.%d", i);
+
+               memset(edid_providers[i], '\0', RS_MAX_LABEL_LEN);
+               r = env_get_param(key, edid_providers[i], RS_MAX_LABEL_LEN);
+               if (r == OK) {
+                       log_debug(&log, "Found key:%s value:%s\n", key, edid_providers[i]);
+               } else {
+                       /* not an error, user is allowed to omit EDID
+                        * providers in order to skip EDID reading and use
+                        * the default settings.
+                        */
+                       log_debug(&log, "Couldn't find key:%s\n", key);
+               }
+       }
+
+       return OK;
+}
+
+/*
+ * Send a read request to the block driver at endpoint endpt.
+ */
+static int
+do_read(endpoint_t driver_endpt, uint8_t *buf, size_t bufsize)
+{
+       int r;
+       message m;
+       cp_grant_id_t grant_nr;
+
+       /* Open Device - required for drivers using libblockdriver */
+       memset(&m, '\0', sizeof(message));
+       m.m_type = BDEV_OPEN;
+       m.BDEV_ACCESS = R_BIT;
+       m.BDEV_ID = 0;
+       m.BDEV_MINOR = 0;
+
+       r = sendrec(driver_endpt, &m);
+       if (r != OK) {
+               log_debug(&log, "sendrec(BDEV_OPEN) failed (r=%d)\n", r);
+               return r;
+       }
+
+       grant_nr = cpf_grant_direct(driver_endpt, (vir_bytes) buf,
+               bufsize, CPF_READ | CPF_WRITE);
+
+       /* Perform the read */
+       memset(&m, '\0', sizeof(message));
+       m.m_type = BDEV_READ;
+       m.BDEV_MINOR = 0;
+       m.BDEV_COUNT = bufsize;
+       m.BDEV_GRANT = grant_nr;
+       m.BDEV_FLAGS = BDEV_NOPAGE; /* the EEPROMs used for EDID are pageless */
+       m.BDEV_ID = 0;
+       m.BDEV_POS_LO = 0;
+       m.BDEV_POS_HI = 0;
+
+       r = sendrec(driver_endpt, &m);
+       cpf_revoke(grant_nr);
+       if (r != OK) {
+               log_debug(&log, "sendrec(BDEV_READ) failed (r=%d)\n", r);
+               /* Clean-up: try to close the device */
+               memset(&m, '\0', sizeof(message));
+               m.m_type = BDEV_CLOSE;
+               m.BDEV_MINOR = 0;
+               m.BDEV_ID = 0;
+               sendrec(driver_endpt, &m);
+               return r;
+       }
+
+       /* Close the device */
+       memset(&m, '\0', sizeof(message));
+       m.m_type = BDEV_CLOSE;
+       m.BDEV_MINOR = 0;
+       m.BDEV_ID = 0;
+       r = sendrec(driver_endpt, &m);
+       if (r != OK) {
+               log_debug(&log, "sendrec(BDEV_CLOSE) failed (r=%d)\n", r);
+               return r;
+       }
+
+       return bufsize;
+}
+
+int
+fb_edid_read(int minor, struct edid_info *info)
+{
+
+       int r;
+       uint8_t buffer[128];
+       endpoint_t endpt;
+
+       if (info == NULL || minor < 0 || minor >= FB_DEV_NR ||
+                                       edid_providers[minor][0] == '\0') {
+               return EINVAL;
+       }
+
+       log_debug(&log, "Contacting %s to get EDID.\n", edid_providers[minor]);
+
+       /* Look up the endpoint that corresponds to the label */
+       endpt = 0;
+       r = ds_retrieve_label_endpt(edid_providers[minor], &endpt);
+       if (r != 0 || endpt == 0) {
+               log_warn(&log, "Couldn't find endpoint for label '%s'\n", edid_providers[minor]);
+               return r;
+       }
+
+       /* Perform the request and put the resulting EDID into the buffer. */
+       memset(buffer, 0x00, 128);
+       r = do_read(endpt, buffer, 128);
+       if (r < 0) {
+               log_debug(&log, "Failed to read EDID\n");
+               return r;
+       }
+
+       /* parse and validate EDID */
+       r = edid_parse(buffer, info);
+       if (r != 0) {
+               log_warn(&log, "Invalid EDID data in buffer.\n");
+               return r;
+       } 
+
+       log_debug(&log, "EDID Retrieved and Parsed OK\n");
+
+       return OK;
+}
+
diff --git a/drivers/fb/fb_edid.h b/drivers/fb/fb_edid.h
new file mode 100644 (file)
index 0000000..2829ba4
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __EDID_H
+#define __EDID_H
+
+#include <stdint.h>                                                             
+#include <dev/videomode/videomode.h>                                            
+#include <dev/videomode/edidvar.h>                                              
+#include <dev/videomode/edidreg.h>
+
+int fb_edid_args_parse(void);
+int fb_edid_read(int minor, struct edid_info *info);
+
+#endif /* __EDID_H */
index ff5e595de38a20cfde68cf2106cc2354cec271ae..47045888f9fb5cc1dfd3e159e214d535800462d8 100644 (file)
@@ -573,7 +573,7 @@ service fb
                PRIVCTL         #  4
         ;
        ipc
-                SYSTEM pm rs ds vm vfs tda19988
+                SYSTEM pm rs ds vm vfs cat24c256 tda19988
        ;
 };
 
index 6667e45d4d5daf7725f1aef07b9130c7b88a52e6..7dfb42ffda07f521752866d4fac96dbb8cfce69c 100644 (file)
@@ -197,10 +197,14 @@ start)
 
        BOARD_NAME=`eepromread -i | sed -n 's/^BOARD_NAME      : \(.*\)$/\1/p'`
        case "${BOARD_NAME}" in
+
                A335BONE)
                        echo "Detected BeagleBone"
                        echo -n "Starting i2c device drivers: "
-                       test -e /dev/eepromb1s50 || (cd /dev && MAKEDEV eepromb1s50)
+
+                       # start EEPROM driver for reading board info
+                       test -e /dev/eepromb1s50 || \
+                               (cd /dev && MAKEDEV eepromb1s50)
                        up cat24c256 -dev /dev/eepromb1s50 \
                                -label cat24c256.1.50 \
                                -args 'bus=1 address=0x50'
@@ -209,13 +213,35 @@ start)
                        up tps65217 -label tps65217.1.24 \
                                -args 'bus=1 address=0x24'
 
+                       # check for the presence of a display
+                       eepromread -f /dev/i2c-2 -n > /dev/null 2>&1
+                       RESULT=$?
+                       if [ $RESULT -eq 0 ]
+                       then
+                               # start eeprom driver for reading EDID.
+                               test -e /dev/eepromb2s50 || \
+                                       (cd /dev && MAKEDEV eepromb2s50)
+                               up cat24c256 -dev /dev/eepromb2s50 \
+                                       -label cat24c256.2.50 \
+                                       -args 'bus=2 address=0x50'
+
+                               # start frame buffer
+                               #up fb -dev /dev/fb0 -args edid.0=cat24c256.2.50
+                               # fb hasn't been ported to AM335X yet.
+                       fi
+
                        ;;
+
                A335BNLT)
                        echo "Detected BeagleBone Black"
                        echo -n "Starting i2c device drivers: "
-                       test -e /dev/eepromb1s50 || (cd /dev && MAKEDEV eepromb1s50)
+
+                       # start EEPROM driver for reading board info
+                       test -e /dev/eepromb1s50 || \
+                               (cd /dev && MAKEDEV eepromb1s50)
                        up cat24c256 -dev /dev/eepromb1s50 \
-                               -label cat24c256.1.50 -args 'bus=1 address=0x50'
+                               -label cat24c256.1.50 \
+                               -args 'bus=1 address=0x50'
 
                        # Start TPS65217 driver for power management.
                        up tps65217 -label tps65217.1.24 \
@@ -224,7 +250,13 @@ start)
                        # Start TDA19988 driver for reading EDID.
                        up tda19988 -label tda19988.1.3470 -args \
                                'cec_bus=1 cec_address=0x34 hdmi_bus=1 hdmi_address=0x70'
+
+                       # start frame buffer
+                       #up fb -dev /dev/fb0 -args edid.0=tda19988.1.3470
+                       # fb hasn't been ported to AM335X yet.
+
                        ;;
+
                UNKNOWN)
                        echo "Unable to detect board -- assuming BeagleBoard-xM"
                        echo -n "Starting i2c device drivers: "
@@ -236,6 +268,22 @@ start)
                        # Set the system time to the time in the TPS65950's RTC
                        readclock
 
+                       # check for the presence of a display
+                       eepromread -f /dev/i2c-3 -n > /dev/null 2>&1
+                       RESULT=$?
+                       if [ $RESULT -eq 0 ]
+                       then
+                               # start eeprom driver for reading edid
+                               test -e /dev/eepromb3s50 || \
+                                       (cd /dev && MAKEDEV eepromb3s50)
+                               up cat24c256 -dev /dev/eepromb3s50 \
+                                       -label cat24c256.3.50 \
+                                       -args 'bus=3 address=0x50'
+
+                               # start frame buffer
+                               up fb -dev /dev/fb0 -args edid.0=cat24c256.3.50
+                       fi
+
                        ;;
        esac