diff options
author | Dan Johansson <dan.johansson@stericsson.com> | 2010-07-01 15:11:24 +0200 |
---|---|---|
committer | John Rigby <john.rigby@linaro.org> | 2010-09-02 22:45:50 -0600 |
commit | 574724fbbb1bd2f78ee1a626dfa18cf707c741ab (patch) | |
tree | b4984ed38c86b35e862c90bc1ac6acc8a9810381 | |
parent | 50a1ade75cf1e3c2ff203b6447c59909b1f6fb84 (diff) |
MCDE: V-sync on main and sub display using DSI BTA
* V-sync support for both primary and secondary display.
* V-sync is disabled by default. It is enabled in menuconfig
(System Type -> Display selection -> Enable v-sync for
primary / secondary display).
* DSI HS clock is set to 840 MHz, DSI esq clock 19.2 MHz.
* Enables VAUX1 if startup graphics is enabled.
ST Ericsson Change-Id: WP264234
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2154
Tested-by: Dan JOHANSSON <dan.johansson@stericsson.com>
Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Change-Id: I47f72cb9449e08f089f6bdb25988bd9958644899
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2809
-rwxr-xr-x | arch/arm/mach-ux500/Kconfig-arch | 14 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-mop500-mcde.c | 68 | ||||
-rwxr-xr-x | arch/arm/mach-ux500/prcmu-fw.c | 8 | ||||
-rw-r--r-- | drivers/video/mcde/display-generic_dsi.c | 18 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_display.c | 7 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_dss.c | 31 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_fb.c | 14 | ||||
-rw-r--r-- | drivers/video/mcde/mcde_hw.c | 244 | ||||
-rw-r--r-- | include/video/mcde.h | 5 | ||||
-rw-r--r-- | include/video/mcde_dss.h | 3 | ||||
-rw-r--r-- | include/video/mcde_fb.h | 17 |
11 files changed, 261 insertions, 168 deletions
diff --git a/arch/arm/mach-ux500/Kconfig-arch b/arch/arm/mach-ux500/Kconfig-arch index cbfdd4d3758..3e6d35c5c46 100755 --- a/arch/arm/mach-ux500/Kconfig-arch +++ b/arch/arm/mach-ux500/Kconfig-arch @@ -48,6 +48,13 @@ config DISPLAY_GENERIC_DSI_PRIMARY help Say yes here if main display exists +config DISPLAY_GENERIC_DSI_PRIMARY_VSYNC + bool "Enable v-sync for primary display" + depends on DISPLAY_GENERIC_DSI_PRIMARY + default n + help + Say yes to enable v-sync for primary display + config DISPLAY_GENERIC_DSI_SECONDARY bool "Sub display support" depends on MACH_U8500_MOP && FB_MCDE @@ -56,6 +63,13 @@ config DISPLAY_GENERIC_DSI_SECONDARY help Say yes here if sub display exists +config DISPLAY_GENERIC_DSI_SECONDARY_VSYNC + bool "Enable v-sync for secondary display" + depends on DISPLAY_GENERIC_DSI_SECONDARY + default n + help + Say yes to enable v-sync for secondary display + config DISPLAY_AB8500_TERTIARY bool "AB8500 TVout display support" depends on MACH_U8500_MOP && !AV8100_SDTV && FB_MCDE diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c index 7fbb35caf22..ef1a7274161 100644 --- a/arch/arm/mach-ux500/board-mop500-mcde.c +++ b/arch/arm/mach-ux500/board-mop500-mcde.c @@ -17,12 +17,12 @@ #include <video/mcde_fb.h> #include <video/mcde_dss.h> -#define DSI_UNIT_INTERVAL_0 0xA -#define DSI_UNIT_INTERVAL_1 0xA -#define DSI_UNIT_INTERVAL_2 0x6 +#define DSI_UNIT_INTERVAL_0 0x9 +#define DSI_UNIT_INTERVAL_1 0x9 +#define DSI_UNIT_INTERVAL_2 0x6 static bool rotate_main = true; -static bool display_initialize_during_boot; +static bool display_initialized_during_boot; static int __init startup_graphics_setup(char *str) { @@ -32,14 +32,14 @@ static int __init startup_graphics_setup(char *str) switch (*str) { case '0': pr_info("No Startup graphics support\n"); - display_initialize_during_boot = false; + display_initialized_during_boot = false; break; case '1': pr_info("Startup graphics supported\n"); - display_initialize_during_boot = true; + display_initialized_during_boot = true; break; default: - display_initialize_during_boot = false; + display_initialized_during_boot = false; break; }; @@ -84,7 +84,11 @@ struct mcde_display_device generic_display0 = { .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, .native_x_res = 864, .native_y_res = 480, +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC + .synchronized_update = true, +#else .synchronized_update = false, +#endif /* TODO: Remove rotation buffers once ESRAM driver is completed */ .rotbuf1 = U8500_ESRAM_BASE + 0x20000 * 4, .rotbuf2 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x10000, @@ -132,7 +136,11 @@ static struct mcde_display_device generic_subdisplay = { .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, .native_x_res = 864, .native_y_res = 480, +#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_VSYNC + .synchronized_update = true, +#else .synchronized_update = false, +#endif .dev = { .platform_data = &generic_subdisplay_pdata, }, @@ -366,7 +374,6 @@ static int display_registered_callback(struct notifier_block *nb, struct mcde_display_device *ddev = dev; u16 width, height; bool rotate; - bool display_initialized; if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED) return 0; @@ -376,7 +383,6 @@ static int display_registered_callback(struct notifier_block *nb, mcde_dss_get_native_resolution(ddev, &width, &height); - display_initialized = (ddev->id == 0 && display_initialize_during_boot); rotate = (ddev->id == 0 && rotate_main); if (rotate) { u16 tmp = height; @@ -389,8 +395,7 @@ static int display_registered_callback(struct notifier_block *nb, width, height, width, height * 2, ddev->default_pixel_format, - rotate ? FB_ROTATE_CW : FB_ROTATE_UR, - display_initialized); + rotate ? FB_ROTATE_CW : FB_ROTATE_UR); if (IS_ERR(fbs[ddev->id])) pr_warning("Failed to create fb for display %s\n", ddev->name); else @@ -403,15 +408,56 @@ static struct notifier_block display_nb = { .notifier_call = display_registered_callback, }; +static int framebuffer_registered_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + int ret = 0; + struct fb_event *event_data = data; + struct fb_info *info; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + + if (event == FB_EVENT_FB_REGISTERED && + !display_initialized_during_boot) { + if (event_data) { + u8 *addr; + info = event_data->info; + if (!lock_fb_info(info)) + return -ENODEV; + var = info->var; + fix = info->fix; + addr = ioremap(fix.smem_start, + var.yres_virtual * fix.line_length); + memset(addr, 0x00, + var.yres_virtual * fix.line_length); + var.yoffset = var.yoffset ? 0 : var.yres; + if (info->fbops->fb_pan_display) + ret = info->fbops->fb_pan_display(&var, info); + unlock_fb_info(info); + } + } + return ret; +} + +static struct notifier_block framebuffer_nb = { + .notifier_call = framebuffer_registered_callback, +}; + int __init init_display_devices(void) { int ret; + ret = fb_register_client(&framebuffer_nb); + if (ret) + pr_warning("Failed to register framebuffer notifier\n"); + ret = mcde_dss_register_notifier(&display_nb); if (ret) pr_warning("Failed to register dss notifier\n"); #ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY + if (display_initialized_during_boot) + generic_display0.power_mode = MCDE_DISPLAY_PM_STANDBY; ret = mcde_display_device_register(&generic_display0); if (ret) pr_warning("Failed to register generic display device 0\n"); diff --git a/arch/arm/mach-ux500/prcmu-fw.c b/arch/arm/mach-ux500/prcmu-fw.c index 8c98f2fa587..474cb919001 100755 --- a/arch/arm/mach-ux500/prcmu-fw.c +++ b/arch/arm/mach-ux500/prcmu-fw.c @@ -92,14 +92,14 @@ static int prcmu_set_hwacc_st(enum hw_acc_t hw_acc, enum hw_accst_t hw_accst); #define PRCMU_UNCLAMP_DSS_DSIPLL 0x00600C00 #define PRCMU_POWER_ON_DSI 0x00008000 -#define PRCMU_DSI_CLOCK_SETTING 0x00000145 -#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000141 -#define PRCMU_PLLDSI_FREQ_SETTING 0x0004012B +#define PRCMU_DSI_CLOCK_SETTING 0x00000148 +#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000F00 +#define PRCMU_PLLDSI_FREQ_SETTING 0x00020123 #define PRCMU_ENABLE_PLLDSI 0x00000001 #define PRCMU_RELEASE_RESET_DSS 0x0000400C #define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000202 -#define PRCMU_ENABLE_ESCAPE_CLOCK 0x07031717 +#define PRCMU_ENABLE_ESCAPE_CLOCK 0x07010101 #define PRCMU_DSI_RESET_SW 0x00000007 #define PRCMU_MCDE_DELAY 10 diff --git a/drivers/video/mcde/display-generic_dsi.c b/drivers/video/mcde/display-generic_dsi.c index 3391d2b3808..15b8ccec59a 100644 --- a/drivers/video/mcde/display-generic_dsi.c +++ b/drivers/video/mcde/display-generic_dsi.c @@ -106,6 +106,22 @@ static int __devinit generic_probe(struct mcde_display_device *dev) regulator_set_voltage(pdata->regulator, pdata->min_supply_voltage, pdata->max_supply_voltage); + /* + * When u-boot has display a startup screen. + * U-boot has turned on display power however the + * regulator framework does not know about that + * This is the case here, the display driver has to + * enable the regulator for the display. + */ + if (dev->power_mode == MCDE_DISPLAY_PM_STANDBY) { + ret = regulator_enable(pdata->regulator); + if (ret < 0) { + dev_err(&dev->dev, + "%s:Failed to enable regulator\n" + , __func__); + goto regulator_enable_failed; + } + } } dev->platform_enable = generic_platform_enable; dev->platform_disable = generic_platform_disable; @@ -119,7 +135,7 @@ static int __devinit generic_probe(struct mcde_display_device *dev) dev_info(&dev->dev, "Generic display probed\n"); goto out; - +regulator_enable_failed: regulator_get_failed: if (pdata->generic_platform_enable && pdata->reset_gpio) gpio_free(pdata->reset_gpio); diff --git a/drivers/video/mcde/mcde_display.c b/drivers/video/mcde/mcde_display.c index aa52eee7475..1537980dcaf 100644 --- a/drivers/video/mcde/mcde_display.c +++ b/drivers/video/mcde/mcde_display.c @@ -92,6 +92,8 @@ static int mcde_display_set_power_mode_default(struct mcde_display_device *ddev, ddev->power_mode = MCDE_DISPLAY_PM_OFF; } + mcde_chnl_set_power_mode(ddev->chnl_state, ddev->power_mode); + return ret; } @@ -205,11 +207,12 @@ static int mcde_display_set_synchronized_update_default( int ret = 0; if (ddev->port->type == MCDE_PORTTYPE_DSI) { if (ddev->port->sync_src == MCDE_SYNCSRC_TE0 || - ddev->port->sync_src == MCDE_SYNCSRC_TE1) { + ddev->port->sync_src == MCDE_SYNCSRC_TE1 || + ddev->port->sync_src == MCDE_SYNCSRC_BTA) { u8 m = 0; ret = mcde_display_dsi_dcs_write(ddev, DCS_CMD_SET_TEAR_ON, &m, 1); - } else if (ddev->port->sync_src != MCDE_SYNCSRC_BTA) { + } else { ret = -EINVAL; } } else { diff --git a/drivers/video/mcde/mcde_dss.c b/drivers/video/mcde/mcde_dss.c index d6930a6ad70..846d7c33e33 100644 --- a/drivers/video/mcde/mcde_dss.c +++ b/drivers/video/mcde/mcde_dss.c @@ -67,8 +67,7 @@ static int apply_overlay(struct mcde_overlay *ovly, /* MCDE DSS operations */ -int mcde_dss_enable_display(struct mcde_display_device *ddev, - bool display_initialized) +int mcde_dss_enable_display(struct mcde_display_device *ddev) { int ret; struct mcde_chnl_state *chnl; @@ -84,22 +83,20 @@ int mcde_dss_enable_display(struct mcde_display_device *ddev, goto get_chnl_failed; } ddev->chnl_state = chnl; - if (!display_initialized) { - /* Initiate display communication */ - ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY); - if (ret < 0) { - dev_warn(&ddev->dev, "Failed to initialize display\n"); - goto display_failed; - } - - dev_dbg(&ddev->dev, "Display enabled, chnl=%d\n", - ddev->chnl_id); - } else { - dev_dbg(&ddev->dev, "Display already enabled, chnl=%d\n", - ddev->chnl_id); - ddev->power_mode = MCDE_DISPLAY_PM_ON; - ret = 0; + /* Initiate display communication */ + ret = ddev->set_power_mode(ddev, MCDE_DISPLAY_PM_STANDBY); + if (ret < 0) { + dev_warn(&ddev->dev, "Failed to initialize display\n"); + goto display_failed; } + + ret = ddev->set_synchronized_update(ddev, ddev->synchronized_update); + if (ret < 0) + dev_warn(&ddev->dev, "Failed to set sync\n"); + /* TODO: call driver for all defaults like sync_update above */ + + dev_dbg(&ddev->dev, "Display enabled, chnl=%d\n", + ddev->chnl_id); ddev->enabled = true; out: return ret; diff --git a/drivers/video/mcde/mcde_fb.c b/drivers/video/mcde/mcde_fb.c index fc77e5be1d8..f9697d2e9df 100644 --- a/drivers/video/mcde/mcde_fb.c +++ b/drivers/video/mcde/mcde_fb.c @@ -411,6 +411,7 @@ static int apply_var(struct fb_info *fbi, struct mcde_display_device *ddev) /* Reallocate memory */ line_len = (fbi->var.bits_per_pixel * var->xres_virtual) / 8; + line_len = ALIGN(line_len, MCDE_BUF_LINE_ALIGMENT); size = line_len * var->yres_virtual; ret = reallocate_fb_mem(fbi, size); if (ret) { @@ -432,7 +433,6 @@ static int apply_var(struct fb_info *fbi, struct mcde_display_device *ddev) memset(&vmode, 0, sizeof(struct mcde_video_mode)); var_to_vmode(var, &vmode); mcde_dss_set_video_mode(ddev, &vmode); - mcde_dss_apply_channel(ddev); } @@ -531,7 +531,7 @@ static struct fb_ops fb_ops = { struct fb_info *mcde_fb_create(struct mcde_display_device *ddev, u16 w, u16 h, u16 vw, u16 vh, enum mcde_ovly_pix_fmt pix_fmt, - u32 rotate, bool display_initialized) + u32 rotate) { int ret = 0; struct fb_info *fbi; @@ -554,7 +554,7 @@ struct fb_info *mcde_fb_create(struct mcde_display_device *ddev, init_fb(fbi); mfb = to_mcde_fb(fbi); - ret = mcde_dss_enable_display(ddev, display_initialized); + ret = mcde_dss_enable_display(ddev); if (ret) goto display_enable_failed; @@ -584,15 +584,7 @@ struct fb_info *mcde_fb_create(struct mcde_display_device *ddev, if (ret) goto fb_register_failed; - if (!display_initialized) { - ret = mcde_dss_update_overlay(ovly); - if (ret) - goto ovly_update_failed; - } - goto out; -ovly_update_failed: - unregister_framebuffer(fbi); fb_register_failed: mcde_dss_disable_overlay(ovly); ovly_enable_failed: diff --git a/drivers/video/mcde/mcde_hw.c b/drivers/video/mcde/mcde_hw.c index c04f06717a2..0ec39e572c8 100644 --- a/drivers/video/mcde/mcde_hw.c +++ b/drivers/video/mcde/mcde_hw.c @@ -181,7 +181,7 @@ struct tv_regs { /* field 1 */ u16 bel1; /* field total vertical blanking lines */ u16 fsl1; /* field vbp */ - /* field 1 *//* REVIEW: Field 2? */ + /* field 2 */ u16 bel2; u16 fsl2; bool interlaced_en; @@ -201,6 +201,8 @@ struct mcde_chnl_state { u32 transactionid_hw; wait_queue_head_t waitq_hw; /* Waitq for transactionid_hw */ + enum mcde_display_power_mode power_mode; + /* Staged settings */ bool synchronized_update; enum mcde_port_pix_fmt pix_fmt; @@ -217,117 +219,6 @@ struct mcde_chnl_state { bool continous_running; }; -/* TODO: give these a place? *//* REVIEW: Remove, move to top move to use? */ -#define MCDE_CONFIG_TVOUT_HBORDER 2 -#define MCDE_CONFIG_TVOUT_VBORDER 2 - -int mcde_chnl_set_video_mode(struct mcde_chnl_state *chnl, - struct mcde_video_mode *vmode) -{ - if (chnl == NULL || vmode == NULL) - return -EINVAL; - - disable_channel(chnl); - chnl->vmode = *vmode; - - return 0; -} - -static void tv_video_mode_apply(struct mcde_chnl_state *chnl) -{ - /* assume xres == 720 */ - dev_vdbg(&mcde_dev->dev, "%s\n", __func__); - /* -4 since MCDE doesn't include SAV/EAV, 2 bytes each, to blanking */ - chnl->tv_regs.hbw = chnl->vmode.hbp + chnl->vmode.hfp - 4; - chnl->tv_regs.bel1 = chnl->vmode.vbp1 + chnl->vmode.vfp1; - chnl->tv_regs.fsl1 = chnl->vmode.vbp1; - chnl->tv_regs.bel2 = chnl->vmode.vbp2 + chnl->vmode.vfp2; - chnl->tv_regs.fsl2 = chnl->vmode.vbp2; - chnl->tv_regs.interlaced_en = chnl->vmode.interlaced; - - if (chnl->port.phy.dpi.num_data_lanes == 4) - chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P_BE; - else - chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P; -} - -static void update_tv_registers(enum mcde_chnl chnl_id, struct tv_regs *regs) -{ - u8 idx = chnl_id; - u8 maj_version; - - dev_dbg(&mcde_dev->dev, "%s\n", __func__); - mcde_wreg(MCDE_TVCRA + idx * MCDE_TVCRA_GROUPOFFSET, - MCDE_TVCRA_SEL_MOD(MCDE_TVCRA_SEL_MOD_TV) | - MCDE_TVCRA_INTEREN(regs->interlaced_en) | - MCDE_TVCRA_IFIELD(1) | - MCDE_TVCRA_TVMODE(regs->tv_mode) | - MCDE_TVCRA_SDTVMODE(MCDE_TVCRA_SDTVMODE_Y0CBY1CR) | - MCDE_TVCRA_AVRGEN(0)); - /* REVIEW: Magic values */ - mcde_wreg(MCDE_TVBLUA + idx * MCDE_TVBLUA_GROUPOFFSET, - MCDE_TVBLUA_TVBLU(0x83) | - MCDE_TVBLUA_TVBCB(0x9c) | - MCDE_TVBLUA_TVBCR(0x2c)); - - /* Vertical timing registers */ - mcde_wreg(MCDE_TVDVOA + idx * MCDE_TVDVOA_GROUPOFFSET, - MCDE_TVDVOA_DVO1(MCDE_CONFIG_TVOUT_VBORDER) | - MCDE_TVDVOA_DVO2(MCDE_CONFIG_TVOUT_VBORDER)); - mcde_wreg(MCDE_TVBL1A + idx * MCDE_TVBL1A_GROUPOFFSET, - MCDE_TVBL1A_BEL1(regs->bel1) | - MCDE_TVBL1A_BSL1(MCDE_CONFIG_TVOUT_VBORDER)); - mcde_wreg(MCDE_TVBL2A + idx * MCDE_TVBL1A_GROUPOFFSET, - MCDE_TVBL2A_BEL2(regs->bel2) | - MCDE_TVBL2A_BSL2(MCDE_CONFIG_TVOUT_VBORDER)); - mcde_wreg(MCDE_TVISLA + idx * MCDE_TVISLA_GROUPOFFSET, - MCDE_TVISLA_FSL1(regs->fsl1) | - MCDE_TVISLA_FSL2(regs->fsl2)); - /* Horizontal timing registers */ - maj_version = MCDE_REG2VAL(/* REVIEW: Make global and do on init? */ - MCDE_PID, MAJOR_VERSION, mcde_rreg(MCDE_PID)); - - if (maj_version > 3) { - mcde_wreg(MCDE_TVLBALWA + idx * MCDE_TVLBALWA_GROUPOFFSET, - MCDE_TVLBALWA_LBW(regs->hbw) | - MCDE_TVLBALWA_ALW(MCDE_CONFIG_TVOUT_HBORDER)); - mcde_wreg(MCDE_TVTIM1A + idx * MCDE_TVTIM1A_GROUPOFFSET, - MCDE_TVTIM1A_DHO(MCDE_CONFIG_TVOUT_HBORDER)); - } else { - /* in earlier versions the LBW and DHO fields are swapped */ - mcde_wreg(MCDE_TVLBALWA + idx * MCDE_TVLBALWA_GROUPOFFSET, - MCDE_TVLBALWA_LBW(MCDE_CONFIG_TVOUT_HBORDER) | - MCDE_TVLBALWA_ALW(MCDE_CONFIG_TVOUT_HBORDER)); - mcde_wreg(MCDE_TVTIM1A + idx * MCDE_TVTIM1A_GROUPOFFSET, - MCDE_TVTIM1A_DHO(regs->hbw)); - } -} - -static void update_col_registers(enum mcde_chnl chnl_id, struct col_regs *regs) -{ - u8 idx = chnl_id; - - dev_vdbg(&mcde_dev->dev, "%s\n", __func__); - mcde_wreg(MCDE_RGBCONV1A + idx * MCDE_RGBCONV1A_GROUPOFFSET, - MCDE_RGBCONV1A_YR_RED(regs->y_red) | - MCDE_RGBCONV1A_YR_GREEN(regs->y_green)); - mcde_wreg(MCDE_RGBCONV2A + idx * MCDE_RGBCONV2A_GROUPOFFSET, - MCDE_RGBCONV2A_YR_BLUE(regs->y_blue) | - MCDE_RGBCONV2A_CR_RED(regs->cr_red)); - mcde_wreg(MCDE_RGBCONV3A + idx * MCDE_RGBCONV3A_GROUPOFFSET, - MCDE_RGBCONV3A_CR_GREEN(regs->cr_green) | - MCDE_RGBCONV3A_CR_BLUE(regs->cr_blue)); - mcde_wreg(MCDE_RGBCONV4A + idx * MCDE_RGBCONV4A_GROUPOFFSET, - MCDE_RGBCONV4A_CB_RED(regs->cb_red) | - MCDE_RGBCONV4A_CB_GREEN(regs->cb_green)); - mcde_wreg(MCDE_RGBCONV5A + idx * MCDE_RGBCONV5A_GROUPOFFSET, - MCDE_RGBCONV5A_CB_BLUE(regs->cb_blue) | - MCDE_RGBCONV5A_OFF_RED(regs->off_red)); - mcde_wreg(MCDE_RGBCONV6A + idx * MCDE_RGBCONV6A_GROUPOFFSET, - MCDE_RGBCONV6A_OFF_GREEN(regs->off_green) | - MCDE_RGBCONV6A_OFF_BLUE(regs->off_blue)); -} -/* REVIEW: Move all structs etc to top, don't mix code and declarations */ static struct mcde_chnl_state channels[] = { { .id = MCDE_CHNL_A, @@ -365,6 +256,7 @@ struct chnl_config { bool f01mux; bool f01mux_set; }; + static /* TODO: const, compiler bug? */ struct chnl_config chnl_configs[] = { /* Channel A */ { .path = MCDE_CHNLPATH_CHNLA_FIFOA_DPI_0, @@ -448,8 +340,117 @@ static /* TODO: const, compiler bug? */ struct chnl_config chnl_configs[] = { .fabmux = true, .fabmux_set = true }, }; -/* MCDE internal helpers */ +/* TODO: give these a place? *//* REVIEW: Remove, move to top move to use? */ +#define MCDE_CONFIG_TVOUT_HBORDER 2 +#define MCDE_CONFIG_TVOUT_VBORDER 2 +int mcde_chnl_set_video_mode(struct mcde_chnl_state *chnl, + struct mcde_video_mode *vmode) +{ + if (chnl == NULL || vmode == NULL) + return -EINVAL; + + disable_channel(chnl); + chnl->vmode = *vmode; + + return 0; +} + +static void tv_video_mode_apply(struct mcde_chnl_state *chnl) +{ + dev_vdbg(&mcde_dev->dev, "%s\n", __func__); + /* -4 since MCDE doesn't include SAV/EAV, 2 bytes each, to blanking */ + chnl->tv_regs.hbw = chnl->vmode.hbp + chnl->vmode.hfp - 4; + chnl->tv_regs.bel1 = chnl->vmode.vbp1 + chnl->vmode.vfp1; + chnl->tv_regs.fsl1 = chnl->vmode.vbp1; + chnl->tv_regs.bel2 = chnl->vmode.vbp2 + chnl->vmode.vfp2; + chnl->tv_regs.fsl2 = chnl->vmode.vbp2; + chnl->tv_regs.interlaced_en = chnl->vmode.interlaced; + + if (chnl->port.phy.dpi.num_data_lanes == 4) + chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P_BE; + else + chnl->tv_regs.tv_mode = MCDE_TVCRA_TVMODE_SDTV_656P; +} + +static void update_tv_registers(enum mcde_chnl chnl_id, struct tv_regs *regs) +{ + u8 idx = chnl_id; + u8 maj_version; + + dev_dbg(&mcde_dev->dev, "%s\n", __func__); + mcde_wreg(MCDE_TVCRA + idx * MCDE_TVCRA_GROUPOFFSET, + MCDE_TVCRA_SEL_MOD(MCDE_TVCRA_SEL_MOD_TV) | + MCDE_TVCRA_INTEREN(regs->interlaced_en) | + MCDE_TVCRA_IFIELD(1) | + MCDE_TVCRA_TVMODE(regs->tv_mode) | + MCDE_TVCRA_SDTVMODE(MCDE_TVCRA_SDTVMODE_Y0CBY1CR) | + MCDE_TVCRA_AVRGEN(0)); + /* REVIEW: Magic values */ + mcde_wreg(MCDE_TVBLUA + idx * MCDE_TVBLUA_GROUPOFFSET, + MCDE_TVBLUA_TVBLU(0x83) | + MCDE_TVBLUA_TVBCB(0x9c) | + MCDE_TVBLUA_TVBCR(0x2c)); + + /* Vertical timing registers */ + mcde_wreg(MCDE_TVDVOA + idx * MCDE_TVDVOA_GROUPOFFSET, + MCDE_TVDVOA_DVO1(MCDE_CONFIG_TVOUT_VBORDER) | + MCDE_TVDVOA_DVO2(MCDE_CONFIG_TVOUT_VBORDER)); + mcde_wreg(MCDE_TVBL1A + idx * MCDE_TVBL1A_GROUPOFFSET, + MCDE_TVBL1A_BEL1(regs->bel1) | + MCDE_TVBL1A_BSL1(MCDE_CONFIG_TVOUT_VBORDER)); + mcde_wreg(MCDE_TVBL2A + idx * MCDE_TVBL1A_GROUPOFFSET, + MCDE_TVBL2A_BEL2(regs->bel2) | + MCDE_TVBL2A_BSL2(MCDE_CONFIG_TVOUT_VBORDER)); + mcde_wreg(MCDE_TVISLA + idx * MCDE_TVISLA_GROUPOFFSET, + MCDE_TVISLA_FSL1(regs->fsl1) | + MCDE_TVISLA_FSL2(regs->fsl2)); + /* Horizontal timing registers */ + maj_version = MCDE_REG2VAL(/* REVIEW: Make global and do on init? */ + MCDE_PID, MAJOR_VERSION, mcde_rreg(MCDE_PID)); + + if (maj_version > 3) { + mcde_wreg(MCDE_TVLBALWA + idx * MCDE_TVLBALWA_GROUPOFFSET, + MCDE_TVLBALWA_LBW(regs->hbw) | + MCDE_TVLBALWA_ALW(MCDE_CONFIG_TVOUT_HBORDER)); + mcde_wreg(MCDE_TVTIM1A + idx * MCDE_TVTIM1A_GROUPOFFSET, + MCDE_TVTIM1A_DHO(MCDE_CONFIG_TVOUT_HBORDER)); + } else { + /* in earlier versions the LBW and DHO fields are swapped */ + mcde_wreg(MCDE_TVLBALWA + idx * MCDE_TVLBALWA_GROUPOFFSET, + MCDE_TVLBALWA_LBW(MCDE_CONFIG_TVOUT_HBORDER) | + MCDE_TVLBALWA_ALW(MCDE_CONFIG_TVOUT_HBORDER)); + mcde_wreg(MCDE_TVTIM1A + idx * MCDE_TVTIM1A_GROUPOFFSET, + MCDE_TVTIM1A_DHO(regs->hbw)); + } +} + +static void update_col_registers(enum mcde_chnl chnl_id, struct col_regs *regs) +{ + u8 idx = chnl_id; + + dev_vdbg(&mcde_dev->dev, "%s\n", __func__); + mcde_wreg(MCDE_RGBCONV1A + idx * MCDE_RGBCONV1A_GROUPOFFSET, + MCDE_RGBCONV1A_YR_RED(regs->y_red) | + MCDE_RGBCONV1A_YR_GREEN(regs->y_green)); + mcde_wreg(MCDE_RGBCONV2A + idx * MCDE_RGBCONV2A_GROUPOFFSET, + MCDE_RGBCONV2A_YR_BLUE(regs->y_blue) | + MCDE_RGBCONV2A_CR_RED(regs->cr_red)); + mcde_wreg(MCDE_RGBCONV3A + idx * MCDE_RGBCONV3A_GROUPOFFSET, + MCDE_RGBCONV3A_CR_GREEN(regs->cr_green) | + MCDE_RGBCONV3A_CR_BLUE(regs->cr_blue)); + mcde_wreg(MCDE_RGBCONV4A + idx * MCDE_RGBCONV4A_GROUPOFFSET, + MCDE_RGBCONV4A_CB_RED(regs->cb_red) | + MCDE_RGBCONV4A_CB_GREEN(regs->cb_green)); + mcde_wreg(MCDE_RGBCONV5A + idx * MCDE_RGBCONV5A_GROUPOFFSET, + MCDE_RGBCONV5A_CB_BLUE(regs->cb_blue) | + MCDE_RGBCONV5A_OFF_RED(regs->off_red)); + mcde_wreg(MCDE_RGBCONV6A + idx * MCDE_RGBCONV6A_GROUPOFFSET, + MCDE_RGBCONV6A_OFF_GREEN(regs->off_green) | + MCDE_RGBCONV6A_OFF_BLUE(regs->off_blue)); +} + +/* MCDE internal helpers */ static u8 portfmt2dsipacking(enum mcde_port_pix_fmt pix_fmt) { switch (pix_fmt) { @@ -575,10 +576,9 @@ static irqreturn_t mcde_irq_handler(int irq, void *dev) } irq_status = dsi_rfld(i, DSI_CMD_MODE_STS_FLAG, ERR_NO_TE_FLAG); if (irq_status) { - trig = true; dsi_wreg(i, DSI_CMD_MODE_STS_CLR, DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR(true)); - dev_vdbg(&mcde_dev->dev, "NO_TE DSI%d\n", i); + dev_info(&mcde_dev->dev, "NO_TE DSI%d\n", i); } if (!trig) continue; @@ -1351,6 +1351,16 @@ int mcde_chnl_enable_synchronized_update(struct mcde_chnl_state *chnl, return 0; } +int mcde_chnl_set_power_mode(struct mcde_chnl_state *chnl, + enum mcde_display_power_mode power_mode) +{ + if (!chnl->inuse) + return -EINVAL; + + chnl->power_mode = power_mode; + return 0; +} + int mcde_chnl_apply(struct mcde_chnl_state *chnl) { /* TODO: lock *//* REVIEW: MCDE locking! */ @@ -1422,7 +1432,8 @@ static void chnl_update_non_continous(struct mcde_chnl_state *chnl) chnl_update_registers(chnl); /* TODO: look at port sync source and synched_update */ - if (chnl->regs.synchronized_update) { + if (chnl->regs.synchronized_update && + chnl->power_mode == MCDE_DISPLAY_PM_ON) { if (chnl->port.type == MCDE_PORTTYPE_DSI && chnl->port.sync_src == MCDE_SYNCSRC_BTA) { while (dsi_rfld(chnl->port.link, DSI_CMD_MODE_STS, @@ -1430,7 +1441,6 @@ static void chnl_update_non_continous(struct mcde_chnl_state *chnl) udelay(100); dsi_te_request(chnl); } - /* TODO: TE sync */ } else { mcde_wreg(MCDE_CHNL0SYNCHSW + chnl->id * MCDE_CHNL0SYNCHSW_GROUPOFFSET, diff --git a/include/video/mcde.h b/include/video/mcde.h index d7ea581d190..415d9db960a 100644 --- a/include/video/mcde.h +++ b/include/video/mcde.h @@ -205,6 +205,8 @@ enum mcde_display_rotation { #define MCDE_MIN_HEIGHT 16 #define MCDE_MAX_WIDTH 2048 #define MCDE_MAX_HEIGHT 2048 +#define MCDE_BUF_START_ALIGMENT 8 +#define MCDE_BUF_LINE_ALIGMENT 8 #define MCDE_FIFO_AB_SIZE 640 #define MCDE_FIFO_C0C1_SIZE 160 @@ -273,6 +275,9 @@ int mcde_chnl_set_rotation(struct mcde_chnl_state *chnl, enum mcde_display_rotation rotation, u32 rotbuf1, u32 rotbuf2); int mcde_chnl_enable_synchronized_update(struct mcde_chnl_state *chnl, bool enable); +int mcde_chnl_set_power_mode(struct mcde_chnl_state *chnl, + enum mcde_display_power_mode power_mode); + int mcde_chnl_apply(struct mcde_chnl_state *chnl); int mcde_chnl_update(struct mcde_chnl_state *chnl, struct mcde_rectangle *update_area); diff --git a/include/video/mcde_dss.h b/include/video/mcde_dss.h index 648b46d0528..a32b2dfdeba 100644 --- a/include/video/mcde_dss.h +++ b/include/video/mcde_dss.h @@ -19,8 +19,7 @@ /* Public MCDE dss (Used by MCDE fb ioctl & MCDE display sysfs) */ -int mcde_dss_enable_display(struct mcde_display_device *ddev, - bool display_initialized); +int mcde_dss_enable_display(struct mcde_display_device *ddev); void mcde_dss_disable_display(struct mcde_display_device *ddev); int mcde_dss_apply_channel(struct mcde_display_device *ddev); struct mcde_overlay *mcde_dss_create_overlay(struct mcde_display_device *ddev, diff --git a/include/video/mcde_fb.h b/include/video/mcde_fb.h index 871b0225c46..6d05f612184 100644 --- a/include/video/mcde_fb.h +++ b/include/video/mcde_fb.h @@ -12,9 +12,18 @@ #define __MCDE_FB__H__ #include <linux/fb.h> - +#include <linux/ioctl.h> +#if !defined(__KERNEL__) && !defined(_KERNEL) +#include <stdint.h> +#else +#include <linux/types.h> +#endif + +#ifdef __KERNEL__ #include "mcde_dss.h" +#endif +#ifdef __KERNEL__ #define to_mcde_fb(x) ((struct mcde_fb *)(x)->par) #define MCDE_FB_MAX_NUM_OVERLAYS 3 @@ -28,8 +37,9 @@ struct mcde_fb { /* MCDE fbdev API */ struct fb_info *mcde_fb_create(struct mcde_display_device *ddev, - u16 w, u16 h, u16 vw, u16 vh, enum mcde_ovly_pix_fmt pix_fmt, - u32 rotate, bool display_initialized); + uint16_t w, uint16_t h, uint16_t vw, uint16_t vh, + enum mcde_ovly_pix_fmt pix_fmt, uint32_t rotate); + int mcde_fb_attach_overlay(struct fb_info *fb_info, struct mcde_overlay *ovl); void mcde_fb_destroy(struct fb_info *fb_info); @@ -37,6 +47,7 @@ void mcde_fb_destroy(struct fb_info *fb_info); /* MCDE fb driver */ int mcde_fb_init(void); void mcde_fb_exit(void); +#endif #endif /* __MCDE_FB__H__ */ |