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 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 int32_t sprdfb_dispc_init(struct sprdfb_device *dev) { FB_PRINT("sprdfb:[%s]\n",__FUNCTION__); /*set bg color*/ dispc_set_bg_color(0xFFFFFFFF); /*enable dithering*/ dispc_dithering_enable(1); /*use MSBs as img exp mode*/ dispc_set_exp_mode(0x0); dispc_layer_init(dev); if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){ if(is_first_frame){ /*set dpi register update only with SW*/ dispc_set_bits((1<<4), DISPC_DPI_CTRL); }else{ /*set dpi register update with SW & VSYNC*/ dispc_clear_bits((1<<4), DISPC_DPI_CTRL); } /*enable dispc update done INT*/ // dispc_write((1<<4), DISPC_INT_EN); }else{ /* enable dispc DONE INT*/ // dispc_write((1<<0), DISPC_INT_EN); } return 0; }
static int32_t sprdfb_dispc_init(struct sprdfb_device *dev) { pr_debug(KERN_INFO "sprdfb:[%s]\n",__FUNCTION__); /*set bg color*/ dispc_set_bg_color(0xFFFFFFFF); /*enable dithering*/ dispc_dithering_enable(true); /*use MSBs as img exp mode*/ dispc_set_exp_mode(0x0); if(dispc_ctx.is_first_frame){ dispc_layer_init(&(dev->fb->var)); }else{ dispc_layer_update(&(dev->fb->var)); } if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){ if(dispc_ctx.is_first_frame){ /*set dpi register update only with SW*/ dispc_set_bits(BIT(4), DISPC_DPI_CTRL); }else{ /*set dpi register update with SW & VSYNC*/ dispc_clear_bits(BIT(4), DISPC_DPI_CTRL); } /*enable dispc update done INT*/ dispc_write((1<<4), DISPC_INT_EN); }else{ /* enable dispc DONE INT*/ dispc_write((1<<0), DISPC_INT_EN); } dispc_set_bits(BIT(2), DISPC_INT_EN); dev->enable = 1; return 0; }
static void dispc_pwr_enable(bool enable) { if(enable){ dispc_set_bits(BIT(7), DISPC_CTRL); }else{ dispc_clear_bits(BIT(7), DISPC_CTRL); } }
static void dispc_dithering_enable(bool enable) { if(enable){ dispc_set_bits(BIT(6), DISPC_CTRL); }else{ dispc_clear_bits(BIT(6), DISPC_CTRL); } }
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)); }
static void dispc_stop(void) { if(DISPC_IF_DPI == autotst_dispc_ctx.dispc_if){ /*dpi register update with SW only*/ dispc_set_bits(BIT(4), DISPC_DPI_CTRL); /* stop refresh */ dispc_clear_bits((1 << 4), DISPC_CTRL); } }
static void dispc_dithering_enable(uint16_t enable) { FB_PRINT("sprdfb:[%s]\n",__FUNCTION__); if(enable){ dispc_set_bits((1<<6), DISPC_CTRL); }else{ dispc_clear_bits((1<<6), DISPC_CTRL); } }
static void dispc_layer_init(struct panel_spec *panel) { uint32_t reg_val = 0; // dispc_clear_bits((1<<0),DISPC_IMG_CTRL); dispc_write(0x0, 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 */ //if (var->bits_per_pixel == 32) { if(1){ /* ABGR */ reg_val |= (3 << 4); /* rb switch */ reg_val |= (1 << 15); } else { /* 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 = ( panel->width & 0xfff) | (( 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 = ( panel->width & 0xfff) ; dispc_write(reg_val, DISPC_OSD_PITCH); /* OSD color_key value */ dispc_set_osd_ck(0x0); /* DISPC workplane size */ reg_val = ( panel->width & 0xfff) | ((panel->height & 0xfff ) << 16); dispc_write(reg_val, DISPC_SIZE_XY); }
static void dispc_stop(struct sprdfb_device *dev) { if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){ /*dpi register update with SW only*/ dispc_set_bits(BIT(4), DISPC_DPI_CTRL); /* stop refresh */ dispc_clear_bits((1 << 4), DISPC_CTRL); dispc_ctx.is_first_frame = true; } }
static void dispc_run(void) { if(DISPC_IF_DPI == autotst_dispc_ctx.dispc_if){ /*dpi register update*/ dispc_set_bits(BIT(5), DISPC_DPI_CTRL); udelay(30); /*dpi register update with SW and VSync*/ dispc_clear_bits(BIT(4), DISPC_DPI_CTRL); /* start refresh */ dispc_set_bits((1 << 4), DISPC_CTRL); }else{ /* start refresh */ dispc_set_bits((1 << 4), DISPC_CTRL); } }
static void dispc_run(struct sprdfb_device *dev) { if(0 == dev->enable){ return; } #ifdef CONFIG_FB_ESD_SUPPORT down(&dev->ESD_lock); #endif if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){ if(!dispc_ctx.is_first_frame){ dispc_ctx.vsync_done = 0; dispc_ctx.vsync_waiter ++; } /*dpi register update*/ dispc_set_bits(BIT(5), DISPC_DPI_CTRL); udelay(30); 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; }else{ dispc_sync(dev); } }else{ dispc_ctx.vsync_done = 0; /* start refresh */ dispc_set_bits((1 << 4), DISPC_CTRL); } #ifdef CONFIG_FB_ESD_SUPPORT up(&dev->ESD_lock); #endif }
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)); }
int32_t autotst_dispc_init(int display_type) { int ret = 0; printk(KERN_INFO "autotst_dispc:[%s]\n",__FUNCTION__); //autotst_dsi_dump(); autotst_dispc_uninit(DISPLAY_TYPE_MIPI); ret = dispc_clk_init(); if(ret){ printk(KERN_WARNING "autotst_dispc: dispc_clk_init fail!\n"); return -1; } dispc_reset(); dispc_module_enable(); /*set bg color*/ dispc_set_bg_color(0xFFFFFFFF); /*enable dithering*/ dispc_dithering_enable(true); /*use MSBs as img exp mode*/ dispc_set_exp_mode(0x0); //enable DISPC Power Control dispc_pwr_enable(true); switch(display_type){ case DISPLAY_TYPE_MCU: autotst_panel = &lcd_dummy_mcu_spec; mcu_dispc_init_config(autotst_panel); mcu_dispc_set_timing(autotst_panel); break; case DISPLAY_TYPE_RGB: autotst_panel = &lcd_dummy_rgb_spec; rgb_dispc_init_config(autotst_panel); rgb_dispc_set_timing(autotst_panel); autotst_dispc_ctx.dispc_if = DISPC_IF_DPI; break; case DISPLAY_TYPE_MIPI: autotst_panel = &lcd_dummy_mipi_spec; mipi_dispc_init_config(autotst_panel); mipi_dispc_set_timing(autotst_panel); autotst_dsi_init(autotst_panel); break; default: printk("autotst_dispc:[%s] error display type (%d)\n", __FUNCTION__, display_type); } dispc_layer_init(autotst_panel); if(DISPC_IF_DPI == autotst_dispc_ctx.dispc_if){ if(1){ /*set dpi register update only with SW*/ dispc_set_bits(BIT(4), DISPC_DPI_CTRL); }else{ /*set dpi register update with SW & VSYNC*/ dispc_clear_bits(BIT(4), DISPC_DPI_CTRL); } /*enable dispc update done INT*/ //dispc_write((1<<4), DISPC_INT_EN); }else{ /* enable dispc DONE INT*/ //dispc_write((1<<0), DISPC_INT_EN); } //dispc_set_bits(BIT(2), DISPC_INT_EN); return 0; }
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; }