提交 9d200153 编写于 作者: S Stepan Moskovchenko 提交者: Greg Kroah-Hartman

Staging: add MSM framebuffer driver

Qualcomm development of the MSM SOC framebuffer driver has
diverged significantly from the driver used by Android. This
is a snapshot of our current driver, in all it's agony. We are
putting this in staging to help with the process of converging
the two drivers.

At this point, the driver has been tested only in dumb
framebuffer mode.
Signed-off-by: NStepan Moskovchenko <stepanm@codeaurora.org>
Signed-off-by: NDavid Brown <davidb@codeaurora.org>
Signed-off-by: NAbhijeet Dharmapurikar <adharmap@codeaurora.org>
[dwalker@codeaurora.org: added a small compile fix and TODO.]
Signed-off-by: NDaniel Walker <dwalker@codeaurora.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 34ef545a
......@@ -145,5 +145,7 @@ source "drivers/staging/xgifb/Kconfig"
source "drivers/staging/mrst-touchscreen/Kconfig"
source "drivers/staging/msm/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
......@@ -53,3 +53,4 @@ obj-$(CONFIG_TI_ST) += ti-st/
obj-$(CONFIG_ADIS16255) += adis16255/
obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
obj-$(CONFIG_MSM_STAGING) += msm/
config MSM_STAGING
tristate "MSM Frame Buffer Support"
depends on FB && ARCH_MSM && !FB_MSM
select FB_BACKLIGHT if FB_MSM_BACKLIGHT
select NEW_LEDS
select LEDS_CLASS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
---help---
Support for MSM Framebuffer.
if MSM_STAGING
config FB_MSM_LCDC_HW
bool
default n
choice
prompt "MDP HW version"
default FB_MSM_MDP31
config FB_MSM_MDP31
select FB_MSM_LCDC_HW
bool "MDP HW ver3.1"
---help---
Support for MSM MDP HW revision 3.1
Say Y here if this is msm8x50 variant platform.
endchoice
config FB_MSM_LCDC
bool
default n
config FB_MSM_TVOUT
bool
default n
config FB_MSM_LCDC_PANEL
bool
select FB_MSM_LCDC
default n
config FB_MSM_LCDC_PRISM_WVGA
bool
select FB_MSM_LCDC_PANEL
default n
config FB_MSM_LCDC_ST1_WXGA
bool
select FB_MSM_LCDC_PANEL
default n
config FB_MSM_LCDC_ST15_WXGA
bool
select FB_MSM_LCDC_PANEL
default n
config FB_MSM_LCDC_WXGA
bool
select FB_MSM_LCDC_PANEL
default n
choice
prompt "LCD Panel"
default FB_MSM_LCDC_ST15_PANEL
config FB_MSM_LCDC_PRISM_WVGA_PANEL
depends on FB_MSM_LCDC_HW
bool "LCDC Prism WVGA Panel"
select FB_MSM_LCDC_PRISM_WVGA
---help---
Support for LCDC Prism WVGA (800x480) panel
config FB_MSM_LCDC_ST15_PANEL
depends on FB_MSM_LCDC_HW
bool "LCDC ST1.5 Panel"
select FB_MSM_LCDC_ST15_WXGA
---help---
Support for ST1.5 WXGA (1366x768) panel
config FB_MSM_PANEL_NONE
bool "NONE"
---help---
This will disable LCD panel
endchoice
choice
prompt "Secondary LCD Panel"
depends on FB_MSM_MDP31
default FB_MSM_SECONDARY_PANEL_NONE
config FB_MSM_SECONDARY_PANEL_NONE
bool "NONE"
---help---
No secondary panel
endchoice
config FB_MSM_TVOUT_NTSC
bool
select FB_MSM_TVOUT
default n
config FB_MSM_TVOUT_PAL
bool
select FB_MSM_TVOUT
default n
choice
depends on (FB_MSM_MDP22 || FB_MSM_MDP31)
prompt "TVOut Region"
default FB_MSM_TVOUT_NTSC_M
config FB_MSM_TVOUT_NTSC_M
bool "NTSC M"
select FB_MSM_TVOUT_NTSC
---help---
Support for NTSC M region (North American and Korea)
config FB_MSM_TVOUT_NONE
bool "NONE"
---help---
This will disable TV Out functionality.
endchoice
config PMEM_KERNEL_SIZE
int "PMEM for kernel components (in MB)"
default 2
depends on ARCH_QSD8X50
help
Configures the amount of PMEM for use by kernel components
(in MB; minimum 2MB)
endif
obj-y := msm_fb.o staging-devices.o memory.o
obj-$(CONFIG_FB_MSM_LOGO) += logo.o
obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
# MDP
obj-y += mdp.o
ifeq ($(CONFIG_FB_MSM_MDP40),y)
obj-y += mdp4_util.o
obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o
else
obj-y += mdp_hw_init.o
obj-y += mdp_ppp.o
ifeq ($(CONFIG_FB_MSM_MDP31),y)
obj-y += mdp_ppp_v31.o
obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o
else
obj-y += mdp_ppp_v20.o
endif
endif
ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
obj-y += mdp4_overlay.o
obj-y += mdp4_overlay_lcdc.o
obj-y += mdp4_overlay_mddi.o
else
obj-y += mdp_dma_lcdc.o
endif
obj-y += mdp_dma.o
obj-y += mdp_dma_s.o
obj-y += mdp_vsync.o
obj-y += mdp_cursor.o
obj-y += mdp_dma_tv.o
# EBI2
obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
# LCDC
obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
# MDDI
msm_mddi-objs := mddi.o mddihost.o mddihosti.o
obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
# External MDDI
msm_mddi_ext-objs := mddihost_e.o mddi_ext.o
obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
# TVEnc
obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
# MSM FB Panel
obj-y += msm_fb_panel.o
obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
obj-y += mddi_prism.o
obj-y += mddi_toshiba.o
obj-y += mddi_toshiba_vga.o
obj-y += mddi_toshiba_wvga_pt.o
obj-y += mddi_toshiba_wvga.o
obj-y += mddi_sharp.o
else
obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o
obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
endif
obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o
obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o
obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o
obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o
obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o
obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
clean:
rm *.o .*cmd
- Merge this code with the existing MSM framebuffer
- General style clean ups.
/* Copyright (c) 2008-2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
#include <linux/memory.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include "linux/proc_fs.h"
#include <linux/delay.h>
#include <mach/hardware.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/mach-types.h>
/* The following are for MSM5100 on Gator
*/
#ifdef FEATURE_PM1000
#include "pm1000.h"
#endif /* FEATURE_PM1000 */
/* The following are for MSM6050 on Bambi
*/
#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
#include "pm.h"
#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */
#ifdef DISP_DEVICE_18BPP
#undef DISP_DEVICE_18BPP
#define DISP_DEVICE_16BPP
#endif
#define QCIF_WIDTH 176
#define QCIF_HEIGHT 220
static void *DISP_CMD_PORT;
static void *DISP_DATA_PORT;
#define DISP_CMD_DISON 0xaf
#define DISP_CMD_DISOFF 0xae
#define DISP_CMD_DISNOR 0xa6
#define DISP_CMD_DISINV 0xa7
#define DISP_CMD_DISCTL 0xca
#define DISP_CMD_GCP64 0xcb
#define DISP_CMD_GCP16 0xcc
#define DISP_CMD_GSSET 0xcd
#define DISP_GS_2 0x02
#define DISP_GS_16 0x01
#define DISP_GS_64 0x00
#define DISP_CMD_SLPIN 0x95
#define DISP_CMD_SLPOUT 0x94
#define DISP_CMD_SD_PSET 0x75
#define DISP_CMD_MD_PSET 0x76
#define DISP_CMD_SD_CSET 0x15
#define DISP_CMD_MD_CSET 0x16
#define DISP_CMD_DATCTL 0xbc
#define DISP_DATCTL_666 0x08
#define DISP_DATCTL_565 0x28
#define DISP_DATCTL_444 0x38
#define DISP_CMD_RAMWR 0x5c
#define DISP_CMD_RAMRD 0x5d
#define DISP_CMD_PTLIN 0xa8
#define DISP_CMD_PTLOUT 0xa9
#define DISP_CMD_ASCSET 0xaa
#define DISP_CMD_SCSTART 0xab
#define DISP_CMD_VOLCTL 0xc6
#define DISP_VOLCTL_TONE 0x80
#define DISP_CMD_NOp 0x25
#define DISP_CMD_OSSEL 0xd0
#define DISP_CMD_3500KSET 0xd1
#define DISP_CMD_3500KEND 0xd2
#define DISP_CMD_14MSET 0xd3
#define DISP_CMD_14MEND 0xd4
#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
/* Epson device column number starts at 2
*/
#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
DISP_CMD_OUT(DISP_CMD_SD_PSET) \
DISP_DATA_OUT((ulhc_row) & 0xFF) \
DISP_DATA_OUT((ulhc_row) >> 8) \
DISP_DATA_OUT((lrhc_row) & 0xFF) \
DISP_DATA_OUT((lrhc_row) >> 8) \
DISP_CMD_OUT(DISP_CMD_SD_CSET) \
DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
DISP_DATA_OUT(((lrhc_col)+2) >> 8)
#define DISP_MIN_CONTRAST 0
#define DISP_MAX_CONTRAST 127
#define DISP_DEFAULT_CONTRAST 80
#define DISP_MIN_BACKLIGHT 0
#define DISP_MAX_BACKLIGHT 15
#define DISP_DEFAULT_BACKLIGHT 2
#define WAIT_SEC(sec) mdelay((sec)/1000)
static word disp_area_start_row;
static word disp_area_end_row;
static byte disp_contrast = DISP_DEFAULT_CONTRAST;
static boolean disp_powered_up;
static boolean disp_initialized = FALSE;
/* For some reason the contrast set at init time is not good. Need to do
* it again
*/
static boolean display_on = FALSE;
static void epsonQcif_disp_init(struct platform_device *pdev);
static void epsonQcif_disp_set_contrast(word contrast);
static void epsonQcif_disp_set_display_area(word start_row, word end_row);
static int epsonQcif_disp_off(struct platform_device *pdev);
static int epsonQcif_disp_on(struct platform_device *pdev);
static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
volatile word databack;
static void epsonQcif_disp_init(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
int i;
if (disp_initialized)
return;
mfd = platform_get_drvdata(pdev);
DISP_CMD_PORT = mfd->cmd_port;
DISP_DATA_PORT = mfd->data_port;
/* Sleep in */
DISP_CMD_OUT(DISP_CMD_SLPIN);
/* Display off */
DISP_CMD_OUT(DISP_CMD_DISOFF);
/* Display normal */
DISP_CMD_OUT(DISP_CMD_DISNOR);
/* Set data mode */
DISP_CMD_OUT(DISP_CMD_DATCTL);
DISP_DATA_OUT(DISP_DATCTL_565);
/* Set display timing */
DISP_CMD_OUT(DISP_CMD_DISCTL);
DISP_DATA_OUT(0x1c); /* p1 */
DISP_DATA_OUT(0x02); /* p1 */
DISP_DATA_OUT(0x82); /* p2 */
DISP_DATA_OUT(0x00); /* p3 */
DISP_DATA_OUT(0x00); /* p4 */
DISP_DATA_OUT(0xe0); /* p5 */
DISP_DATA_OUT(0x00); /* p5 */
DISP_DATA_OUT(0xdc); /* p6 */
DISP_DATA_OUT(0x00); /* p6 */
DISP_DATA_OUT(0x02); /* p7 */
DISP_DATA_OUT(0x00); /* p8 */
/* Set 64 gray scale level */
DISP_CMD_OUT(DISP_CMD_GCP64);
DISP_DATA_OUT(0x08); /* p01 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0x2a); /* p02 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0x4e); /* p03 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0x6b); /* p04 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0x88); /* p05 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0xa3); /* p06 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0xba); /* p07 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0xd1); /* p08 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0xe5); /* p09 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0xf3); /* p10 */
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0x03); /* p11 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x13); /* p12 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x22); /* p13 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x2f); /* p14 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x3b); /* p15 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x46); /* p16 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x51); /* p17 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x5b); /* p18 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x64); /* p19 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x6c); /* p20 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x74); /* p21 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x7c); /* p22 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x83); /* p23 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x8a); /* p24 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x91); /* p25 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x98); /* p26 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x9f); /* p27 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xa6); /* p28 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xac); /* p29 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xb2); /* p30 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xb7); /* p31 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xbc); /* p32 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xc1); /* p33 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xc6); /* p34 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xcb); /* p35 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xd0); /* p36 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xd4); /* p37 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xd8); /* p38 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xdc); /* p39 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xe0); /* p40 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xe4); /* p41 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xe8); /* p42 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xec); /* p43 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xf0); /* p44 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xf4); /* p45 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xf8); /* p46 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xfb); /* p47 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xfe); /* p48 */
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0x01); /* p49 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x03); /* p50 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x05); /* p51 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x07); /* p52 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x09); /* p53 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x0b); /* p54 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x0d); /* p55 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x0f); /* p56 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x11); /* p57 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x13); /* p58 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x15); /* p59 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x17); /* p60 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x19); /* p61 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x1b); /* p62 */
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x1c); /* p63 */
DISP_DATA_OUT(0x02);
/* Set 16 gray scale level */
DISP_CMD_OUT(DISP_CMD_GCP16);
DISP_DATA_OUT(0x1a); /* p01 */
DISP_DATA_OUT(0x32); /* p02 */
DISP_DATA_OUT(0x42); /* p03 */
DISP_DATA_OUT(0x4c); /* p04 */
DISP_DATA_OUT(0x58); /* p05 */
DISP_DATA_OUT(0x5f); /* p06 */
DISP_DATA_OUT(0x66); /* p07 */
DISP_DATA_OUT(0x6b); /* p08 */
DISP_DATA_OUT(0x70); /* p09 */
DISP_DATA_OUT(0x74); /* p10 */
DISP_DATA_OUT(0x78); /* p11 */
DISP_DATA_OUT(0x7b); /* p12 */
DISP_DATA_OUT(0x7e); /* p13 */
DISP_DATA_OUT(0x80); /* p14 */
DISP_DATA_OUT(0x82); /* p15 */
/* Set DSP column */
DISP_CMD_OUT(DISP_CMD_MD_CSET);
DISP_DATA_OUT(0xff);
DISP_DATA_OUT(0x03);
DISP_DATA_OUT(0xff);
DISP_DATA_OUT(0x03);
/* Set DSP page */
DISP_CMD_OUT(DISP_CMD_MD_PSET);
DISP_DATA_OUT(0xff);
DISP_DATA_OUT(0x01);
DISP_DATA_OUT(0xff);
DISP_DATA_OUT(0x01);
/* Set ARM column */
DISP_CMD_OUT(DISP_CMD_SD_CSET);
DISP_DATA_OUT(0x02);
DISP_DATA_OUT(0x00);
DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
/* Set ARM page */
DISP_CMD_OUT(DISP_CMD_SD_PSET);
DISP_DATA_OUT(0x00);
DISP_DATA_OUT(0x00);
DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
/* Set 64 gray scales */
DISP_CMD_OUT(DISP_CMD_GSSET);
DISP_DATA_OUT(DISP_GS_64);
DISP_CMD_OUT(DISP_CMD_OSSEL);
DISP_DATA_OUT(0);
/* Sleep out */
DISP_CMD_OUT(DISP_CMD_SLPOUT);
WAIT_SEC(40000);
/* Initialize power IC */
DISP_CMD_OUT(DISP_CMD_VOLCTL);
DISP_DATA_OUT(DISP_VOLCTL_TONE);
WAIT_SEC(40000);
/* Set electronic volume, d'xx */
DISP_CMD_OUT(DISP_CMD_VOLCTL);
DISP_DATA_OUT(DISP_DEFAULT_CONTRAST); /* value from 0 to 127 */
/* Initialize display data */
DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
DISP_CMD_OUT(DISP_CMD_RAMWR);
for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
DISP_DATA_OUT(0xffff);
DISP_CMD_OUT(DISP_CMD_RAMRD);
databack = DISP_DATA_IN();
databack = DISP_DATA_IN();
databack = DISP_DATA_IN();
databack = DISP_DATA_IN();
WAIT_SEC(80000);
DISP_CMD_OUT(DISP_CMD_DISON);
disp_area_start_row = 0;
disp_area_end_row = QCIF_HEIGHT - 1;
disp_powered_up = TRUE;
disp_initialized = TRUE;
epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
display_on = TRUE;
}
static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
{
if (!disp_initialized)
return;
DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
DISP_CMD_OUT(DISP_CMD_RAMWR);
}
static void epsonQcif_disp_set_display_area(word start_row, word end_row)
{
if (!disp_initialized)
return;
if ((start_row == disp_area_start_row)
&& (end_row == disp_area_end_row))
return;
disp_area_start_row = start_row;
disp_area_end_row = end_row;
/* Range checking
*/
if (end_row >= QCIF_HEIGHT)
end_row = QCIF_HEIGHT - 1;
if (start_row > end_row)
start_row = end_row;
/* When display is not the full screen, gray scale is set to
** 2; otherwise it is set to 64.
*/
if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
/* The whole screen */
DISP_CMD_OUT(DISP_CMD_PTLOUT);
WAIT_SEC(10000);
DISP_CMD_OUT(DISP_CMD_DISOFF);
WAIT_SEC(100000);
DISP_CMD_OUT(DISP_CMD_GSSET);
DISP_DATA_OUT(DISP_GS_64);
WAIT_SEC(100000);
DISP_CMD_OUT(DISP_CMD_DISON);
} else {
/* partial screen */
DISP_CMD_OUT(DISP_CMD_PTLIN);
DISP_DATA_OUT(start_row);
DISP_DATA_OUT(start_row >> 8);
DISP_DATA_OUT(end_row);
DISP_DATA_OUT(end_row >> 8);
DISP_CMD_OUT(DISP_CMD_GSSET);
DISP_DATA_OUT(DISP_GS_2);
}
}
static int epsonQcif_disp_off(struct platform_device *pdev)
{
if (!disp_initialized)
epsonQcif_disp_init(pdev);
if (display_on) {
DISP_CMD_OUT(DISP_CMD_DISOFF);
DISP_CMD_OUT(DISP_CMD_SLPIN);
display_on = FALSE;
}
return 0;
}
static int epsonQcif_disp_on(struct platform_device *pdev)
{
if (!disp_initialized)
epsonQcif_disp_init(pdev);
if (!display_on) {
DISP_CMD_OUT(DISP_CMD_SLPOUT);
WAIT_SEC(40000);
DISP_CMD_OUT(DISP_CMD_DISON);
epsonQcif_disp_set_contrast(disp_contrast);
display_on = TRUE;
}
return 0;
}
static void epsonQcif_disp_set_contrast(word contrast)
{
if (!disp_initialized)
return;
/* Initialize power IC, d'24 */
DISP_CMD_OUT(DISP_CMD_VOLCTL);
DISP_DATA_OUT(DISP_VOLCTL_TONE);
WAIT_SEC(40000);
/* Set electronic volume, d'xx */
DISP_CMD_OUT(DISP_CMD_VOLCTL);
if (contrast > 127)
contrast = 127;
DISP_DATA_OUT(contrast); /* value from 0 to 127 */
disp_contrast = (byte) contrast;
} /* End disp_set_contrast */
static void epsonQcif_disp_clear_screen_area(
word start_row, word end_row, word start_column, word end_column) {
int32 i;
/* Clear the display screen */
DISP_SET_RECT(start_row, end_row, start_column, end_column);
DISP_CMD_OUT(DISP_CMD_RAMWR);
i = (end_row - start_row + 1) * (end_column - start_column + 1);
for (; i > 0; i--)
DISP_DATA_OUT(0xffff);
}
static int __init epsonQcif_probe(struct platform_device *pdev)
{
msm_fb_add_device(pdev);
return 0;
}
static struct platform_driver this_driver = {
.probe = epsonQcif_probe,
.driver = {
.name = "ebi2_epson_qcif",
},
};
static struct msm_fb_panel_data epsonQcif_panel_data = {
.on = epsonQcif_disp_on,
.off = epsonQcif_disp_off,
.set_rect = epsonQcif_disp_set_rect,
};
static struct platform_device this_device = {
.name = "ebi2_epson_qcif",
.id = 0,
.dev = {
.platform_data = &epsonQcif_panel_data,
}
};
static int __init epsonQcif_init(void)
{
int ret;
struct msm_panel_info *pinfo;
ret = platform_driver_register(&this_driver);
if (!ret) {
pinfo = &epsonQcif_panel_data.panel_info;
pinfo->xres = QCIF_WIDTH;
pinfo->yres = QCIF_HEIGHT;
pinfo->type = EBI2_PANEL;
pinfo->pdest = DISPLAY_2;
pinfo->wait_cycle = 0x808000;
pinfo->bpp = 16;
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(epsonQcif_init);
/* Copyright (c) 2008-2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
#include <linux/string.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/vmalloc.h>
#include <linux/debugfs.h>
#include "msm_fb.h"
static int ebi2_lcd_probe(struct platform_device *pdev);
static int ebi2_lcd_remove(struct platform_device *pdev);
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 = {
.name = "ebi2_lcd",
},
};
static void *ebi2_base;
static void *ebi2_lcd_cfg0;
static void *ebi2_lcd_cfg1;
static void __iomem *lcd01_base;
static void __iomem *lcd02_base;
static int ebi2_lcd_resource_initialized;
static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
static int pdev_list_cnt;
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;
if (pdev->id == 0) {
for (i = 0; i < pdev->num_resources; i++) {
if (!strncmp(pdev->resource[i].name, "base", 4)) {
ebi2_base = ioremap(pdev->resource[i].start,
pdev->resource[i].end -
pdev->resource[i].start + 1);
if (!ebi2_base) {
printk(KERN_ERR
"ebi2_base ioremap failed!\n");
return -ENOMEM;
}
ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20);
ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
} else if (!strncmp(pdev->resource[i].name,
"lcd01", 5)) {
lcd01_base = ioremap(pdev->resource[i].start,
pdev->resource[i].end -
pdev->resource[i].start + 1);
if (!lcd01_base) {
printk(KERN_ERR
"lcd01_base ioremap failed!\n");
return -ENOMEM;
}
} else if (!strncmp(pdev->resource[i].name,
"lcd02", 5)) {
lcd02_base = ioremap(pdev->resource[i].start,
pdev->resource[i].end -
pdev->resource[i].start + 1);
if (!lcd02_base) {
printk(KERN_ERR
"lcd02_base ioremap failed!\n");
return -ENOMEM;
}
}
}
ebi2_lcd_resource_initialized = 1;
return 0;
}
if (!ebi2_lcd_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;
if (ebi2_base == NULL)
return -ENOMEM;
mdp_dev = platform_device_alloc("mdp", pdev->id);
if (!mdp_dev)
return -ENOMEM;
/* link to the latest pdev */
mfd->pdev = mdp_dev;
mfd->dest = DISPLAY_LCD;
/* add panel data */
if (platform_device_add_data
(mdp_dev, pdev->dev.platform_data,
sizeof(struct msm_fb_panel_data))) {
printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n");
platform_device_put(mdp_dev);
return -ENOMEM;
}
/* data chain */
pdata = mdp_dev->dev.platform_data;
pdata->on = panel_next_on;
pdata->off = panel_next_off;
pdata->next = pdev;
/* get/set panel specific fb info */
mfd->panel_info = pdata->panel_info;
if (mfd->panel_info.bpp == 24)
mfd->fb_imgType = MDP_RGB_888;
else
mfd->fb_imgType = MDP_RGB_565;
/* config msm ebi2 lcd register */
if (mfd->panel_info.pdest == DISPLAY_1) {
outp32(ebi2_base,
(inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) |
EBI2_PRIM_LCD_SEL);
/*
* current design has one set of cfg0/1 register to control
* both EBI2 channels. so, we're using the PRIM channel to
* 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);
} else {
#ifdef DEBUG_EBI2_LCD
/*
* confliting with QCOM SURF FPGA CS.
* OEM should enable below for their CS mapping
*/
outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR)))
|EBI2_SECD_LCD_SEL);
#endif
}
/*
* map cs (chip select) address
*/
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);
} else {
mfd->cmd_port = lcd01_base;
mfd->data_port =
(void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN);
mfd->data_port_phys =
(void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN);
}
/*
* set driver data
*/
platform_set_drvdata(mdp_dev, mfd);
/*
* register in mdp driver
*/
rc = platform_device_add(mdp_dev);
if (rc) {
goto ebi2_lcd_probe_err;
}
pdev_list[pdev_list_cnt++] = pdev;
return 0;
ebi2_lcd_probe_err:
platform_device_put(mdp_dev);
return rc;
}
static int ebi2_lcd_remove(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
if (!mfd)
return 0;
if (mfd->key != MFD_KEY)
return 0;
iounmap(mfd->cmd_port);
return 0;
}
static int ebi2_lcd_register_driver(void)
{
return platform_driver_register(&ebi2_lcd_driver);
}
static int __init ebi2_lcd_driver_init(void)
{
return ebi2_lcd_register_driver();
}
module_init(ebi2_lcd_driver_init);
\ No newline at end of file
此差异已折叠。
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/i2c.h>
#include <linux/delay.h>
#include "msm_fb.h"
#define DEVICE_NAME "sii9022"
#define SII9022_DEVICE_ID 0xB0
struct sii9022_i2c_addr_data{
u8 addr;
u8 data;
};
/* video mode data */
static u8 video_mode_data[] = {
0x00,
0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
};
static u8 avi_io_format[] = {
0x09,
0x00, 0x00,
};
/* power state */
static struct sii9022_i2c_addr_data regset0[] = {
{ 0x60, 0x04 },
{ 0x63, 0x00 },
{ 0x1E, 0x00 },
};
static u8 video_infoframe[] = {
0x0C,
0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
};
/* configure audio */
static struct sii9022_i2c_addr_data regset1[] = {
{ 0x26, 0x90 },
{ 0x20, 0x90 },
{ 0x1F, 0x80 },
{ 0x26, 0x80 },
{ 0x24, 0x02 },
{ 0x25, 0x0B },
{ 0xBC, 0x02 },
{ 0xBD, 0x24 },
{ 0xBE, 0x02 },
};
/* enable audio */
static u8 misc_infoframe[] = {
0xBF,
0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* set HDMI, active */
static struct sii9022_i2c_addr_data regset2[] = {
{ 0x1A, 0x01 },
{ 0x3D, 0x00 },
};
static int send_i2c_data(struct i2c_client *client,
struct sii9022_i2c_addr_data *regset,
int size)
{
int i;
int rc = 0;
for (i = 0; i < size; i++) {
rc = i2c_smbus_write_byte_data(
client,
regset[i].addr, regset[i].data);
if (rc)
break;
}
return rc;
}
static int hdmi_sii_enable(struct i2c_client *client)
{
int rc;
int retries = 10;
int count;
rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
if (rc)
goto enable_exit;
do {
msleep(1);
rc = i2c_smbus_read_byte_data(client, 0x1B);
} while ((rc != SII9022_DEVICE_ID) && retries--);
if (rc != SII9022_DEVICE_ID)
return -ENODEV;
rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
if (rc)
goto enable_exit;
count = ARRAY_SIZE(video_mode_data);
rc = i2c_master_send(client, video_mode_data, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
if (rc)
goto enable_exit;
count = ARRAY_SIZE(avi_io_format);
rc = i2c_master_send(client, avi_io_format, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
if (rc)
goto enable_exit;
count = ARRAY_SIZE(video_infoframe);
rc = i2c_master_send(client, video_infoframe, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
if (rc)
goto enable_exit;
count = ARRAY_SIZE(misc_infoframe);
rc = i2c_master_send(client, misc_infoframe, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
if (rc)
goto enable_exit;
return 0;
enable_exit:
printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
return rc;
}
static const struct i2c_device_id hmdi_sii_id[] = {
{ DEVICE_NAME, 0 },
{ }
};
static int hdmi_sii_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rc;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
return -ENODEV;
rc = hdmi_sii_enable(client);
return rc;
}
static struct i2c_driver hdmi_sii_i2c_driver = {
.driver = {
.name = DEVICE_NAME,
.owner = THIS_MODULE,
},
.probe = hdmi_sii_probe,
.remove = __exit_p(hdmi_sii_remove),
.id_table = hmdi_sii_id,
};
static int __init hdmi_sii_init(void)
{
int ret;
struct msm_panel_info pinfo;
if (msm_fb_detect_client("hdmi_sii9022"))
return 0;
pinfo.xres = 1280;
pinfo.yres = 720;
pinfo.type = HDMI_PANEL;
pinfo.pdest = DISPLAY_1;
pinfo.wait_cycle = 0;
pinfo.bpp = 24;
pinfo.fb_num = 2;
pinfo.clk_rate = 74250000;
pinfo.lcdc.h_back_porch = 124;
pinfo.lcdc.h_front_porch = 110;
pinfo.lcdc.h_pulse_width = 136;
pinfo.lcdc.v_back_porch = 19;
pinfo.lcdc.v_front_porch = 5;
pinfo.lcdc.v_pulse_width = 6;
pinfo.lcdc.border_clr = 0;
pinfo.lcdc.underflow_clr = 0xff;
pinfo.lcdc.hsync_skew = 0;
ret = lcdc_device_register(&pinfo);
if (ret) {
printk(KERN_ERR "%s: failed to register device\n", __func__);
goto init_exit;
}
ret = i2c_add_driver(&hdmi_sii_i2c_driver);
if (ret)
printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
init_exit:
return ret;
}
static void __exit hdmi_sii_exit(void)
{
i2c_del_driver(&hdmi_sii_i2c_driver);
}
module_init(hdmi_sii_init);
module_exit(hdmi_sii_exit);
MODULE_LICENSE("GPL v2");
MODULE_VERSION("0.1");
MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
MODULE_DESCRIPTION("SiI9022 HDMI driver");
MODULE_ALIAS("platform:hdmi-sii9022");
/* Copyright (c) 2008-2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <mach/hardware.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/pm_qos_params.h>
#include "msm_fb.h"
static int lcdc_probe(struct platform_device *pdev);
static int lcdc_remove(struct platform_device *pdev);
static int lcdc_off(struct platform_device *pdev);
static int lcdc_on(struct platform_device *pdev);
static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
static int pdev_list_cnt;
static struct clk *mdp_lcdc_pclk_clk;
static struct clk *mdp_lcdc_pad_pclk_clk;
int mdp_lcdc_pclk_clk_rate;
int mdp_lcdc_pad_pclk_clk_rate;
static struct platform_driver lcdc_driver = {
.probe = lcdc_probe,
.remove = lcdc_remove,
.suspend = NULL,
.resume = NULL,
.shutdown = NULL,
.driver = {
.name = "lcdc",
},
};
static struct lcdc_platform_data *lcdc_pdata;
static int lcdc_off(struct platform_device *pdev)
{
int ret = 0;
ret = panel_next_off(pdev);
clk_disable(mdp_lcdc_pclk_clk);
clk_disable(mdp_lcdc_pad_pclk_clk);
if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
lcdc_pdata->lcdc_power_save(0);
if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
ret = lcdc_pdata->lcdc_gpio_config(0);
// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
// PM_QOS_DEFAULT_VALUE);
return ret;
}
static int lcdc_on(struct platform_device *pdev)
{
int ret = 0;
struct msm_fb_data_type *mfd;
unsigned long panel_pixclock_freq , pm_qos_freq;
mfd = platform_get_drvdata(pdev);
panel_pixclock_freq = mfd->fbi->var.pixclock;
if (panel_pixclock_freq > 58000000)
/* pm_qos_freq should be in Khz */
pm_qos_freq = panel_pixclock_freq / 1000 ;
else
pm_qos_freq = 58000;
// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
// pm_qos_freq);
mfd = platform_get_drvdata(pdev);
clk_enable(mdp_lcdc_pclk_clk);
clk_enable(mdp_lcdc_pad_pclk_clk);
if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
lcdc_pdata->lcdc_power_save(1);
if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
ret = lcdc_pdata->lcdc_gpio_config(1);
clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock);
clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock);
mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk);
mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk);
ret = panel_next_on(pdev);
return ret;
}
static int lcdc_probe(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
struct fb_info *fbi;
struct platform_device *mdp_dev = NULL;
struct msm_fb_panel_data *pdata = NULL;
int rc;
if (pdev->id == 0) {
lcdc_pdata = pdev->dev.platform_data;
return 0;
}
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;
mdp_dev = platform_device_alloc("mdp", pdev->id);
if (!mdp_dev)
return -ENOMEM;
/*
* link to the latest pdev
*/
mfd->pdev = mdp_dev;
mfd->dest = DISPLAY_LCDC;
/*
* alloc panel device data
*/
if (platform_device_add_data
(mdp_dev, pdev->dev.platform_data,
sizeof(struct msm_fb_panel_data))) {
printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n");
platform_device_put(mdp_dev);
return -ENOMEM;
}
/*
* data chain
*/
pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
pdata->on = lcdc_on;
pdata->off = lcdc_off;
pdata->next = pdev;
/*
* get/set panel specific fb info
*/
mfd->panel_info = pdata->panel_info;
mfd->fb_imgType = MDP_RGB_565;
fbi = mfd->fbi;
fbi->var.pixclock = mfd->panel_info.clk_rate;
fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
/*
* set driver data
*/
platform_set_drvdata(mdp_dev, mfd);
/*
* register in mdp driver
*/
rc = platform_device_add(mdp_dev);
if (rc)
goto lcdc_probe_err;
pdev_list[pdev_list_cnt++] = pdev;
return 0;
lcdc_probe_err:
platform_device_put(mdp_dev);
return rc;
}
static int lcdc_remove(struct platform_device *pdev)
{
// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc");
return 0;
}
static int lcdc_register_driver(void)
{
return platform_driver_register(&lcdc_driver);
}
static int __init lcdc_driver_init(void)
{
mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
if (IS_ERR(mdp_lcdc_pclk_clk)) {
printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n");
return IS_ERR(mdp_lcdc_pclk_clk);
}
mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
if (IS_ERR(mdp_lcdc_pad_pclk_clk)) {
printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n");
return IS_ERR(mdp_lcdc_pad_pclk_clk);
}
// pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
// PM_QOS_DEFAULT_VALUE);
return lcdc_register_driver();
}
module_init(lcdc_driver_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
static int __init lcdc_external_init(void)
{
int ret;
struct msm_panel_info pinfo;
if (msm_fb_detect_client("lcdc_external"))
return 0;
pinfo.xres = 1280;
pinfo.yres = 720;
pinfo.type = LCDC_PANEL;
pinfo.pdest = DISPLAY_1;
pinfo.wait_cycle = 0;
pinfo.bpp = 24;
pinfo.fb_num = 2;
pinfo.clk_rate = 74250000;
pinfo.lcdc.h_back_porch = 124;
pinfo.lcdc.h_front_porch = 110;
pinfo.lcdc.h_pulse_width = 136;
pinfo.lcdc.v_back_porch = 19;
pinfo.lcdc.v_front_porch = 5;
pinfo.lcdc.v_pulse_width = 6;
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
ret = lcdc_device_register(&pinfo);
if (ret)
printk(KERN_ERR "%s: failed to register device!\n", __func__);
return ret;
}
module_init(lcdc_external_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/delay.h>
#include <mach/gpio.h>
#include "msm_fb.h"
/* registers */
#define GORDON_REG_NOP 0x00
#define GORDON_REG_IMGCTL1 0x10
#define GORDON_REG_IMGCTL2 0x11
#define GORDON_REG_IMGSET1 0x12
#define GORDON_REG_IMGSET2 0x13
#define GORDON_REG_IVBP1 0x14
#define GORDON_REG_IHBP1 0x15
#define GORDON_REG_IVNUM1 0x16
#define GORDON_REG_IHNUM1 0x17
#define GORDON_REG_IVBP2 0x18
#define GORDON_REG_IHBP2 0x19
#define GORDON_REG_IVNUM2 0x1A
#define GORDON_REG_IHNUM2 0x1B
#define GORDON_REG_LCDIFCTL1 0x30
#define GORDON_REG_VALTRAN 0x31
#define GORDON_REG_AVCTL 0x33
#define GORDON_REG_LCDIFCTL2 0x34
#define GORDON_REG_LCDIFCTL3 0x35
#define GORDON_REG_LCDIFSET1 0x36
#define GORDON_REG_PCCTL 0x3C
#define GORDON_REG_TPARAM1 0x40
#define GORDON_REG_TLCDIF1 0x41
#define GORDON_REG_TSSPB_ST1 0x42
#define GORDON_REG_TSSPB_ED1 0x43
#define GORDON_REG_TSCK_ST1 0x44
#define GORDON_REG_TSCK_WD1 0x45
#define GORDON_REG_TGSPB_VST1 0x46
#define GORDON_REG_TGSPB_VED1 0x47
#define GORDON_REG_TGSPB_CH1 0x48
#define GORDON_REG_TGCK_ST1 0x49
#define GORDON_REG_TGCK_ED1 0x4A
#define GORDON_REG_TPCTL_ST1 0x4B
#define GORDON_REG_TPCTL_ED1 0x4C
#define GORDON_REG_TPCHG_ED1 0x4D
#define GORDON_REG_TCOM_CH1 0x4E
#define GORDON_REG_THBP1 0x4F
#define GORDON_REG_TPHCTL1 0x50
#define GORDON_REG_EVPH1 0x51
#define GORDON_REG_EVPL1 0x52
#define GORDON_REG_EVNH1 0x53
#define GORDON_REG_EVNL1 0x54
#define GORDON_REG_TBIAS1 0x55
#define GORDON_REG_TPARAM2 0x56
#define GORDON_REG_TLCDIF2 0x57
#define GORDON_REG_TSSPB_ST2 0x58
#define GORDON_REG_TSSPB_ED2 0x59
#define GORDON_REG_TSCK_ST2 0x5A
#define GORDON_REG_TSCK_WD2 0x5B
#define GORDON_REG_TGSPB_VST2 0x5C
#define GORDON_REG_TGSPB_VED2 0x5D
#define GORDON_REG_TGSPB_CH2 0x5E
#define GORDON_REG_TGCK_ST2 0x5F
#define GORDON_REG_TGCK_ED2 0x60
#define GORDON_REG_TPCTL_ST2 0x61
#define GORDON_REG_TPCTL_ED2 0x62
#define GORDON_REG_TPCHG_ED2 0x63
#define GORDON_REG_TCOM_CH2 0x64
#define GORDON_REG_THBP2 0x65
#define GORDON_REG_TPHCTL2 0x66
#define GORDON_REG_POWCTL 0x80
static int lcdc_gordon_panel_off(struct platform_device *pdev);
static int spi_cs;
static int spi_sclk;
static int spi_sdo;
static int spi_sdi;
static int spi_dac;
static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
(1 << 6),
(1 << 5),
(1 << 4),
(1 << 3),
(1 << 2),
(1 << 1),
(1 << 0) /* LSB */
};
struct gordon_state_type{
boolean disp_initialized;
boolean display_on;
boolean disp_powered_up;
};
static struct gordon_state_type gordon_state = { 0 };
static struct msm_panel_common_pdata *lcdc_gordon_pdata;
static void serigo(uint16 reg, uint8 data)
{
unsigned int tx_val = ((0x00FF & reg) << 8) | data;
unsigned char i, val = 0;
/* Enable the Chip Select */
gpio_set_value(spi_cs, 1);
udelay(33);
/* Transmit it in two parts, Higher Byte first, then Lower Byte */
val = (unsigned char)((tx_val & 0xFF00) >> 8);
/* Clock should be Low before entering ! */
for (i = 0; i < 8; i++) {
/* #1: Drive the Data (High or Low) */
if (val & bit_shift[i])
gpio_set_value(spi_sdi, 1);
else
gpio_set_value(spi_sdi, 0);
/* #2: Drive the Clk High and then Low */
udelay(33);
gpio_set_value(spi_sclk, 1);
udelay(33);
gpio_set_value(spi_sclk, 0);
}
/* Idle state of SDO (MOSI) is Low */
gpio_set_value(spi_sdi, 0);
/* ..then Lower Byte */
val = (uint8) (tx_val & 0x00FF);
/* Before we enter here the Clock should be Low ! */
for (i = 0; i < 8; i++) {
/* #1: Drive the Data (High or Low) */
if (val & bit_shift[i])
gpio_set_value(spi_sdi, 1);
else
gpio_set_value(spi_sdi, 0);
/* #2: Drive the Clk High and then Low */
udelay(33);
gpio_set_value(spi_sclk, 1);
udelay(33);
gpio_set_value(spi_sclk, 0);
}
/* Idle state of SDO (MOSI) is Low */
gpio_set_value(spi_sdi, 0);
/* Now Disable the Chip Select */
udelay(33);
gpio_set_value(spi_cs, 0);
}
static void spi_init(void)
{
/* Setting the Default GPIO's */
spi_sclk = *(lcdc_gordon_pdata->gpio_num);
spi_cs = *(lcdc_gordon_pdata->gpio_num + 1);
spi_sdi = *(lcdc_gordon_pdata->gpio_num + 2);
spi_sdo = *(lcdc_gordon_pdata->gpio_num + 3);
/* Set the output so that we dont disturb the slave device */
gpio_set_value(spi_sclk, 0);
gpio_set_value(spi_sdi, 0);
/* Set the Chip Select De-asserted */
gpio_set_value(spi_cs, 0);
}
static void gordon_disp_powerup(void)
{
if (!gordon_state.disp_powered_up && !gordon_state.display_on) {
/* Reset the hardware first */
/* Include DAC power up implementation here */
gordon_state.disp_powered_up = TRUE;
}
}
static void gordon_init(void)
{
/* Image interface settings */
serigo(GORDON_REG_IMGCTL2, 0x00);
serigo(GORDON_REG_IMGSET1, 0x00);
/* Exchange the RGB signal for J510(Softbank mobile) */
serigo(GORDON_REG_IMGSET2, 0x12);
serigo(GORDON_REG_LCDIFSET1, 0x00);
/* Pre-charge settings */
serigo(GORDON_REG_PCCTL, 0x09);
serigo(GORDON_REG_LCDIFCTL2, 0x7B);
mdelay(1);
}
static void gordon_disp_on(void)
{
if (gordon_state.disp_powered_up && !gordon_state.display_on) {
gordon_init();
mdelay(20);
/* gordon_dispmode setting */
serigo(GORDON_REG_TPARAM1, 0x30);
serigo(GORDON_REG_TLCDIF1, 0x00);
serigo(GORDON_REG_TSSPB_ST1, 0x8B);
serigo(GORDON_REG_TSSPB_ED1, 0x93);
serigo(GORDON_REG_TSCK_ST1, 0x88);
serigo(GORDON_REG_TSCK_WD1, 0x00);
serigo(GORDON_REG_TGSPB_VST1, 0x01);
serigo(GORDON_REG_TGSPB_VED1, 0x02);
serigo(GORDON_REG_TGSPB_CH1, 0x5E);
serigo(GORDON_REG_TGCK_ST1, 0x80);
serigo(GORDON_REG_TGCK_ED1, 0x3C);
serigo(GORDON_REG_TPCTL_ST1, 0x50);
serigo(GORDON_REG_TPCTL_ED1, 0x74);
serigo(GORDON_REG_TPCHG_ED1, 0x78);
serigo(GORDON_REG_TCOM_CH1, 0x50);
serigo(GORDON_REG_THBP1, 0x84);
serigo(GORDON_REG_TPHCTL1, 0x00);
serigo(GORDON_REG_EVPH1, 0x70);
serigo(GORDON_REG_EVPL1, 0x64);
serigo(GORDON_REG_EVNH1, 0x56);
serigo(GORDON_REG_EVNL1, 0x48);
serigo(GORDON_REG_TBIAS1, 0x88);
/* QVGA settings */
serigo(GORDON_REG_TPARAM2, 0x28);
serigo(GORDON_REG_TLCDIF2, 0x14);
serigo(GORDON_REG_TSSPB_ST2, 0x49);
serigo(GORDON_REG_TSSPB_ED2, 0x4B);
serigo(GORDON_REG_TSCK_ST2, 0x4A);
serigo(GORDON_REG_TSCK_WD2, 0x02);
serigo(GORDON_REG_TGSPB_VST2, 0x02);
serigo(GORDON_REG_TGSPB_VED2, 0x03);
serigo(GORDON_REG_TGSPB_CH2, 0x2F);
serigo(GORDON_REG_TGCK_ST2, 0x40);
serigo(GORDON_REG_TGCK_ED2, 0x1E);
serigo(GORDON_REG_TPCTL_ST2, 0x2C);
serigo(GORDON_REG_TPCTL_ED2, 0x3A);
serigo(GORDON_REG_TPCHG_ED2, 0x3C);
serigo(GORDON_REG_TCOM_CH2, 0x28);
serigo(GORDON_REG_THBP2, 0x4D);
serigo(GORDON_REG_TPHCTL2, 0x1A);
/* VGA settings */
serigo(GORDON_REG_IVBP1, 0x02);
serigo(GORDON_REG_IHBP1, 0x90);
serigo(GORDON_REG_IVNUM1, 0xA0);
serigo(GORDON_REG_IHNUM1, 0x78);
/* QVGA settings */
serigo(GORDON_REG_IVBP2, 0x02);
serigo(GORDON_REG_IHBP2, 0x48);
serigo(GORDON_REG_IVNUM2, 0x50);
serigo(GORDON_REG_IHNUM2, 0x3C);
/* Gordon Charge pump settings and ON */
serigo(GORDON_REG_POWCTL, 0x03);
mdelay(15);
serigo(GORDON_REG_POWCTL, 0x07);
mdelay(15);
serigo(GORDON_REG_POWCTL, 0x0F);
mdelay(15);
serigo(GORDON_REG_AVCTL, 0x03);
mdelay(15);
serigo(GORDON_REG_POWCTL, 0x1F);
mdelay(15);
serigo(GORDON_REG_POWCTL, 0x5F);
mdelay(15);
serigo(GORDON_REG_POWCTL, 0x7F);
mdelay(15);
serigo(GORDON_REG_LCDIFCTL1, 0x02);
mdelay(15);
serigo(GORDON_REG_IMGCTL1, 0x00);
mdelay(15);
serigo(GORDON_REG_LCDIFCTL3, 0x00);
mdelay(15);
serigo(GORDON_REG_VALTRAN, 0x01);
mdelay(15);
serigo(GORDON_REG_LCDIFCTL1, 0x03);
mdelay(1);
gordon_state.display_on = TRUE;
}
}
static int lcdc_gordon_panel_on(struct platform_device *pdev)
{
if (!gordon_state.disp_initialized) {
/* Configure reset GPIO that drives DAC */
lcdc_gordon_pdata->panel_config_gpio(1);
spi_dac = *(lcdc_gordon_pdata->gpio_num + 4);
gpio_set_value(spi_dac, 0);
udelay(15);
gpio_set_value(spi_dac, 1);
spi_init(); /* LCD needs SPI */
gordon_disp_powerup();
gordon_disp_on();
gordon_state.disp_initialized = TRUE;
}
return 0;
}
static int lcdc_gordon_panel_off(struct platform_device *pdev)
{
if (gordon_state.disp_powered_up && gordon_state.display_on) {
serigo(GORDON_REG_LCDIFCTL2, 0x7B);
serigo(GORDON_REG_VALTRAN, 0x01);
serigo(GORDON_REG_LCDIFCTL1, 0x02);
serigo(GORDON_REG_LCDIFCTL3, 0x01);
mdelay(20);
serigo(GORDON_REG_VALTRAN, 0x01);
serigo(GORDON_REG_IMGCTL1, 0x01);
serigo(GORDON_REG_LCDIFCTL1, 0x00);
mdelay(20);
serigo(GORDON_REG_POWCTL, 0x1F);
mdelay(40);
serigo(GORDON_REG_POWCTL, 0x07);
mdelay(40);
serigo(GORDON_REG_POWCTL, 0x03);
mdelay(40);
serigo(GORDON_REG_POWCTL, 0x00);
mdelay(40);
lcdc_gordon_pdata->panel_config_gpio(0);
gordon_state.display_on = FALSE;
gordon_state.disp_initialized = FALSE;
}
return 0;
}
static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
{
int bl_level = mfd->bl_level;
if (bl_level <= 1) {
/* keep back light OFF */
serigo(GORDON_REG_LCDIFCTL2, 0x0B);
udelay(15);
serigo(GORDON_REG_VALTRAN, 0x01);
} else {
/* keep back light ON */
serigo(GORDON_REG_LCDIFCTL2, 0x7B);
udelay(15);
serigo(GORDON_REG_VALTRAN, 0x01);
}
}
static int __init gordon_probe(struct platform_device *pdev)
{
if (pdev->id == 0) {
lcdc_gordon_pdata = pdev->dev.platform_data;
return 0;
}
msm_fb_add_device(pdev);
return 0;
}
static struct platform_driver this_driver = {
.probe = gordon_probe,
.driver = {
.name = "lcdc_gordon_vga",
},
};
static struct msm_fb_panel_data gordon_panel_data = {
.on = lcdc_gordon_panel_on,
.off = lcdc_gordon_panel_off,
.set_backlight = lcdc_gordon_set_backlight,
};
static struct platform_device this_device = {
.name = "lcdc_gordon_vga",
.id = 1,
.dev = {
.platform_data = &gordon_panel_data,
}
};
static int __init lcdc_gordon_panel_init(void)
{
int ret;
struct msm_panel_info *pinfo;
#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
if (msm_fb_detect_client("lcdc_gordon_vga"))
return 0;
#endif
ret = platform_driver_register(&this_driver);
if (ret)
return ret;
pinfo = &gordon_panel_data.panel_info;
pinfo->xres = 480;
pinfo->yres = 640;
pinfo->type = LCDC_PANEL;
pinfo->pdest = DISPLAY_1;
pinfo->wait_cycle = 0;
pinfo->bpp = 24;
pinfo->fb_num = 2;
pinfo->clk_rate = 24500000;
pinfo->bl_max = 4;
pinfo->bl_min = 1;
pinfo->lcdc.h_back_porch = 84;
pinfo->lcdc.h_front_porch = 33;
pinfo->lcdc.h_pulse_width = 60;
pinfo->lcdc.v_back_porch = 0;
pinfo->lcdc.v_front_porch = 2;
pinfo->lcdc.v_pulse_width = 2;
pinfo->lcdc.border_clr = 0; /* blk */
pinfo->lcdc.underflow_clr = 0xff; /* blue */
pinfo->lcdc.hsync_skew = 0;
ret = platform_device_register(&this_device);
if (ret)
platform_driver_unregister(&this_driver);
return ret;
}
module_init(lcdc_gordon_panel_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
#include "mddihosti.h"
#endif
static int __init lcdc_grapefruit_init(void)
{
int ret;
struct msm_panel_info pinfo;
#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
if (msm_fb_detect_client("lcdc_grapefruit_vga"))
return 0;
#endif
pinfo.xres = 1024;
pinfo.yres = 600;
pinfo.type = LCDC_PANEL;
pinfo.pdest = DISPLAY_1;
pinfo.wait_cycle = 0;
pinfo.bpp = 18;
pinfo.fb_num = 2;
pinfo.clk_rate = 40000000;
pinfo.lcdc.h_back_porch = 88;
pinfo.lcdc.h_front_porch = 40;
pinfo.lcdc.h_pulse_width = 128;
pinfo.lcdc.v_back_porch = 23;
pinfo.lcdc.v_front_porch = 1;
pinfo.lcdc.v_pulse_width = 4;
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
ret = lcdc_device_register(&pinfo);
if (ret)
printk(KERN_ERR "%s: failed to register device!\n", __func__);
return ret;
}
module_init(lcdc_grapefruit_init);
/* Copyright (c) 2008-2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
static int lcdc_panel_on(struct platform_device *pdev)
{
return 0;
}
static int lcdc_panel_off(struct platform_device *pdev)
{
return 0;
}
static int __init lcdc_panel_probe(struct platform_device *pdev)
{
msm_fb_add_device(pdev);
return 0;
}
static struct platform_driver this_driver = {
.probe = lcdc_panel_probe,
.driver = {
.name = "lcdc_panel",
},
};
static struct msm_fb_panel_data lcdc_panel_data = {
.on = lcdc_panel_on,
.off = lcdc_panel_off,
};
static int lcdc_dev_id;
int lcdc_device_register(struct msm_panel_info *pinfo)
{
struct platform_device *pdev = NULL;
int ret;
pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id);
if (!pdev)
return -ENOMEM;
lcdc_panel_data.panel_info = *pinfo;
ret = platform_device_add_data(pdev, &lcdc_panel_data,
sizeof(lcdc_panel_data));
if (ret) {
printk(KERN_ERR
"%s: platform_device_add_data failed!\n", __func__);
goto err_device_put;
}
ret = platform_device_add(pdev);
if (ret) {
printk(KERN_ERR
"%s: platform_device_register failed!\n", __func__);
goto err_device_put;
}
return 0;
err_device_put:
platform_device_put(pdev);
return ret;
}
static int __init lcdc_panel_init(void)
{
return platform_driver_register(&this_driver);
}
module_init(lcdc_panel_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
#include "mddihosti.h"
#endif
static int __init lcdc_prism_init(void)
{
int ret;
struct msm_panel_info pinfo;
#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
ret = msm_fb_detect_client("lcdc_prism_wvga");
if (ret == -ENODEV)
return 0;
if (ret && (mddi_get_client_id() != 0))
return 0;
#endif
pinfo.xres = 800;
pinfo.yres = 480;
pinfo.type = LCDC_PANEL;
pinfo.pdest = DISPLAY_1;
pinfo.wait_cycle = 0;
pinfo.bpp = 24;
pinfo.fb_num = 2;
pinfo.clk_rate = 38460000;
pinfo.lcdc.h_back_porch = 21;
pinfo.lcdc.h_front_porch = 81;
pinfo.lcdc.h_pulse_width = 60;
pinfo.lcdc.v_back_porch = 18;
pinfo.lcdc.v_front_porch = 27;
pinfo.lcdc.v_pulse_width = 2;
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
ret = lcdc_device_register(&pinfo);
if (ret)
printk(KERN_ERR "%s: failed to register device!\n", __func__);
return ret;
}
module_init(lcdc_prism_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/delay.h>
#ifdef CONFIG_ARCH_MSM7X30
#include <linux/mfd/pmic8058.h>
#endif
#include <mach/gpio.h>
#include "msm_fb.h"
static int lcdc_sharp_panel_off(struct platform_device *pdev);
static int spi_cs;
static int spi_sclk;
static int spi_mosi;
static int spi_miso;
static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
(1 << 6),
(1 << 5),
(1 << 4),
(1 << 3),
(1 << 2),
(1 << 1),
(1 << 0) /* LSB */
};
struct sharp_state_type {
boolean disp_initialized;
boolean display_on;
boolean disp_powered_up;
};
struct sharp_spi_data {
u8 addr;
u8 data;
};
static struct sharp_spi_data init_sequence[] = {
{ 15, 0x01 },
{ 5, 0x01 },
{ 7, 0x10 },
{ 9, 0x1E },
{ 10, 0x04 },
{ 17, 0xFF },
{ 21, 0x8A },
{ 22, 0x00 },
{ 23, 0x82 },
{ 24, 0x24 },
{ 25, 0x22 },
{ 26, 0x6D },
{ 27, 0xEB },
{ 28, 0xB9 },
{ 29, 0x3A },
{ 49, 0x1A },
{ 50, 0x16 },
{ 51, 0x05 },
{ 55, 0x7F },
{ 56, 0x15 },
{ 57, 0x7B },
{ 60, 0x05 },
{ 61, 0x0C },
{ 62, 0x80 },
{ 63, 0x00 },
{ 92, 0x90 },
{ 97, 0x01 },
{ 98, 0xFF },
{ 113, 0x11 },
{ 114, 0x02 },
{ 115, 0x08 },
{ 123, 0xAB },
{ 124, 0x04 },
{ 6, 0x02 },
{ 133, 0x00 },
{ 134, 0xFE },
{ 135, 0x22 },
{ 136, 0x0B },
{ 137, 0xFF },
{ 138, 0x0F },
{ 139, 0x00 },
{ 140, 0xFE },
{ 141, 0x22 },
{ 142, 0x0B },
{ 143, 0xFF },
{ 144, 0x0F },
{ 145, 0x00 },
{ 146, 0xFE },
{ 147, 0x22 },
{ 148, 0x0B },
{ 149, 0xFF },
{ 150, 0x0F },
{ 202, 0x30 },
{ 30, 0x01 },
{ 4, 0x01 },
{ 31, 0x41 },
};
static struct sharp_state_type sharp_state = { 0 };
static struct msm_panel_common_pdata *lcdc_sharp_pdata;
static void sharp_spi_write_byte(u8 val)
{
int i;
/* Clock should be Low before entering */
for (i = 0; i < 8; i++) {
/* #1: Drive the Data (High or Low) */
if (val & bit_shift[i])
gpio_set_value(spi_mosi, 1);
else
gpio_set_value(spi_mosi, 0);
/* #2: Drive the Clk High and then Low */
gpio_set_value(spi_sclk, 1);
gpio_set_value(spi_sclk, 0);
}
}
static void serigo(u8 reg, u8 data)
{
/* Enable the Chip Select - low */
gpio_set_value(spi_cs, 0);
udelay(1);
/* Transmit register address first, then data */
sharp_spi_write_byte(reg);
/* Idle state of MOSI is Low */
gpio_set_value(spi_mosi, 0);
udelay(1);
sharp_spi_write_byte(data);
gpio_set_value(spi_mosi, 0);
gpio_set_value(spi_cs, 1);
}
static void sharp_spi_init(void)
{
spi_sclk = *(lcdc_sharp_pdata->gpio_num);
spi_cs = *(lcdc_sharp_pdata->gpio_num + 1);
spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2);
spi_miso = *(lcdc_sharp_pdata->gpio_num + 3);
/* Set the output so that we don't disturb the slave device */
gpio_set_value(spi_sclk, 0);
gpio_set_value(spi_mosi, 0);
/* Set the Chip Select deasserted (active low) */
gpio_set_value(spi_cs, 1);
}
static void sharp_disp_powerup(void)
{
if (!sharp_state.disp_powered_up && !sharp_state.display_on)
sharp_state.disp_powered_up = TRUE;
}
static void sharp_disp_on(void)
{
int i;
if (sharp_state.disp_powered_up && !sharp_state.display_on) {
for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
serigo(init_sequence[i].addr,
init_sequence[i].data);
}
mdelay(10);
serigo(31, 0xC1);
mdelay(10);
serigo(31, 0xD9);
serigo(31, 0xDF);
sharp_state.display_on = TRUE;
}
}
static int lcdc_sharp_panel_on(struct platform_device *pdev)
{
if (!sharp_state.disp_initialized) {
lcdc_sharp_pdata->panel_config_gpio(1);
sharp_spi_init();
sharp_disp_powerup();
sharp_disp_on();
sharp_state.disp_initialized = TRUE;
}
return 0;
}
static int lcdc_sharp_panel_off(struct platform_device *pdev)
{
if (sharp_state.disp_powered_up && sharp_state.display_on) {
serigo(4, 0x00);
mdelay(40);
serigo(31, 0xC1);
mdelay(40);
serigo(31, 0x00);
mdelay(100);
sharp_state.display_on = FALSE;
sharp_state.disp_initialized = FALSE;
}
return 0;
}
static int __init sharp_probe(struct platform_device *pdev)
{
if (pdev->id == 0) {
lcdc_sharp_pdata = pdev->dev.platform_data;
return 0;
}
msm_fb_add_device(pdev);
return 0;
}
static struct platform_driver this_driver = {
.probe = sharp_probe,
.driver = {
.name = "lcdc_sharp_wvga",
},
};
static struct msm_fb_panel_data sharp_panel_data = {
.on = lcdc_sharp_panel_on,
.off = lcdc_sharp_panel_off,
};
static struct platform_device this_device = {
.name = "lcdc_sharp_wvga",
.id = 1,
.dev = {
.platform_data = &sharp_panel_data,
}
};
static int __init lcdc_sharp_panel_init(void)
{
int ret;
struct msm_panel_info *pinfo;
#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
if (msm_fb_detect_client("lcdc_sharp_wvga_pt"))
return 0;
#endif
ret = platform_driver_register(&this_driver);
if (ret)
return ret;
pinfo = &sharp_panel_data.panel_info;
pinfo->xres = 480;
pinfo->yres = 800;
pinfo->type = LCDC_PANEL;
pinfo->pdest = DISPLAY_1;
pinfo->wait_cycle = 0;
pinfo->bpp = 18;
pinfo->fb_num = 2;
pinfo->clk_rate = 24500000;
pinfo->bl_max = 4;
pinfo->bl_min = 1;
pinfo->lcdc.h_back_porch = 20;
pinfo->lcdc.h_front_porch = 10;
pinfo->lcdc.h_pulse_width = 10;
pinfo->lcdc.v_back_porch = 2;
pinfo->lcdc.v_front_porch = 2;
pinfo->lcdc.v_pulse_width = 2;
pinfo->lcdc.border_clr = 0;
pinfo->lcdc.underflow_clr = 0xff;
pinfo->lcdc.hsync_skew = 0;
ret = platform_device_register(&this_device);
if (ret)
platform_driver_unregister(&this_driver);
return ret;
}
module_init(lcdc_sharp_panel_init);
/* Copyright (c) 2010, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/i2c.h>
#include <linux/delay.h>
#include "msm_fb.h"
#define DEVICE_NAME "sii9022"
#define SII9022_DEVICE_ID 0xB0
struct sii9022_i2c_addr_data{
u8 addr;
u8 data;
};
/* video mode data */
static u8 video_mode_data[] = {
0x00,
0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
};
static u8 avi_io_format[] = {
0x09,
0x00, 0x00,
};
/* power state */
static struct sii9022_i2c_addr_data regset0[] = {
{ 0x60, 0x04 },
{ 0x63, 0x00 },
{ 0x1E, 0x00 },
};
static u8 video_infoframe[] = {
0x0C,
0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
};
/* configure audio */
static struct sii9022_i2c_addr_data regset1[] = {
{ 0x26, 0x90 },
{ 0x20, 0x90 },
{ 0x1F, 0x80 },
{ 0x26, 0x80 },
{ 0x24, 0x02 },
{ 0x25, 0x0B },
{ 0xBC, 0x02 },
{ 0xBD, 0x24 },
{ 0xBE, 0x02 },
};
/* enable audio */
static u8 misc_infoframe[] = {
0xBF,
0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* set HDMI, active */
static struct sii9022_i2c_addr_data regset2[] = {
{ 0x1A, 0x01 },
{ 0x3D, 0x00 },
};
static int send_i2c_data(struct i2c_client *client,
struct sii9022_i2c_addr_data *regset,
int size)
{
int i;
int rc = 0;
for (i = 0; i < size; i++) {
rc = i2c_smbus_write_byte_data(
client,
regset[i].addr, regset[i].data);
if (rc)
break;
}
return rc;
}
static int hdmi_sii_enable(struct i2c_client *client)
{
int rc;
int retries = 10;
int count;
rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
if (rc)
goto enable_exit;
do {
msleep(1);
rc = i2c_smbus_read_byte_data(client, 0x1B);
} while ((rc != SII9022_DEVICE_ID) && retries--);
if (rc != SII9022_DEVICE_ID)
return -ENODEV;
rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
if (rc)
goto enable_exit;
count = ARRAY_SIZE(video_mode_data);
rc = i2c_master_send(client, video_mode_data, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
if (rc)
goto enable_exit;
count = ARRAY_SIZE(avi_io_format);
rc = i2c_master_send(client, avi_io_format, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
if (rc)
goto enable_exit;
count = ARRAY_SIZE(video_infoframe);
rc = i2c_master_send(client, video_infoframe, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
if (rc)
goto enable_exit;
count = ARRAY_SIZE(misc_infoframe);
rc = i2c_master_send(client, misc_infoframe, count);
if (rc != count) {
rc = -EIO;
goto enable_exit;
}
rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
if (rc)
goto enable_exit;
return 0;
enable_exit:
printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
return rc;
}
static const struct i2c_device_id hmdi_sii_id[] = {
{ DEVICE_NAME, 0 },
{ }
};
static int hdmi_sii_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rc;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
return -ENODEV;
rc = hdmi_sii_enable(client);
return rc;
}
static struct i2c_driver hdmi_sii_i2c_driver = {
.driver = {
.name = DEVICE_NAME,
.owner = THIS_MODULE,
},
.probe = hdmi_sii_probe,
.remove = __exit_p(hdmi_sii_remove),
.id_table = hmdi_sii_id,
};
static int __init lcdc_st15_init(void)
{
int ret;
struct msm_panel_info pinfo;
if (msm_fb_detect_client("lcdc_st15"))
return 0;
pinfo.xres = 1366;
pinfo.yres = 768;
pinfo.type = LCDC_PANEL;
pinfo.pdest = DISPLAY_1;
pinfo.wait_cycle = 0;
pinfo.bpp = 24;
pinfo.fb_num = 2;
pinfo.clk_rate = 74250000;
pinfo.lcdc.h_back_porch = 120;
pinfo.lcdc.h_front_porch = 20;
pinfo.lcdc.h_pulse_width = 40;
pinfo.lcdc.v_back_porch = 25;
pinfo.lcdc.v_front_porch = 1;
pinfo.lcdc.v_pulse_width = 7;
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
ret = lcdc_device_register(&pinfo);
if (ret) {
printk(KERN_ERR "%s: failed to register device!\n", __func__);
goto init_exit;
}
ret = i2c_add_driver(&hdmi_sii_i2c_driver);
if (ret)
printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
init_exit:
return ret;
}
module_init(lcdc_st15_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
static int __init lcdc_st1_wxga_init(void)
{
int ret;
struct msm_panel_info pinfo;
if (msm_fb_detect_client("lcdc_st1_wxga"))
return 0;
pinfo.xres = 1280;
pinfo.yres = 720;
pinfo.type = LCDC_PANEL;
pinfo.pdest = DISPLAY_1;
pinfo.wait_cycle = 0;
pinfo.bpp = 18;
pinfo.fb_num = 2;
pinfo.clk_rate = 74250000;
pinfo.lcdc.h_back_porch = 124;
pinfo.lcdc.h_front_porch = 110;
pinfo.lcdc.h_pulse_width = 136;
pinfo.lcdc.v_back_porch = 19;
pinfo.lcdc.v_front_porch = 5;
pinfo.lcdc.v_pulse_width = 6;
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
ret = lcdc_device_register(&pinfo);
if (ret)
printk(KERN_ERR "%s: failed to register device!\n", __func__);
return ret;
}
module_init(lcdc_st1_wxga_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <mach/gpio.h>
#include <mach/pmic.h>
#include "msm_fb.h"
#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
#include "mddihosti.h"
#endif
static int spi_cs;
static int spi_sclk;
static int spi_mosi;
static int spi_miso;
struct toshiba_state_type{
boolean disp_initialized;
boolean display_on;
boolean disp_powered_up;
};
static struct toshiba_state_type toshiba_state = { 0 };
static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
static void toshiba_spi_write_byte(char dc, uint8 data)
{
uint32 bit;
int bnum;
gpio_set_value(spi_sclk, 0); /* clk low */
/* dc: 0 for command, 1 for parameter */
gpio_set_value(spi_mosi, dc);
udelay(1); /* at least 20 ns */
gpio_set_value(spi_sclk, 1); /* clk high */
udelay(1); /* at least 20 ns */
bnum = 8; /* 8 data bits */
bit = 0x80;
while (bnum) {
gpio_set_value(spi_sclk, 0); /* clk low */
if (data & bit)
gpio_set_value(spi_mosi, 1);
else
gpio_set_value(spi_mosi, 0);
udelay(1);
gpio_set_value(spi_sclk, 1); /* clk high */
udelay(1);
bit >>= 1;
bnum--;
}
}
static void toshiba_spi_write(char cmd, uint32 data, int num)
{
char *bp;
gpio_set_value(spi_cs, 1); /* cs high */
/* command byte first */
toshiba_spi_write_byte(0, cmd);
/* followed by parameter bytes */
if (num) {
bp = (char *)&data;;
bp += (num - 1);
while (num) {
toshiba_spi_write_byte(1, *bp);
num--;
bp--;
}
}
gpio_set_value(spi_cs, 0); /* cs low */
udelay(1);
}
void toshiba_spi_read_bytes(char cmd, uint32 *data, int num)
{
uint32 dbit, bits;
int bnum;
gpio_set_value(spi_cs, 1); /* cs high */
/* command byte first */
toshiba_spi_write_byte(0, cmd);
if (num > 1) {
/* extra dc bit */
gpio_set_value(spi_sclk, 0); /* clk low */
udelay(1);
dbit = gpio_get_value(spi_miso);/* dc bit */
udelay(1);
gpio_set_value(spi_sclk, 1); /* clk high */
}
/* followed by data bytes */
bnum = num * 8; /* number of bits */
bits = 0;
while (bnum) {
bits <<= 1;
gpio_set_value(spi_sclk, 0); /* clk low */
udelay(1);
dbit = gpio_get_value(spi_miso);
udelay(1);
gpio_set_value(spi_sclk, 1); /* clk high */
bits |= dbit;
bnum--;
}
*data = bits;
udelay(1);
gpio_set_value(spi_cs, 0); /* cs low */
udelay(1);
}
static void spi_pin_assign(void)
{
/* Setting the Default GPIO's */
spi_sclk = *(lcdc_toshiba_pdata->gpio_num);
spi_cs = *(lcdc_toshiba_pdata->gpio_num + 1);
spi_mosi = *(lcdc_toshiba_pdata->gpio_num + 2);
spi_miso = *(lcdc_toshiba_pdata->gpio_num + 3);
}
static void toshiba_disp_powerup(void)
{
if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
/* Reset the hardware first */
/* Include DAC power up implementation here */
toshiba_state.disp_powered_up = TRUE;
}
}
static void toshiba_disp_on(void)
{
uint32 data;
gpio_set_value(spi_cs, 0); /* low */
gpio_set_value(spi_sclk, 1); /* high */
gpio_set_value(spi_mosi, 0);
gpio_set_value(spi_miso, 0);
if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
toshiba_spi_write(0, 0, 0);
mdelay(7);
toshiba_spi_write(0, 0, 0);
mdelay(7);
toshiba_spi_write(0, 0, 0);
mdelay(7);
toshiba_spi_write(0xba, 0x11, 1);
toshiba_spi_write(0x36, 0x00, 1);
mdelay(1);
toshiba_spi_write(0x3a, 0x60, 1);
toshiba_spi_write(0xb1, 0x5d, 1);
mdelay(1);
toshiba_spi_write(0xb2, 0x33, 1);
toshiba_spi_write(0xb3, 0x22, 1);
mdelay(1);
toshiba_spi_write(0xb4, 0x02, 1);
toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
mdelay(1);
toshiba_spi_write(0xb6, 0x27, 1);
toshiba_spi_write(0xb7, 0x03, 1);
mdelay(1);
toshiba_spi_write(0xb9, 0x24, 1);
toshiba_spi_write(0xbd, 0xa1, 1);
mdelay(1);
toshiba_spi_write(0xbb, 0x00, 1);
toshiba_spi_write(0xbf, 0x01, 1);
mdelay(1);
toshiba_spi_write(0xbe, 0x00, 1);
toshiba_spi_write(0xc0, 0x11, 1);
mdelay(1);
toshiba_spi_write(0xc1, 0x11, 1);
toshiba_spi_write(0xc2, 0x11, 1);
mdelay(1);
toshiba_spi_write(0xc3, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc4, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc5, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc6, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc7, 0x6445, 2);
mdelay(1);
toshiba_spi_write(0xc8, 0x44, 1);
toshiba_spi_write(0xc9, 0x52, 1);
mdelay(1);
toshiba_spi_write(0xca, 0x00, 1);
mdelay(1);
toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */
mdelay(1);
toshiba_spi_write(0xcf, 0x01, 1);
mdelay(1);
toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */
mdelay(1);
toshiba_spi_write(0xd1, 0x01, 1);
mdelay(1);
toshiba_spi_write(0xd2, 0x0028, 2);
mdelay(1);
toshiba_spi_write(0xd3, 0x0028, 2);
mdelay(1);
toshiba_spi_write(0xd4, 0x26a4, 2);
mdelay(1);
toshiba_spi_write(0xd5, 0x20, 1);
mdelay(1);
toshiba_spi_write(0xef, 0x3200, 2);
mdelay(32);
toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */
toshiba_spi_write(0x3b, 0x00, 1);
mdelay(1);
toshiba_spi_write(0xb0, 0x16, 1);
mdelay(1);
toshiba_spi_write(0xb8, 0xfff5, 2);
mdelay(1);
toshiba_spi_write(0x11, 0, 0);
mdelay(5);
toshiba_spi_write(0x29, 0, 0);
mdelay(5);
toshiba_state.display_on = TRUE;
}
data = 0;
toshiba_spi_read_bytes(0x04, &data, 3);
printk(KERN_INFO "toshiba_disp_on: id=%x\n", data);
}
static int lcdc_toshiba_panel_on(struct platform_device *pdev)
{
if (!toshiba_state.disp_initialized) {
/* Configure reset GPIO that drives DAC */
if (lcdc_toshiba_pdata->panel_config_gpio)
lcdc_toshiba_pdata->panel_config_gpio(1);
toshiba_disp_powerup();
toshiba_disp_on();
toshiba_state.disp_initialized = TRUE;
}
return 0;
}
static int lcdc_toshiba_panel_off(struct platform_device *pdev)
{
if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
/* Main panel power off (Deep standby in) */
toshiba_spi_write(0x28, 0, 0); /* display off */
mdelay(1);
toshiba_spi_write(0xb8, 0x8002, 2); /* output control */
mdelay(1);
toshiba_spi_write(0x10, 0x00, 1); /* sleep mode in */
mdelay(85); /* wait 85 msec */
toshiba_spi_write(0xb0, 0x00, 1); /* deep standby in */
mdelay(1);
if (lcdc_toshiba_pdata->panel_config_gpio)
lcdc_toshiba_pdata->panel_config_gpio(0);
toshiba_state.display_on = FALSE;
toshiba_state.disp_initialized = FALSE;
}
return 0;
}
static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
{
int bl_level;
int ret = -EPERM;
bl_level = mfd->bl_level;
ret = pmic_set_led_intensity(LED_LCD, bl_level);
if (ret)
printk(KERN_WARNING "%s: can't set lcd backlight!\n",
__func__);
}
static int __init toshiba_probe(struct platform_device *pdev)
{
if (pdev->id == 0) {
lcdc_toshiba_pdata = pdev->dev.platform_data;
spi_pin_assign();
return 0;
}
msm_fb_add_device(pdev);
return 0;
}
static struct platform_driver this_driver = {
.probe = toshiba_probe,
.driver = {
.name = "lcdc_toshiba_wvga",
},
};
static struct msm_fb_panel_data toshiba_panel_data = {
.on = lcdc_toshiba_panel_on,
.off = lcdc_toshiba_panel_off,
.set_backlight = lcdc_toshiba_set_backlight,
};
static struct platform_device this_device = {
.name = "lcdc_toshiba_wvga",
.id = 1,
.dev = {
.platform_data = &toshiba_panel_data,
}
};
static int __init lcdc_toshiba_panel_init(void)
{
int ret;
struct msm_panel_info *pinfo;
#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
if (mddi_get_client_id() != 0)
return 0;
ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt");
if (ret)
return 0;
#endif
ret = platform_driver_register(&this_driver);
if (ret)
return ret;
pinfo = &toshiba_panel_data.panel_info;
pinfo->xres = 480;
pinfo->yres = 800;
pinfo->type = LCDC_PANEL;
pinfo->pdest = DISPLAY_1;
pinfo->wait_cycle = 0;
pinfo->bpp = 18;
pinfo->fb_num = 2;
/* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
pinfo->clk_rate = 27648000;
pinfo->bl_max = 15;
pinfo->bl_min = 1;
pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */
pinfo->lcdc.h_front_porch = 4;
pinfo->lcdc.h_pulse_width = 8;
pinfo->lcdc.v_back_porch = 2; /* vsw=1 + vbp = 2 */
pinfo->lcdc.v_front_porch = 3;
pinfo->lcdc.v_pulse_width = 1;
pinfo->lcdc.border_clr = 0; /* blk */
pinfo->lcdc.underflow_clr = 0xff; /* blue */
pinfo->lcdc.hsync_skew = 0;
ret = platform_device_register(&this_device);
if (ret)
platform_driver_unregister(&this_driver);
return ret;
}
device_initcall(lcdc_toshiba_panel_init);
/* Copyright (c) 2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
static int __init lcdc_wxga_init(void)
{
int ret;
struct msm_panel_info pinfo;
#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
if (msm_fb_detect_client("lcdc_wxga"))
return 0;
#endif
pinfo.xres = 1280;
pinfo.yres = 720;
pinfo.type = LCDC_PANEL;
pinfo.pdest = DISPLAY_1;
pinfo.wait_cycle = 0;
pinfo.bpp = 24;
pinfo.fb_num = 2;
pinfo.clk_rate = 74250000;
pinfo.lcdc.h_back_porch = 124;
pinfo.lcdc.h_front_porch = 110;
pinfo.lcdc.h_pulse_width = 136;
pinfo.lcdc.v_back_porch = 19;
pinfo.lcdc.v_front_porch = 5;
pinfo.lcdc.v_pulse_width = 6;
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
ret = lcdc_device_register(&pinfo);
if (ret)
printk(KERN_ERR "%s: failed to register device!\n", __func__);
return ret;
}
module_init(lcdc_wxga_init);
/* drivers/video/msm/logo.c
*
* Show Logo in RLE 565 format
*
* Copyright (C) 2008 Google Incorporated
*
* 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 <linux/module.h>
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/unistd.h>
#include <linux/syscalls.h>
#include <linux/irq.h>
#include <asm/system.h>
#define fb_width(fb) ((fb)->var.xres)
#define fb_height(fb) ((fb)->var.yres)
#define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * 2)
static void memset16(void *_ptr, unsigned short val, unsigned count)
{
unsigned short *ptr = _ptr;
count >>= 1;
while (count--)
*ptr++ = val;
}
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
int load_565rle_image(char *filename)
{
struct fb_info *info;
int fd, err = 0;
unsigned count, max;
unsigned short *data, *bits, *ptr;
info = registered_fb[0];
if (!info) {
printk(KERN_WARNING "%s: Can not access framebuffer\n",
__func__);
return -ENODEV;
}
fd = sys_open(filename, O_RDONLY, 0);
if (fd < 0) {
printk(KERN_WARNING "%s: Can not open %s\n",
__func__, filename);
return -ENOENT;
}
count = (unsigned)sys_lseek(fd, (off_t)0, 2);
if (count == 0) {
sys_close(fd);
err = -EIO;
goto err_logo_close_file;
}
sys_lseek(fd, (off_t)0, 0);
data = kmalloc(count, GFP_KERNEL);
if (!data) {
printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
err = -ENOMEM;
goto err_logo_close_file;
}
if ((unsigned)sys_read(fd, (char *)data, count) != count) {
err = -EIO;
goto err_logo_free_data;
}
max = fb_width(info) * fb_height(info);
ptr = data;
bits = (unsigned short *)(info->screen_base);
while (count > 3) {
unsigned n = ptr[0];
if (n > max)
break;
memset16(bits, ptr[1], n << 1);
bits += n;
max -= n;
ptr += 2;
count -= 4;
}
err_logo_free_data:
kfree(data);
err_logo_close_file:
sys_close(fd);
return err;
}
EXPORT_SYMBOL(load_565rle_image);
/* Copyright (c) 2008-2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <linux/semaphore.h>
#include <linux/uaccess.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include "msm_fb.h"
#include "mddihosti.h"
#include "mddihost.h"
#include <mach/gpio.h>
#include <mach/clk.h>
static int mddi_probe(struct platform_device *pdev);
static int mddi_remove(struct platform_device *pdev);
static int mddi_off(struct platform_device *pdev);
static int mddi_on(struct platform_device *pdev);
static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
static int mddi_resume(struct platform_device *pdev);
#ifdef CONFIG_HAS_EARLYSUSPEND
static void mddi_early_suspend(struct early_suspend *h);
static void mddi_early_resume(struct early_suspend *h);
#endif
static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
static int pdev_list_cnt;
static struct clk *mddi_clk;
static struct clk *mddi_pclk;
static struct mddi_platform_data *mddi_pdata;
static struct platform_driver mddi_driver = {
.probe = mddi_probe,
.remove = mddi_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND
#ifdef CONFIG_PM
.suspend = mddi_suspend,
.resume = mddi_resume,
#endif
#endif
.suspend_late = NULL,
.resume_early = NULL,
.shutdown = NULL,
.driver = {
.name = "mddi",
},
};
extern int int_mddi_pri_flag;
static int mddi_off(struct platform_device *pdev)
{
int ret = 0;
ret = panel_next_off(pdev);
if (mddi_pdata && mddi_pdata->mddi_power_save)
mddi_pdata->mddi_power_save(0);
return ret;
}
static int mddi_on(struct platform_device *pdev)
{
int ret = 0;
u32 clk_rate;
struct msm_fb_data_type *mfd;
mfd = platform_get_drvdata(pdev);
if (mddi_pdata && mddi_pdata->mddi_power_save)
mddi_pdata->mddi_power_save(1);
clk_rate = mfd->fbi->var.pixclock;
clk_rate = min(clk_rate, mfd->panel_info.clk_max);
if (mddi_pdata &&
mddi_pdata->mddi_sel_clk &&
mddi_pdata->mddi_sel_clk(&clk_rate))
printk(KERN_ERR
"%s: can't select mddi io clk targate rate = %d\n",
__func__, clk_rate);
if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
printk(KERN_ERR "%s: clk_set_min_rate failed\n",
__func__);
ret = panel_next_on(pdev);
return ret;
}
static int mddi_resource_initialized;
static int mddi_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;
resource_size_t size ;
u32 clk_rate;
if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
mddi_pdata = pdev->dev.platform_data;
size = resource_size(&pdev->resource[0]);
msm_pmdh_base = ioremap(pdev->resource[0].start, size);
MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
pdev->resource[0].start, (int) msm_pmdh_base);
if (unlikely(!msm_pmdh_base))
return -ENOMEM;
if (mddi_pdata && mddi_pdata->mddi_power_save)
mddi_pdata->mddi_power_save(1);
mddi_resource_initialized = 1;
return 0;
}
if (!mddi_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;
mdp_dev = platform_device_alloc("mdp", pdev->id);
if (!mdp_dev)
return -ENOMEM;
/*
* link to the latest pdev
*/
mfd->pdev = mdp_dev;
mfd->dest = DISPLAY_LCD;
/*
* alloc panel device data
*/
if (platform_device_add_data
(mdp_dev, pdev->dev.platform_data,
sizeof(struct msm_fb_panel_data))) {
printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
platform_device_put(mdp_dev);
return -ENOMEM;
}
/*
* data chain
*/
pdata = mdp_dev->dev.platform_data;
pdata->on = mddi_on;
pdata->off = mddi_off;
pdata->next = pdev;
/*
* get/set panel specific fb info
*/
mfd->panel_info = pdata->panel_info;
mfd->fb_imgType = MDP_RGB_565;
clk_rate = mfd->panel_info.clk_max;
if (mddi_pdata &&
mddi_pdata->mddi_sel_clk &&
mddi_pdata->mddi_sel_clk(&clk_rate))
printk(KERN_ERR
"%s: can't select mddi io clk targate rate = %d\n",
__func__, clk_rate);
if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
/*
* set driver data
*/
platform_set_drvdata(mdp_dev, mfd);
/*
* register in mdp driver
*/
rc = platform_device_add(mdp_dev);
if (rc)
goto mddi_probe_err;
pdev_list[pdev_list_cnt++] = pdev;
#ifdef CONFIG_HAS_EARLYSUSPEND
mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
mfd->mddi_early_suspend.suspend = mddi_early_suspend;
mfd->mddi_early_suspend.resume = mddi_early_resume;
register_early_suspend(&mfd->mddi_early_suspend);
#endif
return 0;
mddi_probe_err:
platform_device_put(mdp_dev);
return rc;
}
static int mddi_pad_ctrl;
static int mddi_power_locked;
static int mddi_is_in_suspend;
void mddi_disable(int lock)
{
mddi_host_type host_idx = MDDI_HOST_PRIM;
if (mddi_power_locked)
return;
if (lock)
mddi_power_locked = 1;
if (mddi_host_timer.function)
del_timer_sync(&mddi_host_timer);
mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
mddi_host_reg_out(PAD_CTL, 0x0);
if (clk_set_min_rate(mddi_clk, 0) < 0)
printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
clk_disable(mddi_clk);
if (mddi_pclk)
clk_disable(mddi_pclk);
disable_irq(INT_MDDI_PRI);
if (mddi_pdata && mddi_pdata->mddi_power_save)
mddi_pdata->mddi_power_save(0);
}
static int mddi_suspend(struct platform_device *pdev, pm_message_t state)
{
if (mddi_is_in_suspend)
return 0;
mddi_is_in_suspend = 1;
mddi_disable(0);
return 0;
}
static int mddi_resume(struct platform_device *pdev)
{
mddi_host_type host_idx = MDDI_HOST_PRIM;
if (!mddi_is_in_suspend)
return 0;
mddi_is_in_suspend = 0;
if (mddi_power_locked)
return 0;
enable_irq(INT_MDDI_PRI);
clk_enable(mddi_clk);
if (mddi_pclk)
clk_enable(mddi_pclk);
mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl);
if (mddi_host_timer.function)
mddi_host_timer_service(0);
return 0;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void mddi_early_suspend(struct early_suspend *h)
{
pm_message_t state;
struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
mddi_early_suspend);
state.event = PM_EVENT_SUSPEND;
mddi_suspend(mfd->pdev, state);
}
static void mddi_early_resume(struct early_suspend *h)
{
struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
mddi_early_suspend);
mddi_resume(mfd->pdev);
}
#endif
static int mddi_remove(struct platform_device *pdev)
{
if (mddi_host_timer.function)
del_timer_sync(&mddi_host_timer);
iounmap(msm_pmdh_base);
return 0;
}
static int mddi_register_driver(void)
{
return platform_driver_register(&mddi_driver);
}
static int __init mddi_driver_init(void)
{
int ret;
mddi_clk = clk_get(NULL, "mddi_clk");
if (IS_ERR(mddi_clk)) {
printk(KERN_ERR "can't find mddi_clk \n");
return PTR_ERR(mddi_clk);
}
clk_enable(mddi_clk);
mddi_pclk = clk_get(NULL, "mddi_pclk");
if (IS_ERR(mddi_pclk))
mddi_pclk = NULL;
else
clk_enable(mddi_pclk);
ret = mddi_register_driver();
if (ret) {
clk_disable(mddi_clk);
clk_put(mddi_clk);
if (mddi_pclk) {
clk_disable(mddi_pclk);
clk_put(mddi_pclk);
}
printk(KERN_ERR "mddi_register_driver() failed!\n");
return ret;
}
mddi_init();
return ret;
}
module_init(mddi_driver_init);
此差异已折叠。
/* Copyright (c) 2008-2009, 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "msm_fb.h"
#include "mddihost.h"
#include "mddihosti.h"
static int mddi_ext_lcd_on(struct platform_device *pdev);
static int mddi_ext_lcd_off(struct platform_device *pdev);
static int mddi_ext_lcd_on(struct platform_device *pdev)
{
return 0;
}
static int mddi_ext_lcd_off(struct platform_device *pdev)
{
return 0;
}
static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
{
msm_fb_add_device(pdev);
return 0;
}
static struct platform_driver this_driver = {
.probe = mddi_ext_lcd_probe,
.driver = {
.name = "extmddi_svga",
},
};
static struct msm_fb_panel_data mddi_ext_lcd_panel_data = {
.panel_info.xres = 800,
.panel_info.yres = 600,
.panel_info.type = EXT_MDDI_PANEL,
.panel_info.pdest = DISPLAY_1,
.panel_info.wait_cycle = 0,
.panel_info.bpp = 18,
.panel_info.fb_num = 2,
.panel_info.clk_rate = 122880000,
.panel_info.clk_min = 120000000,
.panel_info.clk_max = 125000000,
.on = mddi_ext_lcd_on,
.off = mddi_ext_lcd_off,
};
static struct platform_device this_device = {
.name = "extmddi_svga",
.id = 0,
.dev = {
.platform_data = &mddi_ext_lcd_panel_data,
}
};
static int __init mddi_ext_lcd_init(void)
{
int ret;
struct msm_panel_info *pinfo;
ret = platform_driver_register(&this_driver);
if (!ret) {
pinfo = &mddi_ext_lcd_panel_data.panel_info;
pinfo->lcd.vsync_enable = FALSE;
pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
ret = platform_device_register(&this_device);
if (ret)
platform_driver_unregister(&this_driver);
}
return ret;
}
module_init(mddi_ext_lcd_init);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册