|  | /* | 
|  | * (C) Copyright 2000 | 
|  | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it | 
|  | * (C) Copyright 2002 | 
|  | * Wolfgang Denk, wd@denx.de | 
|  | * (C) Copyright 2006 | 
|  | * Aubrey Li, aubrey.li@analog.com | 
|  | * | 
|  | * 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 <stdarg.h> | 
|  | #include <common.h> | 
|  | #include <config.h> | 
|  | #include <asm/blackfin.h> | 
|  | #include <i2c.h> | 
|  | #include <linux/types.h> | 
|  | #include <devices.h> | 
|  |  | 
|  | #ifdef CONFIG_VIDEO | 
|  | #define NTSC_FRAME_ADDR 0x06000000 | 
|  | #include "video.h" | 
|  |  | 
|  | /* NTSC OUTPUT SIZE  720 * 240 */ | 
|  | #define VERTICAL	2 | 
|  | #define HORIZONTAL	4 | 
|  |  | 
|  | int is_vblank_line(const int line) | 
|  | { | 
|  | /* | 
|  | *  This array contains a single bit for each line in | 
|  | *  an NTSC frame. | 
|  | */ | 
|  | if ((line <= 18) || (line >= 264 && line <= 281) || (line == 528)) | 
|  | return true; | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | int NTSC_framebuffer_init(char *base_address) | 
|  | { | 
|  | const int NTSC_frames = 1; | 
|  | const int NTSC_lines = 525; | 
|  | char *dest = base_address; | 
|  | int frame_num, line_num; | 
|  |  | 
|  | for (frame_num = 0; frame_num < NTSC_frames; ++frame_num) { | 
|  | for (line_num = 1; line_num <= NTSC_lines; ++line_num) { | 
|  | unsigned int code; | 
|  | int offset = 0; | 
|  | int i; | 
|  |  | 
|  | if (is_vblank_line(line_num)) | 
|  | offset++; | 
|  |  | 
|  | if (line_num > 266 || line_num < 3) | 
|  | offset += 2; | 
|  |  | 
|  | /* Output EAV code */ | 
|  | code = SystemCodeMap[offset].EAV; | 
|  | write_dest_byte((char)(code >> 24) & 0xff); | 
|  | write_dest_byte((char)(code >> 16) & 0xff); | 
|  | write_dest_byte((char)(code >> 8) & 0xff); | 
|  | write_dest_byte((char)(code) & 0xff); | 
|  |  | 
|  | /* Output horizontal blanking */ | 
|  | for (i = 0; i < 67 * 2; ++i) { | 
|  | write_dest_byte(0x80); | 
|  | write_dest_byte(0x10); | 
|  | } | 
|  |  | 
|  | /* Output SAV */ | 
|  | code = SystemCodeMap[offset].SAV; | 
|  | write_dest_byte((char)(code >> 24) & 0xff); | 
|  | write_dest_byte((char)(code >> 16) & 0xff); | 
|  | write_dest_byte((char)(code >> 8) & 0xff); | 
|  | write_dest_byte((char)(code) & 0xff); | 
|  |  | 
|  | /* Output empty horizontal data */ | 
|  | for (i = 0; i < 360 * 2; ++i) { | 
|  | write_dest_byte(0x80); | 
|  | write_dest_byte(0x10); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return dest - base_address; | 
|  | } | 
|  |  | 
|  | void fill_frame(char *Frame, int Value) | 
|  | { | 
|  | int *OddPtr32; | 
|  | int OddLine; | 
|  | int *EvenPtr32; | 
|  | int EvenLine; | 
|  | int i; | 
|  | int *data; | 
|  | int m, n; | 
|  |  | 
|  | /* fill odd and even frames */ | 
|  | for (OddLine = 22, EvenLine = 285; OddLine < 263; OddLine++, EvenLine++) { | 
|  | OddPtr32 = (int *)((Frame + (OddLine * 1716)) + 276); | 
|  | EvenPtr32 = (int *)((Frame + (EvenLine * 1716)) + 276); | 
|  | for (i = 0; i < 360; i++, OddPtr32++, EvenPtr32++) { | 
|  | *OddPtr32 = Value; | 
|  | *EvenPtr32 = Value; | 
|  | } | 
|  | } | 
|  |  | 
|  | for (m = 0; m < VERTICAL; m++) { | 
|  | data = (int *)u_boot_logo.data; | 
|  | for (OddLine = (22 + m), EvenLine = (285 + m); | 
|  | OddLine < (u_boot_logo.height * VERTICAL) + (22 + m); | 
|  | OddLine += VERTICAL, EvenLine += VERTICAL) { | 
|  | OddPtr32 = (int *)((Frame + ((OddLine) * 1716)) + 276); | 
|  | EvenPtr32 = | 
|  | (int *)((Frame + ((EvenLine) * 1716)) + 276); | 
|  | for (i = 0; i < u_boot_logo.width / 2; i++) { | 
|  | /* enlarge one pixel to m x n */ | 
|  | for (n = 0; n < HORIZONTAL; n++) { | 
|  | *OddPtr32++ = *data; | 
|  | *EvenPtr32++ = *data; | 
|  | } | 
|  | data++; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void video_putc(const char c) | 
|  | { | 
|  | } | 
|  |  | 
|  | void video_puts(const char *s) | 
|  | { | 
|  | } | 
|  |  | 
|  | static int video_init(void) | 
|  | { | 
|  | char *NTSCFrame; | 
|  | NTSCFrame = (char *)NTSC_FRAME_ADDR; | 
|  | NTSC_framebuffer_init(NTSCFrame); | 
|  | fill_frame(NTSCFrame, BLUE); | 
|  |  | 
|  | *pPPI_CONTROL = 0x0082; | 
|  | *pPPI_FRAME = 0x020D; | 
|  |  | 
|  | *pDMA0_START_ADDR = NTSCFrame; | 
|  | *pDMA0_X_COUNT = 0x035A; | 
|  | *pDMA0_X_MODIFY = 0x0002; | 
|  | *pDMA0_Y_COUNT = 0x020D; | 
|  | *pDMA0_Y_MODIFY = 0x0002; | 
|  | *pDMA0_CONFIG = 0x1015; | 
|  | *pPPI_CONTROL = 0x0083; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int drv_video_init(void) | 
|  | { | 
|  | int error, devices = 1; | 
|  |  | 
|  | device_t videodev; | 
|  |  | 
|  | video_init();		/* Video initialization */ | 
|  |  | 
|  | memset(&videodev, 0, sizeof(videodev)); | 
|  |  | 
|  | strcpy(videodev.name, "video"); | 
|  | videodev.ext = DEV_EXT_VIDEO;	/* Video extensions */ | 
|  | videodev.flags = DEV_FLAGS_OUTPUT;	/* Output only */ | 
|  | videodev.putc = video_putc;	/* 'putc' function */ | 
|  | videodev.puts = video_puts;	/* 'puts' function */ | 
|  |  | 
|  | error = device_register(&videodev); | 
|  |  | 
|  | return (error == 0) ? devices : error; | 
|  | } | 
|  | #endif |