📄 s1d13706fb.c
字号:
u8 r, g, b; s1d13706_write_reg(regno, S1D13706_LUT_RD_ADDR_REG); r = s1d13706_read_reg(S1D13706_LUT_R_RD_DATA_REG); g = s1d13706_read_reg(S1D13706_LUT_G_RD_DATA_REG); b = s1d13706_read_reg(S1D13706_LUT_B_RD_DATA_REG); *red = r << 8; *green = g << 8; *blue = b << 8;#ifdef DBUG printk("s1d13706_getcolreg done\n");#endif return 0;}/* * Changes: 2002/12/13 adapted to s1d13706 */static int s1d13706_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ u8 r = (red >> 8) & 0xfc; u8 g = (green>>8) & 0xfc; u8 b = (blue>> 8) & 0xfc; s1d13706_write_reg(r, S1D13706_LUT_R_WR_DATA_REG); s1d13706_write_reg(g, S1D13706_LUT_G_WR_DATA_REG); s1d13706_write_reg(b, S1D13706_LUT_B_WR_DATA_REG); s1d13706_write_reg(regno, S1D13706_LUT_WR_ADDR_REG);#ifdef DBUG printk("s1d13706_setcolreg done\n");#endif return 0;}static int s1d13706_pan_display(const struct fb_var_screeninfo *var, struct fb_info_gen *info){#ifdef DBUG printk("s1d13706_pan_display done\n");#endif BUG(); return -EINVAL;}#undef AERO_HACKSstatic int s1d13706_blank(int blank_mode, struct fb_info_gen *info){ u8 disp; switch (blank_mode) { case VESA_NO_BLANKING: disp = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG); disp |= 1; s1d13706_write_reg(disp, S1D13706_DISPLAY_MODE_REG); break; case VESA_VSYNC_SUSPEND: case VESA_HSYNC_SUSPEND: case VESA_POWERDOWN: disp = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG); disp &= ~1; s1d13706_write_reg(disp, S1D13706_DISPLAY_MODE_REG); break; default: return -EINVAL; }#ifdef DBUG printk("s1d13706_blank done\n");#endif return 0;}static struct display_switch s1d13706_dispsw;static void s1d13706_set_disp(const void *unused, struct display *disp, struct fb_info_gen *info){ struct display_switch *d; disp->screen_base = (void *)S1D13706_FB_BASE; disp->dispsw = &s1d13706_dispsw; switch(disp->var.bits_per_pixel) {#ifdef FBCON_HAS_MFB case 1: d = &fbcon_mfb; break;#endif#ifdef FBCON_HAS_CFB8 case 8: d = &fbcon_cfb8; break;#endif default: BUG(); break; } memcpy(&s1d13706_dispsw, d, sizeof *d);#ifdef DBUG printk("s1d13706_set_disp done\n");#endif}int __init s1d13706fb_setup(char *str){#ifdef DBUG printk("s1d13706fb_setup done\n");#endif return 0;}int __init s1d13706fb_init(void){ u8 * pRegs = (u8 *)S1D_PHYSICAL_REG_ADDR; unsigned int idx=0; unsigned int tmp, tmp1;#ifdef DBUG printk("s1d13706fb_init started\n");#endif /* * all according to s1d13xxxfb.c * ** Initialize the chip according to the following steps: ** 1. Blank display (REG[70h] bit 7 = 1) ** (This is not necessary if the chip powers up for the first time) ** 2. If the system implementation uses a clock chip instead of a fixed ** oscillator, program the clock chip. ** 3. Write to all S1D13706 registers ** 4. Update LookUp Table ** 5. Power Up LCD: ** a. If s/w power save mode is on (REG[A0h] bit 0 = 1), turn off s/w ** power save mode. ** b. If LCD power is off (REG[ADh] bit 7=0), delay for xx milli-seconds ** (depending on panel specifications). ** c. Turn on LCD power (REG[ADh] bit 7=1). ** 6. Disable "blanking" display (set REG[70h] bit 7 to 0) */ /* Step 1 -> blank display*/ s1d13706_write_reg((s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG) | 0x80), S1D13706_DISPLAY_MODE_REG); /* Step 2 -> there is no clock chip, so here's nothing to do*/ /* Step 3 -> Write to all S1D13706 registers*/ while (1) { if ( (aS1DRegs[idx].Index==0xff) && (aS1DRegs[idx].Value==0xff) ) break; *(pRegs + aS1DRegs[idx].Index) = (u8)(aS1DRegs[idx].Value); idx++; } /* Step 4: Update LookUp Table ** Note that the data can be arranged such that one dword write will ** initialize red, green, blue, and also set the LUT address at the ** same time. However, some systems may reverse the bytes (big versus ** little-endian systems), so the code below is designed to work for ** both big and little-endian systems. */ for (idx = 0; idx < 256; idx++) { s1d13706_write_reg(LUT8_Color[3*idx], S1D13706_LUT_R_WR_DATA_REG); s1d13706_write_reg(LUT8_Color[3*idx+1], S1D13706_LUT_G_WR_DATA_REG); s1d13706_write_reg(LUT8_Color[3*idx+2], S1D13706_LUT_B_WR_DATA_REG); s1d13706_write_reg(LUT8_Color[idx], S1D13706_LUT_WR_ADDR_REG); } /* Step 5: Power Up LCD ** a. If s/w power save mode is on (REG[A0h] bit 0 = 1), turn off ** s/w power save mode. ** b. If LCD power is off (REG[ADh] bit 7 = 0), delay for xx ** milli-seconds (depending on panel specification). ** c. Turn on LCD power (REG[ADh] bit 7 = 1). */ tmp = s1d13706_read_reg(S1D13706_POWER_SAVE_CONFIG_REG); if ( tmp & 0x01 ){ s1d13706_write_reg((u8)(tmp & ~0x01), S1D13706_POWER_SAVE_CONFIG_REG); } if ( !( s1d13706_read_reg(S1D13706_GPIO_CTL1_REG) & 0x80) ) { /* delay at least 2 vertical periods for this panel */ tmp1 = s1d13706_read_reg(S1D13706_POWER_SAVE_CONFIG_REG) & 0x80; for ( idx=0; idx<5; idx++) { tmp = tmp1; while (1) { tmp1 = s1d13706_read_reg(S1D13706_POWER_SAVE_CONFIG_REG) & 0x80; if ( tmp1 != tmp ) break; } } } s1d13706_write_reg(s1d13706_read_reg(S1D13706_GPIO_CTL1_REG) | 0x80, S1D13706_GPIO_CTL1_REG); /* Step 6: Disable "blanking" display (set REG[70h] bit 7 to 0) */ tmp = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG); s1d13706_write_reg((u8) (tmp & ~0x80), S1D13706_DISPLAY_MODE_REG); /* End of initializing the s1d13706 controller chip*/ fb_info.gen.fbhw = &s1d13706_switch; fb_info.gen.fbhw->detect(); strcpy(fb_info.gen.info.modename, "S1D13706"); fb_info.gen.info.changevar = NULL; fb_info.gen.info.node = -1; fb_info.gen.info.fbops = &s1d13706fb_ops; fb_info.gen.info.disp = &disp; fb_info.gen.parsize = sizeof(struct s1d13706_par); fb_info.gen.info.switch_con = &fbgen_switch; fb_info.gen.info.updatevar = &fbgen_update_var; fb_info.gen.info.blank = &fbgen_blank; fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; /* This should give a reasonable default video mode */ fbgen_get_var(&disp.var, -1, &fb_info.gen.info); fbgen_do_set_var(&disp.var, 1, &fb_info.gen); fbgen_set_disp(-1, &fb_info.gen); if (disp.var.bits_per_pixel > 1) fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info) < 0) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename); return 0;} /* * Cleanup */void s1d13706fb_cleanup(struct fb_info *info){ /* * If your driver supports multiple boards, you should unregister and * clean up all instances. */#ifdef DBUG printk("s1d13706fb_cleanup done\n");#endif unregister_framebuffer(info); /* ... */}static void set_color_bitfields(struct fb_var_screeninfo *var){ switch (var->bits_per_pixel) { case 1: var->red.offset = 0; var->red.length = 1; var->green.offset = 0; var->green.length = 1; var->blue.offset = 0; var->blue.length = 1; var->transp.offset = 0; var->transp.length = 0; break; case 8: var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case 16: /* RGB 565 */ var->red.offset = 0; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 11; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; break; case 24: /* RGB 888 */ var->red.offset = 0; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 16; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case 32: /* RGBA 8888 */ var->red.offset = 0; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 16; var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; break; } var->red.msb_right = 0; var->green.msb_right = 0; var->blue.msb_right = 0; var->transp.msb_right = 0;}static int s1d13706_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){#ifdef DBUG printk(KERN_DEBUG "fb%d: start: s1d13706_get_fix\n", GET_FB_IDX(fb_info.gen.info.node));#endif /* we only have one mode, so our fix_screeninfo struct always has the same values, just throw it back to the user current_fix was initialized earlier in init */#ifdef DBUG printk(KERN_DEBUG "fb: info: getting fix for console %d\n", con);#endif memcpy(fix, ¤t_fix, sizeof(struct fb_fix_screeninfo)); return 0;} /* * Get the User Defined Part of the Display */static int s1d13706_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){#ifdef DBUG printk(KERN_DEBUG "fb%d: start: s1d13706_get_var\n", GET_FB_IDX(fb_info.gen.info.node)); printk(KERN_DEBUG "fb: info: getting var for console %d\n", con);#endif if (con == -1) *var = default_var; else *var = fb_display[con].var; set_color_bitfields(var); return 0;} /* * Set the User Defined Part of the Display */static int s1d13706_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ int activate = var->activate; struct display *display;#ifdef DBUG printk(KERN_DEBUG "fb%d: start: s1d13706_set_var\n", GET_FB_IDX(fb_info.gen.info.node));#endif if (con >= 0) { display = &fb_display[con]; } else display = &disp; /* used during initialization */ /* * We are working with an LCD, which means that we * can't allow for modifications of many of the screen's * usually updateable parameters */ if (var->xres != display->var.xres || var->yres != display->var.yres || var->xres_virtual != var->xres || /* virtual is not supported yet */ var->yres_virtual != var->yres || (var->xoffset != 0 && !(var->vmode & FB_VMODE_CONUPDATE)) || (var->yoffset != 0 && !(var->vmode & FB_VMODE_CONUPDATE)) || (var->bits_per_pixel != display->var.bits_per_pixel)) { return -EINVAL; } set_color_bitfields(var); /* Since we don't allow anything to change anyways, there's no need to update the display var, makes our lifes much easier :-)*/ return 0;} /* * Get the Colormap */static int s1d13706_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (con == currcon) /* current console? */ return fb_get_cmap(cmap, kspc, s1d13706_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0;} /* * Set the Colormap */static int s1d13706_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; if (!fb_display[con].cmap.len) { /* no colormap allocated? */ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0))) return err; } if (con == currcon) /* current console? */ return fb_set_cmap(cmap, kspc, s1d13706_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -