static int32_t dispc_mcu_send_cmd_data(uint32_t cmd, uint32_t data) { int wait_count = 0; /* busy wait for ahb fifo full sign's disappearance */ while((dispc_read(DISPC_DBI_QUEUE) & BIT(5)) && (wait_count < 20000)){ udelay(5); wait_count++; } if(wait_count >= 20000){ printk("sprdfb: [%s] send cmd data not finish 1!!!\n", __FUNCTION__); return -1; } dispc_write(cmd, DISPC_DBI_CMD); wait_count = 0; /* busy wait for ahb fifo full sign's disappearance */ while((dispc_read(DISPC_DBI_QUEUE) & BIT(5)) && (wait_count < 20000)){ udelay(5); wait_count++; } if(wait_count >= 20000){ printk("sprdfb: [%s] send cmd data not finish 2!!!\n", __FUNCTION__); return -1; } dispc_write(data, DISPC_DBI_DATA); return 0; }
static int32_t dispc_sync(struct sprdfb_device *dev) { int ret; if (dev->enable == 0) { printk("sprdfb: dispc_sync fb suspeneded already!!\n"); return -1; } ret = wait_event_interruptible_timeout(dispc_ctx.vsync_queue, dispc_ctx.vsync_done, msecs_to_jiffies(100)); if (!ret) { /* time out */ dispc_ctx.vsync_done = 1; /*error recovery */ printk(KERN_ERR "sprdfb: dispc_sync time out!!!!!\n"); {/*for debug*/ int32_t i; for(i=0;i<256;i+=16){ printk("sprdfb: %x: 0x%x, 0x%x, 0x%x, 0x%x\n", i, dispc_read(i), dispc_read(i+4), dispc_read(i+8), dispc_read(i+12)); } printk("**************************************\n"); } return -1; } return 0; }
uint32_t autotst_dispc_mcu_read_data(void) { /* busy wait for ahb fifo full sign's disappearance */ while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); dispc_write(1 << 24, DISPC_DBI_DATA); udelay(50); return dispc_read(DISPC_DBI_RDATA); }
static void rgb_dispc_init_config(struct panel_spec *panel) { uint32_t reg_val = dispc_read(DISPC_DPI_CTRL); pr_debug("autotst_dispc: [%s]\n", __FUNCTION__); if(NULL == panel){ printk(KERN_ERR "autotst_dispc: [%s] fail.(Invalid Param)\n", __FUNCTION__); return; } if(SPRDFB_PANEL_TYPE_RGB != panel->type){ printk(KERN_ERR "autotst_dispc: [%s] fail.(not mcu panel)\n", __FUNCTION__); return; } /*use dpi as interface*/ dispc_clear_bits((3<<1), DISPC_CTRL); autotst_dispc_ctx.dispc_if = DISPC_IF_DPI; /*h sync pol*/ if(SPRDFB_POLARITY_NEG == panel->info.rgb->h_sync_pol){ reg_val |= (1<<0); } /*v sync pol*/ if(SPRDFB_POLARITY_NEG == panel->info.rgb->v_sync_pol){ reg_val |= (1<<1); } /*de sync pol*/ if(SPRDFB_POLARITY_NEG == panel->info.rgb->de_pol){ reg_val |= (1<<2); } #ifdef CONFIG_DPI_SINGLE_RUN /*single run mode*/ reg_val |= (1<<3); #endif /*dpi bits*/ switch(panel->info.rgb->video_bus_width){ case 16: break; case 18: reg_val |= (1 << 6); break; case 24: reg_val |= (2 << 6); break; default: break; } dispc_write(reg_val, DISPC_DPI_CTRL); pr_debug("autotst_dispc: [%s] DISPC_DPI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DPI_CTRL)); }
void dispc_dump(void) { int i = 0; for(i=0;i<256;i+=16){ printk("autotst_dispc: %x: 0x%x, 0x%x, 0x%x, 0x%x\n", i, dispc_read(i), dispc_read(i+4), dispc_read(i+8), dispc_read(i+12)); } printk("**************************\n"); }
static uint32_t dispc_mcu_read_data(void) { int i = 0; /* busy wait for ahb fifo full sign's disappearance */ while(dispc_read(DISPC_DBI_QUEUE) & (1<<5)){ if(0x0 == ++i%10000){ printf("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__); } } dispc_write(1 << 24, DISPC_DBI_DATA); udelay(50); return dispc_read(DISPC_DBI_RDATA); }
int32_t autotst_dispc_mcu_send_cmd_data(uint32_t cmd, uint32_t data) { /* busy wait for ahb fifo full sign's disappearance */ while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); dispc_write(cmd, DISPC_DBI_CMD); /* busy wait for ahb fifo full sign's disappearance */ while(dispc_read(DISPC_DBI_QUEUE) & BIT(5)); dispc_write(data, DISPC_DBI_DATA); return 0; }
static uint32_t dispc_mcu_read_data(void) { int wait_count = 0; /* busy wait for ahb fifo full sign's disappearance */ while((dispc_read(DISPC_DBI_QUEUE) & BIT(5)) && (wait_count < 20000)){ udelay(5); wait_count++; } if(wait_count >= 20000){ printk("sprdfb: [%s] read data not finish!!!\n", __FUNCTION__); return -1; } dispc_write(1 << 24, DISPC_DBI_DATA); udelay(50); return dispc_read(DISPC_DBI_RDATA); }
static void dispc_set_exp_mode(uint16_t exp_mode) { uint32_t reg_val = dispc_read(DISPC_CTRL); reg_val &= ~(0x3 << 16); reg_val |= (exp_mode << 16); dispc_write(reg_val, DISPC_CTRL); }
static void dispc_set_exp_mode(uint16_t exp_mode) { uint32_t reg_val = dispc_read(DISPC_CTRL); FB_PRINT("sprdfb:[%s]\n",__FUNCTION__); reg_val &= ~(0x3 << 16); reg_val |= (exp_mode << 16); dispc_write(reg_val, DISPC_CTRL); }
int32_t autotst_dispc_refresh (void) { int ret = 0; uint32_t size = (autotst_panel->width& 0xffff) | ((autotst_panel->height) << 16); printk(KERN_INFO "autotst_dispc:[%s]\n",__FUNCTION__); //autotst_dsi_dump(); ret = dispc_fb_prepare(autotst_panel); if(0 != ret){ printk("autotst_dispc: refresh fail!(can't prepare frame buffer)!]n"); return -1; } dispc_write(autotst_dispc_ctx.fb_addr_p, DISPC_OSD_BASE_ADDR); dispc_write(0, DISPC_OSD_DISP_XY); dispc_write(size, DISPC_OSD_SIZE_XY); dispc_write(autotst_panel->width, DISPC_OSD_PITCH); dispc_write(size, DISPC_SIZE_XY); dispc_run(); #if 1 pr_debug("DISPC_CTRL: 0x%x\n", dispc_read(DISPC_CTRL)); pr_debug("DISPC_SIZE_XY: 0x%x\n", dispc_read(DISPC_SIZE_XY)); pr_debug("DISPC_BG_COLOR: 0x%x\n", dispc_read(DISPC_BG_COLOR)); pr_debug("DISPC_INT_EN: 0x%x\n", dispc_read(DISPC_INT_EN)); pr_debug("DISPC_OSD_CTRL: 0x%x\n", dispc_read(DISPC_OSD_CTRL)); pr_debug("DISPC_OSD_BASE_ADDR: 0x%x\n", dispc_read(DISPC_OSD_BASE_ADDR)); pr_debug("DISPC_OSD_SIZE_XY: 0x%x\n", dispc_read(DISPC_OSD_SIZE_XY)); pr_debug("DISPC_OSD_PITCH: 0x%x\n", dispc_read(DISPC_OSD_PITCH)); pr_debug("DISPC_OSD_DISP_XY: 0x%x\n", dispc_read(DISPC_OSD_DISP_XY)); pr_debug("DISPC_OSD_ALPHA : 0x%x\n", dispc_read(DISPC_OSD_ALPHA)); #else mdelay(20); dispc_dump(); autotst_dsi_dump(); autotst_dsi_dump1(); #endif return 0; }
static int32_t sprdfb_dispc_refresh (struct sprdfb_device *dev) { FB_PRINT("sprdfb:[%s]\n",__FUNCTION__); uint32_t i; if(SPRDFB_PANEL_IF_DPI != dev->panel_if_type){ sprdfb_panel_invalidate(dev->panel); } sprdfb_panel_before_refresh(dev); if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){ //dispc_write(0x0, DISPC_OSD_CTRL); //dispc_write(0x0, DISPC_BG_COLOR); /*dpi register update*/ dispc_set_bits((1<<5), DISPC_DPI_CTRL); if(is_first_frame){ udelay(30); /*dpi register update with SW and VSync*/ dispc_clear_bits((1<<4), DISPC_DPI_CTRL); /* start refresh */ dispc_set_bits((1 << 4), DISPC_CTRL); is_first_frame = 0; }else{ for(i=0;i<1000;i++){ if(!(dispc_read(DISPC_INT_RAW) & (0x10))){ udelay(100); }else{ break; } } if(i >= 1000){ FB_PRINT("sprdfb:[%s] wait dispc update int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW)); }else{ FB_PRINT("sprdfb:[%s] got dispc update int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW)); } dispc_set_bits((1<<5), DISPC_INT_CLR); } }else{ /* start refresh */ dispc_set_bits((1 << 4), DISPC_CTRL); for(i=0;i<500;i++){ if(0x1 != (dispc_read(DISPC_INT_RAW) & (1<<0))){ udelay(1000); }else{ break; } } if(i >= 1000){ FB_PRINT("sprdfb:[%s] wait dispc done int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW)); }else{ FB_PRINT("sprdfb:[%s] got dispc done int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW)); } dispc_set_bits((1<<0), DISPC_INT_CLR); } sprdfb_panel_after_refresh(dev); return 0; }
static inline void dispc_osd_enable(bool is_enable) { uint32_t reg_val; reg_val = dispc_read(DISPC_OSD_CTRL); if(is_enable){ reg_val = reg_val | (BIT(0)); } else{ reg_val = reg_val & (~(BIT(0))); } dispc_write(reg_val, DISPC_OSD_CTRL); }
static int32_t dispc_mcu_send_cmd(uint32_t cmd) { int i = 0; /* busy wait for ahb fifo full sign's disappearance */ while(dispc_read(DISPC_DBI_QUEUE) & (1<<5)){ if(0x0 == ++i%10000){ printf("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__); } } dispc_write(cmd, DISPC_DBI_CMD); return 0; }
static void dispc_layer_init(struct sprdfb_device *dev) { uint32_t reg_val = 0; FB_PRINT("sprdfb:[%s]\n",__FUNCTION__); dispc_clear_bits((1<<0),DISPC_IMG_CTRL); dispc_clear_bits((1<<0),DISPC_OSD_CTRL); /******************* OSD layer setting **********************/ /*enable OSD layer*/ reg_val |= (1 << 0); /*disable color key */ /* alpha mode select - block alpha*/ reg_val |= (1 << 2); /* data format */ /* RGB565 */ reg_val |= (5 << 4); /* B2B3B0B1 */ reg_val |= (2 << 8); dispc_write(reg_val, DISPC_OSD_CTRL); /* OSD layer alpha value */ dispc_write(0xff, DISPC_OSD_ALPHA); /* OSD layer size */ reg_val = ( dev->panel->width& 0xfff) | ((dev->panel->height & 0xfff ) << 16); dispc_write(reg_val, DISPC_OSD_SIZE_XY); /* OSD layer start position */ dispc_write(0, DISPC_OSD_DISP_XY); /* OSD layer pitch */ reg_val = ( dev->panel->width & 0xfff) ; dispc_write(reg_val, DISPC_OSD_PITCH); /*OSD base address*/ dispc_write(dev->smem_start, DISPC_OSD_BASE_ADDR); /* OSD color_key value */ dispc_set_osd_ck(0x0); /* DISPC workplane size */ dispc_set_disp_size(dev); FB_PRINT("DISPC_OSD_CTRL: 0x%x\n", dispc_read(DISPC_OSD_CTRL)); FB_PRINT("DISPC_OSD_ALPHA: 0x%x\n", dispc_read(DISPC_OSD_ALPHA)); FB_PRINT("DISPC_OSD_SIZE_XY: 0x%x\n", dispc_read(DISPC_OSD_SIZE_XY)); FB_PRINT("DISPC_OSD_DISP_XY: 0x%x\n", dispc_read(DISPC_OSD_DISP_XY)); FB_PRINT("DISPC_OSD_PITCH: 0x%x\n", dispc_read(DISPC_OSD_PITCH)); FB_PRINT("DISPC_OSD_BASE_ADDR: 0x%x\n", dispc_read(DISPC_OSD_BASE_ADDR)); }
static void mipi_dispc_init_config(struct panel_spec *panel) { uint32_t reg_val = dispc_read(DISPC_DPI_CTRL); pr_debug("autotst_dispc: [%s]\n", __FUNCTION__); if(NULL == panel){ printk(KERN_ERR "autotst_dispc: [%s] fail.(Invalid Param)\n", __FUNCTION__); return; } if(SPRDFB_PANEL_TYPE_MIPI != panel->type){ printk(KERN_ERR "autotst_dispc: [%s] fail.(not mcu panel)\n", __FUNCTION__); return; } if(SPRDFB_MIPI_MODE_CMD == panel->info.mipi->work_mode){ /*use edpi as interface*/ dispc_set_bits((1<<1), DISPC_CTRL); autotst_dispc_ctx.dispc_if = DISPC_IF_EDPI; }else{ /*use dpi as interface*/ dispc_clear_bits((3<<1), DISPC_CTRL); autotst_dispc_ctx.dispc_if = DISPC_IF_DPI; } /*h sync pol*/ if(SPRDFB_POLARITY_NEG == panel->info.mipi->h_sync_pol){ reg_val |= (1<<0); } /*v sync pol*/ if(SPRDFB_POLARITY_NEG == panel->info.mipi->v_sync_pol){ reg_val |= (1<<1); } /*de sync pol*/ if(SPRDFB_POLARITY_NEG == panel->info.mipi->de_pol){ reg_val |= (1<<2); } if(SPRDFB_MIPI_MODE_VIDEO == panel->info.mipi->work_mode){ #ifdef CONFIG_DPI_SINGLE_RUN /*single run mode*/ reg_val |= (1<<3); #endif }else{ if(!(panel->cap & PANEL_CAP_NOT_TEAR_SYNC)){ printk("autotst_dispc: mipi_dispc_init_config not support TE\n"); /*enable te*/ reg_val |= (1<<8); } /*te pol*/ if(SPRDFB_POLARITY_NEG == panel->info.mipi->te_pol){ reg_val |= (1<<9); } /*use external te*/ reg_val |= (1<<10); } /*dpi bits*/ switch(panel->info.rgb->video_bus_width){ case 16: break; case 18: reg_val |= (1 << 6); break; case 24: reg_val |= (2 << 6); break; default: break; } dispc_write(reg_val, DISPC_DPI_CTRL); pr_debug("autotst_dispc: [%s] DISPC_DPI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DPI_CTRL)); }
/*cs0*/ static void mcu_dispc_init_config(struct panel_spec *panel) { uint32_t reg_val = 0; pr_debug("autotst_dispc: [%s] for cs0\n", __FUNCTION__); if(NULL == panel){ printk(KERN_ERR "autotst_dispc: [%s] fail.(Invalid Param)\n", __FUNCTION__); return; } if(SPRDFB_PANEL_TYPE_MCU != panel->type){ printk(KERN_ERR "autotst_dispc: [%s] fail.(not mcu panel)\n", __FUNCTION__); return; } /*use dbi as interface*/ dispc_set_bits((2<<1), DISPC_CTRL); autotst_dispc_ctx.dispc_if = DISPC_IF_DBI; /* CS0 bus mode [BIT0]: 8080/6800 */ switch (panel->info.mcu->bus_mode) { case LCD_BUS_8080: break; case LCD_BUS_6800: reg_val |= 1; break; default: break; } /* CS0 bus width [BIT3:1] */ switch (panel->info.mcu->bus_width) { case 8: break; case 9: reg_val |= (1 << 1); break; case 16: reg_val |= (2 << 1); break; case 18: reg_val |= (3 << 1) ; break; case 24: reg_val |= (4 << 1); break; default: break; } /*CS0 pixel bits [BIT5:4]*/ switch (panel->info.mcu->bpp) { case 16: break; case 18: reg_val |= (1 << 4) ; break; case 24: reg_val |= (2 << 4); break; default: break; } #ifndef CONFIG_FB_NO_FMARK /*TE enable*/ reg_val |= (1 << 16); if(SPRDFB_POLARITY_NEG == panel->info.mcu->te_pol){ reg_val |= (1<< 17); } dispc_write(panel->info.mcu->te_sync_delay, DISPC_TE_SYNC_DELAY); #endif #ifdef CONFIG_LCD_CS_ALWAYS_LOW /*CS alway low mode*/ reg_val |= (1<<21); #else /*CS not alway low mode*/ #endif /*CS0 selected*/ dispc_write(reg_val, DISPC_DBI_CTRL); pr_debug("autotst_dispc: [%s] DISPC_DBI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DBI_CTRL)); }
static irqreturn_t dispc_isr(int irq, void *data) { struct sprdfb_dispc_context *dispc_ctx = (struct sprdfb_dispc_context *)data; uint32_t reg_val; struct sprdfb_device *dev = dispc_ctx->dev; bool done = false; reg_val = dispc_read(DISPC_INT_STATUS); pr_debug("dispc_isr (0x%x)\n",reg_val ); if(reg_val & 0x04){ printk("Warning: dispc underflow (0x%x)!\n",reg_val); dispc_write(0x04, DISPC_INT_CLR); } if(NULL == dev){ return IRQ_HANDLED; } if((reg_val & 0x10) && (SPRDFB_PANEL_IF_DPI == dev->panel_if_type)){/*dispc update done isr*/ #if 0 if(dispc_ctx->is_first_frame){ /*dpi register update with SW and VSync*/ dispc_clear_bits(BIT(4), DISPC_DPI_CTRL); /* start refresh */ dispc_set_bits((1 << 4), DISPC_CTRL); dispc_ctx->is_first_frame = false; } #endif dispc_write(0x10, DISPC_INT_CLR); done = true; }else if ((reg_val & 0x1) && (SPRDFB_PANEL_IF_DPI != dev->panel_if_type)){ /* dispc done isr */ dispc_write(1, DISPC_INT_CLR); dispc_ctx->is_first_frame = false; done = true; } if(done){ dispc_ctx->vsync_done = 1; #ifdef CONFIG_FB_LCD_OVERLAY_SUPPORT if(SPRD_OVERLAY_STATUS_STARTED == dispc_ctx->overlay_state){ overlay_close(dev); } #endif #ifdef CONFIG_FB_DYNAMIC_CLK_SUPPORT if(SPRDFB_PANEL_IF_DPI != dev->panel_if_type){ clk_disable(dispc_ctx->clk_dispc); clk_disable(dispc_ctx->clk_dispc_dpi); clk_disable(dispc_ctx->clk_dispc_dbi); dispc_ctx->clk_open = false; } #endif if (dispc_ctx->vsync_waiter) { wake_up_interruptible_all(&(dispc_ctx->vsync_queue)); dispc_ctx->vsync_waiter = 0; } sprdfb_panel_after_refresh(dev); pr_debug(KERN_INFO "sprdfb: [%s]: Done INT, reg_val = %d !\n", __FUNCTION__, reg_val); } return IRQ_HANDLED; }
/*cs1*/ void mcu_dispc_init_config(struct panel_spec *panel) { uint32_t reg_val = 0; FB_PRINT("sprdfb: [%s] for cs1\n", __FUNCTION__); if(NULL == panel){ printf("sprdfb: [%s] fail.(Invalid Param)\n", __FUNCTION__); return; } if(SPRDFB_PANEL_TYPE_MCU != panel->type){ printf("sprdfb: [%s] fail.(not mcu panel)\n", __FUNCTION__); return; } /*use dbi as interface*/ dispc_set_bits((2<<1), DISPC_CTRL); /* CS1 bus mode [BIT8]: 8080/6800 */ switch (panel->info.mcu->bus_mode) { case LCD_BUS_8080: break; case LCD_BUS_6800: reg_val |= (1<<8); break; default: break; } /* CS1 bus width [BIT11:9] */ switch (panel->info.mcu->bus_width) { case 8: break; case 9: reg_val |= (1 << 9); break; case 16: reg_val |= (2 << 9); break; case 18: reg_val |= (3 << 9) ; break; case 24: reg_val |= (4 << 9); break; default: break; } /*CS1 pixel bits [BIT13:12]*/ switch (panel->info.mcu->bpp) { case 16: break; case 18: reg_val |= (1 << 12) ; break; case 24: reg_val |= (2 << 12); break; default: break; } #ifndef CONFIG_FB_NO_FMARK /*TE enable*/ reg_val |= (1 << 16); if(SPRDFB_POLARITY_NEG == panel->info.mcu->te_pol){ reg_val |= (1<< 17); } dispc_write(panel->info.mcu->te_sync_delay, DISPC_TE_SYNC_DELAY); #endif #ifdef CONFIG_LCD_CS_ALWAYS_LOW /*CS alway low mode*/ reg_val |= (1<<21); #else /*CS not alway low mode*/ #endif /*CS1 selected*/ reg_val |= (1 << 20); dispc_write(reg_val, DISPC_DBI_CTRL); FB_PRINT("sprdfb: [%s] DISPC_DBI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DBI_CTRL)); }