aboutsummaryrefslogtreecommitdiff
path: root/recipes-bsp/u-boot/files/v2017.03/0005-Add-DE10-Nano-HDMI-configuration-and-debug-apps.patch
diff options
context:
space:
mode:
authorWestergreen, Dalon <dalon.westergreen@intel.com>2017-03-29 15:41:36 -0700
committerWestergreen, Dalon <dalon.westergreen@intel.com>2017-03-30 16:35:30 -0700
commit9a293641b9abf9e4fca34f46a2de781f50847da9 (patch)
tree743a6aaa5f9834987a2e69881ced6eaf9efb3592 /recipes-bsp/u-boot/files/v2017.03/0005-Add-DE10-Nano-HDMI-configuration-and-debug-apps.patch
parent8abd3fefd939f796ae49191d6f5af641f2d624d0 (diff)
downloadmeta-de10-nano-9a293641b9abf9e4fca34f46a2de781f50847da9.tar.xz
Initial commit of de10-nano recipes
Please note that this is purely for development. Only superficial efforts have been made to resolve security concerns, and it should be noted that the board ships with an EMPTY ROOT PASSWORD and support for root login via ssh. This allows passwordless access to the board via ssh. recipes-bsp/u-boot: Contains the uboot 2017.03rc2 recipe and patches to support the de10-nano board recipes-connectivity/avahi: bbappend to remove unwanted packages recipes-connectivity/bluez: bbappend to add --compat to the bluetooth service to support legacy SDP APIs recipes-connectivity/openssh: bbappend to add a custom sshd_config recipes-core/base-files: bbappend to customize fstab and inputrc recipes-core/imagemagick: bbappend to change build configuration for the de10-nano board recipes-core/packagegroups: bbappend to remove an unwanted package recipes-core/webkit: bbappend to remove support for opengl recipes-demo: Various demo applications recipes-devtools: MRAA and UPM recipes recipes-images/angstrom/de10-nano-image.bb: DE10-Nano image definition recipes-kernel/de10-nano-linux-firmware: FPGA related firmware required for fpga configuration and devicetree overlay support recipes-kernel/linux: bbappend to customize configuration of linux kernel as well as patch in the de10-nano devicetree recipes-misc: various initialization and systemd scripts recipes-qt/qt5: bbappend to modify qt build options recipes-support/neon: bbappend to remove unwanted package recipes-support/upower: bbappend to remove unwanted package recipes-webserver: webserver configuration and webcontent for board hostedweb portal recipes-xfce/thunar-volman: bbappend to remove unwanted package recipes-xfce/xfce-pointers: add configuration so that xfce does not use the adxl input as a mouse recipes-xfce/xfce4-settings: bbappend to remove unwanted package Signed-off-by: Westergreen, Dalon <dalon.westergreen@intel.com>
Diffstat (limited to 'recipes-bsp/u-boot/files/v2017.03/0005-Add-DE10-Nano-HDMI-configuration-and-debug-apps.patch')
-rw-r--r--recipes-bsp/u-boot/files/v2017.03/0005-Add-DE10-Nano-HDMI-configuration-and-debug-apps.patch2404
1 files changed, 2404 insertions, 0 deletions
diff --git a/recipes-bsp/u-boot/files/v2017.03/0005-Add-DE10-Nano-HDMI-configuration-and-debug-apps.patch b/recipes-bsp/u-boot/files/v2017.03/0005-Add-DE10-Nano-HDMI-configuration-and-debug-apps.patch
new file mode 100644
index 0000000..fd4ece3
--- /dev/null
+++ b/recipes-bsp/u-boot/files/v2017.03/0005-Add-DE10-Nano-HDMI-configuration-and-debug-apps.patch
@@ -0,0 +1,2404 @@
+From e6f372d6f357184bedb18b4384e3c752bb60d342 Mon Sep 17 00:00:00 2001
+From: Dalon Westergreen <dwesterg@gmail.com>
+Date: Sun, 12 Feb 2017 14:22:46 -0800
+Subject: [PATCH 5/6] Add DE10-Nano HDMI configuration and debug apps
+
+Signed-off-by: Dalon Westergreen <dwesterg@gmail.com>
+---
+ examples/standalone/Makefile | 3 +
+ examples/standalone/de10_nano_hdmi_config.c | 1324 +++++++++++++++++++++++++++
+ examples/standalone/de10_nano_hdmi_config.h | 195 ++++
+ examples/standalone/dump_adv7513_edid.c | 697 ++++++++++++++
+ examples/standalone/dump_adv7513_regs.c | 129 +++
+ 5 files changed, 2348 insertions(+)
+ create mode 100644 examples/standalone/de10_nano_hdmi_config.c
+ create mode 100644 examples/standalone/de10_nano_hdmi_config.h
+ create mode 100644 examples/standalone/dump_adv7513_edid.c
+ create mode 100644 examples/standalone/dump_adv7513_regs.c
+
+diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile
+index 5a6ae00..c23ac50 100644
+--- a/examples/standalone/Makefile
++++ b/examples/standalone/Makefile
+@@ -6,6 +6,9 @@
+ #
+
+ extra-y := hello_world
++extra-y += de10_nano_hdmi_config
++extra-y += dump_adv7513_regs
++extra-y += dump_adv7513_edid
+ extra-$(CONFIG_SMC91111) += smc91111_eeprom
+ extra-$(CONFIG_SMC911X) += smc911x_eeprom
+ extra-$(CONFIG_SPI_FLASH_ATMEL) += atmel_df_pow2
+diff --git a/examples/standalone/de10_nano_hdmi_config.c b/examples/standalone/de10_nano_hdmi_config.c
+new file mode 100644
+index 0000000..a7dd2c1
+--- /dev/null
++++ b/examples/standalone/de10_nano_hdmi_config.c
+@@ -0,0 +1,1324 @@
++/*
++ * The MIT License (MIT)
++ * Copyright (c) 2017 Intel Corporation
++ *
++ * 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
++ * AUTHORS OR COPYRIGHT HOLDERS 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.
++ */
++
++#include <common.h>
++#include <exports.h>
++#include "de10_nano_hdmi_config.h"
++
++/*
++This program is built to run as a u-boot standalone application and leverage the
++u-boot provided runtime environment. Prior to running this program you will
++need to configure a few things in the u-boot environment.
++
++run fpga_cfg
++i2c dev 2
++load mmc 0:1 0x0c300000 STARTUP.BMP
++dcache flush
++dcache off
++
++load this program into memory at 0x0C100000 and then run it at 0x0C100001, yes
++you set the lsb of the address to indicate a thumb mode branch or something like
++that.
++
++load mmc 0:1 0x0c100000 de10_nano_hdmi_config.bin
++go 0x0C100001
++
++*/
++
++/* ADV7513 register configurations */
++init_config init_config_array[] = {
++ {0x98, 0x03}, // must be set
++ {0x9A, 0xE0}, // must be set
++ {0x9C, 0x30}, // must be set
++ {0x9D, 0x61}, // must be set
++ {0xA2, 0xA4}, // must be set
++ {0xA3, 0xA4}, // must be set
++ {0xE0, 0xD0}, // must be set
++ {0xF9, 0x00}, // must be set
++ {0x16, 0x30}, // 8-bit color depth
++ {0x17, 0x02}, // aspect ratio 16:9, modified below if needed
++ {0xAF, 0x06}, // HDMI mode, no HDCP
++ {0x0C, 0x00}, // disable I2S inputs
++ {0x96, 0xF6}, // clear all interrupts
++};
++
++/* prototypes */
++void pll_calc_fixed(struct pll_calc_struct *the_pll_calc_struct);
++void uitoa(uint32_t uint32_input, char **output_str);
++
++/* main configuration function */
++int de10_nano_hdmi_config(int argc, char * const argv[]) {
++
++ int i;
++ int j;
++ int result;
++ char *print_str;
++ uint8_t adv7513_read_buffer[256];
++ uint8_t adv7513_edid_buffer[256];
++ uint8_t adv7513_write_val;
++ uint8_t checksum;
++ uint8_t edid_header_pattern_array[8] = {
++ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
++ uint8_t *descriptor_base;
++ uint8_t dtd_offset;
++ uint8_t dtd_count;
++
++ uint16_t pixel_clock;
++ uint16_t horizontal_active_pixels;
++ uint16_t horizontal_blanking_pixels;
++ uint16_t vertical_active_lines;
++ uint16_t vertical_blanking_lines;
++ uint16_t horizontal_sync_offset;
++ uint16_t horizontal_sync_width;
++ uint8_t vertical_sync_offset;
++ uint8_t vertical_sync_width;
++ uint8_t interlaced;
++
++ uint32_t pixel_clock_MHz;
++ uint8_t bad_pixel_clock_MHz;
++ uint8_t bad_horizontal_active_pixels_value;
++ uint8_t bad_vertical_active_lines_value;
++ uint8_t bad_interlaced_value;
++ uint8_t valid_timing_configuration_located;
++ uint8_t monitor_connected;
++
++ int32_t aspect_ratio;
++
++ uint32_t N_reg;
++ uint32_t M_reg;
++ uint32_t C_reg;
++ uint32_t K_reg;
++ uint32_t BW_reg;
++ uint32_t CP_reg;
++ uint32_t VCODIV_reg;
++
++ volatile uint32_t *pll_ptr;
++ volatile uint32_t *fbr_ptr;
++ volatile uint32_t *cvo_ptr;
++ volatile uint32_t *cvo_reset_pio_ptr;
++ volatile uint32_t *pll_reset_pio_ptr;
++ volatile uint32_t *pll_locked_pio_ptr;
++ volatile uint32_t *video_ptr;
++ volatile struct bmp_image_header *bmp_header_ptr;
++ volatile struct bmp_24_bit_pixel *bmp_pixel_ptr;
++
++ struct pll_calc_struct shared_struct;
++
++ char snprintf_buffer[256];
++ char *snprintf_buffer_ptr;
++ uint32_t milestones;
++
++ /* initialize u-boot application environment */
++ app_startup(argv);
++
++ /* initialize pointers and status */
++ setenv(HDMI_STATUS_ENV, "startup");
++ setenv(HDMI_INFO_ENV, "none");
++ setenv(HDMI_ERROR_ENV, "none");
++
++ pll_ptr = (uint32_t*)(LWH2F_BASE + PLL_RECNFG_BASE);
++ fbr_ptr = (uint32_t*)(LWH2F_BASE + FBR_BASE);
++ cvo_ptr = (uint32_t*)(LWH2F_BASE + CVO_BASE);
++ cvo_reset_pio_ptr = (uint32_t*)(LWH2F_BASE + CVO_RESET_PIO_BASE);
++ pll_reset_pio_ptr = (uint32_t*)(LWH2F_BASE + PLL_RESET_PIO_BASE);
++ pll_locked_pio_ptr = (uint32_t*)(LWH2F_BASE + PLL_LOCKED_PIO_BASE);
++ video_ptr = (uint32_t*)VIDEO_BUFFER;
++
++ valid_timing_configuration_located = 0;
++ milestones = 0;
++
++ /* since we cannot read a single register from the ADV7513 with the
++ * default I2C driver, we just read the first N registers starting
++ * from ZERO and reaching up to the register we want
++ */
++ setenv(HDMI_STATUS_ENV, "read ADV7513 chip ID");
++ milestones |= 0x01 << 0;
++ result = i2c_read(
++ ADV7513_MAIN_ADDR, // uint8_t chip
++ 0x00, // unsigned int addr
++ 0, // int alen
++ adv7513_read_buffer, // uint8_t *buffer
++ ADV7513_CHIP_ID_LO + 1 // int len
++ );
++
++ if(result != 0) {
++ print_str = "reading I2C";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(1);
++ }
++
++ /* verify the chip id for the ADV7513 */
++ setenv(HDMI_STATUS_ENV, "verify ADV7513 chip ID");
++ milestones |= 0x01 << 1;
++ if(
++ (adv7513_read_buffer[ADV7513_CHIP_ID_HI] !=
++ ADV7513_CHIP_ID_HI_VAL) ||
++ (adv7513_read_buffer[ADV7513_CHIP_ID_LO] !=
++ ADV7513_CHIP_ID_LO_VAL) ) {
++
++ print_str = "Bad Chip ID";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(2);
++ }
++
++ /* verify that we see a monitor attached to the HDMI connector */
++ setenv(HDMI_STATUS_ENV, "verify monitor attached");
++ milestones |= 0x01 << 2;
++ monitor_connected = 1;
++ if((adv7513_read_buffer[ADV7513_HPD_MNSNS] & ADV7513_HPD_MNSNS_BITS) !=
++ ADV7513_HPD_MNSNS_BITS) {
++
++ print_str = "No HDMI display detected";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ monitor_connected = 0;
++ }
++
++ /* force HPD true */
++ setenv(HDMI_STATUS_ENV, "force HPD true");
++ milestones |= 0x01 << 3;
++ adv7513_write_val = ADV7513_HPD_CNTL_BITS;
++ result = i2c_write(
++ ADV7513_MAIN_ADDR, // uint8_t chip
++ ADV7513_HPD_CNTL, // unsigned int addr
++ 1, // int alen
++ &adv7513_write_val, // uint8_t *buffer
++ 1 // int len
++ );
++
++ if(result != 0) {
++ print_str = "writing I2C";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(4);
++ }
++
++ /* power down the ADV7513 */
++ setenv(HDMI_STATUS_ENV, "power down ADV7513");
++ milestones |= 0x01 << 4;
++ adv7513_write_val = adv7513_read_buffer[ADV7513_PWR_DWN];
++ adv7513_write_val |= ADV7513_PWR_DWN_BIT;
++ result = i2c_write(
++ ADV7513_MAIN_ADDR, // uint8_t chip
++ ADV7513_PWR_DWN, // unsigned int addr
++ 1, // int alen
++ &adv7513_write_val, // uint8_t *buffer
++ 1 // int len
++ );
++
++ if(result != 0) {
++ print_str = "writing I2C";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(4);
++ }
++
++ /* power up the ADV7513 */
++ setenv(HDMI_STATUS_ENV, "power up ADV7513");
++ milestones |= 0x01 << 5;
++ adv7513_write_val &= ~ADV7513_PWR_DWN_BIT;
++ result = i2c_write(
++ ADV7513_MAIN_ADDR, // uint8_t chip
++ ADV7513_PWR_DWN, // unsigned int addr
++ 1, // int alen
++ &adv7513_write_val, // uint8_t *buffer
++ 1 // int len
++ );
++
++ if(result != 0) {
++ print_str = "writing I2C";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(5);
++ }
++
++ /*
++ if we sense a monitor is attached then we attempt to read the EDID data
++ and configure ourselves according to that. Otherwise we apply a default
++ 1024*728 configuration
++ */
++ setenv(HDMI_STATUS_ENV, "monitor present fork");
++ milestones |= 0x01 << 6;
++ if(monitor_connected == 0)
++ goto post_EDID_evaluation;
++
++ /* wait for the EDID data to become ready */
++ setenv(HDMI_STATUS_ENV, "wait EDID ready");
++ milestones |= 0x01 << 7;
++ for(i = 0 ; i < 1000 ; i++) {
++ result = i2c_read(
++ ADV7513_MAIN_ADDR, // uint8_t chip
++ 0x00, // unsigned int addr
++ 0, // int alen
++ adv7513_read_buffer, // uint8_t *buffer
++ ADV7513_EDID_RDY + 1 // int len
++ );
++
++ if(result != 0) {
++ print_str = "reading I2C";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(6);
++ }
++
++ if((adv7513_read_buffer[ADV7513_EDID_RDY] &
++ ADV7513_EDID_RDY_BIT) == ADV7513_EDID_RDY_BIT)
++ break;
++ }
++
++ if(i >= 1000) {
++ print_str = "EDID timeout";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ goto post_EDID_evaluation;
++ }
++
++ /* read the EDID data */
++ setenv(HDMI_STATUS_ENV, "read EDID data");
++ milestones |= 0x01 << 8;
++ result = i2c_read(
++ ADV7513_EDID_ADDR, // uint8_t chip
++ 0x00, // unsigned int addr
++ 0, // int alen
++ adv7513_edid_buffer, // uint8_t *buffer
++ 256 // int len
++ );
++
++ if(result != 0) {
++ print_str = "reading I2C";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(8);
++ }
++
++ /* verify EDID block 0 checksum */
++ setenv(HDMI_STATUS_ENV, "verify EDID block 0 checksum");
++ milestones |= 0x01 << 9;
++ checksum = 0;
++ for(i = 0 ; i < 128 ; i++)
++ checksum += adv7513_edid_buffer[i];
++
++ if(checksum != 0) {
++ print_str = "EDID block 0 checksum";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ goto post_EDID_evaluation;
++ }
++
++ /* verify block 0 header pattern */
++ setenv(HDMI_STATUS_ENV, "verify block 0 header pattern");
++ milestones |= 0x01 << 10;
++ for(i = 0 ; i < 8 ; i++) {
++ if(edid_header_pattern_array[i] != adv7513_edid_buffer[i]) {
++ print_str = "EDID header pattern";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ goto post_EDID_evaluation;
++ }
++ }
++
++ /* decode descriptor blocks */
++ setenv(HDMI_STATUS_ENV, "decode EDID block 0");
++ milestones |= 0x01 << 11;
++ bad_horizontal_active_pixels_value = 0;
++ bad_vertical_active_lines_value = 0;
++ bad_interlaced_value = 0;
++ for(i = 0 ; i < 4 ; i++) {
++ descriptor_base = &adv7513_edid_buffer[54];
++ descriptor_base += i * 18;
++ if(
++ (descriptor_base[0] == 0) &&
++ (descriptor_base[1] == 0) &&
++ (descriptor_base[2] == 0) &&
++ (descriptor_base[4] == 0)
++ ) {
++ /* not a Detailed Timing Descriptor */
++ continue;
++ }
++ /* Detailed Timing Descriptor
++ * extract the relevant fields of the descriptor
++ */
++ pixel_clock =
++ (descriptor_base[1] << 8) |
++ descriptor_base[0];
++
++ horizontal_active_pixels =
++ (((descriptor_base[4] >> 4) & 0x0F) << 8) |
++ descriptor_base[2];
++
++ horizontal_blanking_pixels =
++ ((descriptor_base[4] & 0x0F) << 8) |
++ descriptor_base[3];
++
++ vertical_active_lines =
++ (((descriptor_base[7] >> 4) & 0x0F) << 8) |
++ descriptor_base[5];
++
++ vertical_blanking_lines =
++ ((descriptor_base[7] & 0x0F) << 8) |
++ descriptor_base[6];
++
++ horizontal_sync_offset =
++ (((descriptor_base[11] >> 6) & 0x03) << 8) |
++ descriptor_base[8];
++
++ horizontal_sync_width =
++ (((descriptor_base[11] >> 4) & 0x03) << 8) |
++ descriptor_base[9];
++
++ vertical_sync_offset =
++ (((descriptor_base[11] >> 2) & 0x03) << 4) |
++ ((descriptor_base[10] >> 4) & 0x0F);
++
++ vertical_sync_width =
++ ((descriptor_base[11] & 0x03) << 4) |
++ (descriptor_base[10] & 0x0F);
++
++ interlaced = (descriptor_base[17] & 0x80) ? 1 : 0;
++
++ /* adjust pixel clock up to MHz */
++ pixel_clock_MHz = pixel_clock * 10000;
++
++ /* check for valid ranges of key parameters */
++ if((pixel_clock_MHz > 150000000) ||
++ (pixel_clock_MHz < 60000000)) {
++ bad_pixel_clock_MHz++;
++ continue;
++ }
++ if((horizontal_active_pixels > 1920) ||
++ (horizontal_active_pixels < 1280)) {
++ bad_horizontal_active_pixels_value++;
++ continue;
++ }
++ if((vertical_active_lines > 1080) ||
++ (vertical_active_lines < 720)) {
++ bad_vertical_active_lines_value++;
++ continue;
++ }
++ if(interlaced != 0) {
++ bad_interlaced_value++;
++ continue;
++ }
++ valid_timing_configuration_located = 1;
++ break;
++ }
++
++ if(valid_timing_configuration_located != 0)
++ goto post_EDID_evaluation;
++
++ /* check for extension blocks */
++ setenv(HDMI_STATUS_ENV, "check for extension blocks");
++ milestones |= 0x01 << 31;
++ if(adv7513_edid_buffer[126] == 0)
++ goto post_EDID_evaluation;
++
++ /* verify extension block checksum */
++ setenv(HDMI_STATUS_ENV, "verify extension block checksum");
++ milestones |= 0x01 << 30;
++ checksum = 0;
++ for(i = 0 ; i < 128 ; i++)
++ checksum += adv7513_edid_buffer[128 + i];
++
++ if(checksum != 0) {
++ print_str = "extension block 1 checksum";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ goto post_EDID_evaluation;
++ }
++
++ /* verify extension tag */
++ setenv(HDMI_STATUS_ENV, "verify extension tag");
++ milestones |= 0x01 << 29;
++ if(adv7513_edid_buffer[128] != 0x02) {
++ print_str = "extension tag";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ goto post_EDID_evaluation;
++ }
++
++ /* verify revision number */
++ setenv(HDMI_STATUS_ENV, "verify revision number");
++ milestones |= 0x01 << 28;
++ if(adv7513_edid_buffer[129] != 0x03) {
++ print_str = "extension revision number";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ goto post_EDID_evaluation;
++ }
++
++ /* check for DTDs in extension block */
++ setenv(HDMI_STATUS_ENV, "check for DTDs in extension block");
++ milestones |= 0x01 << 27;
++ dtd_offset = adv7513_edid_buffer[130];
++ dtd_count = adv7513_edid_buffer[131] & 0x0F;
++ if(
++ (dtd_offset == 0x00) ||
++ (dtd_count == 0x00)
++ ) {
++ print_str = "No DTDs present in extension block";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ goto post_EDID_evaluation;
++ }
++
++ /* decode descriptor blocks */
++ setenv(HDMI_STATUS_ENV, "decode EDID block 1");
++ milestones |= 0x01 << 26;
++ for(i = 0 ; i < dtd_count ; i++) {
++ descriptor_base = &adv7513_edid_buffer[128];
++ descriptor_base += dtd_offset;
++ descriptor_base += i * 18;
++ if(
++ (descriptor_base[0] == 0) &&
++ (descriptor_base[1] == 0) &&
++ (descriptor_base[2] == 0) &&
++ (descriptor_base[4] == 0)
++ ) {
++ /* not a Detailed Timing Descriptor */
++ continue;
++ }
++ /* Detailed Timing Descriptor
++ * extract the relevant fields of the descriptor
++ */
++ pixel_clock =
++ (descriptor_base[1] << 8) |
++ descriptor_base[0];
++
++ horizontal_active_pixels =
++ (((descriptor_base[4] >> 4) & 0x0F) << 8) |
++ descriptor_base[2];
++
++ horizontal_blanking_pixels =
++ ((descriptor_base[4] & 0x0F) << 8) |
++ descriptor_base[3];
++
++ vertical_active_lines =
++ (((descriptor_base[7] >> 4) & 0x0F) << 8) |
++ descriptor_base[5];
++
++ vertical_blanking_lines =
++ ((descriptor_base[7] & 0x0F) << 8) |
++ descriptor_base[6];
++
++ horizontal_sync_offset =
++ (((descriptor_base[11] >> 6) & 0x03) << 8) |
++ descriptor_base[8];
++
++ horizontal_sync_width =
++ (((descriptor_base[11] >> 4) & 0x03) << 8) |
++ descriptor_base[9];
++
++ vertical_sync_offset =
++ (((descriptor_base[11] >> 2) & 0x03) << 4) |
++ ((descriptor_base[10] >> 4) & 0x0F);
++
++ vertical_sync_width =
++ ((descriptor_base[11] & 0x03) << 4) |
++ (descriptor_base[10] & 0x0F);
++
++ interlaced = (descriptor_base[17] & 0x80) ? 1 : 0;
++
++ /* adjust pixel clock up to MHz */
++ pixel_clock_MHz = pixel_clock * 10000;
++
++ /* check for valid ranges of key parameters */
++ if((pixel_clock_MHz > 150000000) ||
++ (pixel_clock_MHz < 60000000)) {
++ bad_pixel_clock_MHz++;
++ continue;
++ }
++ if((horizontal_active_pixels > 1920) ||
++ (horizontal_active_pixels < 1280)) {
++ bad_horizontal_active_pixels_value++;
++ continue;
++ }
++ if((vertical_active_lines > 1080) ||
++ (vertical_active_lines < 720)) {
++ bad_vertical_active_lines_value++;
++ continue;
++ }
++ if(interlaced != 0) {
++ bad_interlaced_value++;
++ continue;
++ }
++ valid_timing_configuration_located = 1;
++ break;
++ }
++
++post_EDID_evaluation:
++
++ /* if no valid timing is found, then set 1024x768 default */
++ setenv(HDMI_STATUS_ENV, "evaluate timing configuration");
++ milestones |= 0x01 << 12;
++ if(valid_timing_configuration_located == 0) {
++ print_str = "no valid timing found, setting 1024x768 default";
++ printf("%s%s\n", WARN_STR, print_str);
++ setenv(HDMI_INFO_ENV, print_str);
++
++ pixel_clock_MHz = 65000000;
++ horizontal_active_pixels = 1024;
++ horizontal_blanking_pixels = 320;
++ vertical_active_lines = 768;
++ vertical_blanking_lines = 38;
++ horizontal_sync_offset = 24;
++ horizontal_sync_width = 136;
++ vertical_sync_offset = 3;
++ vertical_sync_width = 6;
++ interlaced = 0;
++ }
++
++ /* determine the aspect ratio of the timing parameters */
++ aspect_ratio = (horizontal_active_pixels * 9) -
++ (vertical_active_lines * 16);
++
++ if(abs(aspect_ratio) > (horizontal_active_pixels * 2))
++ for(i = 0 ;
++ i < (int)(sizeof(init_config_array) /
++ sizeof(init_config)) ;
++ i++)
++ if(init_config_array[i].addr == 0x17)
++ /* set to 4:3 aspect */
++ init_config_array[i].value = 0x00;
++
++ /* calculate the PLL reconfiguration register values */
++ shared_struct.desired_frequency = pixel_clock_MHz;
++ shared_struct.m_value = 0;
++ shared_struct.c_value = 0;
++ shared_struct.k_value = 0;
++ pll_calc_fixed(&shared_struct);
++
++ if(shared_struct.desired_frequency == 0) {
++ print_str = "PLL calculation failure";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(11);
++ }
++
++ /* stop the FBR and wait for it to idle */
++ setenv(HDMI_STATUS_ENV, "stop FBR");
++ milestones |= 0x01 << 13;
++ fbr_ptr[FBR_CNTL_REG] = 0x00000000;
++
++ for(i = 0 ; i < 100000 ; i++) {
++ if((fbr_ptr[FBR_STAT_REG] & 0x01) == 0x00)
++ break;
++ }
++ if(i >= 100000) {
++ print_str = "FBR stop timeout";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(12);
++ }
++
++ /* stop the CVO */
++ setenv(HDMI_STATUS_ENV, "stop CVO");
++ milestones |= 0x01 << 14;
++ cvo_ptr[CVO_CNTL_REG] = 0x00000000;
++
++ for(i = 0 ; i < 100000 ; i++) {
++ if((cvo_ptr[CVO_STAT_REG] & 0x01) == 0x00)
++ break;
++ }
++ if(i >= 100000) {
++ print_str = "CVO stop timeout";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(13);
++ }
++
++ /* assert CVO reset */
++ setenv(HDMI_STATUS_ENV, "assert CVO reset");
++ milestones |= 0x01 << 15;
++ cvo_reset_pio_ptr[0] = 0x00000001;
++
++ /* apply PLL reconfiguration */
++ N_reg = 0x00010000;
++
++ if((shared_struct.m_value & 0x01) != 0) {
++ M_reg = (1 << 17) |
++ (((shared_struct.m_value >> 1) + 1) << 8) |
++ (shared_struct.m_value >> 1);
++ } else {
++ M_reg = ((shared_struct.m_value >> 1) << 8) |
++ (shared_struct.m_value >> 1);
++ }
++
++ if((shared_struct.c_value & 0x01) != 0) {
++ C_reg = (1 << 17) |
++ (((shared_struct.c_value >> 1) + 1) << 8) |
++ (shared_struct.c_value >> 1);
++ } else {
++ C_reg = ((shared_struct.c_value >> 1) << 8) |
++ (shared_struct.c_value >> 1);
++ }
++
++ K_reg = shared_struct.k_value;
++
++ if((shared_struct.m_value == 12) || (shared_struct.m_value == 13)) {
++ BW_reg = 8;
++ CP_reg = 3;
++ } else {
++ BW_reg = 7;
++ CP_reg = 2;
++ }
++
++ VCODIV_reg = 0x00000000;
++
++ pll_ptr[PLL_MODE_REG] = 0x00; /* waitrequest mode */
++ pll_ptr[PLL_N_CNTR_REG] = N_reg;
++ pll_ptr[PLL_M_CNTR_REG] = M_reg;
++ pll_ptr[PLL_C_CNTR_REG] = C_reg;
++ pll_ptr[PLL_K_REG] = K_reg;
++ pll_ptr[PLL_BW_REG] = BW_reg;
++ pll_ptr[PLL_CP_REG] = CP_reg;
++ pll_ptr[PLL_VCODIV_REG] = VCODIV_reg;
++
++ pll_ptr[PLL_START_REG] = 0x01;
++
++ /* assert and release PLL reset, then wait for lock */
++ setenv(HDMI_STATUS_ENV, "reset PLL");
++ milestones |= 0x01 << 16;
++ pll_reset_pio_ptr[0] = 0x00000001;
++ pll_reset_pio_ptr[0] = 0x00000000;
++
++ for(i = 0 ; i < 100000 ; i++) {
++ if((pll_locked_pio_ptr[0] & 0x01) == 0x01)
++ break;
++ }
++ if(i >= 100000) {
++ print_str = "PLL lock timeout";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(14);
++ }
++
++ /* release CVO reset */
++ setenv(HDMI_STATUS_ENV, "release CVO reset");
++ milestones |= 0x01 << 17;
++ cvo_reset_pio_ptr[0] = 0x00000000;
++
++ /* configure the FBR */
++ fbr_ptr[FBR_FRM_INFO_REG] = (horizontal_active_pixels << 13) |
++ vertical_active_lines;
++ fbr_ptr[FBR_MISC_REG] = 0x00000000;
++ fbr_ptr[FBR_FRM_STRT_ADDR_REG] = VIDEO_BUFFER;
++
++ /* start the FBR */
++ fbr_ptr[FBR_CNTL_REG] = 0x00000001;
++
++ /* start the CVO */
++ cvo_ptr[CVO_CNTL_REG] = 0x00000007;
++
++ /* configure the CVO */
++ cvo_ptr[CVO_BANK_SELECT_REG] = 0;
++ cvo_ptr[CVO_M_VALID_REG] = 0;
++ cvo_ptr[CVO_M_CNTL_REG] = 0;
++ cvo_ptr[CVO_M_SMPL_CNT_REG] = horizontal_active_pixels;
++ cvo_ptr[CVO_M_F0_LN_CNT_REG] = vertical_active_lines;
++ cvo_ptr[CVO_M_F1_LN_CNT_REG] = 0;
++ cvo_ptr[CVO_M_HOR_FRNT_PRCH_REG] = horizontal_sync_offset;
++ cvo_ptr[CVO_M_HOR_SYNC_LEN_REG] = horizontal_sync_width;
++ cvo_ptr[CVO_M_HOR_BLNK_REG] = horizontal_blanking_pixels;
++ cvo_ptr[CVO_M_VER_FRNT_PRCH_REG] = vertical_sync_offset;
++ cvo_ptr[CVO_M_VER_SYNC_LEN_REG] = vertical_sync_width;
++ cvo_ptr[CVO_M_VER_BLNK_REG] = vertical_blanking_lines;
++ cvo_ptr[CVO_M_F0_VER_F_PRCH_REG] = 0;
++ cvo_ptr[CVO_M_F0_VER_SYNC_REG] = 0;
++ cvo_ptr[CVO_M_F0_VER_BLNK_REG] = 0;
++ cvo_ptr[CVO_M_ACT_PIC_LINE_REG] = 0;
++ cvo_ptr[CVO_M_F0_VER_RIS_REG] = 0;
++ cvo_ptr[CVO_M_FLD_RIS_REG] = 0;
++ cvo_ptr[CVO_M_FLD_FLL_REG] = 0;
++ cvo_ptr[CVO_M_STNDRD_REG] = 0;
++ cvo_ptr[CVO_M_SOF_SMPL_REG] = 0;
++ cvo_ptr[CVO_M_SOF_LINE_REG] = 0;
++ cvo_ptr[CVO_M_VCOCLK_DIV_REG] = 0;
++ cvo_ptr[CVO_M_ANC_LINE_REG] = 0;
++ cvo_ptr[CVO_M_F0_ANC_LINE_REG] = 0;
++ cvo_ptr[CVO_M_H_SYNC_POL_REG] = 1;
++ cvo_ptr[CVO_M_V_SYNC_POL_REG] = 1;
++ cvo_ptr[CVO_M_VALID_REG] = 1;
++
++ /* configure the ADV7513 */
++ setenv(HDMI_STATUS_ENV, "configure ADV7513");
++ milestones |= 0x01 << 18;
++ for(i = 0 ; i < (int)(sizeof(init_config_array) / sizeof(init_config))
++ ; i++) {
++
++ result = i2c_write(
++ ADV7513_MAIN_ADDR, // uint8_t chip
++ init_config_array[i].addr, // unsigned int addr
++ 1, // int alen
++ &init_config_array[i].value, // uint8_t *buffer
++ 1 // int len
++ );
++
++ if(result != 0) {
++ print_str = "writing I2C";
++ printf("%s%s\n", ERROR_STR, print_str);
++ setenv(HDMI_ERROR_ENV, print_str);
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++ return(15);
++ }
++ }
++
++ /* report configuration details to u-boot environment */
++ setenv(HDMI_STATUS_ENV, "report configuration");
++ milestones |= 0x01 << 19;
++
++ print_str = "HDMI_vld_tmng_fnd";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(valid_timing_configuration_located, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_h_active_pix";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(horizontal_active_pixels, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_h_blank_pix";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(horizontal_blanking_pixels, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_h_sync_off";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(horizontal_sync_offset, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_h_sync_width";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(horizontal_sync_width, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_v_active_lin";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(vertical_active_lines, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_v_blank_lin";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(vertical_blanking_lines, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_v_sync_off";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(vertical_sync_offset, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_v_sync_width";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(vertical_sync_width, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_pll_freq";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(shared_struct.desired_frequency, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_pll_m";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(shared_struct.m_value, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_pll_c";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(shared_struct.c_value, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_pll_k";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(shared_struct.k_value, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_stride";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(horizontal_active_pixels * 4, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ print_str = "HDMI_milestones";
++ snprintf_buffer_ptr = &snprintf_buffer[0];
++ uitoa(milestones, &snprintf_buffer_ptr);
++ setenv(print_str, snprintf_buffer);
++ printf("%s = %s\n", print_str, snprintf_buffer);
++
++ setenv(HDMI_STATUS_ENV, "complete");
++
++ /* paint the frame buffer */
++/*
++ for(j = 0 ; j < vertical_active_lines ; j++) {
++ for(i = 0 ; i < horizontal_active_pixels ; i++) {
++ if(i < (horizontal_active_pixels / 3))
++ video_ptr[i + (j * horizontal_active_pixels)] =
++ 0x00FF0000;
++ else if(i < (2 * (horizontal_active_pixels / 3)))