diff options
Diffstat (limited to 'board/gdsys/common')
-rw-r--r-- | board/gdsys/common/Makefile | 9 | ||||
-rw-r--r-- | board/gdsys/common/adv7611.c | 177 | ||||
-rw-r--r-- | board/gdsys/common/adv7611.h | 13 | ||||
-rw-r--r-- | board/gdsys/common/ch7301.c | 64 | ||||
-rw-r--r-- | board/gdsys/common/ch7301.h | 13 | ||||
-rw-r--r-- | board/gdsys/common/dp501.c | 27 | ||||
-rw-r--r-- | board/gdsys/common/fanctrl.c | 32 | ||||
-rw-r--r-- | board/gdsys/common/fanctrl.h | 13 | ||||
-rw-r--r-- | board/gdsys/common/ioep-fpga.c | 232 | ||||
-rw-r--r-- | board/gdsys/common/ioep-fpga.h | 14 | ||||
-rw-r--r-- | board/gdsys/common/osd.c | 194 | ||||
-rw-r--r-- | board/gdsys/common/osd.h | 1 |
12 files changed, 719 insertions, 70 deletions
diff --git a/board/gdsys/common/Makefile b/board/gdsys/common/Makefile index 4957943..ce23045 100644 --- a/board/gdsys/common/Makefile +++ b/board/gdsys/common/Makefile @@ -9,7 +9,10 @@ obj-$(CONFIG_SYS_FPGA_COMMON) += fpga.o obj-$(CONFIG_CMD_IOLOOP) += cmd_ioloop.o obj-$(CONFIG_IO) += miiphybb.o obj-$(CONFIG_IO64) += miiphybb.o -obj-$(CONFIG_IOCON) += osd.o mclink.o dp501.o phy.o -obj-$(CONFIG_DLVISION_10G) += osd.o +obj-$(CONFIG_IOCON) += osd.o mclink.o dp501.o phy.o ch7301.o +obj-$(CONFIG_DLVISION_10G) += osd.o dp501.o obj-$(CONFIG_CONTROLCENTERD) += dp501.o -obj-$(CONFIG_HRCON) += osd.o mclink.o dp501.o phy.o +obj-$(CONFIG_HRCON) += osd.o mclink.o dp501.o phy.o ioep-fpga.o fanctrl.o +obj-$(CONFIG_STRIDER) += mclink.o dp501.o phy.o ioep-fpga.o adv7611.o ch7301.o +obj-$(CONFIG_STRIDER) += fanctrl.o +obj-$(CONFIG_STRIDER_CON) += osd.o diff --git a/board/gdsys/common/adv7611.c b/board/gdsys/common/adv7611.c new file mode 100644 index 0000000..b728274 --- /dev/null +++ b/board/gdsys/common/adv7611.c @@ -0,0 +1,177 @@ +/* + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> + +#define ADV7611_I2C_ADDR 0x4c +#define ADV7611_RDINFO 0x2051 + +/* + * ADV7611 I2C Addresses in u-boot notation + */ +enum { + CP_I2C_ADDR = 0x22, + DPLL_I2C_ADDR = 0x26, + KSV_I2C_ADDR = 0x32, + HDMI_I2C_ADDR = 0x34, + EDID_I2C_ADDR = 0x36, + INFOFRAME_I2C_ADDR = 0x3e, + CEC_I2C_ADDR = 0x40, + IO_I2C_ADDR = ADV7611_I2C_ADDR, +}; + +/* + * Global Control Registers + */ +enum { + IO_RD_INFO_MSB = 0xea, + IO_RD_INFO_LSB = 0xeb, + IO_CEC_ADDR = 0xf4, + IO_INFOFRAME_ADDR = 0xf5, + IO_DPLL_ADDR = 0xf8, + IO_KSV_ADDR = 0xf9, + IO_EDID_ADDR = 0xfa, + IO_HDMI_ADDR = 0xfb, + IO_CP_ADDR = 0xfd, +}; + +int adv7611_i2c[] = CONFIG_SYS_ADV7611_I2C; + +int adv7611_probe(unsigned int screen) +{ + int old_bus = i2c_get_bus_num(); + unsigned int rd_info; + int res = 0; + + i2c_set_bus_num(adv7611_i2c[screen]); + + rd_info = (i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_MSB) << 8) + | i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_LSB); + + if (rd_info != ADV7611_RDINFO) { + res = -1; + goto out; + } + + /* + * set I2C addresses to default values + */ + i2c_reg_write(IO_I2C_ADDR, IO_CEC_ADDR, CEC_I2C_ADDR << 1); + i2c_reg_write(IO_I2C_ADDR, IO_INFOFRAME_ADDR, INFOFRAME_I2C_ADDR << 1); + i2c_reg_write(IO_I2C_ADDR, IO_DPLL_ADDR, DPLL_I2C_ADDR << 1); + i2c_reg_write(IO_I2C_ADDR, IO_KSV_ADDR, KSV_I2C_ADDR << 1); + i2c_reg_write(IO_I2C_ADDR, IO_EDID_ADDR, EDID_I2C_ADDR << 1); + i2c_reg_write(IO_I2C_ADDR, IO_HDMI_ADDR, HDMI_I2C_ADDR << 1); + i2c_reg_write(IO_I2C_ADDR, IO_CP_ADDR, CP_I2C_ADDR << 1); + + /* + * do magic initialization sequence from + * "ADV7611 Register Settings Recommendations Revision 1.5" + * with most registers undocumented + */ + i2c_reg_write(CP_I2C_ADDR, 0x6c, 0x00); + i2c_reg_write(HDMI_I2C_ADDR, 0x9b, 0x03); + i2c_reg_write(HDMI_I2C_ADDR, 0x6f, 0x08); + i2c_reg_write(HDMI_I2C_ADDR, 0x85, 0x1f); + i2c_reg_write(HDMI_I2C_ADDR, 0x87, 0x70); + i2c_reg_write(HDMI_I2C_ADDR, 0x57, 0xda); + i2c_reg_write(HDMI_I2C_ADDR, 0x58, 0x01); + i2c_reg_write(HDMI_I2C_ADDR, 0x03, 0x98); + i2c_reg_write(HDMI_I2C_ADDR, 0x4c, 0x44); + + /* + * IO_REG_02, default 0xf0 + * + * INP_COLOR_SPACE (IO, Address 0x02[7:4]) + * default: 0b1111 auto + * set to : 0b0001 force RGB (range 0 to 255) input + * + * RGB_OUT (IO, Address 0x02[1]) + * default: 0 YPbPr color space output + * set to : 1 RGB color space output + */ + i2c_reg_write(IO_I2C_ADDR, 0x02, 0x12); + + /* + * IO_REG_03, default 0x00 + * + * OP_FORMAT_SEL (IO, Address 0x03[7:0]) + * default: 0x00 8-bit SDR ITU-656 mode + * set to : 0x40 24-bit 4:4:4 SDR mode + */ + i2c_reg_write(IO_I2C_ADDR, 0x03, 0x40); + + /* + * IO_REG_05, default 0x2c + * + * AVCODE_INSERT_EN (IO, Address 0x05[2]) + * default: 1 insert AV codes into data stream + * set to : 0 do not insert AV codes into data stream + */ + i2c_reg_write(IO_I2C_ADDR, 0x05, 0x28); + + /* + * IO_REG_0C, default 0x62 + * + * POWER_DOWN (IO, Address 0x0C[5]) + * default: 1 chip is powered down + * set to : 0 chip is operational + */ + i2c_reg_write(IO_I2C_ADDR, 0x0c, 0x42); + + /* + * IO_REG_15, default 0xbe + * + * TRI_SYNCS (IO, Address 0x15[3) + * TRI_LLC (IO, Address 0x15[2]) + * TRI_PIX (IO, Address 0x15[1]) + * default: 1 video output pins are tristate + * set to : 0 video output pins are active + */ + i2c_reg_write(IO_I2C_ADDR, 0x15, 0xb0); + + /* + * HDMI_REGISTER_02H, default 0xff + * + * CLOCK_TERMA_DISABLE (HDMI, Address 0x83[0]) + * default: 1 disable termination + * set to : 0 enable termination + * Future options are: + * - use the chips automatic termination control + * - set this manually on cable detect + * but at the moment this seems a safe default. + */ + i2c_reg_write(HDMI_I2C_ADDR, 0x83, 0xfe); + + /* + * HDMI_CP_CNTRL_1, default 0x01 + * + * HDMI_FRUN_EN (CP, Address 0xBA[0]) + * default: 1 Enable the free run feature in HDMI mode + * set to : 0 Disable the free run feature in HDMI mode + */ + i2c_reg_write(CP_I2C_ADDR, 0xba, 0x00); + + /* + * INT1_CONFIGURATION, default 0x20 + * + * INTRQ_DUR_SEL[1:0] (IO, Address 0x40[7:6]) + * default: 00 Interrupt signal is active for 4 Xtal periods + * set to : 11 Active until cleared + * + * INTRQ_OP_SEL[1:0] (IO, Address 0x40[1:0]) + * default: 00 Open drain + * set to : 10 Drives high when active + */ + i2c_reg_write(IO_I2C_ADDR, 0x40, 0xc2); + +out: + i2c_set_bus_num(old_bus); + + return res; +} diff --git a/board/gdsys/common/adv7611.h b/board/gdsys/common/adv7611.h new file mode 100644 index 0000000..25a8367 --- /dev/null +++ b/board/gdsys/common/adv7611.h @@ -0,0 +1,13 @@ +/* + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ADV7611_H_ +#define _ADV7611_H_ + +int adv7611_probe(unsigned int screen); + +#endif diff --git a/board/gdsys/common/ch7301.c b/board/gdsys/common/ch7301.c new file mode 100644 index 0000000..c054e55 --- /dev/null +++ b/board/gdsys/common/ch7301.c @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Chrontel CH7301C DVI Transmitter */ + +#include <common.h> +#include <asm/io.h> +#include <errno.h> +#include <i2c.h> + +#define CH7301_I2C_ADDR 0x75 + +enum { + CH7301_CM = 0x1c, /* Clock Mode Register */ + CH7301_IC = 0x1d, /* Input Clock Register */ + CH7301_GPIO = 0x1e, /* GPIO Control Register */ + CH7301_IDF = 0x1f, /* Input Data Format Register */ + CH7301_CD = 0x20, /* Connection Detect Register */ + CH7301_DC = 0x21, /* DAC Control Register */ + CH7301_HPD = 0x23, /* Hot Plug Detection Register */ + CH7301_TCTL = 0x31, /* DVI Control Input Register */ + CH7301_TPCP = 0x33, /* DVI PLL Charge Pump Ctrl Register */ + CH7301_TPD = 0x34, /* DVI PLL Divide Register */ + CH7301_TPVT = 0x35, /* DVI PLL Supply Control Register */ + CH7301_TPF = 0x36, /* DVI PLL Filter Register */ + CH7301_TCT = 0x37, /* DVI Clock Test Register */ + CH7301_TSTP = 0x48, /* Test Pattern Register */ + CH7301_PM = 0x49, /* Power Management register */ + CH7301_VID = 0x4a, /* Version ID Register */ + CH7301_DID = 0x4b, /* Device ID Register */ + CH7301_DSP = 0x56, /* DVI Sync polarity Register */ +}; + +int ch7301_i2c[] = CONFIG_SYS_CH7301_I2C; + +int ch7301_probe(unsigned screen, bool power) +{ + u8 value; + + i2c_set_bus_num(ch7301_i2c[screen]); + if (i2c_probe(CH7301_I2C_ADDR)) + return -1; + + value = i2c_reg_read(CH7301_I2C_ADDR, CH7301_DID); + if (value != 0x17) + return -1; + + if (power) { + i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPCP, 0x08); + i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPD, 0x16); + i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPF, 0x60); + i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x09); + i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0xc0); + } else { + i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x00); + i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0x01); + } + + return 0; +} diff --git a/board/gdsys/common/ch7301.h b/board/gdsys/common/ch7301.h new file mode 100644 index 0000000..8383719 --- /dev/null +++ b/board/gdsys/common/ch7301.h @@ -0,0 +1,13 @@ +/* + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CH7301_H_ +#define _CH7301_H_ + +int ch7301_probe(unsigned screen, bool power); + +#endif diff --git a/board/gdsys/common/dp501.c b/board/gdsys/common/dp501.c index 7eb15ed..d35aee0 100644 --- a/board/gdsys/common/dp501.c +++ b/board/gdsys/common/dp501.c @@ -40,11 +40,29 @@ static int dp501_detect_cable_adapter(u8 addr) static void dp501_link_training(u8 addr) { u8 val; + u8 link_bw; + u8 max_lane_cnt; + u8 lane_cnt; val = i2c_reg_read(addr, 0x51); - i2c_reg_write(addr, 0x5d, val); /* set link_bw */ + if (val >= 0x0a) + link_bw = 0x0a; + else + link_bw = 0x06; + if (link_bw != val) + printf("DP sink supports %d Mbps link rate, set to %d Mbps\n", + val * 270, link_bw * 270); + i2c_reg_write(addr, 0x5d, link_bw); /* set link_bw */ val = i2c_reg_read(addr, 0x52); - i2c_reg_write(addr, 0x5e, val); /* set lane_cnt */ + max_lane_cnt = val & 0x1f; + if (max_lane_cnt >= 4) + lane_cnt = 4; + else + lane_cnt = max_lane_cnt; + if (lane_cnt != max_lane_cnt) + printf("DP sink supports %d lanes, set to %d lanes\n", + max_lane_cnt, lane_cnt); + i2c_reg_write(addr, 0x5e, lane_cnt | (val & 0x80)); /* set lane_cnt */ val = i2c_reg_read(addr, 0x53); i2c_reg_write(addr, 0x5c, val); /* set downspread_ctl */ @@ -77,6 +95,8 @@ void dp501_powerup(u8 addr) i2c_reg_write(addr + 2, 0x24, 0x02); /* clock input single ended */ #endif + i2c_reg_write(addr + 2, 0x1a, 0x04); /* SPDIF input method TTL */ + i2c_reg_write(addr + 2, 0x00, 0x18); /* driving strength */ i2c_reg_write(addr + 2, 0x03, 0x06); /* driving strength */ i2c_reg_write(addr, 0x2c, 0x00); /* configure N value */ @@ -86,7 +106,8 @@ void dp501_powerup(u8 addr) dp501_setbits(addr, 0x78, 0x03); /* clear all interrupt */ i2c_reg_write(addr, 0x75, 0xf8); /* aux channel reset */ i2c_reg_write(addr, 0x75, 0x00); /* clear aux channel reset */ - i2c_reg_write(addr, 0x87, 0x70); /* set retry counter as 7 */ + i2c_reg_write(addr, 0x87, 0x7f); /* set retry counter as 7 + retry interval 400us */ if (dp501_detect_cable_adapter(addr)) { printf("DVI/HDMI cable adapter detected\n"); diff --git a/board/gdsys/common/fanctrl.c b/board/gdsys/common/fanctrl.c new file mode 100644 index 0000000..44569bb --- /dev/null +++ b/board/gdsys/common/fanctrl.c @@ -0,0 +1,32 @@ +/* + * (C) Copyright 2015 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <i2c.h> + +enum { + FAN_CONFIG = 0x03, + FAN_TACHLIM_LSB = 0x48, + FAN_TACHLIM_MSB = 0x49, + FAN_PWM_FREQ = 0x4D, +}; + +void init_fan_controller(u8 addr) +{ + int val; + + /* set PWM Frequency to 2.5% resolution */ + i2c_reg_write(addr, FAN_PWM_FREQ, 20); + + /* set Tachometer Limit */ + i2c_reg_write(addr, FAN_TACHLIM_LSB, 0x10); + i2c_reg_write(addr, FAN_TACHLIM_MSB, 0x0a); + + /* enable Tach input */ + val = i2c_reg_read(addr, FAN_CONFIG) | 0x04; + i2c_reg_write(addr, FAN_CONFIG, val); +} diff --git a/board/gdsys/common/fanctrl.h b/board/gdsys/common/fanctrl.h new file mode 100644 index 0000000..12bc850 --- /dev/null +++ b/board/gdsys/common/fanctrl.h @@ -0,0 +1,13 @@ +/* + * (C) Copyright 2015 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FANCTRL_H_ +#define _FANCTRL_H_ + +void init_fan_controller(u8 addr); + +#endif diff --git a/board/gdsys/common/ioep-fpga.c b/board/gdsys/common/ioep-fpga.c new file mode 100644 index 0000000..96f02d6 --- /dev/null +++ b/board/gdsys/common/ioep-fpga.c @@ -0,0 +1,232 @@ +/* + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#include <gdsys_fpga.h> + +enum { + UNITTYPE_MAIN_SERVER = 0, + UNITTYPE_MAIN_USER = 1, + UNITTYPE_VIDEO_SERVER = 2, + UNITTYPE_VIDEO_USER = 3, +}; + +enum { + UNITTYPEPCB_DVI = 0, + UNITTYPEPCB_DP_165 = 1, + UNITTYPEPCB_DP_300 = 2, + UNITTYPEPCB_HDMI = 3, +}; + +enum { + COMPRESSION_NONE = 0, + COMPRESSION_TYPE1_DELTA = 1, + COMPRESSION_TYPE1_TYPE2_DELTA = 3, +}; + +enum { + AUDIO_NONE = 0, + AUDIO_TX = 1, + AUDIO_RX = 2, + AUDIO_RXTX = 3, +}; + +enum { + SYSCLK_147456 = 0, +}; + +enum { + RAM_DDR2_32 = 0, + RAM_DDR3_32 = 1, + RAM_DDR3_48 = 2, +}; + +enum { + CARRIER_SPEED_1G = 0, + CARRIER_SPEED_2_5G = 1, +}; + +bool ioep_fpga_has_osd(unsigned int fpga) +{ + u16 fpga_features; + unsigned feature_osd; + + FPGA_GET_REG(0, fpga_features, &fpga_features); + feature_osd = fpga_features & (1<<11); + + return feature_osd; +} + +void ioep_fpga_print_info(unsigned int fpga) +{ + u16 versions; + u16 fpga_version; + u16 fpga_features; + unsigned unit_type; + unsigned unit_type_pcb_video; + unsigned feature_compression; + unsigned feature_osd; + unsigned feature_audio; + unsigned feature_sysclock; + unsigned feature_ramconfig; + unsigned feature_carrier_speed; + unsigned feature_carriers; + unsigned feature_video_channels; + + FPGA_GET_REG(fpga, versions, &versions); + FPGA_GET_REG(fpga, fpga_version, &fpga_version); + FPGA_GET_REG(fpga, fpga_features, &fpga_features); + + unit_type = (versions & 0xf000) >> 12; + unit_type_pcb_video = (versions & 0x01c0) >> 6; + feature_compression = (fpga_features & 0xe000) >> 13; + feature_osd = fpga_features & (1<<11); + feature_audio = (fpga_features & 0x0600) >> 9; + feature_sysclock = (fpga_features & 0x0180) >> 7; + feature_ramconfig = (fpga_features & 0x0060) >> 5; + feature_carrier_speed = fpga_features & (1<<4); + feature_carriers = (fpga_features & 0x000c) >> 2; + feature_video_channels = fpga_features & 0x0003; + + switch (unit_type) { + case UNITTYPE_MAIN_SERVER: + case UNITTYPE_MAIN_USER: + printf("Mainchannel"); + break; + + case UNITTYPE_VIDEO_SERVER: + case UNITTYPE_VIDEO_USER: + printf("Videochannel"); + break; + + default: + printf("UnitType %d(not supported)", unit_type); + break; + } + + switch (unit_type) { + case UNITTYPE_MAIN_SERVER: + case UNITTYPE_VIDEO_SERVER: + printf(" Server"); + if (versions & (1<<4)) + printf(" UC"); + break; + + case UNITTYPE_MAIN_USER: + case UNITTYPE_VIDEO_USER: + printf(" User"); + break; + + default: + break; + } + + if (versions & (1<<5)) + printf(" Fiber"); + else + printf(" CAT"); + + switch (unit_type_pcb_video) { + case UNITTYPEPCB_DVI: + printf(" DVI,"); + break; + + case UNITTYPEPCB_DP_165: + printf(" DP 165MPix/s,"); + break; + + case UNITTYPEPCB_DP_300: + printf(" DP 300MPix/s,"); + break; + + case UNITTYPEPCB_HDMI: + printf(" HDMI,"); + break; + } + + printf(" FPGA V %d.%02d\n features:", + fpga_version / 100, fpga_version % 100); + + + switch (feature_compression) { + case COMPRESSION_NONE: + printf(" no compression"); + break; + + case COMPRESSION_TYPE1_DELTA: + printf(" type1-deltacompression"); + break; + + case COMPRESSION_TYPE1_TYPE2_DELTA: + printf(" type1-deltacompression, type2-inlinecompression"); + break; + + default: + printf(" compression %d(not supported)", feature_compression); + break; + } + + printf(", %sosd", feature_osd ? "" : "no "); + + switch (feature_audio) { + case AUDIO_NONE: + printf(", no audio"); + break; + + case AUDIO_TX: + printf(", audio tx"); + break; + + case AUDIO_RX: + printf(", audio rx"); + break; + + case AUDIO_RXTX: + printf(", audio rx+tx"); + break; + + default: + printf(", audio %d(not supported)", feature_audio); + break; + } + + puts(",\n "); + + switch (feature_sysclock) { + case SYSCLK_147456: + printf("clock 147.456 MHz"); + break; + + default: + printf("clock %d(not supported)", feature_sysclock); + break; + } + + switch (feature_ramconfig) { + case RAM_DDR2_32: + printf(", RAM 32 bit DDR2"); + break; + + case RAM_DDR3_32: + printf(", RAM 32 bit DDR3"); + break; + + case RAM_DDR3_48: + printf(", RAM 48 bit DDR3"); + break; + + default: + printf(", RAM %d(not supported)", feature_ramconfig); + break; + } + + printf(", %d carrier(s) %s", feature_carriers, + feature_carrier_speed ? "2.5Gbit/s" : "1Gbit/s"); + + printf(", %d video channel(s)\n", feature_video_channels); +} diff --git a/board/gdsys/common/ioep-fpga.h b/board/gdsys/common/ioep-fpga.h new file mode 100644 index 0000000..44f7139 --- /dev/null +++ b/board/gdsys/common/ioep-fpga.h @@ -0,0 +1,14 @@ +/* + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _IOEP_FPGA_H_ +#define _IOEP_FPGA_H_ + +void ioep_fpga_print_info(unsigned int fpga); +bool ioep_fpga_has_osd(unsigned int fpga); + +#endif diff --git a/board/gdsys/common/osd.c b/board/gdsys/common/osd.c index 55ecdf1..7444bee 100644 --- a/board/gdsys/common/osd.c +++ b/board/gdsys/common/osd.c @@ -9,11 +9,10 @@ #include <i2c.h> #include <malloc.h> +#include "ch7301.h" #include "dp501.h" #include <gdsys_fpga.h> -#define CH7301_I2C_ADDR 0x75 - #define ICS8N3QV01_I2C_ADDR 0x6E #define ICS8N3QV01_FREF 114285000 #define ICS8N3QV01_FREF_LL 114285000LL @@ -28,43 +27,53 @@ #define DP501_I2C_ADDR 0x08 #define PIXCLK_640_480_60 25180000 +#define MAX_X_CHARS 53 +#define MAX_Y_CHARS 26 + +#ifdef CONFIG_SYS_OSD_DH +#define MAX_OSD_SCREEN 8 +#define OSD_DH_BASE 4 +#else +#define MAX_OSD_SCREEN 4 +#endif + +#ifdef CONFIG_SYS_OSD_DH +#define OSD_SET_REG(screen, fld, val) \ + do { \ + if (screen >= OSD_DH_BASE) \ + FPGA_SET_REG(screen - OSD_DH_BASE, osd1.fld, val); \ + else \ + FPGA_SET_REG(screen, osd0.fld, val); \ + } while (0) +#else +#define OSD_SET_REG(screen, fld, val) \ + FPGA_SET_REG(screen, osd0.fld, val) +#endif -enum { - CH7301_CM = 0x1c, /* Clock Mode Register */ - CH7301_IC = 0x1d, /* Input Clock Register */ - CH7301_GPIO = 0x1e, /* GPIO Control Register */ - CH7301_IDF = 0x1f, /* Input Data Format Register */ - CH7301_CD = 0x20, /* Connection Detect Register */ - CH7301_DC = 0x21, /* DAC Control Register */ - CH7301_HPD = 0x23, /* Hot Plug Detection Register */ - CH7301_TCTL = 0x31, /* DVI Control Input Register */ - CH7301_TPCP = 0x33, /* DVI PLL Charge Pump Ctrl Register */ - CH7301_TPD = 0x34, /* DVI PLL Divide Register */ - CH7301_TPVT = 0x35, /* DVI PLL Supply Control Register */ - CH7301_TPF = 0x36, /* DVI PLL Filter Register */ - CH7301_TCT = 0x37, /* DVI Clock Test Register */ - CH7301_TSTP = 0x48, /* Test Pattern Register */ - CH7301_PM = 0x49, /* Power Management register */ - CH7301_VID = 0x4a, /* Version ID Register */ - CH7301_DID = 0x4b, /* Device ID Register */ - CH7301_DSP = 0x56, /* DVI Sync polarity Register */ -}; +#ifdef CONFIG_SYS_OSD_DH +#define OSD_GET_REG(screen, fld, val) \ + do { \ + if (screen >= OSD_DH_BASE) \ + FPGA_GET_REG(screen - OSD_DH_BASE, osd1.fld, val); \ + else \ + FPGA_GET_REG(screen, osd0.fld, val); \ + } while (0) +#else +#define OSD_GET_REG(screen, fld, val) \ + FPGA_GET_REG(screen, osd0.fld, val) +#endif unsigned int base_width; unsigned int base_height; size_t bufsize; u16 *buf; -unsigned int max_osd_screen = CONFIG_SYS_OSD_SCREENS - 1; +unsigned int osd_screen_mask = 0; #ifdef CONFIG_SYS_ICS8N3QV01_I2C int ics8n3qv01_i2c[] = CONFIG_SYS_ICS8N3QV01_I2C; #endif -#ifdef CONFIG_SYS_CH7301_I2C -int ch7301_i2c[] = CONFIG_SYS_CH7301_I2C; -#endif - #ifdef CONFIG_SYS_SIL1178_I2C int sil1178_i2c[] = CONFIG_SYS_SIL1178_I2C; #endif @@ -73,6 +82,9 @@ int sil1178_i2c[] = CONFIG_SYS_SIL1178_I2C; int dp501_i2c[] = CONFIG_SYS_DP501_I2C; #endif +#ifdef CONFIG_SYS_DP501_BASE +int dp501_base[] = CONFIG_SYS_DP501_BASE; +#endif #ifdef CONFIG_SYS_MPC92469AC static void mpc92469ac_calc_parameters(unsigned int fout, @@ -242,7 +254,15 @@ static int osd_write_videomem(unsigned screen, unsigned offset, for (k = 0; k < charcount; ++k) { if (offset + k >= bufsize) return -1; - FPGA_SET_REG(screen, videomem[offset + k], data[k]); +#ifdef CONFIG_SYS_OSD_DH + if (screen >= OSD_DH_BASE) + FPGA_SET_REG(screen - OSD_DH_BASE, + videomem1[offset + k], data[k]); + else + FPGA_SET_REG(screen, videomem0[offset + k], data[k]); +#else + FPGA_SET_REG(screen, videomem0[offset + k], data[k]); +#endif } return charcount; @@ -252,7 +272,12 @@ static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned screen; - for (screen = 0; screen <= max_osd_screen; ++screen) { + if (argc < 5) { + cmd_usage(cmdtp); + return 1; + } + + for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) { unsigned x; unsigned y; unsigned charcount; @@ -262,10 +287,8 @@ static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) char *text; int res; - if (argc < 5) { - cmd_usage(cmdtp); - return 1; - } + if (!(osd_screen_mask & (1 << screen))) + continue; x = simple_strtoul(argv[1], NULL, 16); y = simple_strtoul(argv[2], NULL, 16); @@ -280,6 +303,8 @@ static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) res = osd_write_videomem(screen, y * base_width + x, buf, len); if (res < 0) return res; + + OSD_SET_REG(screen, control, 0x0049); } return 0; @@ -292,9 +317,16 @@ int osd_probe(unsigned screen) int old_bus = i2c_get_bus_num(); bool pixclock_present = false; bool output_driver_present = false; +#ifdef CONFIG_SYS_DP501_I2C +#ifdef CONFIG_SYS_DP501_BASE + uint8_t dp501_addr = dp501_base[screen]; +#else + uint8_t dp501_addr = DP501_I2C_ADDR; +#endif +#endif - FPGA_GET_REG(0, osd.version, &version); - FPGA_GET_REG(0, osd.features, &features); + OSD_GET_REG(0, version, &version); + OSD_GET_REG(0, features, &features); base_width = ((features & 0x3f00) >> 8) + 1; base_height = (features & 0x001f) + 1; @@ -303,9 +335,15 @@ int osd_probe(unsigned screen) if (!buf) return -1; +#ifdef CONFIG_SYS_OSD_DH + printf("OSD%d-%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n", + (screen >= OSD_DH_BASE) ? (screen - OSD_DH_BASE) : screen, + (screen > 3) ? 1 : 0, version/100, version%100, base_width, + base_height); +#else printf("OSD%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n", - screen, version/100, version%100, base_width, base_height); - + screen, version/100, version%100, base_width, base_height); +#endif /* setup pixclock */ #ifdef CONFIG_SYS_MPC92469AC @@ -327,19 +365,8 @@ int osd_probe(unsigned screen) /* setup output driver */ #ifdef CONFIG_SYS_CH7301_I2C - i2c_set_bus_num(ch7301_i2c[screen]); - if (!i2c_probe(CH7301_I2C_ADDR)) { - u8 value = i2c_reg_read(CH7301_I2C_ADDR, CH7301_DID); - - if (value == 0x17) { - i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPCP, 0x08); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPD, 0x16); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPF, 0x60); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x09); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0xc0); - output_driver_present = true; - } - } + if (!ch7301_probe(screen, true)) + output_driver_present = true; #endif #ifdef CONFIG_SYS_SIL1178_I2C @@ -367,8 +394,8 @@ int osd_probe(unsigned screen) #ifdef CONFIG_SYS_DP501_I2C i2c_set_bus_num(dp501_i2c[screen]); - if (!i2c_probe(DP501_I2C_ADDR)) { - dp501_powerup(DP501_I2C_ADDR); + if (!i2c_probe(dp501_addr)) { + dp501_powerup(dp501_addr); output_driver_present = true; } #endif @@ -376,14 +403,12 @@ int osd_probe(unsigned screen) if (!output_driver_present) printf(" no output driver found\n"); - FPGA_SET_REG(screen, osd.control, 0x0049); - - FPGA_SET_REG(screen, osd.xy_size, ((32 - 1) << 8) | (16 - 1)); - FPGA_SET_REG(screen, osd.x_pos, 0x007f); - FPGA_SET_REG(screen, osd.y_pos, 0x005f); + OSD_SET_REG(screen, xy_size, ((32 - 1) << 8) | (16 - 1)); + OSD_SET_REG(screen, x_pos, 0x007f); + OSD_SET_REG(screen, y_pos, 0x005f); - if (screen > max_osd_screen) - max_osd_screen = screen; + if (pixclock_present && output_driver_present) + osd_screen_mask |= 1 << screen; i2c_set_bus_num(old_bus); @@ -394,7 +419,12 @@ int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned screen; - for (screen = 0; screen <= max_osd_screen; ++screen) { + if ((argc < 4) || (strlen(argv[3]) % 4)) { + cmd_usage(cmdtp); + return 1; + } + + for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) { unsigned x; unsigned y; unsigned k; @@ -404,10 +434,8 @@ int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned count = (argc > 4) ? simple_strtoul(argv[4], NULL, 16) : 1; - if ((argc < 4) || (strlen(argv[3]) % 4)) { - cmd_usage(cmdtp); - return 1; - } + if (!(osd_screen_mask & (1 << screen))) + continue; x = simple_strtoul(argv[1], NULL, 16); y = simple_strtoul(argv[2], NULL, 16); @@ -433,6 +461,37 @@ int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) osd_write_videomem(screen, offset, buffer, wp - buffer); } + + OSD_SET_REG(screen, control, 0x0049); + } + + return 0; +} + +int osd_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned screen; + unsigned x; + unsigned y; + + if (argc < 3) { + cmd_usage(cmdtp); + return 1; + } + + x = simple_strtoul(argv[1], NULL, 16); + y = simple_strtoul(argv[2], NULL, 16); + + if (!x || (x > 64) || (x > MAX_X_CHARS) || + !y || (y > 32) || (y > MAX_Y_CHARS)) { + cmd_usage(cmdtp); + return 1; + } + + for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) { + OSD_SET_REG(screen, xy_size, ((x - 1) << 8) | (y - 1)); + OSD_SET_REG(screen, x_pos, 32767 * (640 - 12 * x) / 65535); + OSD_SET_REG(screen, y_pos, 32767 * (480 - 18 * y) / 65535); } return 0; @@ -449,3 +508,10 @@ U_BOOT_CMD( "write ASCII buffer to osd memory", "pos_x pos_y color text\n" ); + +U_BOOT_CMD( + osdsize, 3, 0, osd_size, + "set OSD XY size in characters", + "size_x(max. " __stringify(MAX_X_CHARS) + ") size_y(max. " __stringify(MAX_Y_CHARS) ")\n" +); diff --git a/board/gdsys/common/osd.h b/board/gdsys/common/osd.h index 440b276..5b3f14b 100644 --- a/board/gdsys/common/osd.h +++ b/board/gdsys/common/osd.h @@ -8,6 +8,7 @@ #ifndef _OSD_H_ #define _OSD_H_ +int ch7301_probe(unsigned screen, bool power); int osd_probe(unsigned screen); #endif |