Add ram console

This commit is contained in:
Markinus 2010-08-27 19:11:34 +02:00
parent 8a9cef7eb0
commit 45c4a05fb6
7 changed files with 467 additions and 3 deletions

View File

@ -254,7 +254,7 @@ CONFIG_MSM_QDSP6=y
CONFIG_WIFI_CONTROL_FUNC=y
# CONFIG_WIFI_MEM_PREALLOC is not set
# CONFIG_VIRTUAL_KPANIC_PARTITION is not set
# CONFIG_HTC_FB_CONSOLE is not set
CONFIG_HTC_FB_CONSOLE=y
CONFIG_VERY_EARLY_CONSOLE=y
CONFIG_HTCLEO_ENABLE_MULTI_TOUCH=y
CONFIG_ENABLE_BRAVO_UART_DRV=y
@ -1459,7 +1459,7 @@ CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT=y
CONFIG_ANDROID_RAM_CONSOLE_EARLY_ADDR=0xF9100000
CONFIG_ANDROID_RAM_CONSOLE_EARLY_ADDR=0x2FFC0000
CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE=0x00040000
CONFIG_ANDROID_TIMED_OUTPUT=y
CONFIG_ANDROID_TIMED_GPIO=y

View File

@ -1048,3 +1048,27 @@ config PHYS_OFFSET
hex
depends on MACH_HTCLEO
default "0x11800000" if MACH_HTCLEO
config HTC_FB_CONSOLE
bool "Boot console for HTC phones (needs a font which has width <= 8)"
default n
config HTC_FB_CONSOLE_DELAY
bool "Wait some time after each message is printed"
default n
depends on HTC_FB_CONSOLE
config HTC_FB_CONSOLE_BOOT
bool "Use console only during boot"
default n
depends on HTC_FB_CONSOLE
config VERY_EARLY_CONSOLE
bool "Support for very early consoles"
default n
help
Add support to initialize consoles very early. For this to have
effect, the driver must support this and the consoles should
be initialized in the board file as soon as possible.

View File

@ -97,7 +97,7 @@ obj-$(CONFIG_MACH_BRAVOC) += board-bravoc-rfkill.o board-bravoc-audio.o
obj-$(CONFIG_MACH_BRAVOC) += board-bravoc-wifi.o htc_awb_cal.o
obj-$(CONFIG_MACH_BRAVOC) += board-bravoc-microp.o
obj-$(CONFIG_MACH_HTCLEO) += board-htcleo.o
obj-$(CONFIG_MACH_HTCLEO) += board-htcleo.o
# MSM7x30 boards
obj-$(CONFIG_ARCH_MSM7X30) += panel-samsungwvga-tl2796a.o panel-samsungwvga-s6e63m0.o panel-sonywvga-s6d16a0x21-7x30.o
@ -219,3 +219,7 @@ obj-$(CONFIG_HTC_HEADSET_PMIC) += htc_headset_pmic.o
obj-$(CONFIG_MACH_MAHIMAHI) += board-mahimahi-tpa2018d1.o
obj-$(CONFIG_MACH_MAHIMAHI) += board-mahimahi-smb329.o
obj-$(CONFIG_MSM_SSBI) += ssbi.o
obj-$(CONFIG_HTC_FB_CONSOLE) += htc_fb_console.o

View File

@ -133,10 +133,30 @@ static void __init htcleo_fixup(struct machine_desc *desc, struct tag *tags,
mi->bank[0].size = MSM_EBI1_BANK0_SIZE;
}
#if defined(CONFIG_VERY_EARLY_CONSOLE)
#if defined(CONFIG_HTC_FB_CONSOLE)
int __init htc_fb_console_init(void);
#endif
#if defined(CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT)
int __init ram_console_early_init(void);
#endif
#endif
static void __init htcleo_map_io(void)
{
msm_map_common_io();
msm_clock_init();
#if defined(CONFIG_VERY_EARLY_CONSOLE)
// Init our consoles _really_ early
#if defined(CONFIG_HTC_FB_CONSOLE)
htc_fb_console_init();
#endif
#if defined(CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT)
ram_console_early_init();
#endif
#endif
}
extern struct sys_timer msm_timer;

View File

@ -0,0 +1,386 @@
/* arch/arm/mach-msm/htc_fb_console.c
*
* By Octavian Voicu <octavian@voicu.gmail.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
*/
/*
* Ugly hack to get some basic console working for HTC Diamond but should
* also work for Raphael and other similar phones. Will register itself
* as an early console to show boot messages. This won't work unless
* the LCD is already powered up and functional (from wince, boot
* using Haret). We just DMA pixels to the LCD, all configuration
* must already be done.
*
* Not exactly very clean nor optimized, but it's a one night hack
* and it works :)
*
* If anyone makes any progress on HTC Diamond drop me a line
* (see email at the top), I do wanna see Android on my HTC Diamond!
*
*/
#include <linux/console.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/font.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <mach/msm_iomap.h>
#include <mach/msm_fb.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
#include "../../../drivers/video/msm/mdp_hw.h"
/* Defined in /arch/arm/mm/mmu.c, helps us map physical memory to virtual memory.
* It should work pretty early in the boot process, that why we use it */
extern void create_mapping(struct map_desc *md);
/* Defined in include/linux/fb.h. When, on write, a registered framebuffer device is detected,
* we immediately unregister ourselves. */
#ifndef CONFIG_HTC_FB_CONSOLE_BOOT
extern int num_registered_fb;
#endif
/* Green message (color = 2), the reset color to white (color = 6) */
#define HTC_FB_MSG ("\n\n" "\x1b" "2" "HTC Linux framebuffer console by druidu" "\x1b" "7" "\n\n")
/* LCD resolution, can differ per device (below is based on HTCLEO) */
#define HTC_FB_LCD_WIDTH 480
#define HTC_FB_LCD_HEIGHT 800
/* Set max console size for a 4x4 font */
#define HTC_FB_CON_MAX_ROWS (HTC_FB_LCD_WIDTH / 4)
#define HTC_FB_CON_MAX_COLS (HTC_FB_LCD_HEIGHT / 4)
/* Device dependent settings, currently configured for HTCLEO */
#define HTC_FB_BASE 0xe2000000 /* virtual page for our fb */
#define HTC_FB_PHYS 0x03800000
#define HTC_FB_OFF 0x00039000
#define HTC_FB_SIZE 0x00400000
#define HTC_MDP_BASE 0xe3000000
#define HTC_MDP_PHYS 0xAA200000
#define HTC_MDP_SIZE 0x000F0000
/* Pack color data in 565 RGB format; r and b are 5 bits, g is 6 bits */
#define HTC_FB_RGB(r, g, b) ((((r) & 0x1f) << 11) | (((g) & 0x3f) << 5) | (((b) & 0x1f) << 0))
/* Some standard colors */
unsigned short htc_fb_colors[8] = {
HTC_FB_RGB(0x00, 0x00, 0x00), /* Black */
HTC_FB_RGB(0x1f, 0x00, 0x00), /* Red */
HTC_FB_RGB(0x00, 0x15, 0x00), /* Green */
HTC_FB_RGB(0x0f, 0x15, 0x00), /* Brown */
HTC_FB_RGB(0x00, 0x00, 0x1f), /* Blue */
HTC_FB_RGB(0x1f, 0x00, 0x1f), /* Magenta */
HTC_FB_RGB(0x00, 0x3f, 0x1f), /* Cyan */
HTC_FB_RGB(0x1f, 0x3f, 0x1f) /* White */
};
/* We can use any font which has width <= 8 pixels */
const struct font_desc *htc_fb_default_font;
/* Pointer to font data (255 * font_rows bytes of data) */
const unsigned char *htc_fb_font_data;
/* Size of font in pixels */
unsigned int htc_fb_font_cols, htc_fb_font_rows;
/* Size of console in chars */
unsigned int htc_fb_console_cols, htc_fb_console_rows;
/* Current position of cursor (where next character will be written) */
unsigned int htc_fb_cur_x, htc_fb_cur_y;
/* Current fg / bg colors */
unsigned char htc_fb_cur_fg, htc_fb_cur_bg;
/* Buffer to hold characters and attributes */
unsigned char htc_fb_chars[HTC_FB_CON_MAX_ROWS][HTC_FB_CON_MAX_COLS];
unsigned char htc_fb_fg[HTC_FB_CON_MAX_ROWS][HTC_FB_CON_MAX_COLS];
unsigned char htc_fb_bg[HTC_FB_CON_MAX_ROWS][HTC_FB_CON_MAX_COLS];
static void htc_fb_console_write(struct console *console, const char *s, unsigned int count);
/* Console data */
static struct console htc_fb_console = {
.name = "htc_fb",
.write = htc_fb_console_write,
.flags =
#ifdef CONFIG_HTC_FB_CONSOLE_BOOT
CON_BOOT |
#endif
CON_PRINTBUFFER | CON_ENABLED,
.index = -1,
};
// Redefine these defines so that we can easily borrow the code, first parameter is ignored
#undef mdp_writel
#define mdp_writel(mdp, value, offset) writel(value, HTC_MDP_BASE + offset)
#undef mdp_readl
#define mdp_readl(mdp, offset) readl(HTC_MDP_BASE + offset)
/* Update the framebuffer from the character buffer then start DMA */
static void htc_fb_console_update(void)
{
unsigned int memaddr, fbram, stride, width, height, x, y, i, j, r1, c1, r2, c2;
#if 0
unsigned int dma2_cfg;
#endif
unsigned short ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
unsigned short *ptr;
unsigned char ch;
fbram = HTC_FB_PHYS + HTC_FB_OFF;
memaddr = HTC_FB_BASE + HTC_FB_OFF;
ptr = (unsigned short*) memaddr;
for (i = 0; i < htc_fb_console_rows * htc_fb_font_rows; i++) {
r1 = i / htc_fb_font_rows;
r2 = i % htc_fb_font_rows;
for (j = 0; j < htc_fb_console_cols * htc_fb_font_cols; j++) {
c1 = j / htc_fb_font_cols;
c2 = j % htc_fb_font_cols;
ch = htc_fb_chars[r1][c1];
*ptr++ = htc_fb_font_data[(((int) ch) * htc_fb_font_rows) + r2] & ((1 << (htc_fb_font_cols - 1)) >> c2)
? htc_fb_colors[htc_fb_fg[r1][c1]]
: htc_fb_colors[htc_fb_bg[r1][c1]];
}
ptr += HTC_FB_LCD_WIDTH - htc_fb_console_cols * htc_fb_font_cols;
}
stride = HTC_FB_LCD_WIDTH * 2;
width = HTC_FB_LCD_WIDTH;
height = HTC_FB_LCD_HEIGHT;
x = 0;
y = 0;
/* In previous versions of htc_fb_console we configured the dma_config.
However, the settings for HTCLEO are still unknown. Currently leaving
the dma unconfigured, which means we just assume bootloader or
Windows Mobile has configured it correctly for us. */
#if 0
dma2_cfg = DMA_PACK_TIGHT |
DMA_PACK_ALIGN_LSB |
DMA_PACK_PATTERN_RGB |
DMA_OUT_SEL_AHB |
DMA_IBUF_NONCONTIGUOUS;
dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
dma2_cfg |= DMA_OUT_SEL_MDDI;
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
dma2_cfg |= DMA_DITHER_EN;
/* 565 16BPP */
dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
/* 666 18BPP */
//dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
#endif
/* setup size, address, and stride */
mdp_writel(NULL, (height << 16) | (width), MDP_DMA_P_SIZE);
mdp_writel(NULL, fbram, MDP_DMA_P_IBUF_ADDR);
mdp_writel(NULL, stride, MDP_DMA_P_IBUF_Y_STRIDE);
/* set y & x offset and MDDI transaction parameters */
mdp_writel(NULL, (y << 16) | (x), MDP_DMA_P_OUT_XY);
mdp_writel(NULL, ld_param, MDP_MDDI_PARAM_WR_SEL);
mdp_writel(NULL, (MDDI_VDO_PACKET_DESC_RGB565 << 16) | MDDI_VDO_PACKET_PRIM,
MDP_MDDI_PARAM);
#if 0
//mdp_writel(NULL, dma2_cfg, MDP_DMA_P_CONFIG);
#endif
mdp_writel(NULL, 0, MDP_DMA_P_START);
/* Wait a bit to let the transfer finish */
mdelay(16);
}
/* Clear screen and buffers */
static void htc_fb_console_clear(void)
{
/* Default white on black, clear everything */
memset((void*) (HTC_FB_BASE + HTC_FB_OFF), 0, HTC_FB_LCD_WIDTH * HTC_FB_LCD_HEIGHT * 2);
memset(htc_fb_chars, 0, htc_fb_console_cols * htc_fb_console_rows);
memset(htc_fb_fg, 7, htc_fb_console_cols * htc_fb_console_rows);
memset(htc_fb_bg, 0, htc_fb_console_cols * htc_fb_console_rows);
htc_fb_cur_x = htc_fb_cur_y = 0;
htc_fb_cur_fg = 7;
htc_fb_cur_bg = 0;
htc_fb_console_update();
}
static struct console htc_fb_console;
/* Write a string to character buffer; handles word wrapping, auto-scrolling, etc
* After that, calls htc_fb_console_update to send data to the LCD */
static void htc_fb_console_write(struct console *console, const char *s, unsigned int count)
{
unsigned int i, j, k, scroll;
const char *p;
#ifndef CONFIG_HTC_FB_CONSOLE_BOOT
// See if a framebuffer has been registered. If so, we disable this console to prevent conflict with
// other FB devices (i.e. msm_fb).
if (num_registered_fb > 0) {
printk(KERN_INFO "htc_fb_console: framebuffer device detected, disabling boot console\n");
console->flags = 0;
return;
}
#endif
scroll = 0;
for (k = 0, p = s; k < count; k++, p++) {
if (*p == '\n') {
/* Jump to next line */
scroll = 1;
} else if (*p == '\t') {
/* Tab size 8 chars */
htc_fb_cur_x = (htc_fb_cur_x + 7) % 8;
if (htc_fb_cur_x >= htc_fb_console_cols) {
scroll = 1;
}
} else if (*p == '\x1b') {
/* Escape char (ascii 27)
* Some primitive way to change color:
* \x1b followed by one digit to represent color (0 black ... 7 white) */
if (k < count - 1) {
p++;
htc_fb_cur_fg = *p - '0';
if (htc_fb_cur_fg >= 8) {
htc_fb_cur_fg = 7;
}
}
} else if (*p != '\r') {
/* Ignore \r, other cars get written here */
htc_fb_chars[htc_fb_cur_y][htc_fb_cur_x] = *p;
htc_fb_fg[htc_fb_cur_y][htc_fb_cur_x] = htc_fb_cur_fg;
htc_fb_bg[htc_fb_cur_y][htc_fb_cur_x] = htc_fb_cur_bg;
htc_fb_cur_x++;
if (htc_fb_cur_x >= htc_fb_console_cols) {
scroll = 1;
}
}
if (scroll) {
scroll = 0;
htc_fb_cur_x = 0;
htc_fb_cur_y++;
if (htc_fb_cur_y == htc_fb_console_rows) {
/* Scroll below last line, shift all rows up
* Should have used a bigger buffer so no shift,
* would actually be needed -- but hey, it's a one night hack */
htc_fb_cur_y--;
for (i = 1; i < htc_fb_console_rows; i++) {
for (j = 0; j < htc_fb_console_cols; j++) {
htc_fb_chars[i - 1][j] = htc_fb_chars[i][j];
htc_fb_fg[i - 1][j] = htc_fb_fg[i][j];
htc_fb_bg[i - 1][j] = htc_fb_bg[i][j];
}
}
for (j = 0; j < htc_fb_console_cols; j++) {
htc_fb_chars[htc_fb_console_rows - 1][j] = 0;
htc_fb_fg[htc_fb_console_rows - 1][j] = htc_fb_cur_fg;
htc_fb_bg[htc_fb_console_rows - 1][j] = htc_fb_cur_bg;
}
}
}
}
htc_fb_console_update();
#ifdef CONFIG_HTC_FB_CONSOLE_DELAY
/* Delay so we can see what's there, we have no keys to scroll */
mdelay(500);
#endif
}
#if defined(CONFIG_VERY_EARLY_CONSOLE)
// Make sure we don't init twice
static bool htc_fb_console_init_done = false;
#endif
/* Init console on LCD using MDDI/MDP interface to transfer pixel data.
* We can DMA to the board, as long as we give a physical address to the LCD
* controller and use the coresponding virtual address to write pixels to.
* The physical address I used is the one wince had for the framebuffer */
#if !defined(CONFIG_VERY_EARLY_CONSOLE)
static
#endif
int __init htc_fb_console_init(void)
{
struct map_desc map, map_mdp;
#if defined(CONFIG_VERY_EARLY_CONSOLE)
if (htc_fb_console_init_done)
{
printk(KERN_INFO "htc_fb_console_init: already initialized, bailing out\n");
return 0;
}
htc_fb_console_init_done = true;
#endif
/* Map the framebuffer Windows was using, as we know the physical address */
map.pfn = __phys_to_pfn(HTC_FB_PHYS & SECTION_MASK);
map.virtual = HTC_FB_BASE;
map.length = ((unsigned long) HTC_FB_SIZE + ~SECTION_MASK) & SECTION_MASK;
map.type = MT_MEMORY;
/* Ugly hack, but we're not sure what works and what doesn't,
* so better use the lowest level we have for setting the mapping */
create_mapping(&map);
/* Map the MDP */
map_mdp.pfn = __phys_to_pfn(HTC_MDP_PHYS & SECTION_MASK);
map_mdp.virtual = HTC_MDP_BASE;
map_mdp.length = ((unsigned long) HTC_MDP_SIZE + ~SECTION_MASK) & SECTION_MASK;
map_mdp.type = MT_MEMORY;
create_mapping(&map_mdp);
/* Init font (we support any font that has width <= 8; height doesn't matter) */
htc_fb_default_font = get_default_font(HTC_FB_LCD_WIDTH, HTC_FB_LCD_HEIGHT, 0xFF, 0xFFFFFFFF);
if (!htc_fb_default_font) {
printk(KERN_WARNING "Can't find a suitable font for htc_fb\n");
return -1;
}
htc_fb_font_data = htc_fb_default_font->data;
htc_fb_font_cols = htc_fb_default_font->width;
htc_fb_font_rows = htc_fb_default_font->height;
htc_fb_console_cols = HTC_FB_LCD_WIDTH / htc_fb_font_cols;
if (htc_fb_console_cols > HTC_FB_CON_MAX_COLS)
htc_fb_console_cols = HTC_FB_CON_MAX_COLS;
htc_fb_console_rows = HTC_FB_LCD_HEIGHT / htc_fb_font_rows;
if (htc_fb_console_rows > HTC_FB_CON_MAX_ROWS)
htc_fb_console_rows = HTC_FB_CON_MAX_ROWS;
/* Clear the buffer; we could probably see the Haret output if we didn't clear
* the buffer (if it used same physical address) */
htc_fb_console_clear();
/* Welcome message */
htc_fb_console_write(&htc_fb_console, HTC_FB_MSG, strlen(HTC_FB_MSG));
/* Register console */
register_console(&htc_fb_console);
console_verbose();
return 0;
}
console_initcall(htc_fb_console_init);

View File

@ -163,3 +163,12 @@
#define MSM_TCSR_PHYS 0xA8700000
#define MSM_TCSR_SIZE SZ_4K
#endif
// Originally this does not need to be defined,
// but is required to make early_ramconsole work.
// These values must match the values used in
// the defconfig.
#define MSM_RAM_CONSOLE_BASE IOMEM(0xF9100000)
#define MSM_RAM_CONSOLE_PHYS 0x2FFC0000
#define MSM_RAM_CONSOLE_SIZE 0x00040000

View File

@ -22,6 +22,14 @@
#include <linux/uaccess.h>
#include <linux/io.h>
#if defined(CONFIG_VERY_EARLY_CONSOLE)
#include <asm/mach/map.h>
/* Defined in /arch/arm/mm/mmu.c, helps us map physical memory to virtual memory.
* It should work pretty early in the boot process, that why we use it */
extern void create_mapping(struct map_desc *md);
#endif
#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
#include <linux/rslib.h>
#endif
@ -308,8 +316,21 @@ static int __init ram_console_init(struct ram_console_buffer *buffer,
}
#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
#if defined(CONFIG_VERY_EARLY_CONSOLE)
static bool ram_console_early_init_done = false;
int __init ram_console_early_init(void)
{
if (ram_console_early_init_done)
{
printk(KERN_INFO "ram_console_early_init: already initialized, bailing out\n");
return 0;
}
ram_console_early_init_done = true;
#else
static int __init ram_console_early_init(void)
{
#endif
return ram_console_init((struct ram_console_buffer *)
CONFIG_ANDROID_RAM_CONSOLE_EARLY_ADDR,
CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE,