diff options
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.patch | 2404 |
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))) ++ video_ptr[i + (j * horizontal_active_pixels)] = ++ 0x0000FF00; ++ else ++ video_ptr[i + (j * horizontal_active_pixels)] = ++ 0x000000FF; ++ } ++ } ++ ++ for(i = 0 ; i < horizontal_active_pixels ; i++) { ++ video_ptr[i] = 0x00FFFFFF; ++ video_ptr[i + (horizontal_active_pixels * ++ (vertical_active_lines - 1))] = 0x00FFFFFF; ++ } ++ ++ for(i = 0 ; i < vertical_active_lines ; i++) { ++ video_ptr[i * horizontal_active_pixels] = 0x00FFFFFF; ++ video_ptr[(horizontal_active_pixels - 1) + ++ (i * horizontal_active_pixels)] = ++ 0x00FFFFFF; ++ } ++*/ ++ for(j = 0 ; j < vertical_active_lines ; j++) { ++ for(i = 0 ; i < horizontal_active_pixels ; i++) { ++ video_ptr[i + (j * horizontal_active_pixels)] = ++ 0x000071C5; ++ } ++ } ++ ++ print_str = "background painted"; ++ setenv(HDMI_INFO_ENV, print_str); ++ ++ bmp_header_ptr = (struct bmp_image_header *)BMP_IMAGE_BASE; ++ ++ if(bmp_header_ptr->bmp_signature != 0x4D42) { ++ print_str = "bad BMP signature"; ++ printf("%s%s\n", INFO_STR, print_str); ++ setenv(HDMI_INFO_ENV, print_str); ++ return(16); ++ } ++ ++ if(bmp_header_ptr->bmp_header_size != 124) { ++ print_str = "bad BMP header size"; ++ printf("%s%s\n", INFO_STR, print_str); ++ setenv(HDMI_INFO_ENV, print_str); ++ return(17); ++ } ++ ++ if(bmp_header_ptr->bmp_color_planes != 1) { ++ print_str = "bad BMP color planes"; ++ printf("%s%s\n", INFO_STR, print_str); ++ setenv(HDMI_INFO_ENV, print_str); ++ return(18); ++ } ++ ++ if(bmp_header_ptr->bmp_bits_per_pixel != 24) { ++ print_str = "bad BMP bits per pixel"; ++ printf("%s%s\n", INFO_STR, print_str); ++ setenv(HDMI_INFO_ENV, print_str); ++ return(19); ++ } ++ ++ if(bmp_header_ptr->bmp_compression_method != 0) { ++ print_str = "bad BMP compression method"; ++ printf("%s%s\n", INFO_STR, print_str); ++ setenv(HDMI_INFO_ENV, print_str); ++ return(20); ++ } ++ ++ if(bmp_header_ptr->bmp_width != 640) { ++ print_str = "bad BMP image width"; ++ printf("%s%s\n", INFO_STR, print_str); ++ setenv(HDMI_INFO_ENV, print_str); ++ return(21); ++ } ++ ++ if(bmp_header_ptr->bmp_height != 480) { ++ print_str = "bad BMP image height"; ++ printf("%s%s\n", INFO_STR, print_str); ++ setenv(HDMI_INFO_ENV, print_str); ++ return(22); |