📄 slcdc.c_bak
字号:
/* * JZ4740 Smart LCD Driver Routines * Copyright (C) 2008 Ingenic Semiconductor Inc. * Author: <zyliu@ingenic.cn> */#include <bsp.h>#include <jz4740.h>#include <slcdc.h>#include <dm.h>#include <function.h>//#undef dprintf//#define dprintf(x...)#ifdef FRAME_BUFF_ADDRESS//#if 0static u8 *lcd_heap = (u8 *)FRAME_BUFF_ADDRESS;static struct jz_dma_desc *lcd_frame_desc2_room;#elsestatic u8 lcd_heap[4096 + (320 * 240 * 4 + 4095) / 4096 * 4096 * FRAMEBUF_NUM] __attribute__((aligned(4096))); // 4Kb alignstatic struct jz_dma_desc lcd_frame_desc2_room[FRAMEBUF_NUM] __attribute__ ((aligned (32)));#endifstatic struct jz_dma_desc lcd_palette_desc __attribute__ ((aligned (32)));struct jz_dma_desc *lcd_frame_desc2;struct jz_dma_desc *cur_lcd_frame_desc,*old_lcd_frame_desc;//static unsigned int frm_size;static int dma_chan = 0;static unsigned int n_doorbell = 0;static unsigned int non_link_desp = 0, link_desp = 0;struct jzfb_slcd_info jzfb_slcd = {#if SLCDTYPE == 101 || SLCDTYPE == 102 /*CONFIG_JZ_SLCD_SPFD5408A)*/ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, 320, 240, 18, 18, 16000000 /* 16bpp 16bus */#endif#if SLCDTYPE == 1 /*CONFIG_JZ_SLCD_LGDP4551)*/ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, 400, 240, 16, 8, 16000000 /* 16bpp 8bus */// 400, 240, 18, 8, 16000000 /* 18bpp 8bus */// 400, 240, 18, 18, 16000000 /* 18bpp 18bus */#endif#if SLCDTYPE == 2 /*CONFIG_JZ_SLCD_SPFD5420A)*/ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL,// 400, 240, 16, 8, 16000000 /* 16bpp 8bus */// 400, 240, 18, 8, 16000000 /* 18bpp 8bus */// 400, 240, 18, 18, 16000000 /* 18bpp 18bus */ 400, 240, 16, 16, 16000000 /* 16bpp 16bus */// 400, 240, 18, 16, 4000000 /* 16bpp 16bus */#endif#if SLCDTYPE == 3 /*CONFIG_JZ_SLCD_SPFD5408A)*/ SLCD_CFG_CS_ACTIVE_LOW | SLCD_CFG_RS_CMD_LOW | SLCD_CFG_TYPE_PARALLEL, 320, 240, 16, 16, 16000000 /* 16bpp 16bus */#endif};u32 lcd_get_width(void) {return jzfb_slcd.w;}u32 lcd_get_height(void) {return jzfb_slcd.h;}u32 lcd_get_bpp(void) { if(jzfb_slcd.bpp > 16) return 32; return jzfb_slcd.bpp;}#if 0 /*for 480x272, 18bpp resoure*/u32 lcd_get_width(void) {return 480;}u32 lcd_get_height(void) {return 272;}u32 lcd_get_bpp(void) {// if(jzfb_slcd.bpp > 16) return 32;// return jzfb_slcd.bpp;}#endif/*The interface functions of framebuffer*/u8* lcd_get_frame(void) {return jzfb_slcd.frame;}u8* lcd_get_cframe(void) {return jzfb_slcd.cframe;}u8* lcd_get_change_frame(void) {return (u8*)LCD_UNCACHED(old_lcd_frame_desc->dsadr);}u8* lcd_get_change_cframe(void) {return (u8*)(old_lcd_frame_desc->dsadr + 0x80000000);}u8* lcd_get_change_phyframe(void){/*printf("old_lcd_frame_desc->dsadr = %x\n",old_lcd_frame_desc->dsadr);*/return (u8*)old_lcd_frame_desc->dsadr;}u8* lcd_get_current_frame(void) {return (u8*)LCD_UNCACHED(cur_lcd_frame_desc->dsadr);}u8* lcd_get_current_cframe(void) {return (u8*)(cur_lcd_frame_desc->dsadr + 0x80000000);}u8* lcd_get_current_phyframe(void){return (u8*)cur_lcd_frame_desc->dsadr;}void lcd_flush_frame(int x,int y,int w,int h){ int i,j; for(i = 0; i < FRAMEBUF_NUM;i++) { for(j = 0; j < h; j++) memset((jzfb_slcd.cframe2[i] + (x + (j + y) * jzfb_slcd.w) * 4),0, w * 4); }}void lcd_clean_frame_other() { int i; for(i = 0; i < FRAMEBUF_NUM;i++) { if((unsigned int)(jzfb_slcd.cframe2[i]) != (unsigned int)lcd_get_current_cframe()) memset(jzfb_slcd.cframe2[i],0, lcd_get_width() * lcd_get_height() * lcd_get_bpp() / 8 ); }}void lcd_clean_frame_all() { int i; for(i = 0; i < FRAMEBUF_NUM;i++) memset(jzfb_slcd.cframe2[i],0, lcd_get_width() * lcd_get_height() * lcd_get_bpp() / 8 );}void lcd_flush_frame_all() {__dcache_writeback_all();}/*Change buffer descriptor*/void lcd_change_frame(void){ int i; //printf("!!!!!!!!!!!!!!!!!!!!!!!!lcd_flush_frame_all = %d\n",n_doorbell);#if 1// n_doorbell++; //printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX old_lcd_frame_desc: %x\n", old_lcd_frame_desc ); if (n_doorbell == 0) { n_doorbell++;// dump_jz_dma_channel(dma_chan); REG_DMAC_DDA(dma_chan) = PHYS(old_lcd_frame_desc); __dmac_channel_set_doorbell(dma_chan); } else n_doorbell++;#endif// printf("Change: n_doorbell = %d\n", n_doorbell);// printf("%d\n", n_doorbell);// old_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) | (frm_size & 0xffffff);// cur_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) | (frm_size & 0xffffff);// old_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) |// ( old_lcd_frame_desc->ddadr & 0xffffff);// cur_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) |// ( old_lcd_frame_desc->ddadr & 0xffffff); cur_lcd_frame_desc = old_lcd_frame_desc; old_lcd_frame_desc++; if((unsigned int)old_lcd_frame_desc > (unsigned int)&lcd_frame_desc2[FRAMEBUF_NUM - 1]) old_lcd_frame_desc = &lcd_frame_desc2[0];#if 0 printf("old_desc= 0x%08x\n", old_lcd_frame_desc); printf("cur_desc= 0x%08x\n", cur_lcd_frame_desc); for(i = 0;i < FRAMEBUF_NUM;i++) { printf("[%d].dsadr= 0x%08x\n", i, lcd_frame_desc2_room[i].dsadr); printf("[%d].dtadr= 0x%08x\n", i, lcd_frame_desc2_room[i].dtadr); printf("[%d].ddadr= 0x%08x\n", i, lcd_frame_desc2_room[i].ddadr); printf("[%d].dcmd= 0x%08x\n", i, lcd_frame_desc2_room[i].dcmd); // printf("\n"); }#endif}/* Enter frame will Change Descriptor to Non-link and Enable Interrupt */void lcd_enter_frame(){ int i;// printf(" 11 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS: %d\n", dma_chan);// non_link_desp = 1;#if 1// printf(" 22 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS%d\n", dma_chan); REG_DMAC_DCMD(dma_chan) |= DMAC_DCMD_TIE; REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_LINK;// printf(" 33 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs\n"); for(i = 0;i < FRAMEBUF_NUM;i++) { lcd_frame_desc2_room[i].dcmd &= ~DMAC_DCMD_LINK; lcd_frame_desc2_room[i].dcmd |= DMAC_DCMD_TIE; } __dcache_writeback_all();#endif for(i = 0;i < FRAMEBUF_NUM;i++) { printf("[%d].dsadr= 0x%08x\n", i, lcd_frame_desc2_room[i].dsadr); printf("[%d].dtadr= 0x%08x\n", i, lcd_frame_desc2_room[i].dtadr); printf("[%d].ddadr= 0x%08x\n", i, lcd_frame_desc2_room[i].ddadr); printf("[%d].dcmd= 0x%08x\n", i, lcd_frame_desc2_room[i].dcmd); printf("\n"); } printf(" 44 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSs\n"); printf("%s\n",__FUNCTION__);}void lcd_reset_frame(){ int i; if((int)cur_lcd_frame_desc != (int)&lcd_frame_desc2[0]) { old_lcd_frame_desc = &lcd_frame_desc2[0];// old_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) | (frm_size & 0xffffff);// cur_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) | (frm_size & 0xffffff); old_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) | (old_lcd_frame_desc->ddadr & 0xffffff); cur_lcd_frame_desc->ddadr = ((PHYS(old_lcd_frame_desc) >> 4) << 24) | (old_lcd_frame_desc->ddadr & 0xffffff); }#if 1 for(i = 0;i < FRAMEBUF_NUM;i++) { lcd_frame_desc2_room[i].dcmd &= ~DMAC_DCMD_TIE; lcd_frame_desc2_room[i].dcmd |= DMAC_DCMD_LINK; } __dcache_writeback_all(); if (n_doorbell == 0) { REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_TIE; __dmac_channel_set_doorbell(dma_chan); } else link_desp = 1;#endif }static __inline__ unsigned int __cpm_divisor_encode(unsigned int n){ unsigned int encode[10] = {1,2,3,4,6,8,12,16,24,32}; int i; for (i=0;i<10;i++) if (n < encode[i]) break; return i;}static int jzfb_setcolreg(u32 regno, u8 red, u8 green, u8 blue){ u16 *ptr, ctmp; if (regno >= NR_PALETTE) return 1; red &= 0xff; green &= 0xff; blue &= 0xff; jzfb_slcd.palette[regno].red = red ; jzfb_slcd.palette[regno].green = green; jzfb_slcd.palette[regno].blue = blue; if (jzfb_slcd.bpp <= 8) { if (((jzfb_slcd.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || ((jzfb_slcd.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) { ctmp = (77L * red + 150L * green + 29L * blue) >> 8; ctmp = ((ctmp >> 3) << 11) | ((ctmp >> 2) << 5) | (ctmp >> 3); } else { /* RGB 565 */ if (((red >> 3) == 0) && ((red >> 2) != 0)) red = 1 << 3; if (((blue >> 3) == 0) && ((blue >> 2) != 0)) blue = 1 << 3; ctmp = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); } ptr = (u16 *)jzfb_slcd.pal; ptr[regno] = ctmp; REG_LCD_DA0 = PHYS(&lcd_palette_desc); } else printf("No palette used.\n"); return 0;}/* * Map screen memory */static int fb_malloc(void){ struct page * map = NULL; u8 *tmp; u32 page_shift, needroom;//, t; u32 i; needroom = ((lcd_get_width() * lcd_get_bpp() + 7) >> 3) * lcd_get_height(); printf("1frame buff addr = %x %d\n",lcd_heap,needroom);#ifdef FRAME_BUFF_ADDRESS//#if 0 jzfb_slcd.cpal = (u8*) lcd_heap; jzfb_slcd.cframe = (u8 *)((u32)lcd_heap); printf("2frame buff addr = %x\n",jzfb_slcd.cframe); lcd_frame_desc2_room = (struct jz_dma_desc *)((((unsigned int)lcd_heap + FRAMEBUF_NUM * needroom) + 31) & (~31));#else jzfb_slcd.cpal = (u8 *)(((u32)lcd_heap) & ~0xfff); jzfb_slcd.cframe = (u8 *)((u32)jzfb_slcd.cpal + 0x1000); for(i = 0; i < FRAMEBUF_NUM;i++) jzfb_slcd.cframe2[i] = (u8 *)((u32)jzfb_slcd.cframe + ((needroom + 0x1000 - 1)/ 0x1000 * 0x1000 * i)); #endif for(i = 0; i < FRAMEBUF_NUM;i++) { jzfb_slcd.cframe2[i] = (u8 *)((u32)jzfb_slcd.cframe + needroom * i); if(!GetLcdInit()) memset(jzfb_slcd.cframe2[i],0,needroom); } jzfb_slcd.pal = (u8 *)LCD_UNCACHED(jzfb_slcd.cpal); jzfb_slcd.frame = (u8 *)LCD_UNCACHED(jzfb_slcd.cframe); for(i = 0; i < FRAMEBUF_NUM;i++) jzfb_slcd.frame2[i] = (u8 *)LCD_UNCACHED(jzfb_slcd.cframe2[i]); memset(jzfb_slcd.cpal, 0, 512); return 0;}/*DMA Interrupt Function*/static void slcd_dma_irq(unsigned int irq)//static int slcd_dma_irq(unsigned int irq){ int i; static unsigned int doormark=0; if (__dmac_channel_transmit_end_detected(dma_chan)) { //printf("DMA TT\n"); __dmac_channel_clear_transmit_end(dma_chan);#if 0 if (non_link_desp == 1) { for(i = 0;i < FRAMEBUF_NUM;i++) { lcd_frame_desc2_room[i].dcmd &= ~DMAC_DCMD_LINK; lcd_frame_desc2_room[i].dcmd |= DMAC_DCMD_TIE; } non_link_desp = 0;// return 0; return; }#endif if (link_desp == 1) { REG_DMAC_DCMD(dma_chan) &= ~DMAC_DCMD_TIE; __dmac_channel_set_doorbell(dma_chan); link_desp = 0; return; } //printf("IRQ: n_doorbell = %d\n", n_doorbell); //printf("IRQ: doormark = %d\n", doormark);// dump_jz_dma_channel(dma_chan); if (doormark == 1) { /* set doorbell by irq */ if (n_doorbell > 1) { n_doorbell = 1; doormark = 0; } else { n_doorbell = 0; doormark = 0;// return 0; return; } } else// n_doorbell--; n_doorbell = 0; if (n_doorbell > 0) { doormark = 1; REG_DMAC_DDA(dma_chan) = PHYS(old_lcd_frame_desc);// REG_DMAC_DDA(dma_chan) = PHYS(cur_lcd_frame_desc); __dmac_channel_set_doorbell(dma_chan); // dump_jz_dma_channel(dma_chan);// return 0; return; } }#if 1 if (__dmac_channel_transmit_halt_detected(dma_chan)) { printf("DMA HALT\n"); __dmac_channel_clear_transmit_halt(dma_chan); } if (__dmac_channel_address_error_detected(dma_chan)) { printf("DMA ADDR ERROR\n"); __dmac_channel_clear_address_error(dma_chan); } if (__dmac_channel_descriptor_invalid_detected(dma_chan)) { printf("DMA DESC INVALID\n"); __dmac_channel_clear_descriptor_invalid(dma_chan); } if (__dmac_channel_count_terminated_detected(dma_chan)) { printf("**DMA CT\n"); dump_jz_dma_channel(dma_chan); Mcupanel_SetAddr(0,0); __dmac_channel_clear_count_terminated(dma_chan); }#endif}/*Set registers of smart lcd*/void Mcupanel_RegSet(unsigned int cmd, unsigned int data){ switch (jzfb_slcd.bus) { case 8: while (REG_SLCD_STATE & SLCD_STATE_BUSY); REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); while (REG_SLCD_STATE & SLCD_STATE_BUSY); REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0); while (REG_SLCD_STATE & SLCD_STATE_BUSY); REG_SLCD_DATA = SLCD_DATA_RS_DATA | (data&0xffff); break; case 9: data = ((data & 0xff) << 1) | ((data & 0xff00) << 2); data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc); while (REG_SLCD_STATE & SLCD_STATE_BUSY); REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8); while (REG_SLCD_STATE & SLCD_STATE_BUSY); REG_SLCD_DATA = SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -