summaryrefslogtreecommitdiff
path: root/board/st/u8500/mcde_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/st/u8500/mcde_display.c')
-rw-r--r--board/st/u8500/mcde_display.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/board/st/u8500/mcde_display.c b/board/st/u8500/mcde_display.c
new file mode 100644
index 000000000..40f7570d6
--- /dev/null
+++ b/board/st/u8500/mcde_display.c
@@ -0,0 +1,297 @@
+/*
+* Copyright (C) ST-Ericsson SA 2010
+*
+* Author: Jimmy Rubin <jimmy.rubin@stericsson.com>
+* for ST-Ericsson.
+*
+* License terms: GNU General Public License (GPL), version 2.
+*/
+
+
+#include <common.h>
+#include <command.h>
+#include "gpio.h"
+#include "mcde_display.h"
+#include "dsilink_regs.h"
+#include <tc35892.h>
+#include "mcde_regs.h"
+#include <malloc.h>
+#include "mcde.h"
+#include <linux/err.h>
+#include <asm/arch/ab8500.h>
+#include "common.h"
+
+#ifdef CONFIG_SYS_VIDEO_USE_GIMP_HEADER
+#include <asm/arch/mcde_video_logo_gimp.h>
+#else
+#include <asm/arch/mcde_video_logo.h>
+#endif
+
+#define DEBUG 0
+#define dbg_printk(format, arg...) \
+ if (DEBUG) \
+ printf("mcde: " format, ##arg) \
+
+static struct mcde_chnl_state *chnl;
+
+static struct mcde_port port0 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .ifc = 0,
+ .link = 0,
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ },
+ },
+};
+
+struct mcde_display_generic_platform_data main_display_data = {
+ .reset_gpio = TC35892_PIN_KPY7,
+ .reset_delay = 1,
+};
+
+struct mcde_display_device main_display = {
+ .port = &port0,
+ .chnl_id = MCDE_CHNL_C0,
+ .fifo = MCDE_FIFO_A,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .port_pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .native_x_res = 864,
+ .native_y_res = 480,
+};
+
+static int mcde_enable_gpio(void)
+{
+ int ret;
+ dbg_printk("Enable GPIO pins!\n");
+
+ /* Only main display should be initialized */
+ ret = tc35892_gpio_dir(CONFIG_SYS_I2C_GPIOE_ADDR,
+ main_display_data.reset_gpio, 1);
+ if (ret) {
+ printf("%s:Could not set direction for gpio \n", __func__);
+ return -EINVAL;
+ }
+ ret = tc35892_gpio_set(CONFIG_SYS_I2C_GPIOE_ADDR,
+ main_display_data.reset_gpio, 0);
+ if (ret) {
+ printf("%s:Could reset gpio \n", __func__);
+ return -EINVAL;
+ }
+ mdelay(main_display_data.reset_delay);
+ ret = tc35892_gpio_set(CONFIG_SYS_I2C_GPIOE_ADDR,
+ main_display_data.reset_gpio, 1);
+ if (ret) {
+ printf("%s:Could set gpior\n", __func__);
+ return -EINVAL;
+ }
+ mdelay(main_display_data.reset_delay);
+
+ dbg_printk("All needed GPIOS enabled!\n");
+ return 0;
+}
+
+#define DCS_CMD_EXIT_SLEEP_MODE 0x11
+#define DCS_CMD_SET_DISPLAY_ON 0x29
+
+static int mcde_turn_on_display(void)
+{
+ int ret = 0;
+ dbg_printk("Turn on display!\n");
+ ret = mcde_dsi_dcs_write(main_display.port,
+ DCS_CMD_EXIT_SLEEP_MODE, NULL, 0);
+ if (!ret) {
+ dbg_printk("mcde_dsi_dcs_write "
+ "DCS_CMD_EXIT_SLEEP_MODE success!\n");
+ ret = mcde_dsi_dcs_write(main_display.port,
+ DCS_CMD_SET_DISPLAY_ON, NULL, 0);
+ if (!ret)
+ dbg_printk("mcde_dsi_dcs_write "
+ "DCS_CMD_SET_DISPLAY_ON success!\n");
+ }
+
+ return ret;
+}
+
+#define LDO_VAUX1_MASK 0x1
+#define LDO_VAUX1_ENABLE 0x1
+#define VAUX1_VOLTAGE_2_5V 0x08
+
+#define VANA_ENABLE_IN_HP_MODE 0x05
+
+#define ENABLE_PWM1 0x01
+#define PWM_DUTY_LOW_1024_1024 0xFF
+#define PWM_DUTY_HI_1024_1024 0x03
+
+static int mcde_display_power_init(void)
+{
+ int ret;
+ int val;
+
+ if (!cpu_is_u8500v11())
+ return 0;
+
+ /* Vaux12Regu */
+ ret = ab8500_read(AB8500_REGU_CTRL2, AB8500_REGU_VAUX12_REGU_REG);
+ if (ret < 0)
+ goto out;
+
+ val = ret;
+
+ /* Vaux1 & Vaux2 HP mode */
+ ret = ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VAUX12_REGU_REG,
+ val | LDO_VAUX1_ENABLE);
+ if (ret < 0)
+ goto out;
+
+ udelay(10 * 1000);
+
+ /* Set the voltage to 2.5V */
+ ret = ab8500_write(AB8500_REGU_CTRL2,
+ AB8500_REGU_VAUX1_SEL_REG, VAUX1_VOLTAGE_2_5V);
+ if (ret < 0)
+ goto out;
+
+ /* DCI & CSI (DSI / PLL / Camera) */ /* Vana & Vpll HP mode */
+ ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VPLLVANA_REGU_REG,
+ VANA_ENABLE_IN_HP_MODE);
+
+ /* Enable the PWM control for the backlight Main display */
+ ab8500_write(AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, ENABLE_PWM1);
+ ab8500_write(AB8500_MISC, AB8500_PWM_OUT_CTRL1_REG,
+ PWM_DUTY_LOW_1024_1024);
+ ab8500_write(AB8500_MISC, AB8500_PWM_OUT_CTRL2_REG,
+ PWM_DUTY_HI_1024_1024);
+out:
+ return ret;
+}
+
+
+int mcde_startup(void)
+{
+ u8 num_dsilinks;
+ int ret;
+ u32 i;
+
+ num_dsilinks = main_display.port->phy.dsi.num_data_lanes;
+ mcde_init(num_dsilinks);
+ ret = mcde_display_power_init();
+ if (ret)
+ goto display_power_failed;
+ mcde_enable_dss();
+
+ ret = mcde_enable_gpio();
+ if (ret)
+ goto enable_gpio_failed;
+
+ chnl = mcde_chnl_get(main_display.chnl_id, main_display.fifo,
+ main_display.port);
+ if (IS_ERR(chnl)) {
+ ret = PTR_ERR(chnl);
+ printf("%s:Failed to acquire MCDE channel\n", __func__);
+ goto get_chnl_failed;
+ }
+
+ ret = mcde_turn_on_display();
+ if (ret)
+ goto display_power_mode_failed;
+ mcde_chnl_set_update_area(chnl, 0, 0, main_display.native_x_res,
+ main_display.native_y_res);
+ mcde_chnl_set_pixel_format(chnl, main_display.port_pixel_format);
+ mcde_chnl_apply(chnl);
+
+display_power_mode_failed:
+get_chnl_failed:
+display_power_failed:
+enable_gpio_failed:
+ mcde_exit();
+ return ret;
+}
+
+int mcde_display_image(void)
+{
+ struct mcde_ovly_state *ovly;
+ u32 xpos = 0;
+ u32 ypos = 0;
+ int ret;
+#ifdef CONFIG_SYS_VIDEO_USE_GIMP_HEADER
+ u32 i = 0;
+ u8 pixels[3];
+ u16 pixel;
+ u16 *sp;
+#endif
+
+ ovly = mcde_ovly_get(chnl);
+ if (IS_ERR(ovly)) {
+ ret = PTR_ERR(ovly);
+ printf("Failed to get channel\n");
+ return -ret;
+ }
+
+#ifdef CONFIG_SYS_VIDEO_USE_GIMP_HEADER
+ /* Add the image data */
+ sp = (u16 *)CONFIG_SYS_VIDEO_FB_ADRS;
+ for (i = 0; i < ((MCDE_VIDEO_LOGO_WIDTH*MCDE_VIDEO_LOGO_HEIGHT)); i++) {
+ HEADER_PIXEL(header_data, pixels);
+ pixels[0] >>= 3; /* Keep 5 bits red */
+ pixels[1] >>= 2; /* 6 bits green */
+ pixels[2] >>= 3; /* and 5 bits blue */
+ pixel = (pixels[0] << 11) | (pixels[1] << 5) | pixels[2];
+ *sp++ = pixel;
+ }
+ mcde_ovly_set_source_buf(ovly, CONFIG_SYS_VIDEO_FB_ADRS);
+#else
+ mcde_ovly_set_source_buf(ovly, (u32)&mcde_video_logo[0]);
+#endif
+ mcde_ovly_set_source_info(ovly, (MCDE_VIDEO_LOGO_WIDTH*2),
+ main_display.default_pixel_format);
+ mcde_ovly_set_source_area(ovly, 0, 0, MCDE_VIDEO_LOGO_WIDTH,
+ MCDE_VIDEO_LOGO_HEIGHT);
+ if (MCDE_VIDEO_LOGO_WIDTH == main_display.native_x_res)
+ xpos = 0;
+ else
+ xpos = (main_display.native_x_res - MCDE_VIDEO_LOGO_WIDTH) / 2;
+
+ if (MCDE_VIDEO_LOGO_HEIGHT == main_display.native_y_res)
+ ypos = 0;
+ else
+ ypos = (main_display.native_y_res - MCDE_VIDEO_LOGO_HEIGHT) / 2;
+
+ mcde_ovly_set_dest_pos(ovly, xpos, ypos, 0);
+ mcde_ovly_apply(ovly);
+ mcde_chnl_update(chnl);
+ /* Wait for refresh to be finished */
+ mdelay(CONFIG_SYS_MCDE_REFRESH_TIME);
+ mcde_exit();
+ return 0;
+}
+
+/*
+ * command line commands
+ */
+
+
+int mcde_power_up(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ return mcde_startup();
+}
+
+int mcde_disply_bitmap(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ return mcde_display_image();
+}
+
+U_BOOT_CMD(
+ mcde_power_up, 1, 1, mcde_power_up,
+ "Power up display",
+ ""
+);
+
+U_BOOT_CMD(
+ mcde_display, 1, 1, mcde_disply_bitmap,
+ "Display bitmap",
+ ""
+);