diff options
| author | Wolfgang Denk <wd@denx.de> | 2010-11-12 22:24:06 +0100 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2010-11-12 22:24:06 +0100 | 
| commit | d963e84c92a63b4e6c4f2f80482a5ecbe9b24fe0 (patch) | |
| tree | 07dd5889d73f4b66ad608815adcf6f2f953d9501 /board/gdsys/common/osd.c | |
| parent | 66fca016057b1c6b697552cc7220ebada9d4f82d (diff) | |
| parent | 0c0892be0d93a5a892b93739c5eb3bf692fed4ff (diff) | |
| download | olio-uboot-2014.01-d963e84c92a63b4e6c4f2f80482a5ecbe9b24fe0.tar.xz olio-uboot-2014.01-d963e84c92a63b4e6c4f2f80482a5ecbe9b24fe0.zip | |
Merge branch 'master' of /home/wd/git/u-boot/master
Diffstat (limited to 'board/gdsys/common/osd.c')
| -rw-r--r-- | board/gdsys/common/osd.c | 247 | 
1 files changed, 247 insertions, 0 deletions
| diff --git a/board/gdsys/common/osd.c b/board/gdsys/common/osd.c new file mode 100644 index 000000000..05800ffba --- /dev/null +++ b/board/gdsys/common/osd.c @@ -0,0 +1,247 @@ +/* + * (C) Copyright 2010 + * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <i2c.h> +#include <asm/io.h> + +#include "fpga.h" + +#define CH7301_I2C_ADDR 0x75 + +#define PIXCLK_640_480_60 25180000 + +#define BASE_WIDTH 32 +#define BASE_HEIGHT 16 +#define BUFSIZE (BASE_WIDTH * BASE_HEIGHT) + +enum { +	REG_CONTROL = 0x0010, +	REG_MPC3W_CONTROL = 0x001a, +	REG_VIDEOCONTROL = 0x0042, +	REG_OSDVERSION = 0x0100, +	REG_OSDFEATURES = 0x0102, +	REG_OSDCONTROL = 0x0104, +	REG_XY_SIZE = 0x0106, +	REG_VIDEOMEM = 0x0800, +}; + +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 */ +}; + +static void mpc92469ac_calc_parameters(unsigned int fout, +	unsigned int *post_div, unsigned int *feedback_div) +{ +	unsigned int n = *post_div; +	unsigned int m = *feedback_div; +	unsigned int a; +	unsigned int b = 14745600 / 16; + +	if (fout < 50169600) +		n = 8; +	else if (fout < 100339199) +		n = 4; +	else if (fout < 200678399) +		n = 2; +	else +		n = 1; + +	a = fout * n + (b / 2); /* add b/2 for proper rounding */ + +	m = a / b; + +	*post_div = n; +	*feedback_div = m; +} + +static void mpc92469ac_set(unsigned int fout) +{ +	unsigned int n; +	unsigned int m; +	unsigned int bitval = 0; +	mpc92469ac_calc_parameters(fout, &n, &m); + +	switch (n) { +	case 1: +		bitval = 0x00; +		break; +	case 2: +		bitval = 0x01; +		break; +	case 4: +		bitval = 0x02; +		break; +	case 8: +		bitval = 0x03; +		break; +	} + +	fpga_set_reg(REG_MPC3W_CONTROL, (bitval << 9) | m); +} + +static int osd_write_videomem(unsigned offset, u16 *data, size_t charcount) +{ +	unsigned int k; + +	for (k = 0; k < charcount; ++k) { +		if (offset + k >= BUFSIZE) +			return -1; +		fpga_set_reg(REG_VIDEOMEM + 2 * (offset + k), data[k]); +	} + +	return charcount; +} + +static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +	unsigned x; +	unsigned y; +	unsigned charcount; +	unsigned len; +	u8 color; +	unsigned int k; +	u16 buf[BUFSIZE]; +	char *text; + +	if (argc < 5) { +		cmd_usage(cmdtp); +		return 1; +	} + +	x = simple_strtoul(argv[1], NULL, 16); +	y = simple_strtoul(argv[2], NULL, 16); +	color = simple_strtoul(argv[3], NULL, 16); +	text = argv[4]; +	charcount = strlen(text); +	len = (charcount > BUFSIZE) ? BUFSIZE : charcount; + +	for (k = 0; k < len; ++k) +		buf[k] = (text[k] << 8) | color; + +	return osd_write_videomem(y * BASE_WIDTH + x, buf, len); +} + +int osd_probe(void) +{ +	u8 value; +	u16 version = fpga_get_reg(REG_OSDVERSION); +	u16 features = fpga_get_reg(REG_OSDFEATURES); +	unsigned width; +	unsigned height; + +	width = ((features & 0x3f00) >> 8) + 1; +	height = (features & 0x001f) + 1; + +	printf("OSD:   Digital-OSD version %01d.%02d, %d" "x%d characters\n", +		version/100, version%100, width, height); + +	value = i2c_reg_read(CH7301_I2C_ADDR, CH7301_DID); +	if (value != 0x17) { +		printf("       Probing CH7301 failed, DID %02x\n", value); +		return -1; +	} +	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); + +	mpc92469ac_set(PIXCLK_640_480_60); +	fpga_set_reg(REG_VIDEOCONTROL, 0x0002); +	fpga_set_reg(REG_OSDCONTROL, 0x0049); + +	fpga_set_reg(REG_XY_SIZE, ((32 - 1) << 8) | (16 - 1)); + +	return 0; +} + +int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +	unsigned x; +	unsigned y; +	unsigned k; +	u16 buffer[BASE_WIDTH]; +	char *rp; +	u16 *wp = buffer; +	unsigned count = (argc > 4) ?  simple_strtoul(argv[4], NULL, 16) : 1; + +	if ((argc < 4) || (strlen(argv[3]) % 4)) { +		cmd_usage(cmdtp); +		return 1; +	} + +	x = simple_strtoul(argv[1], NULL, 16); +	y = simple_strtoul(argv[2], NULL, 16); +	rp = argv[3]; + + +	while (*rp) { +		char substr[5]; + +		memcpy(substr, rp, 4); +		substr[4] = 0; +		*wp = simple_strtoul(substr, NULL, 16); + +		rp += 4; +		wp++; +		if (wp - buffer > BASE_WIDTH) +			break; +	} + +	for (k = 0; k < count; ++k) { +		unsigned offset = y * BASE_WIDTH + x + k * (wp - buffer); +		osd_write_videomem(offset, buffer, wp - buffer); +	} + +	return 0; +} + +U_BOOT_CMD( +	osdw, 5, 0, osd_write, +	"write 16-bit hex encoded buffer to osd memory", +	"pos_x pos_y buffer count\n" +); + +U_BOOT_CMD( +	osdp, 5, 0, osd_print, +	"write ASCII buffer to osd memory", +	"pos_x pos_y color text\n" +); |