コード例 #1
0
static void einkfb_remove(struct fb_info *info, einkfb_init_err_t err)
{
    switch ( err )
    {
    case einkfb_init_err_none:
        BLANK_DONE();
        unregister_framebuffer(info);

    case einkfb_init_err_register_framebuffer:
        HAL_HW_DONE(einkfb_hw_shutdown_mode);
        fb_dealloc_cmap(&info->cmap);

    case einkfb_init_err_fb_alloc_cmap:
        EINKFB_FREE_HAL(einkfb, einkfb_dma ? &einkfb_phys : NULL);

    case einkfb_init_err_einkfb_malloc_hal:
        HAL_SW_DONE();

    case einkfb_init_err_hw_sw_init:
        framebuffer_release(info);

    default:
    case einkfb_init_err_framebuffer_alloc:
        if ( err )
            einkfb_print_crit("failed to initialize, err = %d\n", err);
        break;
    }

    boot_milestone_write(EINK_HAL_STOPPED_BOM, EINK_HAL_STOPPED_BOM_SZ);
}
コード例 #2
0
static bool bs_cmd_ck_reg(u16 ra, u16 rd)
{
    u16 rd_reg = bs_cmd_rd_reg(ra);
    bool result = true;

    if ( rd_reg != rd )
    {
        einkfb_print_crit("REG[0x%04X] is 0x%04X but should be 0x%04X\n",
            ra, rd_reg, rd);
            
        result = false;
    }
    
    return ( result );
}
コード例 #3
0
static int einkfb_schedule_timeout_guts(unsigned long hardware_timeout, einkfb_hardware_ready_t hardware_ready, void *data, bool interruptible)
{
    unsigned long start_time = jiffies, stop_time = start_time + hardware_timeout,
        timeout = CONTROLLER_COMMON_TIMEOUT_MIN;
    int result = EINKFB_SUCCESS;

    // Ask the hardware whether it's ready or not.  And, if it's not ready, start yielding
    // the CPU for CONTROLLER_COMMON_TIMEOUT_MIN jiffies, increasing the yield time up to
    // CONTROLLER_COMMON_TIMEOUT_MAX jiffies.  Time out after the requested number of
    // of jiffies has occurred.
    //
    while ( !(*hardware_ready)(data) && time_before_eq(jiffies, stop_time) )
    {
        timeout = min(timeout++, CONTROLLER_COMMON_TIMEOUT_MAX);
        
        if ( interruptible )
            schedule_timeout_interruptible(timeout);
        else
            schedule_timeout(timeout);
    }

    if ( time_after(jiffies, stop_time) )
    {
       einkfb_print_crit("Timed out waiting for the hardware to become ready!\n");
       result = EINKFB_FAILURE;
    }
    else
    {
        // For debugging purposes, dump the time it took for the hardware to
        // become ready if it was more than CONTROLLER_COMMON_TIMEOUT_MAX.
        //
        stop_time = jiffies - start_time;
        
        if ( CONTROLLER_COMMON_TIMEOUT_MAX < stop_time )
            einkfb_debug("Timeout time = %ld\n", stop_time);
    }

    return ( result );    
}
コード例 #4
0
bool bs_hw_init(void)
{

	bool result = true;
	bsaddr = ioremap(0x10000000, 4);

	//printk(KERN_ALERT "hello broadsheet!\n");

//reset broadsheet

	// GPC7  EINK_3.3V_EN config output
		gpcon = __raw_readl(S3C64XX_GPCCON);
		gpcon = gpcon & ~(0xF << 28);
		__raw_writel(gpcon | (0x1 << 28), S3C64XX_GPCCON);		
	//GPC7 EINK_3.3V_EN set low
		gpdata = __raw_readl(S3C64XX_GPCDAT);
		gpdata =(gpdata & ~(1<<7));
		__raw_writel(gpdata,S3C64XX_GPCDAT);

	//GPC6 EINK_1.8V_EN config output
		gpcon = __raw_readl(S3C64XX_GPCCON);
		gpcon = gpcon & ~(0xF << 24);
		__raw_writel(gpcon | (0x1 << 24), S3C64XX_GPCCON);
	
	//GPC6 EINK_1.8V_EN set low
		gpdata = __raw_readl(S3C64XX_GPCDAT);
		gpdata =(gpdata & ~(1<<6));
		__raw_writel(gpdata,S3C64XX_GPCDAT);
	
	//GPP2 OSC_EN config output
		gpcon = __raw_readl(S3C64XX_GPPCON);
		gpcon  = (gpcon & ~(3<<4));
		 __raw_writel(gpcon|(0x1<<4), S3C64XX_GPPCON);
	//GPP2 OSC_EN set high
		gpdata = __raw_readl(S3C64XX_GPPDAT);
		gpdata =(gpdata & ~(1<<2));
		__raw_writel(gpdata|(0x1<<2),S3C64XX_GPPDAT);
		mdelay(10);

	//GPP9 HnRST config output
	gpcon = __raw_readl(S3C64XX_GPPCON);
	gpcon  = (gpcon & ~(3<<18));
	__raw_writel(gpcon|(0x1<<18), S3C64XX_GPPCON);
	
      HIGH_RESET_PIN;
	mdelay(10);
      LOW_RESET_PIN;
      mdelay(100); 
      HIGH_RESET_PIN;


//setup HD/C signalconfig
	gpcon = __raw_readl(S3C64XX_GPOCON);
	gpcon =(gpcon & ~(3<<4));
	__raw_writel(gpcon|(0x1<<4),S3C64XX_GPOCON);

	gpdata = __raw_readl(S3C64XX_GPODAT);
        gpdata =(gpdata & ~(1<<2));
        __raw_writel(gpdata|(0x1<<2),S3C64XX_GPODAT);

	//GPO3 HIRQ config input
		gpcon = __raw_readl(S3C64XX_GPOCON);
		gpcon  = (gpcon & ~(3<<6));
		__raw_writel(gpcon, S3C64XX_GPOCON);

//now HRDY  setup to input
	gpcon = __raw_readl(S3C64XX_GPOCON);
        gpcon  = (gpcon & ~(3<<8));
        __raw_writel(gpcon, S3C64XX_GPOCON);


	sromdata = __raw_readl(S3C64XX_VA_SROMC);
        sromdata &=~(0xF<<0);
        sromdata |= (1<<3) | (1<<2) | (1<<0);
        __raw_writel(sromdata, S3C64XX_VA_SROMC);
		
	//SROM_BC0 config
		//__raw_writel((0x1<<28)|(0xf<<24)|(0x1c<<16)|(0x1<<12)|(0x6<<8)|(0x2<<4)|(0x0<<0), S3C64XX_VA_SROMC+4);
    __raw_writel((0x0<<28)|(0x0<<24)|(0xA<<16)|(0x1<<12)|(0x0<<8)|(0x2<<4)|(0x0<<0), S3C64XX_VA_SROMC+4);

	//printk(KERN_ALERT "Product id is %x\n",__raw_readw(bsaddr));
	//printk(KERN_ALERT "The new bs driver\n");
#ifdef MXC31
	for(i=0;i<100;i++)
	{
	mdelay(500);
	__raw_writew(0xffff,bsaddr);
	//printk(KERN_ALERT "write the %dth times data\n",i);
	}
#endif

#ifdef USE_BS_IRQ
    int  rqstatus;
#endif
#ifdef MXC31
    ipu_adc_sig_cfg_t sig = { 0, 0, 0, 0, 0, 0, 0, 0,
            IPU_ADC_BURST_WCS,
            IPU_ADC_IFC_MODE_SYS80_TYPE2,
            16, 0, 0, IPU_ADC_SER_NO_RW
    };

    // Init DI interface
    if ( IS_NELL() || IS_MARIO() || IS_ADS() )
    {
        broadsheet_screen_height = BROADSHEET_SCREEN_HEIGHT_NELL;
        broadsheet_screen_width  = BROADSHEET_SCREEN_WIDTH_NELL;

        broadsheet_screen_size   = BROADSHEET_SCREEN_SIZE_NELL;
    }

    ipu_adc_init_panel(BROADSHEET_DISPLAY_NUMBER,
                       broadsheet_screen_width,
                       broadsheet_screen_height,
                       BROADSHEET_PIXEL_FORMAT, broadsheet_screen_size, sig, XY, 0, VsyncInternal);

    // Set IPU timing for read cycles
    ipu_adc_init_ifc_timing(BROADSHEET_DISPLAY_NUMBER, true,
                            BROADSHEET_READ_CYCLE_TIME,
                            BROADSHEET_READ_UP_TIME,
                            BROADSHEET_READ_DOWN_TIME,
                            BROADSHEET_READ_LATCH_TIME,
                            BROADSHEET_PIXEL_CLK);
    // Set IPU timing for write cycles
    ipu_adc_init_ifc_timing(BROADSHEET_DISPLAY_NUMBER, false,
                            BROADSHEET_WRITE_CYCLE_TIME,
                            BROADSHEET_WRITE_UP_TIME,
                            BROADSHEET_WRITE_DOWN_TIME,
                            0, 0);

    ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE, 0, 0, 0);

    gpio_lcd_active();
    slcd_gpio_config();

#ifdef CONFIG_MACH_MX31ADS
    // Reset the level translator for the two GPIO inputs (HIRQ and HRDY)
    pin_addr = PBC_BCTRL2_LDCIO_EN;
    __raw_writew(pin_addr, PBC_BASE_ADDRESS + PBC_BCTRL2_CLEAR);
#endif

#ifdef USE_BS_IRQ
    // Set up IRQ for for Broadsheet HIRQ line
    disable_irq(BROADSHEET_HIRQ_IRQ);
    set_irq_type(BROADSHEET_HIRQ_IRQ, IRQF_TRIGGER_RISING);
    rqstatus = request_irq(BROADSHEET_HIRQ_IRQ, (irq_handler_t) bs_irq_handler, 0, "eink_fb_hal_broads", NULL);
    if (rqstatus != 0) {
        einkfb_print_crit("Failed IRQ request for Broadsheet HIRQ line; request status = %d\n", rqstatus);
        result = false;
    }
#endif

     // Set up GPIO pins
    if (mxc_request_gpio(BROADSHEET_HIRQ_LINE)) {
        einkfb_print_crit("Could not obtain GPIO pin for HIRQ\n");
        result = false;
    }
    else {
        // Set HIRQ pin as input
        mxc_set_gpio_direction(BROADSHEET_HIRQ_LINE, 1);
    }
    if (mxc_request_gpio(BROADSHEET_HRDY_LINE)) {
        einkfb_print_crit("Could not obtain GPIO pin for HRDY\n");
        result = false;
    }
    else {
        // Set HRDY pin as input
        mxc_set_gpio_direction(BROADSHEET_HRDY_LINE, 1);
    }
#ifdef CONFIG_MACH_MARIO_MX
    if (mxc_request_gpio(BROADSHEET_RST_LINE)) {
        einkfb_print_crit("Could not obtain GPIO pin for RST\n");
        result = false;
    }
    else {
        // Set RST pin as output and initialize to zero (it's active LOW)
        mxc_set_gpio_direction(BROADSHEET_RST_LINE, 0);
        mxc_set_gpio_dataout(BROADSHEET_RST_LINE, 0);
    }
#endif

#ifdef CONFIG_MACH_MX31ADS
    // Enable the level translator for the two GPIO inputs (HIRQ and HRDY)
    mdelay(100);    // Pause 100 ms to allow level translator to settle
    pin_addr = PBC_BCTRL2_LDCIO_EN;
    __raw_writew(pin_addr, PBC_BASE_ADDRESS + PBC_BCTRL2_SET);
#endif
    // Reset Broadsheet
    einkfb_debug("Sending RST signal to Broadsheet...\n");
    LOW_RESET_PIN;	//WR_GPIO_LINE(BROADSHEET_RST_LINE, BROADSHEET_RESET_VAL);     // Assert RST
    mdelay(100);    // Pause 100 ms during reset
    HIGH_RESET_PIN;
 //WR_GPIO_LINE(BROADSHEET_RST_LINE, BROADSHEET_NON_RESET_VAL); // Clear RST
    mdelay(400);    // Pause 400 ms to allow Broasheet time to come up
    einkfb_debug("Broadsheet reset done.\n");
//#ifdef TEST_BROADSHEET
//    test_broadsheet(disp);
//#endif
#endif
#ifdef USE_BS_IRQ
    // Set up Broadsheet for interrupt generation (enable all conditions)
    bs_cmd_wr_reg(BS_INTR_CTL_REG, BS_ALL_IRQS);
    bs_cmd_wr_reg(BS_INTR_RAW_STATUS_REG, BS_ALL_IRQS);

    // Enable all Broadsheet display engine interrupts
    bs_cmd_wr_reg(BS_DE_INTR_ENABLE_REG, BS_DE_ALL_IRQS);
    bs_cmd_wr_reg(BS_DE_INTR_RAW_STATUS_REG, BS_DE_ALL_IRQS);
#endif
    //ipu_adc_write_cmd(CMD,0x11);
    //ipu_adc_write_cmd(DAT,0x030a);
    //ipu_adc_write_cmd(DAT,0x0123);

/*
    	ipu_adc_write_cmd(CMD,0x10);
        __raw_writew(0x02,bsaddr);

        udelay(1);

        printk(KERN_ALERT "Product id re-get is %x\n",__raw_readw(bsaddr));
        //printk(KERN_ALERT "The new bs driver\n");
*/

#if defined(CONFIG_HW_EP3_DVT) || defined(CONFIG_HW_EP4_DVT)  || defined(CONFIG_HW_EP1_DVT)  || defined(CONFIG_HW_EP2_DVT)			
    u16 rd_reg;
    unsigned short value = 0;	
    rd_reg = bs_cmd_rd_reg(0x00a) & ~(1 << 12);
    bs_cmd_wr_reg(0x00a, (value | (1 << 12)));		//REG[000Ah] bit 12 = 1b

 //Henry Li 0927 fro saving time in resume 	
    mdelay(4);
    
    bs_cmd_init_sys_run();
    udelay(EPD_CMD_DELAY);
    rd_reg=0;
    while(!value)
	{
		value = GET_HRDY_STATUS;
   	       udelay(50);
		rd_reg++;
		if (rd_reg > 60000)
			break;
	}
    //rd_reg = bs_cmd_rd_reg(0x0204) | (1 << 7);  // spi flash control reg: Display Engine access mode is selected.
       rd_reg = 0x99;
    bs_cmd_wr_reg(0x0204, rd_reg);
/* //Henry Li 0927 fro saving time in resume 	
    udelay(EPD_CMD_DELAY);
    printk("reg[0x0204] is 0x%x\n", rd_reg);
*/    
#endif	
/* //Henry Li 0927 fro saving time in resume 	
    ipu_adc_write_cmd(CMD,0x10);
    ipu_adc_write_cmd(DAT,0x02);
    printk(KERN_ALERT "register 0x0002 content is 0x%4x\n",ipu_adc_read_data());
*/
     einkfb_debug("GPIOs and IRQ set; Broadsheet has been reset\n");
#if defined(CONFIG_HW_EP3_DVT) || defined(CONFIG_HW_EP4_DVT) 
/* //Henry Li 0927 fro saving time in resume 	
    mdelay(1);
*/    
    bs_cmd_wr_reg(0x300, BS97_INIT_VSIZE);	//Frame Data Length Register
    											//Henry: as instruction code init it as 825
/* //Henry Li 0927 fro saving time in resume 	
    mdelay(1);
*/    
#endif
    return ( result );
}
コード例 #5
0
static bool fslepdc_send_update(struct mxcfb_update_data *update_data, bool retry)
{
    bool result = false;
    
    if ( update_data )
    {
        unsigned long start_time, stop_time;
        int send_update_err;
        
        // If this isn't a retry...
        //
        if ( !retry )
        {
            // ...cancel any pending retries.
            //
            cancel_delayed_work(&fslepdc_send_update_work);
            
            // But accumulate any pending retry with the new data.
            //
            if ( fslepdc_send_update_retry_counter )
            {
                struct mxcfb_rect old_retry = fslepdc_send_update_retry_data.update_region,
                                  new_retry,
                                  update    = update_data->update_region;
                u32               old_retry_right,
                                  old_retry_bot,
                                  new_retry_right,
                                  new_retry_bot,
                                  update_right,
                                  update_bot;
                
                // First, accumulate the update region.
                //
                old_retry_right  = (old_retry.left + old_retry.width)  - 1;
                old_retry_bot    = (old_retry.top  + old_retry.height) - 1;
                update_right     = (update.left    + update.width)     - 1;
                update_bot       = (update.top     + update.height)    - 1;
                
                new_retry.left   = min(old_retry.left,  update.left);
                new_retry.top    = min(old_retry.top,   update.top);
                new_retry_right  = max(old_retry_right, update_right);
                new_retry_bot    = max(old_retry_bot,   update_bot);
                
                new_retry.width  = (new_retry_right - new_retry.left)  + 1;
                new_retry.height = (new_retry_bot   - new_retry.top)   + 1;
                
                fslepdc_send_update_retry_data.update_region = new_retry;
                
                // Since it's a retry, go for the highest fidelity possible.
                //
                fslepdc_send_update_retry_data.waveform_mode = fslepdc_get_waveform_mode(WF_UPD_MODE_GC);
                fslepdc_send_update_retry_data.update_mode   = UPDATE_MODE_FULL;
                
                // Use the latest marker and temperature.
                //
                fslepdc_send_update_retry_data.update_marker = update_data->update_marker;
                fslepdc_send_update_retry_data.temp          = update_data->temp;
                
                // Copy the retry data back for this attempt.
                //
                *update_data = fslepdc_send_update_retry_data;
            }
        }
        
        // We can get errors sending updates to EPDC if it's not ready to do
        // an update yet.  So, back off and retry a few times here first
        // before scheduling a retry.
        //
        start_time = jiffies; stop_time = start_time + FSLEPDC_SU_TIMEOUT;    

        do
        {
            send_update_err = mxc_epdc_fb_send_update(update_data, NULL);
            
            if ( 0 != send_update_err )
            {
                einkfb_print_error("EPDC_send_update_error=%d:\n", send_update_err);
                schedule_timeout_uninterruptible(FSLEPDC_SU_WAIT);
            }
        }
        while ( (0 != send_update_err) && time_before_eq(jiffies, stop_time) );
        
        if ( time_after(jiffies, stop_time) )
        {
             einkfb_print_crit("EDPC_send_update_timed_out=true:\n");
        }
        else
        {
            char temp_string[16];
            
            if ( TEMP_USE_AMBIENT == update_data->temp )
                strcpy(temp_string, "ambient");
            else
                sprintf(temp_string, "%d", update_data->temp);
            
            einkfb_debug("update_data:\n");
            einkfb_debug("  rect x: %d\n", update_data->update_region.left);
            einkfb_debug("  rect y: %d\n", update_data->update_region.top);
            einkfb_debug("  rect w: %d\n", update_data->update_region.width);
            einkfb_debug("  rect h: %d\n", update_data->update_region.height);
            einkfb_debug("  wfmode: %d\n", update_data->waveform_mode);
            einkfb_debug("  update: %s\n", update_data->update_mode ? "flashing" : "non-flashing");
            einkfb_debug("  marker: %d\n", update_data->update_marker);
            einkfb_debug("  temp:   %s\n", temp_string);
            
            fslepdc_send_update_retry_counter = 0;
            result = true;
        }

        // If our attempt to send an update failed, try it again later.
        //
        if ( !result )
        {
            if ( FSLEPDC_SU_RETRIES > ++fslepdc_send_update_retry_counter )
            {
                // If this isn't a retry, use the current update data.
                //
                if ( !retry )
                    fslepdc_send_update_retry_data = *update_data;
                
                schedule_delayed_work(&fslepdc_send_update_work, FSLEPDC_SU_DELAY);
            }
            else
            {
                einkfb_print_crit("Updates are failing...\n");
            }
        }
    }
    
    return ( result );
}
コード例 #6
0
bool bs_hw_init(void)
{
    bool result = true;
#ifdef USE_BS_IRQ
    int  rqstatus;
#endif
    
    ipu_adc_sig_cfg_t sig = { 0, 0, 0, 0, 0, 0, 0, 0,
            IPU_ADC_BURST_WCS,
            IPU_ADC_IFC_MODE_SYS80_TYPE2,
            16, 0, 0, IPU_ADC_SER_NO_RW
    };

    // Init DI interface
    if ( IS_NELL() || IS_MARIO() || IS_ADS() )
    {
        broadsheet_screen_height = BROADSHEET_SCREEN_HEIGHT_NELL;
        broadsheet_screen_width  = BROADSHEET_SCREEN_WIDTH_NELL;
        
        broadsheet_screen_size   = BROADSHEET_SCREEN_SIZE_NELL;
    }

    ipu_adc_init_panel(BROADSHEET_DISPLAY_NUMBER,
                       broadsheet_screen_width,
                       broadsheet_screen_height,
                       BROADSHEET_PIXEL_FORMAT, broadsheet_screen_size, sig, XY, 0, VsyncInternal);

    // Set IPU timing for read cycles
    ipu_adc_init_ifc_timing(BROADSHEET_DISPLAY_NUMBER, true,
                            BROADSHEET_READ_CYCLE_TIME,
                            BROADSHEET_READ_UP_TIME,
                            BROADSHEET_READ_DOWN_TIME,
                            BROADSHEET_READ_LATCH_TIME,
                            BROADSHEET_PIXEL_CLK);
    // Set IPU timing for write cycles
    ipu_adc_init_ifc_timing(BROADSHEET_DISPLAY_NUMBER, false,
                            BROADSHEET_WRITE_CYCLE_TIME,
                            BROADSHEET_WRITE_UP_TIME,
                            BROADSHEET_WRITE_DOWN_TIME,
                            0, 0);

    ipu_adc_set_update_mode(ADC_SYS1, IPU_ADC_REFRESH_NONE, 0, 0, 0);

    gpio_lcd_active();
    slcd_gpio_config();

#ifdef CONFIG_MACH_MX31ADS
    // Reset the level translator for the two GPIO inputs (HIRQ and HRDY)
    pin_addr = PBC_BCTRL2_LDCIO_EN;
    __raw_writew(pin_addr, PBC_BASE_ADDRESS + PBC_BCTRL2_CLEAR);
#endif

#ifdef USE_BS_IRQ
    // Set up IRQ for for Broadsheet HIRQ line
    disable_irq(BROADSHEET_HIRQ_IRQ);
    set_irq_type(BROADSHEET_HIRQ_IRQ, IRQF_TRIGGER_RISING);
    rqstatus = request_irq(BROADSHEET_HIRQ_IRQ, (irq_handler_t) bs_irq_handler, 0, "eink_fb_hal_broads", NULL);
    if (rqstatus != 0) {
        einkfb_print_crit("Failed IRQ request for Broadsheet HIRQ line; request status = %d\n", rqstatus);
        result = false;
    }
#endif

     // Set up GPIO pins
    if (mxc_request_gpio(BROADSHEET_HIRQ_LINE)) {
        einkfb_print_crit("Could not obtain GPIO pin for HIRQ\n");
        result = false;
    }
    else {
        // Set HIRQ pin as input
        mxc_set_gpio_direction(BROADSHEET_HIRQ_LINE, 1);
    }
    if (mxc_request_gpio(BROADSHEET_HRDY_LINE)) {
        einkfb_print_crit("Could not obtain GPIO pin for HRDY\n");
        result = false;
    }
    else {
        // Set HRDY pin as input
        mxc_set_gpio_direction(BROADSHEET_HRDY_LINE, 1);
    }
#ifdef CONFIG_MACH_MARIO_MX
    if (mxc_request_gpio(BROADSHEET_RST_LINE)) {
        einkfb_print_crit("Could not obtain GPIO pin for RST\n");
        result = false;
    }
    else {
        // Set RST pin as output and initialize to zero (it's active LOW)
        mxc_set_gpio_direction(BROADSHEET_RST_LINE, 0);
        mxc_set_gpio_dataout(BROADSHEET_RST_LINE, 0);
    }
#endif

#ifdef CONFIG_MACH_MX31ADS
    // Enable the level translator for the two GPIO inputs (HIRQ and HRDY)
    mdelay(100);    // Pause 100 ms to allow level translator to settle
    pin_addr = PBC_BCTRL2_LDCIO_EN;
    __raw_writew(pin_addr, PBC_BASE_ADDRESS + PBC_BCTRL2_SET);
#endif

    // Reset Broadsheet
    einkfb_debug("Sending RST signal to Broadsheet...\n");
    WR_GPIO_LINE(BROADSHEET_RST_LINE, BROADSHEET_RESET_VAL);     // Assert RST
    mdelay(100);    // Pause 100 ms during reset
    WR_GPIO_LINE(BROADSHEET_RST_LINE, BROADSHEET_NON_RESET_VAL); // Clear RST
    mdelay(400);    // Pause 400 ms to allow Broasheet time to come up
    einkfb_debug("Broadsheet reset done.\n");

#ifdef TEST_BROADSHEET
    test_broadsheet(disp);
#endif

#ifdef USE_BS_IRQ
    // Set up Broadsheet for interrupt generation (enable all conditions)
    bs_cmd_wr_reg(BS_INTR_CTL_REG, BS_ALL_IRQS);
    bs_cmd_wr_reg(BS_INTR_RAW_STATUS_REG, BS_ALL_IRQS);

    // Enable all Broadsheet display engine interrupts
    bs_cmd_wr_reg(BS_DE_INTR_ENABLE_REG, BS_DE_ALL_IRQS);
    bs_cmd_wr_reg(BS_DE_INTR_RAW_STATUS_REG, BS_DE_ALL_IRQS);
#endif

    einkfb_debug("GPIOs and IRQ set; Broadsheet has been reset\n");
    
    return ( result );
}