diff options
28 files changed, 345 insertions, 168 deletions
diff --git a/arch/arm/configs/imx6s_defconfig b/arch/arm/configs/imx6s_defconfig index ac7afdfdf5ff..41f43e5c0d63 100644 --- a/arch/arm/configs/imx6s_defconfig +++ b/arch/arm/configs/imx6s_defconfig @@ -1620,7 +1620,7 @@ CONFIG_MXC_CAMERA_OV5640=y # CONFIG_MXC_CAMERA_OV5640_MIPI is not set CONFIG_MXC_CAMERA_SENSOR_CLK=y CONFIG_VIDEO_MXC_OUTPUT=y -# CONFIG_VIDEO_MXC_PXP_V4L2 is not set +CONFIG_VIDEO_MXC_PXP_V4L2=y # CONFIG_VIDEO_MXC_OPL is not set # CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_TIMBERDALE is not set diff --git a/arch/arm/mach-mx6/board-mx6sl_common.h b/arch/arm/mach-mx6/board-mx6sl_common.h index 465863ec504d..1db30542391f 100644 --- a/arch/arm/mach-mx6/board-mx6sl_common.h +++ b/arch/arm/mach-mx6/board-mx6sl_common.h @@ -389,40 +389,11 @@ static iomux_v3_cfg_t mx6sl_brd_spdc_disable_pads[] = { MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14, }; -static iomux_v3_cfg_t mx6sl_brd_csi_enable_pads[] = { - MX6SL_PAD_EPDC_GDRL__CSI_MCLK, - MX6SL_PAD_EPDC_SDCE3__I2C3_SDA, - MX6SL_PAD_EPDC_SDCE2__I2C3_SCL, - MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK, - MX6SL_PAD_EPDC_GDSP__CSI_VSYNC, - MX6SL_PAD_EPDC_GDOE__CSI_HSYNC, - MX6SL_PAD_EPDC_SDLE__CSI_D_9, - MX6SL_PAD_EPDC_SDCLK__CSI_D_8, - MX6SL_PAD_EPDC_D7__CSI_D_7, - MX6SL_PAD_EPDC_D6__CSI_D_6, - MX6SL_PAD_EPDC_D5__CSI_D_5, - MX6SL_PAD_EPDC_D4__CSI_D_4, - MX6SL_PAD_EPDC_D3__CSI_D_3, - MX6SL_PAD_EPDC_D2__CSI_D_2, - MX6SL_PAD_EPDC_D1__CSI_D_1, - MX6SL_PAD_EPDC_D0__CSI_D_0, - - MX6SL_PAD_EPDC_SDSHR__GPIO_1_26, /* CMOS_RESET_B GPIO */ - MX6SL_PAD_EPDC_SDOE__GPIO_1_25, /* CMOS_PWDN GPIO */ -}; - static iomux_v3_cfg_t mx6sl_brd_elan_pads[] = { MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10, /* INT */ MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9, /* CE */ MX6SL_PAD_KEY_COL6__GPIO_4_4, /* RST */ }; - /* uart2 pins */ -static iomux_v3_cfg_t mx6sl_uart2_pads[] = { - MX6SL_PAD_SD2_DAT5__UART2_TXD, - MX6SL_PAD_SD2_DAT4__UART2_RXD, - MX6SL_PAD_SD2_DAT6__UART2_RTS, - MX6SL_PAD_SD2_DAT7__UART2_CTS, -}; #define MX6SL_USDHC_8BIT_PAD_SETTING(id, speed) \ mx6sl_sd##id##_##speed##mhz[] = { \ diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c index 03705bb105ae..6b479a2a9500 100644 --- a/arch/arm/mach-mx6/board-mx6sl_evk.c +++ b/arch/arm/mach-mx6/board-mx6sl_evk.c @@ -86,6 +86,36 @@ extern int __init mx6sl_evk_init_pfuze100(u32 int_gpio); static int csi_enabled; +static iomux_v3_cfg_t mx6sl_brd_csi_enable_pads[] = { + MX6SL_PAD_EPDC_GDRL__CSI_MCLK, + MX6SL_PAD_EPDC_SDCE3__I2C3_SDA, + MX6SL_PAD_EPDC_SDCE2__I2C3_SCL, + MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK, + MX6SL_PAD_EPDC_GDSP__CSI_VSYNC, + MX6SL_PAD_EPDC_GDOE__CSI_HSYNC, + MX6SL_PAD_EPDC_SDLE__CSI_D_9, + MX6SL_PAD_EPDC_SDCLK__CSI_D_8, + MX6SL_PAD_EPDC_D7__CSI_D_7, + MX6SL_PAD_EPDC_D6__CSI_D_6, + MX6SL_PAD_EPDC_D5__CSI_D_5, + MX6SL_PAD_EPDC_D4__CSI_D_4, + MX6SL_PAD_EPDC_D3__CSI_D_3, + MX6SL_PAD_EPDC_D2__CSI_D_2, + MX6SL_PAD_EPDC_D1__CSI_D_1, + MX6SL_PAD_EPDC_D0__CSI_D_0, + + MX6SL_PAD_EPDC_SDSHR__GPIO_1_26, /* CMOS_RESET_B GPIO */ + MX6SL_PAD_EPDC_SDOE__GPIO_1_25, /* CMOS_PWDN GPIO */ +}; + +/* uart2 pins */ +static iomux_v3_cfg_t mx6sl_uart2_pads[] = { + MX6SL_PAD_SD2_DAT5__UART2_TXD, + MX6SL_PAD_SD2_DAT4__UART2_RXD, + MX6SL_PAD_SD2_DAT6__UART2_RTS, + MX6SL_PAD_SD2_DAT7__UART2_CTS, +}; + enum sd_pad_mode { SD_PAD_MODE_LOW_SPEED, SD_PAD_MODE_MED_SPEED, diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c index 9d18423c85c5..f25882bd40d1 100644 --- a/arch/arm/mach-mx6/bus_freq.c +++ b/arch/arm/mach-mx6/bus_freq.c @@ -110,7 +110,7 @@ static struct clk *pll1; static struct clk *pll1_sw_clk; static struct clk *pll3_sw_clk; static struct clk *pll2_200; -static struct clk *mmdc_ch0_axi; +struct clk *mmdc_ch0_axi; static struct clk *pll3_540; static struct delayed_work low_bus_freq_handler; @@ -155,8 +155,6 @@ void reduce_bus_freq(void) u32 div; unsigned long flags; - spin_lock_irqsave(&freq_lock, flags); - if (high_bus_freq_mode) { /* Set periph_clk to be sourced from OSC_CLK */ /* Set AXI to 24MHz. */ @@ -170,8 +168,11 @@ void reduce_bus_freq(void) if (lp_audio_freq) { /* PLL2 is on in this mode, as DDR is at 50MHz. */ /* Now change DDR freq while running from IRAM. */ + + spin_lock_irqsave(&freq_lock, flags); mx6sl_ddr_freq_change_iram(DDR_AUDIO_CLK, low_bus_freq_mode); + spin_unlock_irqrestore(&freq_lock, flags); if (low_bus_freq_mode) { /* Swtich ARM to run off PLL2_PFD2_400MHz @@ -213,14 +214,15 @@ void reduce_bus_freq(void) ; clk_set_parent(pll1_sw_clk, pll1); + spin_lock_irqsave(&freq_lock, flags); /* Now change DDR freq while running from IRAM. */ mx6sl_ddr_freq_change_iram(LPAPM_CLK, low_bus_freq_mode); + spin_unlock_irqrestore(&freq_lock, flags); low_bus_freq_mode = 1; audio_bus_freq_mode = 0; } - spin_unlock_irqrestore(&freq_lock, flags); } high_bus_freq_mode = 0; @@ -325,6 +327,7 @@ int set_high_bus_freq(int high_bus_freq) spin_lock_irqsave(&freq_lock, flags); /* Change DDR freq in IRAM. */ mx6sl_ddr_freq_change_iram(ddr_normal_rate, low_bus_freq_mode); + spin_unlock_irqrestore(&freq_lock, flags); /* Set periph_clk to be sourced from pll2_pfd2_400M */ /* First need to set the divider before changing the */ @@ -348,7 +351,6 @@ int set_high_bus_freq(int high_bus_freq) high_bus_freq_mode = 1; low_bus_freq_mode = 0; audio_bus_freq_mode = 0; - spin_unlock_irqrestore(&freq_lock, flags); } else { clk_enable(pll3); if (high_bus_freq) { diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c index 19a98aa167c5..9ceff4f07c71 100755 --- a/arch/arm/mach-mx6/clock_mx6sl.c +++ b/arch/arm/mach-mx6/clock_mx6sl.c @@ -101,9 +101,7 @@ DEFINE_SPINLOCK(mx6sl_clk_lock); u32 gpt_ticks; \ u32 gpt_cnt; \ u32 reg; \ - unsigned long flags; \ int result = 1; \ - spin_lock_irqsave(&mx6sl_clk_lock, flags); \ gpt_rate = clk_get_rate(&gpt_clk[0]); \ gpt_ticks = timeout / (1000000000 / gpt_rate); \ reg = __raw_readl(timer_base + V2_TSTAT);\ @@ -133,7 +131,6 @@ DEFINE_SPINLOCK(mx6sl_clk_lock); } \ } \ } \ - spin_unlock_irqrestore(&mx6sl_clk_lock, flags); \ result; \ }) diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c index 99336d873756..e6ef0261a285 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.c +++ b/arch/arm/mach-mx6/cpu_op-mx6.c @@ -217,32 +217,24 @@ static struct cpu_op mx6sl_cpu_op_1G[] = { .pll_rate = 996000000, .cpu_rate = 996000000, .cpu_podf = 0, - .pu_voltage = 1225000, - .soc_voltage = 1225000, - .cpu_voltage = 1275000,}, + .pu_voltage = 1200000, + .soc_voltage = 1200000, + .cpu_voltage = 1250000,}, { .pll_rate = 792000000, .cpu_rate = 792000000, .cpu_podf = 0, .pu_voltage = 1150000, .soc_voltage = 1150000, - .cpu_voltage = 1200000,}, + .cpu_voltage = 1150000,}, { .pll_rate = 396000000, .pll_lpm_rate = 792000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1050000, - .soc_voltage = 1050000, - .cpu_voltage = 1100000,}, - { - .pll_rate = 396000000, - .pll_lpm_rate = 792000000, - .cpu_rate = 198000000, - .cpu_podf = 1, - .pu_voltage = 1050000, - .soc_voltage = 1050000, - .cpu_voltage = 1050000,}, + .pu_voltage = 1150000, + .soc_voltage = 1150000, + .cpu_voltage = 950000,}, }; static struct cpu_op mx6sl_cpu_op[] = { @@ -252,23 +244,15 @@ static struct cpu_op mx6sl_cpu_op[] = { .cpu_podf = 0, .pu_voltage = 1150000, .soc_voltage = 1150000, - .cpu_voltage = 1200000,}, + .cpu_voltage = 1150000,}, { .pll_rate = 396000000, .pll_lpm_rate = 792000000, .cpu_rate = 396000000, .cpu_podf = 0, - .pu_voltage = 1050000, - .soc_voltage = 1050000, - .cpu_voltage = 1100000,}, - { - .pll_rate = 396000000, - .pll_lpm_rate = 792000000, - .cpu_rate = 198000000, - .cpu_podf = 1, - .pu_voltage = 1050000, - .soc_voltage = 1050000, - .cpu_voltage = 1050000,}, + .pu_voltage = 1150000, + .soc_voltage = 1150000, + .cpu_voltage = 950000,}, }; static struct dvfs_op dvfs_core_setpoint_1_2G[] = { diff --git a/arch/arm/mach-mx6/cpu_regulator-mx6.c b/arch/arm/mach-mx6/cpu_regulator-mx6.c index 5019f8bedff2..8eb976d2eefd 100644 --- a/arch/arm/mach-mx6/cpu_regulator-mx6.c +++ b/arch/arm/mach-mx6/cpu_regulator-mx6.c @@ -62,7 +62,9 @@ void mx6_cpu_regulator_init(void) { int cpu; u32 curr_cpu = 0; - +#ifndef CONFIG_SMP + unsigned long old_loops_per_jiffy; +#endif external_pureg = 0; cpu_regulator = regulator_get(NULL, gp_reg_id); if (IS_ERR(cpu_regulator)) @@ -90,7 +92,7 @@ void mx6_cpu_regulator_init(void) curr_cpu / 1000, clk_get_rate(cpu_clk) / 1000); #else - u32 old_loops_per_jiffy = loops_per_jiffy; + old_loops_per_jiffy = loops_per_jiffy; loops_per_jiffy = mx6_cpu_jiffies(old_loops_per_jiffy, diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S index 1987581e56aa..f712700a8e68 100644 --- a/arch/arm/mach-mx6/mx6_suspend.S +++ b/arch/arm/mach-mx6/mx6_suspend.S @@ -233,6 +233,11 @@ wait_for_pll_lock: bic r6, r6, #0x2000000 str r6, [r3, #0x14] +periph_clk_switch1: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne periph_clk_switch1 + /* Set the dividers to default value. */ ldr r6, [r3, #0x14] bic r6, r6, #0x70000 @@ -241,14 +246,9 @@ wait_for_pll_lock: str r6, [r3, #0x14] ahb_podf1: - ldr r0, [r3, #0x48] - cmp r0, #0 - bne ahb_podf1 - -periph_clk_switch1: ldr r6, [r3, #0x48] cmp r6, #0 - bne periph_clk_switch1 + bne ahb_podf1 /* Move MMDC back to PLL2_PFD2_400 */ ldr r6, [r3, #0x14] @@ -262,7 +262,7 @@ mmdc_loop2: /* Set DDR clock to divide by 1. */ ldr r6, [r3, #0x14] - bic r6, r0, #0x38 + bic r6, r6, #0x38 str r6, [r3, #0x14] mmdc_div1: @@ -1099,6 +1099,12 @@ set ddr iomux to low power mode ldr r1, =CCM_BASE_ADDR add r1, r1, #PERIPBASE_VIRT ldr r0, [r1] + ldr r1, =GPC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r0, [r1] + ldr r1, =CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r0, [r1] #ifdef CONFIG_MX6_INTER_LDO_BYPASS ldr r1, =ANATOP_BASE_ADDR add r1, r1, #PERIPBASE_VIRT @@ -1173,6 +1179,66 @@ save resume pointer into SRC_GPR1 add r1, r1, #PERIPBASE_VIRT str r3, [r1, #SRC_GPR1_OFFSET] + /* Mask all GPC interrupts before + * enabling the RBC counters to + * avoid the counter starting too + * early if an interupt is already + * pending. + */ + ldr r3, =GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT + ldr r4, [r3, #0x08] + ldr r5, [r3, #0x0c] + ldr r6, [r3, #0x10] + ldr r7, [r3, #0x14] + + ldr r8, =0xffffffff + str r8, [r3, #0x08] + str r8, [r3, #0x0c] + str r8, [r3, #0x10] + str r8, [r3, #0x14] + + /* Enable the RBC bypass counter here + * to hold off the interrupts. + * RBC counter = 32 (1ms) + * Minimum RBC delay should be + * 400us for the analog LDOs to + * power down. + */ + ldr r1, =CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r8, [r1, #0x0] + ldr r0, =0x7E00000 + bic r8, r8, r0 + ldr r0, =0x4000000 + orr r8, r8, r0 + str r8, [r1, #0x0] + + /* Enable the counter. */ + ldr r8, [r1, #0x0] + orr r8, r8, #0x8000000 + str r8, [r1, #0x0] + + /* Unmask all the GPC interrupts. */ + str r4, [r3, #0x08] + str r5, [r3, #0x0c] + str r6, [r3, #0x10] + str r7, [r3, #0x14] + + /* Now delay for a short while (3usec) + * ARM is at 1GHz at this point + * so a short loop should be enough. + * This delay is required to ensure that + * the RBC counter can start counting in case an + * interrupt is already pending or in case an interrupt + * arrives just as ARM is about to assert DSM_request. + */ + ldr r4, =2000 +rbc_loop: + sub r4, r4, #0x1 + cmp r4, #0x0 + bne rbc_loop + #ifdef CONFIG_MX6_INTER_LDO_BYPASS ldr r1, =ANATOP_BASE_ADDR add r1, r1, #PERIPBASE_VIRT diff --git a/arch/arm/mach-mx6/mx6sl_wfi.S b/arch/arm/mach-mx6/mx6sl_wfi.S index dc4107dff7e8..4ec97e424237 100644 --- a/arch/arm/mach-mx6/mx6sl_wfi.S +++ b/arch/arm/mach-mx6/mx6sl_wfi.S @@ -29,12 +29,6 @@ ldr r7, [r1, #0x318] /* DRAM_DQM3 */ stmfd r9!, {r4-r7} - ldr r4, [r1, #0x344] /* DRAM_SDQS0 */ - ldr r5, [r1, #0x348] /* DRAM_SDQS1 */ - ldr r6, [r1, #0x34c] /* DRAM_SDQS2 */ - ldr r7, [r1, #0x350] /* DRAM_SDQS3 */ - stmfd r9!, {r4-r7} - ldr r4, [r1, #0x5c4] /* GPR_B0DS */ ldr r5, [r1, #0x5cc] /* GPR_B1DS */ ldr r6, [r1, #0x5d4] /* GPR_B2DS */ @@ -56,13 +50,16 @@ ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */ ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */ ldr r6, [r1, #0x320] /* DRAM_RESET */ - ldr r7, [r1, #0x5c8] /* GPR_CTLDS */ - stmfd r9!, {r4-r7} + stmfd r9!, {r4-r6} .endm .macro sl_ddr_io_restore + /* r9 points to IRAM stack. + * r1 points to IOMUX base address. + * r8 points to MMDC base address. + */ ldmea r9!, {r4-r7} str r4, [r1, #0x30c] /* DRAM_DQM0 */ str r5, [r1, #0x310] /* DRAM_DQM1 */ @@ -70,12 +67,6 @@ str r7, [r1, #0x318] /* DRAM_DQM3 */ ldmea r9!, {r4-r7} - str r4, [r1, #0x344] /* DRAM_SDQS0 */ - str r5, [r1, #0x348] /* DRAM_SDQS1 */ - str r6, [r1, #0x34c] /* DRAM_SDQS2 */ - str r7, [r1, #0x350] /* DRAM_SDQS3 */ - - ldmea r9!, {r4-r7} str r4, [r1, #0x5c4] /* GPR_B0DS */ str r5, [r1, #0x5cc] /* GPR_B1DS */ str r6, [r1, #0x5d4] /* GPR_B2DS */ @@ -93,11 +84,35 @@ str r6, [r1, #0x33c] /* DRAM_SODT0*/ str r7, [r1, #0x340] /* DRAM_SODT1*/ - ldmea r9!, {r4-r7} + ldmea r9!, {r4-r6} str r4, [r1, #0x330] /* DRAM_SDCKE0 */ str r5, [r1, #0x334] /* DRAM_SDCKE1 */ str r6, [r1, #0x320] /* DRAM_RESET */ - str r7, [r1, #0x5c8] /* GPR_CTLDS */ + + /* Need to reset the FIFO to avoid MMDC lockup + * caused because of floating/changing the + * configuration of many DDR IO pads. + */ + /* reset read FIFO, RST_RD_FIFO */ + ldr r7, =0x83c + ldr r6, [r8, r7] + orr r6, r6, #0x80000000 + str r6, [r8, r7] +fifo_reset1_wait: + ldr r6, [r8, r7] + and r6, r6, #0x80000000 + cmp r6, #0 + bne fifo_reset1_wait + + /* reset FIFO a second time */ + ldr r6, [r8, r7] + orr r6, r6, #0x80000000 + str r6, [r8, r7] +fifo_reset2_wait: + ldr r6, [r8, r7] + and r6, r6, #0x80000000 + cmp r6, #0 + bne fifo_reset2_wait .endm @@ -109,18 +124,6 @@ str r4, [r1, #0x314] /* DRAM_DQM2 */ str r4, [r1, #0x318] /* DRAM_DQM3 */ - /* Make sure the Pull Ups are enabled. - * So only reduce the drive stength, but - * leave the pull-ups in the original state. - * This is required for LPDDR2. - */ - ldr r4, [r1, #0x344] - orr r4, r4, #0x3000 - str r4, [r1, #0x344] /* DRAM_SDQS0 */ - str r4, [r1, #0x348] /* DRAM_SDQS1 */ - str r4, [r1, #0x34c] /* DRAM_SDQS2 */ - str r4, [r1, #0x350] /* DRAM_SDQS3 */ - str r4, [r1, #0x5c4] /* GPR_B0DS */ str r4, [r1, #0x5cc] /* GPR_B1DS */ str r4, [r1, #0x5d4] /* GPR_B2DS */ diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c index fb48a3ec94a5..654881af57bd 100644 --- a/arch/arm/mach-mx6/pm.c +++ b/arch/arm/mach-mx6/pm.c @@ -72,7 +72,6 @@ static struct clk *cpu_clk; static struct clk *axi_clk; static struct clk *periph_clk; -static struct clk *axi_org_parent; static struct clk *pll3_usb_otg_main_clk; static struct pm_platform_data *pm_data; @@ -177,14 +176,10 @@ static void usb_power_up_handler(void) } -/* - * For safety, DO NOT define ENABLE_DISP_POWER_GATING for MX6SL EVK. - * Otherwise will meet PxP processing timeout When run EPDC unit test. - * The cause is under investigation. - */ static void disp_power_down(void) { -#ifdef ENABLE_DISP_POWER_GATING +#if !defined(CONFIG_FB_MXC_ELCDIF_FB) && \ + !defined(CONFIG_FB_MXC_ELCDIF_FB_MODULE) if (cpu_is_mx6sl()) { __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PUPSCR_OFFSET); __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_DISP_PDNSCR_OFFSET); @@ -206,7 +201,8 @@ static void disp_power_down(void) static void disp_power_up(void) { -#ifdef ENABLE_DISP_POWER_GATING +#if !defined(CONFIG_FB_MXC_ELCDIF_FB) && \ + !defined(CONFIG_FB_MXC_ELCDIF_FB_MODULE) if (cpu_is_mx6sl()) { /* * Need to enable EPDC/LCDIF pix clock, and @@ -344,9 +340,6 @@ static int mx6_suspend_enter(suspend_state_t state) return -EINVAL; } - axi_org_parent = clk_get_parent(axi_clk); - clk_set_parent(axi_clk, periph_clk); - if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { if (pm_data && pm_data->suspend_enter) pm_data->suspend_enter(); @@ -363,6 +356,30 @@ static int mx6_suspend_enter(suspend_state_t state) suspend_in_iram(state, (unsigned long)iram_paddr, (unsigned long)suspend_iram_base, cpu_type); + /* Reset the RBC counter. */ + /* All interrupts should be masked before the + * RBC counter is reset. + */ + /* Mask all interrupts. These will be unmasked by + * the mx6_suspend_restore routine below. + */ + __raw_writel(0xffffffff, gpc_base + 0x08); + __raw_writel(0xffffffff, gpc_base + 0x0c); + __raw_writel(0xffffffff, gpc_base + 0x10); + __raw_writel(0xffffffff, gpc_base + 0x14); + + /* Clear the RBC counter and RBC_EN bit. */ + /* Disable the REG_BYPASS_COUNTER. */ + __raw_writel(__raw_readl(MXC_CCM_CCR) & + ~MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR); + /* Make sure we clear REG_BYPASS_COUNT*/ + __raw_writel(__raw_readl(MXC_CCM_CCR) & + (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR); + /* Need to wait for a minimum of 2 CLKILS (32KHz) for the + * counter to clear and reset. + */ + udelay(80); + if (arm_pg) { /* restore gic registers */ restore_gic_dist_state(0, &gds); @@ -383,7 +400,6 @@ static int mx6_suspend_enter(suspend_state_t state) } else { cpu_do_idle(); } - clk_set_parent(axi_clk, axi_org_parent); return 0; } diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index 533d4f5dbfab..6ecd51e9f9ea 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -51,7 +51,7 @@ extern unsigned int gpc_wake_irq[4]; static void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR); -static struct clk *ddr_clk; +extern struct clk *mmdc_ch0_axi; volatile unsigned int num_cpu_idle; volatile unsigned int num_cpu_idle_lock = 0x0; @@ -86,7 +86,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) int stop_mode = 0; void __iomem *anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR); - u32 ccm_clpcr, anatop_val, reg; + u32 ccm_clpcr, anatop_val; ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK); @@ -153,8 +153,15 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) if (stop_mode > 0) { gpc_set_wakeup(gpc_wake_irq); /* Power down and power up sequence */ - __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET); - __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET); + /* The PUPSCR counter counts in terms of CLKIL (32KHz) cycles. + * The PUPSCR should include the time it takes for the ARM LDO to + * ramp up. + */ + __raw_writel(0x202, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET); + /* The PDNSCR is a counter that counts in IPG_CLK cycles. This counter + * can be set to minimum values to power down faster. + */ + __raw_writel(0x101, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET); if (stop_mode >= 2) { /* dormant mode, need to power off the arm core */ __raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET); @@ -198,25 +205,17 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) HW_ANADIG_REG_2P5); } } - /* DL's TO1.0 can't support DSM mode due to ipg glitch */ - if ((mx6dl_revision() != IMX_CHIP_REVISION_1_0) - && stop_mode != 3) - __raw_writel(__raw_readl(MXC_CCM_CCR) | - MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR); - if (stop_mode != 3) { /* Make sure we clear WB_COUNT * and re-config it. */ __raw_writel(__raw_readl(MXC_CCM_CCR) & - (~MXC_CCM_CCR_WB_COUNT_MASK) & - (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR); - udelay(80); - /* Reconfigurate WB and RBC counter, need to set WB counter + (~MXC_CCM_CCR_WB_COUNT_MASK), + MXC_CCM_CCR); + /* Reconfigure WB, need to set WB counter * to 0x7 to make sure it work normally */ __raw_writel(__raw_readl(MXC_CCM_CCR) | - (0x7 << MXC_CCM_CCR_WB_COUNT_OFFSET) | - (0x20 << MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET), + (0x7 << MXC_CCM_CCR_WB_COUNT_OFFSET), MXC_CCM_CCR); /* Set WB_PER enable */ @@ -272,11 +271,9 @@ void arch_idle_single_core(void) ca9_do_idle(); } else { if (low_bus_freq_mode || audio_bus_freq_mode) { - u32 ddr_usecount; - if (ddr_clk == NULL) - ddr_clk = clk_get(NULL , - "mmdc_ch0_axi"); - ddr_usecount = clk_get_usecount(ddr_clk); + int ddr_usecount = 0; + if ((mmdc_ch0_axi != NULL)) + ddr_usecount = clk_get_usecount(mmdc_ch0_axi); if (cpu_is_mx6sl() && low_bus_freq_mode && ddr_usecount == 1) { diff --git a/arch/arm/plat-mxc/cpu.c b/arch/arm/plat-mxc/cpu.c index 073c237cc387..eb163abd4f36 100755 --- a/arch/arm/plat-mxc/cpu.c +++ b/arch/arm/plat-mxc/cpu.c @@ -61,6 +61,16 @@ static int __init jtag_wfi_setup(char *p) return 0; } early_param("jtag", jtag_wfi_setup); + + +static int __init setup_debug_uart(char *p) +{ + uart_at_24 = 1; + return 0; +} + +early_param("debug_uart", setup_debug_uart); + /** * early_console_setup - setup debugging console * diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c index a4a15482c71f..b5cfba1a5047 100755 --- a/arch/arm/plat-mxc/dvfs_core.c +++ b/arch/arm/plat-mxc/dvfs_core.c @@ -722,6 +722,9 @@ void stop_dvfs(void) unsigned long flags; u32 curr_cpu; int cpu; +#ifndef CONFIG_SMP + unsigned long old_loops_per_jiffy; +#endif if (dvfs_core_is_active) { @@ -752,7 +755,7 @@ void stop_dvfs(void) dvfs_cpu_jiffies(per_cpu(cpu_data, cpu).loops_per_jiffy, curr_cpu/1000, clk_get_rate(cpu_clk) / 1000); #else - u32 old_loops_per_jiffy = loops_per_jiffy; + old_loops_per_jiffy = loops_per_jiffy; loops_per_jiffy = dvfs_cpu_jiffies(old_loops_per_jiffy, diff --git a/drivers/char/fsl_otp.c b/drivers/char/fsl_otp.c index 05ad55e9d6a9..7021c42c4bfd 100755 --- a/drivers/char/fsl_otp.c +++ b/drivers/char/fsl_otp.c @@ -1,7 +1,7 @@ /* * Freescale On-Chip OTP driver * - * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. 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 as published by @@ -153,6 +153,7 @@ static int __init alloc_otp_attr(struct mxc_otp_platform_data *pdata) goto error_out; for (i = 0; i < otp_data->fuse_num; i++) { + sysfs_attr_init(&kattr[i].attr); kattr[i].attr.name = pdata->fuse_name[i]; kattr[i].attr.mode = 0600; kattr[i].show = otp_show; diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c index b74f62cac032..c6098774ecf2 100644 --- a/drivers/dma/pxp/pxp_dma_v2.c +++ b/drivers/dma/pxp/pxp_dma_v2.c @@ -436,22 +436,27 @@ static void pxp_set_olparam(int layer_no, struct pxps *pxp) static void pxp_set_s0param(struct pxps *pxp) { struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; - struct pxp_layer_param *s0params_data = &pxp_conf->s0_param; struct pxp_proc_data *proc_data = &pxp_conf->proc_data; u32 s0param; - s0param = BF_PXP_OUT_PS_ULC_X(proc_data->srect.left); - s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->srect.top); + /* contains the coordinate for the PS in the OUTPUT buffer. */ + s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left); + s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top); __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC); - s0param = BF_PXP_OUT_PS_LRC_X(s0params_data->width); - s0param |= BF_PXP_OUT_PS_LRC_Y(s0params_data->height); + s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left + + proc_data->drect.width - 1); + s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top + + proc_data->drect.height - 1); __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC); - } -/* TODO: crop behavior is re-designed in h/w. */ +/* crop behavior is re-designed in h/w. */ static void pxp_set_s0crop(struct pxps *pxp) { + /* + * place-holder, it's implemented in other functions in this driver. + * Refer to "Clipping source images" section in RM for detail. + */ } static int pxp_set_scaling(struct pxps *pxp) @@ -706,19 +711,36 @@ static void pxp_set_s0buf(struct pxps *pxp) { struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; struct pxp_layer_param *s0_params = &pxp_conf->s0_param; + struct pxp_proc_data *proc_data = &pxp_conf->proc_data; dma_addr_t Y, U, V; + dma_addr_t Y1, U1, V1; + u32 offset, bpp = 1; Y = s0_params->paddr; - __raw_writel(Y, pxp->base + HW_PXP_PS_BUF); + + if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565) + bpp = 2; + else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB24) + bpp = 4; + offset = (proc_data->srect.top * s0_params->width + + proc_data->srect.left) * bpp; + /* clipping or cropping */ + Y1 = Y + offset; + __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF); if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) || (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) || (s0_params->pixel_fmt == PXP_PIX_FMT_GREY)) { /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */ int s = 2; + + offset = proc_data->srect.top * s0_params->width / 4 + + proc_data->srect.left / 2; U = Y + (s0_params->width * s0_params->height); + U1 = U + offset; V = U + ((s0_params->width * s0_params->height) >> s); - __raw_writel(U, pxp->base + HW_PXP_PS_UBUF); - __raw_writel(V, pxp->base + HW_PXP_PS_VBUF); + V1 = V + offset; + __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF); + __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF); } /* TODO: only support RGB565, Y8, Y4, YUV420 */ diff --git a/drivers/input/touchscreen/elan_ts.c b/drivers/input/touchscreen/elan_ts.c index fd85c1b33b7c..9f200ebcbf7e 100644 --- a/drivers/input/touchscreen/elan_ts.c +++ b/drivers/input/touchscreen/elan_ts.c @@ -406,6 +406,33 @@ static const struct i2c_device_id elan_touch_id[] = { {} }; +static int elan_suspend(struct device *dev) +{ + return 0; +} + +static int elan_resume(struct device *dev) +{ + uint8_t buf[IDX_PACKET_SIZE] = { 0 }; + + if (0 == elan_touch_detect_int_level()) { + dev_dbg(dev, "Got touch during suspend period.\n"); + /* + * if touch screen during suspend, recv and drop the + * data, then touch interrupt pin will return high after + * receving data. + */ + elan_touch_recv_data(elan_touch_data.client, buf); + } + + return 0; +} + +static const struct dev_pm_ops elan_dev_pm_ops = { + .suspend = elan_suspend, + .resume = elan_resume, +}; + static struct i2c_driver elan_touch_driver = { .probe = elan_touch_probe, .remove = elan_touch_remove, @@ -413,6 +440,9 @@ static struct i2c_driver elan_touch_driver = { .driver = { .name = "elan-touch", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &elan_dev_pm_ops, +#endif }, }; diff --git a/drivers/media/video/mxc/capture/csi_v4l2_capture.c b/drivers/media/video/mxc/capture/csi_v4l2_capture.c index a0887b930ea4..3756b00a844d 100644 --- a/drivers/media/video/mxc/capture/csi_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/csi_v4l2_capture.c @@ -1142,6 +1142,7 @@ static long csi_v4l_do_ioctl(struct file *file, strcpy(cap->driver, "csi_v4l2"); cap->version = KERNEL_VERSION(0, 1, 11); cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_READWRITE; cap->card[0] = '\0'; cap->bus_info[0] = '\0'; @@ -1536,7 +1537,8 @@ static int csi_v4l2_suspend(struct platform_device *pdev, pm_message_t state) if (cam->overlay_on == true) stop_preview(cam); - camera_power(cam, false); + if (cam->capture_on == true || cam->overlay_on == true) + camera_power(cam, false); return 0; } @@ -1561,7 +1563,8 @@ static int csi_v4l2_resume(struct platform_device *pdev) cam->low_power = false; wake_up_interruptible(&cam->power_queue); - camera_power(cam, true); + if (cam->capture_on == true || cam->overlay_on == true) + camera_power(cam, true); if (cam->overlay_on == true) start_preview(cam); diff --git a/drivers/media/video/mxc/capture/fsl_csi.c b/drivers/media/video/mxc/capture/fsl_csi.c index 33a82242e95e..f5677e473e87 100644 --- a/drivers/media/video/mxc/capture/fsl_csi.c +++ b/drivers/media/video/mxc/capture/fsl_csi.c @@ -250,12 +250,14 @@ static void csi_mclk_recalc(struct clk *clk) void csi_mclk_enable(void) { + clk_enable(&csi_mclk); __raw_writel(__raw_readl(CSI_CSICR1) | BIT_MCLKEN, CSI_CSICR1); } void csi_mclk_disable(void) { __raw_writel(__raw_readl(CSI_CSICR1) & ~BIT_MCLKEN, CSI_CSICR1); + clk_disable(&csi_mclk); } static int __devinit csi_probe(struct platform_device *pdev) @@ -293,8 +295,13 @@ static int __devinit csi_probe(struct platform_device *pdev) return PTR_ERR(per_clk); clk_put(per_clk); + /* + * On mx6sl, there's no divider in CSI module(BIT_MCLKDIV in CSI_CSICR1 + * is marked as reserved). We use CSI clock in CCM. + * However, the value read from BIT_MCLKDIV bits are 0, which is + * equivalent to "divider=1". The code works for mx6sl without change. + */ csi_mclk.parent = per_clk; - clk_enable(per_clk); csi_mclk_recalc(&csi_mclk); err: @@ -303,7 +310,6 @@ err: static int __devexit csi_remove(struct platform_device *pdev) { - clk_disable(&csi_mclk); iounmap(csi_regbase); return 0; diff --git a/drivers/media/video/mxc/output/mxc_pxp_v4l2.c b/drivers/media/video/mxc/output/mxc_pxp_v4l2.c index a3a8294efb8e..08d16b9f75d3 100644 --- a/drivers/media/video/mxc/output/mxc_pxp_v4l2.c +++ b/drivers/media/video/mxc/output/mxc_pxp_v4l2.c @@ -54,6 +54,7 @@ #define V4L2_OUTPUT_TYPE_INTERNAL 4 +static int video_nr = -1; /* -1 ==> auto assign */ static struct pxp_data_format pxp_s0_formats[] = { { .name = "24-bit RGB", @@ -395,7 +396,12 @@ static int pxp_s_output(struct file *file, void *fh, bpp = 2; pxp->outb_size = fmt->width * fmt->height * bpp; - pxp->outb = kmalloc(fmt->width * fmt->height * bpp, GFP_KERNEL); + pxp->outb = kmalloc(fmt->width * fmt->height * bpp, + GFP_KERNEL | GFP_DMA); + if (pxp->outb == NULL) { + dev_err(&pxp->pdev->dev, "No enough memory!\n"); + return -ENOMEM; + } pxp->outb_phys = virt_to_phys(pxp->outb); dma_map_single(NULL, pxp->outb, fmt->width * fmt->height * bpp, DMA_TO_DEVICE); @@ -1175,7 +1181,7 @@ static int pxp_probe(struct platform_device *pdev) memcpy(pxp->vdev, &pxp_template, sizeof(pxp_template)); video_set_drvdata(pxp->vdev, pxp); - err = video_register_device(pxp->vdev, VFL_TYPE_GRABBER, 0); + err = video_register_device(pxp->vdev, VFL_TYPE_GRABBER, video_nr); if (err) { dev_err(&pdev->dev, "failed to register video device\n"); goto freevdev; @@ -1235,6 +1241,7 @@ static void __exit pxp_exit(void) module_init(pxp_init); module_exit(pxp_exit); +module_param(video_nr, int, 0444); MODULE_DESCRIPTION("MXC PxP V4L2 driver"); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 3dea9b5b29ff..062a6c319695 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -841,12 +841,18 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd MMC_VDD_32_33 | MMC_VDD_33_34; host->ocr_avail_mmc = MMC_VDD_29_30 | MMC_VDD_30_31 | \ MMC_VDD_32_33 | MMC_VDD_33_34; + host->ocr_avail_sdio = MMC_VDD_29_30 | MMC_VDD_30_31 | \ + MMC_VDD_32_33 | MMC_VDD_33_34; if (cpu_is_mx6q() || cpu_is_mx6dl()) sdhci_esdhc_ops.platform_execute_tuning = esdhc_execute_tuning; - if (boarddata->support_18v) + if (boarddata->support_18v) { host->ocr_avail_sd |= MMC_VDD_165_195; + host->ocr_avail_mmc |= MMC_VDD_165_195; + host->ocr_avail_sdio |= MMC_VDD_165_195; + } + if (boarddata->support_8bit) host->mmc->caps |= MMC_CAP_8_BIT_DATA; if (boarddata->keep_power_at_suspend) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2c32faad3b4b..ba625b3ca376 100755 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -30,7 +30,7 @@ #include "sdhci.h" #define DRIVER_NAME "sdhci" -#define CLK_TIMEOUT (10 * HZ) +#define CLK_TIMEOUT (1 * HZ) #define DBG(f, x...) \ pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 8a66f3eeb992..5e9594d744d9 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1742,6 +1742,8 @@ static int serial_imx_resume(struct platform_device *dev) return 0; } +extern int uart_at_24; + static int serial_imx_probe(struct platform_device *pdev) { struct imx_port *sport; @@ -1788,6 +1790,9 @@ static int serial_imx_probe(struct platform_device *pdev) ret = PTR_ERR(sport->clk); goto unmap; } + if (uart_at_24) + clk_set_parent(sport->clk, clk_get(NULL, "osc")); + clk_enable(sport->clk); sport->port.uartclk = clk_get_rate(sport->clk); diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index b91cf9f82543..08118b3ba61e 100755 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -1695,6 +1695,10 @@ static void setup_received_irq(struct fsl_udc *udc, else if (setup->bRequest == USB_DEVICE_A_ALT_HNP_SUPPORT) udc->gadget.a_alt_hnp_support = 1; + else + break; + } else { + break; } rc = 0; } else @@ -3065,6 +3069,8 @@ static int __devinit fsl_udc_probe(struct platform_device *pdev) goto err2a; } + spin_lock_init(&pdata->lock); + /* Due to mx35/mx25's phy's bug */ reset_phy(); @@ -3210,7 +3216,6 @@ static int __devinit fsl_udc_probe(struct platform_device *pdev) udc_controller->charger.enable = false; #endif - spin_lock_init(&pdata->lock); return 0; err4: diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index e09f4dfd05d9..35815869bb8d 100755 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -260,6 +260,8 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, goto err4; } + spin_lock_init(&pdata->lock); + fsl_platform_set_host_mode(hcd); hcd->power_budget = pdata->power_budget; ehci = hcd_to_ehci(hcd); @@ -308,7 +310,6 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, ehci = hcd_to_ehci(hcd); pdata->pm_command = ehci->command; - spin_lock_init(&pdata->lock); return retval; err6: free_irq(irq, (void *)pdev); diff --git a/drivers/video/mxc/Kconfig b/drivers/video/mxc/Kconfig index 8a4a0792724f..83b094267760 100644 --- a/drivers/video/mxc/Kconfig +++ b/drivers/video/mxc/Kconfig @@ -61,7 +61,7 @@ config FB_MXC_SII902X tristate "Si Image SII9022 DVI/HDMI Interface Chip" config FB_MXC_SII902X_ELCDIF - depends on FB_MXC_SYNC_PANEL && I2C + depends on FB_MXC_ELCDIF_FB && FB_MXC_SYNC_PANEL && I2C tristate "Si Image SII9022 DVI/HDMI Interface Chip for ELCDIF FB" config FB_MXC_CH7026 diff --git a/drivers/video/mxc/mxc_elcdif_fb.c b/drivers/video/mxc/mxc_elcdif_fb.c index 7475bfbd2c9e..e98245dc3709 100644 --- a/drivers/video/mxc/mxc_elcdif_fb.c +++ b/drivers/video/mxc/mxc_elcdif_fb.c @@ -586,6 +586,7 @@ void mxcfb_elcdif_register_mode(const struct fb_videomode *modedb, return; } +EXPORT_SYMBOL(mxcfb_elcdif_register_mode); int mxc_elcdif_frame_addr_setup(dma_addr_t phys) { diff --git a/drivers/video/mxc/mxc_epdc_fb.c b/drivers/video/mxc/mxc_epdc_fb.c index b702788ae823..2df44041e65c 100644 --- a/drivers/video/mxc/mxc_epdc_fb.c +++ b/drivers/video/mxc/mxc_epdc_fb.c @@ -735,18 +735,24 @@ static int epdc_choose_next_lut(int rev, int *next_lut) { u64 luts_status, unprocessed_luts; bool next_lut_found = false; + /* Available LUTs are reduced to 16 in 5-bit waveform mode */ + u32 format_p5n = __raw_readl(EPDC_FORMAT) & + EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N; luts_status = __raw_readl(EPDC_STATUS_LUTS); - if (rev < 20) + if ((rev < 20) || format_p5n) luts_status &= 0xFFFF; else luts_status |= ((u64)__raw_readl(EPDC_STATUS_LUTS2) << 32); - if (rev < 20) + if (rev < 20) { unprocessed_luts = __raw_readl(EPDC_IRQ) & 0xFFFF; - else + } else { unprocessed_luts = __raw_readl(EPDC_IRQ1) | ((u64)__raw_readl(EPDC_IRQ2) << 32); + if (format_p5n) + unprocessed_luts &= 0xFFFF; + } while (!next_lut_found) { /* @@ -762,7 +768,7 @@ static int epdc_choose_next_lut(int rev, int *next_lut) */ *next_lut = fls64(luts_status); - if (rev < 20) { + if ((rev < 20) || format_p5n) { if (*next_lut > 15) *next_lut = ffz(luts_status); } else { @@ -1160,6 +1166,8 @@ static void epdc_init_sequence(struct mxc_epdc_fb_data *fb_data) fb_data->in_init = true; epdc_powerup(fb_data); draw_mode0(fb_data); + /* Force power down event */ + fb_data->powering_down = true; epdc_powerdown(fb_data); fb_data->updates_active = false; } @@ -3694,7 +3702,13 @@ static void epdc_intr_work_func(struct work_struct *work) next_marker->update_marker); complete(&next_marker->update_completion); } - } else if (epdc_lut_cancelled) { + } else if (epdc_lut_cancelled && !epdc_collision) { + /* + * Note: The update may be cancelled (void) if all + * pixels collided. In that case we handle it as a + * collision, not a cancel. + */ + /* Clear LUT status (might be set if no AUTOWV used) */ /* diff --git a/drivers/video/mxc/mxcfb_seiko_wvga.c b/drivers/video/mxc/mxcfb_seiko_wvga.c index c96238d80cb2..6e9abaf8566b 100644 --- a/drivers/video/mxc/mxcfb_seiko_wvga.c +++ b/drivers/video/mxc/mxcfb_seiko_wvga.c @@ -89,11 +89,6 @@ static int lcd_fb_event(struct notifier_block *nb, unsigned long val, void *v) return 0; switch (val) { - case FB_EVENT_FB_REGISTERED: - lcd_init_fb(event->info); - fb_show_logo(event->info, 0); - lcd_poweron(); - break; case FB_EVENT_BLANK: if ((event->info->var.xres != 800) || (event->info->var.yres != 480)) { |