diff options
author | Simon Glass <sjg@chromium.org> | 2011-05-26 21:48:17 -0700 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2011-08-29 10:39:16 -0700 |
commit | ad828a69c4ea6d882fd1a822e4a6c25e2d3f075d (patch) | |
tree | eae117a7646a44e5eb147cb1fa5545bed94f15dc /drivers | |
parent | 35adf423791e6b0773e79617430645f76120ecf4 (diff) |
tegra2: Add LCD display driver
This adds basic LCD support for the Tegra2.
BUG=chromium-os:13228
TEST=Build, boot on Seaboard
Change-Id: Ib30a4e2fd1ba8e31d6bdf3f9d1d2bc70bef054ee
Reviewed-on: http://gerrit.chromium.org/gerrit/1764
Reviewed-by: Anton Staaf <robotboy@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/tegra2.c | 229 |
2 files changed, 230 insertions, 0 deletions
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 086dc053834..6d6cf35807b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -40,6 +40,7 @@ COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o COBJS-$(CONFIG_SED156X) += sed156x.o COBJS-$(CONFIG_VIDEO_SM501) += sm501.o COBJS-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o +COBJS-$(CONFIG_VIDEO_TEGRA2) += tegra2.o COBJS-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o COBJS := $(COBJS-y) diff --git a/drivers/video/tegra2.c b/drivers/video/tegra2.c new file mode 100644 index 00000000000..b69b7c3af74 --- /dev/null +++ b/drivers/video/tegra2.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * 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 <lcd.h> +#include <fdt_decode.h> +#include <asm/clocks.h> +#include <asm/arch/clock.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/power.h> +#include <asm/arch/pwfm.h> +#include <asm/arch/display.h> + +DECLARE_GLOBAL_DATA_PTR; + +int lcd_line_length; +int lcd_color_fg; +int lcd_color_bg; + +void *lcd_base; /* Start of framebuffer memory */ +void *lcd_console_address; /* Start of console buffer */ + +short console_col; +short console_row; + +vidinfo_t panel_info = { + /* Insert a value here so that we don't end up in the BSS */ + .vl_col = -1, +}; + +char lcd_cursor_enabled = 0; /* set initial value to false */ + +ushort lcd_cursor_width; +ushort lcd_cursor_height; + + +static void clk_init(void) +{ + /* TODO: Put this into the FDT when we have clock support there */ + clock_start_periph_pll(PERIPH_ID_3D, CLOCK_ID_MEMORY, CLK_300M); + clock_start_periph_pll(PERIPH_ID_2D, CLOCK_ID_MEMORY, CLK_300M); + clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH, CLK_144M); + clock_start_periph_pll(PERIPH_ID_DISP1, CLOCK_ID_PERIPH, CLK_216M); + clock_start_periph_pll(PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ, CLK_32768); +} + +/* + * The PINMUX macro is used per board to setup the pinmux configuration. + */ +#define PINMUX(grp, mux, pupd, tri) \ + {PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri} + +struct pingroup_config pinmux_cros_1[] = { + PINMUX(GPU, PWM, NORMAL, NORMAL), + PINMUX(LD0, DISPA, NORMAL, NORMAL), + PINMUX(LD1, DISPA, NORMAL, NORMAL), + PINMUX(LD10, DISPA, NORMAL, NORMAL), + PINMUX(LD11, DISPA, NORMAL, NORMAL), + PINMUX(LD12, DISPA, NORMAL, NORMAL), + PINMUX(LD13, DISPA, NORMAL, NORMAL), + PINMUX(LD14, DISPA, NORMAL, NORMAL), + PINMUX(LD15, DISPA, NORMAL, NORMAL), + PINMUX(LD16, DISPA, NORMAL, NORMAL), + PINMUX(LD17, DISPA, NORMAL, NORMAL), + PINMUX(LD2, DISPA, NORMAL, NORMAL), + PINMUX(LD3, DISPA, NORMAL, NORMAL), + PINMUX(LD4, DISPA, NORMAL, NORMAL), + PINMUX(LD5, DISPA, NORMAL, NORMAL), + PINMUX(LD6, DISPA, NORMAL, NORMAL), + PINMUX(LD7, DISPA, NORMAL, NORMAL), + PINMUX(LD8, DISPA, NORMAL, NORMAL), + PINMUX(LD9, DISPA, NORMAL, NORMAL), + PINMUX(LDI, DISPA, NORMAL, NORMAL), + PINMUX(LHP0, DISPA, NORMAL, NORMAL), + PINMUX(LHP1, DISPA, NORMAL, NORMAL), + PINMUX(LHP2, DISPA, NORMAL, NORMAL), + PINMUX(LHS, DISPA, NORMAL, NORMAL), + PINMUX(LM0, RSVD4, NORMAL, NORMAL), + PINMUX(LPP, DISPA, NORMAL, NORMAL), + PINMUX(LPW0, RSVD4, NORMAL, NORMAL), + PINMUX(LPW1, RSVD4, NORMAL, TRISTATE), + PINMUX(LPW2, RSVD4, NORMAL, NORMAL), + PINMUX(LSC0, DISPA, NORMAL, NORMAL), + PINMUX(LSPI, DISPA, NORMAL, NORMAL), + PINMUX(LVP1, DISPA, NORMAL, NORMAL), + PINMUX(LVS, DISPA, NORMAL, NORMAL), + PINMUX(SLXD, SPDIF, NORMAL, NORMAL), +}; + +/* Initialize the Tegra LCD panel and controller */ +void init_lcd(struct fdt_lcd *config) +{ + clk_init(); + + /* TODO: put pinmux into the FDT */ + pinmux_config_table(pinmux_cros_1, ARRAY_SIZE(pinmux_cros_1)); + power_enable_partition(POWERP_3D); + fdt_setup_gpios(config->gpios); + + tegra2_display_register(config); + + /* Enable PWM at 15/16 high, divider 1 */ + pwfm_setup(config->pwfm, 1, 0xdf, 1); +} + +void lcd_cursor_size(ushort width, ushort height) +{ + lcd_cursor_width = width; + lcd_cursor_height = height; +} + +void lcd_toggle_cursor(void) +{ + ushort x, y; + uchar *dest; + ushort row; + + x = console_col * lcd_cursor_width; + y = console_row * lcd_cursor_height; + dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / + 8); + + for (row = 0; row < lcd_cursor_height; ++row, dest += lcd_line_length) { + ushort *d = (ushort *)dest; + ushort color; + int i; + + for (i = 0; i < lcd_cursor_width; ++i) { + color = *d; + color ^= lcd_color_fg; + *d = color; + ++d; + } + } +} + +void lcd_cursor_on(void) +{ + lcd_cursor_enabled = 1; + lcd_toggle_cursor(); +} +void lcd_cursor_off(void) +{ + lcd_cursor_enabled = 0; + lcd_toggle_cursor(); +} + +char lcd_is_cursor_enabled(void) +{ + return lcd_cursor_enabled; +} + +static void update_panel_size(struct fdt_lcd *config) +{ + panel_info.vl_col = config->width; + panel_info.vl_row = config->height; + panel_info.vl_bpix = config->log2_bpp; +} + +/* + * Main init function called by lcd driver. + * Inits and then prints test pattern if required. + */ + +void lcd_ctrl_init(void *lcdbase) +{ + struct fdt_lcd config; + + /* get panel details */ + if (fdt_decode_lcd(gd->blob, &config)) { + printf("No LCD information in device tree\n"); + return; + } + + /* + * The device tree allows for the frame buffer to be specified if + * needed, but for now, U-Boot will set this. This may change if + * we find that Linux is unable to use the address that U-Boot picks, + * and this causes screen flicker. + */ + config.frame_buffer = (u32)lcd_base; + update_panel_size(&config); + + /* call board specific hw init */ + init_lcd(&config); + debug("LCD frame buffer at %p\n", lcd_base); +} + +ulong calc_fbsize(void) +{ + return (panel_info.vl_col * panel_info.vl_row * + NBITS(panel_info.vl_bpix)) / 8; +} + +void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) +{ +} + +void lcd_enable(void) +{ +} + +void lcd_early_init(const void *blob) +{ + struct fdt_lcd config; + + /* get panel details */ + if (!fdt_decode_lcd(gd->blob, &config)) + update_panel_size(&config); +} + |