diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile index e6c869fa636..5a72ad4ba8d 100644 --- a/drivers/video/msm/Makefile +++ b/drivers/video/msm/Makefile @@ -3,6 +3,8 @@ obj-y := msm_fb.o obj-$(CONFIG_FB_MSM_LOGO) += logo.o obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o +ifeq ($(CONFIG_FB_MSM_MDP_HW),y) + # MDP obj-y += mdp.o @@ -177,6 +179,12 @@ obj-$(CONFIG_FB_MSM_WRITEBACK_MSM_PANEL) += mdp4_overlay_writeback.o obj-$(CONFIG_MSM_VIDC_1080P) += vidc/ obj-$(CONFIG_MSM_VIDC_720P) += vidc/ +else +obj-$(CONFIG_FB_MSM_EBI2) += ebi2_host.o +obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o +obj-y += msm_fb_panel.o +obj-$(CONFIG_FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL) += ebi2_epson_s1d_qvga.o +endif clean: rm *.o .*cmd diff --git a/drivers/video/msm/ebi2_epson_s1d_qvga.c b/drivers/video/msm/ebi2_epson_s1d_qvga.c new file mode 100644 index 00000000000..8821eabbcb2 --- /dev/null +++ b/drivers/video/msm/ebi2_epson_s1d_qvga.c @@ -0,0 +1,374 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + * + */ + +#include "msm_fb.h" + +#include +#include +#include +#include +#include +#include +#include "linux/proc_fs.h" + +#include + +#include +#include + +#include +#include + +#define CMD_NOP_C 0x00 +#define CMD_SOFT_RESET_C 0x99 +#define CMD_DISPLAY_ON_C 0xAF +#define CMD_DISPLAY_OFF_C 0xAE +#define CMD_SET_DISPLAY_C 0xCA +#define CMD_SET_DISPLAY_TIMING_C 0xA1 +#define CMD_SET_DATA_C 0xBC +#define CMD_SET_START_ADDRESS_C 0x15 +#define CMD_SET_END_ADDRESS_C 0x75 +#define CMD_RAM_WRITE_C 0x5C +#define CMD_RAM_READ_C 0x5D +#define CMD_SET_AREA_SCROLLING_C 0xAA +#define CMD_SET_DISPLAY_START_LINE_C 0xAB +#define CMD_PARTIAL_DISPLAY_IN_C 0xA8 +#define CMD_PARTIAL_DISPLAY_OUT_C 0xA9 +#define CMD_SET_DISPLAY_DATA_INTERFACE_C 0x31 +#define CMD_SET_DISPLAY_COLOR_MODE_C 0x8B +#define CMD_SELECT_MTP_ROM_MODE_C 0x65 +#define CMD_MTP_ROM_MODE_IN_C 0x67 +#define CMD_MTP_ROM_MODE_OUT_C 0x68 +#define CMD_MTP_ROM_OPERATION_IN_C 0x69 +#define CMD_MTP_ROM_OPERATION_OUT_C 0x70 +#define CMD_GATE_LINE_SCAN_MODE_C 0x6F +#define CMD_SET_AC_OPERATION_DRIVE_C 0x8C +#define CMD_SET_ELECTRONIC_CONTROL_C 0x20 +#define CMD_SET_POSITIVE_CORRECTION_CHARS_C 0x22 +#define CMD_SET_NEGATIVE_CORRECTION_CHARS_C 0x25 +#define CMD_SET_POWER_CONTROL_C 0x21 +#define CMD_SET_PARTIAL_POWER_CONTROL_C 0x23 +#define CMD_SET_8_COLOR_CONTROL_C 0x24 +#define CMD_SLEEP_IN_C 0x95 +#define CMD_SLEEP_OUT_C 0x94 +#define CMD_VDD_OFF_C 0x97 +#define CMD_VDD_ON_C 0x96 +#define CMD_STOP_OSCILLATION_C 0x93 +#define CMD_START_OSCILLATION_C 0x92 +#define CMD_TEST_SOURCE_C 0xFD +#define CMD_TEST_FUSE_C 0xFE +#define CMD_TEST_C 0xFF +#define CMD_STATUS_READ_C 0xE8 +#define CMD_REVISION_READ_C 0xE9 + +#define PANEL_WIDTH 240 +#define PANEL_HEIGHT 320 +#define ACTIVE_WIN_WIDTH PANEL_WIDTH +#define ACTIVE_WIN_HEIGHT PANEL_HEIGHT + +#define ACTIVE_WIN_H_START 0 +#define ACTIVE_WIN_V_START 0 + +#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, (cmd << 1)); +#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, (data << 1)); +#define DISP_DATA_IN() inpw(DISP_DATA_PORT); + +static void *DISP_CMD_PORT; +static void *DISP_DATA_PORT; +static boolean disp_initialized; +static boolean display_on; +static struct msm_panel_common_pdata *ebi2_epson_pdata; + +static void epson_s1d_disp_init(struct platform_device *pdev); +static int epson_s1d_disp_off(struct platform_device *pdev); +static int epson_s1d_disp_on(struct platform_device *pdev); +static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres); + +static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres) +{ + int right, bottom; + + if (!disp_initialized) + return; + + right = x + xres - 1; + bottom = y + yres - 1; + + x += ACTIVE_WIN_H_START; + y += ACTIVE_WIN_V_START; + right += ACTIVE_WIN_H_START; + bottom += ACTIVE_WIN_V_START; + + if ((PANEL_WIDTH > x) && + (PANEL_HEIGHT > y) && + (PANEL_WIDTH > right) && + (PANEL_HEIGHT > bottom)) { + DISP_CMD_OUT(CMD_SET_START_ADDRESS_C); + DISP_DATA_OUT((uint8)x); + DISP_DATA_OUT((uint8)(y>>8)); + DISP_DATA_OUT((uint8)y); + + DISP_CMD_OUT(CMD_SET_END_ADDRESS_C); + DISP_DATA_OUT((uint8)right); + DISP_DATA_OUT((uint8)(bottom>>8)); + DISP_DATA_OUT((uint8)bottom); + DISP_CMD_OUT(CMD_RAM_WRITE_C); + } +} + +static void epson_s1d_disp_init(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + + if (disp_initialized) + return; + + mfd = platform_get_drvdata(pdev); + + DISP_CMD_PORT = mfd->cmd_port; + DISP_DATA_PORT = mfd->data_port; + + disp_initialized = TRUE; +} + +static int epson_s1d_disp_off(struct platform_device *pdev) +{ + if (!disp_initialized) + epson_s1d_disp_init(pdev); + + if (display_on) { + DISP_CMD_OUT(CMD_SOFT_RESET_C); + DISP_CMD_OUT(CMD_VDD_OFF_C); + display_on = FALSE; + } + + return 0; +} + +static int epson_s1d_disp_on(struct platform_device *pdev) +{ + int i; + if (!disp_initialized) + epson_s1d_disp_init(pdev); + + if (!display_on) { + /* Enable Vdd regulator */ + DISP_CMD_OUT(CMD_VDD_ON_C); + msleep(20); + + /* Soft Reset before configuring display */ + DISP_CMD_OUT(CMD_SOFT_RESET_C); + msleep(20); + + /* Set display attributes */ + + /* GATESCAN */ + DISP_CMD_OUT(CMD_GATE_LINE_SCAN_MODE_C); + DISP_DATA_OUT(0x0); + + /* DISSET */ + DISP_CMD_OUT(CMD_SET_DISPLAY_C); + DISP_DATA_OUT(0x31); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT((uint8)((PANEL_HEIGHT - 1)>>8)); + DISP_DATA_OUT((uint8)(PANEL_HEIGHT - 1)); + DISP_DATA_OUT(0x03); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x08); + + /* VOLSET */ + DISP_CMD_OUT( + CMD_SET_ELECTRONIC_CONTROL_C); + DISP_DATA_OUT(0x10); + DISP_DATA_OUT(0x80); + DISP_DATA_OUT(0x11); + DISP_DATA_OUT(0x1B); + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x0D); + DISP_DATA_OUT(0x00); + + /* PWRCTL */ + DISP_CMD_OUT(CMD_SET_POWER_CONTROL_C); + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x24); + DISP_DATA_OUT(0x0F); + DISP_DATA_OUT(0xFE); + DISP_DATA_OUT(0x33); + DISP_DATA_OUT(0x31); + DISP_DATA_OUT(0xFF); + DISP_DATA_OUT(0x03); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x77); + DISP_DATA_OUT(0x33); + DISP_DATA_OUT(0x11); + DISP_DATA_OUT(0x44); + DISP_DATA_OUT(0x00); + + /* PPWRCTL */ + DISP_CMD_OUT(CMD_SET_PARTIAL_POWER_CONTROL_C); + DISP_DATA_OUT(0x33); + DISP_DATA_OUT(0xFF); + DISP_DATA_OUT(0x03); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x44); + DISP_DATA_OUT(0x00); + + /* SPLOUT */ + DISP_CMD_OUT(CMD_SLEEP_OUT_C); + msleep(100); + + /* DATSET */ + DISP_CMD_OUT(CMD_SET_DATA_C); + DISP_DATA_OUT(0x00); + + /* DISTMEMSET */ + DISP_CMD_OUT(CMD_SET_DISPLAY_TIMING_C); + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x2E); + DISP_DATA_OUT(0x0A); + DISP_DATA_OUT(0x2C); + DISP_DATA_OUT(0x23); + DISP_DATA_OUT(0x2F); + DISP_DATA_OUT(0x00); + + /* GAMSETP */ + DISP_CMD_OUT(CMD_SET_POSITIVE_CORRECTION_CHARS_C); + DISP_DATA_OUT(0x37); + DISP_DATA_OUT(0xFF); + DISP_DATA_OUT(0x7F); + DISP_DATA_OUT(0x15); + DISP_DATA_OUT(0x37); + DISP_DATA_OUT(0x05); + + /* GAMSETN */ + DISP_CMD_OUT(CMD_SET_NEGATIVE_CORRECTION_CHARS_C); + DISP_DATA_OUT(0x37); + DISP_DATA_OUT(0xFF); + DISP_DATA_OUT(0x7F); + DISP_DATA_OUT(0x15); + DISP_DATA_OUT(0x37); + DISP_DATA_OUT(0x05); + + /* ACDRIVE */ + DISP_CMD_OUT(CMD_SET_AC_OPERATION_DRIVE_C); + DISP_DATA_OUT(0x00); + + /* TEST */ + DISP_CMD_OUT(CMD_TEST_C); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x01); + + /* COLMOD */ + DISP_CMD_OUT(CMD_SET_DISPLAY_COLOR_MODE_C); + DISP_DATA_OUT(0x00); + + /* STADDSET */ + DISP_CMD_OUT(CMD_SET_START_ADDRESS_C); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x00); + + /* EDADDSET */ + DISP_CMD_OUT(CMD_SET_END_ADDRESS_C); + DISP_DATA_OUT(0xEF); + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x3F); + + /* Set Display Start Line */ + DISP_CMD_OUT(CMD_SET_DISPLAY_START_LINE_C); + DISP_DATA_OUT(0x00); + + /* Set Display Data Interface */ + DISP_CMD_OUT(CMD_SET_DISPLAY_DATA_INTERFACE_C); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x04); + + epson_s1d_disp_set_rect(0, + 0, + ACTIVE_WIN_WIDTH, + ACTIVE_WIN_HEIGHT); + + for (i = 0; i < (ACTIVE_WIN_WIDTH * ACTIVE_WIN_HEIGHT); i++) + outpdw(DISP_DATA_PORT, 0); + + /* DISON */ + DISP_CMD_OUT(CMD_DISPLAY_ON_C); + msleep(60); + + display_on = TRUE; + } + + return 0; +} + +static int epson_s1d_probe(struct platform_device *pdev) +{ + if (pdev->id == 0) { + ebi2_epson_pdata = pdev->dev.platform_data; + return 0; + } + + msm_fb_add_device(pdev); + return 0; +} + +static struct platform_driver this_driver = { + .probe = epson_s1d_probe, + .driver = { + .name = "ebi2_epson_s1d_qvga", + }, +}; + +static struct msm_fb_panel_data epson_s1d_panel_data = { + .on = epson_s1d_disp_on, + .off = epson_s1d_disp_off, + .set_rect = epson_s1d_disp_set_rect, +}; + +static struct platform_device this_device = { + .name = "ebi2_epson_s1d_qvga", + .id = 1, + .dev = { + .platform_data = &epson_s1d_panel_data, + } +}; + +static int __init epson_s1d_init(void) +{ + int ret; + struct msm_panel_info *pinfo; + + ret = platform_driver_register(&this_driver); + if (!ret) { + pinfo = &epson_s1d_panel_data.panel_info; + pinfo->xres = PANEL_WIDTH; + pinfo->yres = PANEL_HEIGHT; + MSM_FB_SINGLE_MODE_PANEL(pinfo); + pinfo->type = EBI2_PANEL; + pinfo->pdest = DISPLAY_1; + pinfo->wait_cycle = 0x048423E8; + pinfo->bpp = 18; + pinfo->fb_num = 2; + pinfo->lcd.vsync_enable = FALSE; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + } + + return ret; +} + +module_init(epson_s1d_init); diff --git a/drivers/video/msm/ebi2_host.c b/drivers/video/msm/ebi2_host.c new file mode 100644 index 00000000000..8ba5506fa6f --- /dev/null +++ b/drivers/video/msm/ebi2_host.c @@ -0,0 +1,307 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "msm_fb.h" + +struct mdp_ccs mdp_ccs_rgb2yuv; +struct mdp_ccs mdp_ccs_yuv2rgb; + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; +static int ebi2_host_resource_initialized; +static struct msm_panel_common_pdata *ebi2_host_pdata; + +static int ebi2_host_probe(struct platform_device *pdev); +static int ebi2_host_remove(struct platform_device *pdev); + +static int ebi2_host_runtime_suspend(struct device *dev) +{ + dev_dbg(dev, "pm_runtime: suspending...\n"); + return 0; +} + +static int ebi2_host_runtime_resume(struct device *dev) +{ + dev_dbg(dev, "pm_runtime: resuming...\n"); + return 0; +} + +static const struct dev_pm_ops ebi2_host_dev_pm_ops = { + .runtime_suspend = ebi2_host_runtime_suspend, + .runtime_resume = ebi2_host_runtime_resume, +}; + + +static struct platform_driver ebi2_host_driver = { + .probe = ebi2_host_probe, + .remove = ebi2_host_remove, + .shutdown = NULL, + .driver = { + /* + * Simulate mdp hw + */ + .name = "mdp", + .pm = &ebi2_host_dev_pm_ops, + }, +}; + +void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state, + boolean isr) +{ + return; +} +int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req) +{ + return 0; +} +int mdp_start_histogram(struct fb_info *info) +{ + return 0; +} +int mdp_stop_histogram(struct fb_info *info) +{ + return 0; +} +void mdp_refresh_screen(unsigned long data) +{ + return; +} + +static int ebi2_host_off(struct platform_device *pdev) +{ + int ret; + ret = panel_next_off(pdev); + return ret; +} + +static int ebi2_host_on(struct platform_device *pdev) +{ + int ret; + ret = panel_next_on(pdev); + return ret; +} + + +static int ebi2_host_probe(struct platform_device *pdev) +{ + struct platform_device *msm_fb_dev = NULL; + struct msm_fb_data_type *mfd; + struct msm_fb_panel_data *pdata = NULL; + int rc; + + if ((pdev->id == 0) && (pdev->num_resources > 0)) { + + ebi2_host_pdata = pdev->dev.platform_data; + + ebi2_host_resource_initialized = 1; + return 0; + } + + ebi2_host_resource_initialized = 1; + if (!ebi2_host_resource_initialized) + return -EPERM; + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) + return -ENOMEM; + + msm_fb_dev = platform_device_alloc("msm_fb", pdev->id); + if (!msm_fb_dev) + return -ENOMEM; + + /* link to the latest pdev */ + mfd->pdev = msm_fb_dev; + + if (ebi2_host_pdata) { + mfd->mdp_rev = ebi2_host_pdata->mdp_rev; + mfd->mem_hid = ebi2_host_pdata->mem_hid; + } + + /* add panel data */ + if (platform_device_add_data + (msm_fb_dev, pdev->dev.platform_data, + sizeof(struct msm_fb_panel_data))) { + pr_err("ebi2_host_probe: platform_device_add_data failed!\n"); + rc = -ENOMEM; + goto ebi2_host_probe_err; + } + /* data chain */ + pdata = msm_fb_dev->dev.platform_data; + pdata->on = ebi2_host_on; + pdata->off = ebi2_host_off; + pdata->next = pdev; + + /* set driver data */ + platform_set_drvdata(msm_fb_dev, mfd); + + rc = platform_device_add(msm_fb_dev); + if (rc) + goto ebi2_host_probe_err; + + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + pdev_list[pdev_list_cnt++] = pdev; + return 0; + +ebi2_host_probe_err: + platform_device_put(msm_fb_dev); + return rc; +} + +void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty, + boolean sync) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + struct fb_info *fbi = mfd->fbi; + struct msm_panel_info *panel_info = &mfd->panel_info; + MDPIBUF *iBuf; + int bpp = info->var.bits_per_pixel / 8; + int yres, remainder; + + if (panel_info->mode2_yres != 0) { + yres = panel_info->mode2_yres; + remainder = (fbi->fix.line_length*yres)%PAGE_SIZE; + } else { + yres = panel_info->yres; + remainder = (fbi->fix.line_length*yres)%PAGE_SIZE; + } + + if (!remainder) + remainder = PAGE_SIZE; + + down(&mfd->sem); + + iBuf = &mfd->ibuf; + /* use virtual address */ + iBuf->buf = (uint8 *) fbi->screen_base; + + if (fbi->var.yoffset < yres) { + iBuf->buf += fbi->var.xoffset * bpp; + } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) { + iBuf->buf += fbi->var.xoffset * bpp + yres * + fbi->fix.line_length + PAGE_SIZE - remainder; + } else { + iBuf->buf += fbi->var.xoffset * bpp + 2 * yres * + fbi->fix.line_length + 2 * (PAGE_SIZE - remainder); + } + + iBuf->ibuf_width = info->var.xres_virtual; + iBuf->bpp = bpp; + + iBuf->vsync_enable = sync; + + if (dirty) { + /* + * ToDo: dirty region check inside var.xoffset+xres + * <-> var.yoffset+yres + */ + iBuf->dma_x = dirty->xoffset % info->var.xres; + iBuf->dma_y = dirty->yoffset % info->var.yres; + iBuf->dma_w = dirty->width; + iBuf->dma_h = dirty->height; + } else { + iBuf->dma_x = 0; + iBuf->dma_y = 0; + iBuf->dma_w = info->var.xres; + iBuf->dma_h = info->var.yres; + } + mfd->ibuf_flushed = FALSE; + up(&mfd->sem); +} + +void mdp_dma_pan_update(struct fb_info *info) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + MDPIBUF *iBuf; + int i, j; + uint32 data; + uint8 *src; + struct msm_fb_panel_data *pdata = + (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; + struct fb_info *fbi = mfd->fbi; + + iBuf = &mfd->ibuf; + + invalidate_caches((unsigned long)fbi->screen_base, + (unsigned long)info->fix.smem_len, + (unsigned long)info->fix.smem_start); + + pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w, + iBuf->dma_h); + for (i = 0; i < iBuf->dma_h; i++) { + src = iBuf->buf + (fbi->fix.line_length * (iBuf->dma_y + i)) + + (iBuf->dma_x * iBuf->bpp); + for (j = 0; j < iBuf->dma_w; j++) { + data = (uint32)(*src++ >> 2) << 12; + data |= (uint32)(*src++ >> 2) << 6; + data |= (uint32)(*src++ >> 2); + data = ((data&0x1FF)<<16) | ((data&0x3FE00)>>9); + outpdw(mfd->data_port, data); + } + } +} + +static int ebi2_host_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int ebi2_host_register_driver(void) +{ + return platform_driver_register(&ebi2_host_driver); +} + +static int __init ebi2_host_driver_init(void) +{ + int ret; + + ret = ebi2_host_register_driver(); + if (ret) { + pr_err("ebi2_host_register_driver() failed!\n"); + return ret; + } + + return 0; +} + +module_init(ebi2_host_driver_init); diff --git a/drivers/video/msm/ebi2_lcd.c b/drivers/video/msm/ebi2_lcd.c index 68590afd04a..966f974291c 100644 --- a/drivers/video/msm/ebi2_lcd.c +++ b/drivers/video/msm/ebi2_lcd.c @@ -56,8 +56,6 @@ static struct platform_driver ebi2_lcd_driver = { .probe = ebi2_lcd_probe, .remove = ebi2_lcd_remove, .suspend = NULL, - .suspend_late = NULL, - .resume_early = NULL, .resume = NULL, .shutdown = NULL, .driver = { @@ -71,17 +69,42 @@ static void *ebi2_lcd_cfg0; static void *ebi2_lcd_cfg1; static void __iomem *lcd01_base; static void __iomem *lcd02_base; +static int lcd01_base_phys; static int ebi2_lcd_resource_initialized; static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; static int pdev_list_cnt; +static struct lcdc_platform_data *ebi2_pdata; + +static int ebi2_lcd_on(struct platform_device *pdev) +{ + int ret; + + if (ebi2_pdata && ebi2_pdata->lcdc_power_save) + ebi2_pdata->lcdc_power_save(1); + + ret = panel_next_on(pdev); + return ret; +} + +static int ebi2_lcd_off(struct platform_device *pdev) +{ + int ret; + + ret = panel_next_off(pdev); + + if (ebi2_pdata && ebi2_pdata->lcdc_power_save) + ebi2_pdata->lcdc_power_save(0); + + return ret; +} static int ebi2_lcd_probe(struct platform_device *pdev) { struct msm_fb_data_type *mfd; struct platform_device *mdp_dev = NULL; struct msm_fb_panel_data *pdata = NULL; - int rc, i; + int rc, i, hw_version; if (pdev->id == 0) { for (i = 0; i < pdev->num_resources; i++) { @@ -98,6 +121,7 @@ static int ebi2_lcd_probe(struct platform_device *pdev) ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24); } else if (!strncmp(pdev->resource[i].name, "lcd01", 5)) { + lcd01_base_phys = pdev->resource[i].start; lcd01_base = ioremap(pdev->resource[i].start, pdev->resource[i].end - pdev->resource[i].start + 1); @@ -118,7 +142,9 @@ static int ebi2_lcd_probe(struct platform_device *pdev) } } } + ebi2_pdata = pdev->dev.platform_data; ebi2_lcd_resource_initialized = 1; + return 0; } @@ -158,15 +184,19 @@ static int ebi2_lcd_probe(struct platform_device *pdev) /* data chain */ pdata = mdp_dev->dev.platform_data; - pdata->on = panel_next_on; - pdata->off = panel_next_off; + pdata->on = ebi2_lcd_on; + pdata->off = ebi2_lcd_off; pdata->next = pdev; /* get/set panel specific fb info */ mfd->panel_info = pdata->panel_info; + hw_version = inp32((int)ebi2_base + 8); + if (mfd->panel_info.bpp == 24) mfd->fb_imgType = MDP_RGB_888; + else if (mfd->panel_info.bpp == 18) + mfd->fb_imgType = MDP_RGB_888; else mfd->fb_imgType = MDP_RGB_565; @@ -181,10 +211,12 @@ static int ebi2_lcd_probe(struct platform_device *pdev) * configure both. */ outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle); - if (mfd->panel_info.bpp == 18) - outp32(ebi2_lcd_cfg1, 0x01000000); - else - outp32(ebi2_lcd_cfg1, 0x0); + if (hw_version < 0x2020) { + if (mfd->panel_info.bpp == 18) + outp32(ebi2_lcd_cfg1, 0x01000000); + else + outp32(ebi2_lcd_cfg1, 0x0); + } } else { #ifdef DEBUG_EBI2_LCD /* @@ -201,10 +233,18 @@ static int ebi2_lcd_probe(struct platform_device *pdev) */ if (mfd->panel_info.pdest == DISPLAY_1) { mfd->cmd_port = lcd01_base; - mfd->data_port = - (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN); - mfd->data_port_phys = - (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN); + if (hw_version >= 0x2020) { + mfd->data_port = + (void *)((uint32) mfd->cmd_port + 0x80); + mfd->data_port_phys = + (void *)(lcd01_base_phys + 0x80); + } else { + mfd->data_port = + (void *)((uint32) mfd->cmd_port + + EBI2_PRIM_LCD_RS_PIN); + mfd->data_port_phys = + (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN); + } } else { mfd->cmd_port = lcd01_base; mfd->data_port = diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c index 91dc16c1664..6ec5d70aa25 100644 --- a/drivers/video/msm/msm_fb.c +++ b/drivers/video/msm/msm_fb.c @@ -1239,6 +1239,8 @@ static int msm_fb_register(struct msm_fb_data_type *mfd) snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id); #elif defined(CONFIG_FB_MSM_MDP40) snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id); +#elif defined(CONFIG_FB_MSM_MDP_NONE) + snprintf(fix->id, sizeof(fix->id), "msmfb0_%x", (__u32) *id); #else error CONFIG_FB_MSM_MDP undefined ! #endif