ãã®èšäºã§ã¯ãã¡ãŒã«ãŒNewhavendisplaysã®320x240ã«ã©ãŒãã£ã¹ãã¬ã€çšã®Linuxãã©ã€ããŒãã€ãŸãçµã¿èŸŒã¿Linuxçšã®NHD-5.7-320240WFB-CTXI-T1ãæžããçµéšãå
±æããããšæããŸãã ç¹ã«ãã·ã¢èªã§ã¯ãframebuferïŒFBïŒãã©ã€ããŒãæžãããã®ãªãœãŒã¹ãããã»ã©å€ããªãã®ã§ãèšäºãæžããšããèãã¯ãŸãã«çããŸããã ãã®ã¢ãžã¥ãŒã«ã¯ææ°ã®ã«ãŒãã«ïŒ2.6.30ïŒåãã«äœæããããã®ã§ã¯ãªãããããã以éFBã€ã³ã¿ãŒãã§ã€ã¹ã§å€ãã®ããšãå€æŽããããšæãããŸãã ããããããã§ããªãããã®èšäºãLinuxã«ãŒãã«ã¬ãã«ã®éçºã«èå³ããã人ã«ãšã£ãŠèå³æ·±ããã®ã«ãªãããšãé¡ã£ãŠããŸãã å®è£
ãããã·ã³ãã«ãã€ãšã¬ã¬ã³ãã«ããããšãã§ããããšãé€å€ããŸããããããã£ãŠãã³ã¡ã³ããæèŠãæè¿ããŸãã

å
å²æ代æåã¯ãQTçµã¿èŸŒã¿ãªã©ã®æšæºããŒã«ã䜿çšããŠã¢ã¯ã»ã¹ã§ãããã©ã€ããŒãäœæããæçµçã«ãŠãŒã¶ãŒãšã®å¯Ÿè©±çšã®ã¢ã€ã³ã³ãšããã¹ããå«ãã·ã³ãã«ãªã¡ãã¥ãŒãäœæããããšã§ããã ãã©ãããã©ãŒã ã¯AT91SAM9G45ã®ã¹ã«ãŒããããæ£ç¢ºã«ã¯
www.armdevs.com/IPC-SAM9G45.htmlã§ããããããªã®ã¹ããªãŒãã³ã°ã¯èšç»ãããŠããŸããã§ããã AT91SAM9G45ã«ã¯ãDMAãµããŒããšéåžžã«é«éãªãã¹ãåããå®å
šã«æ©èœããçµã¿èŸŒã¿LCDã³ã³ãããŒã©ãŒãå«ãŸããŠããããããªã®é床ãããªãåäžãããããšãã§ããå¯èœæ§ããããŸãããæ®å¿µãªããSSD1963ãšããŒããŠã§ã¢äºææ§ã¯ãããŸããã ãããã£ãŠãå¯äžã®ä»£æ¿æ段ãšããŠããã®ç®çã®ããã«éåžžã®GPIOã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããããšã決å®ãããŸããã
SSD1963ã³ã³ãããŒã©ã€ã³ã¿ãŒãã§ã€ã¹ã³ã³ãããŒã©ãŒã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯ã衚瀺ããŒã¿ã·ãŒãã®å³ã®åœ¢åŒã§è¡šç€ºããã®ãæãç°¡åã§ãã

ãã©ã€ããŒéçºè
ã®èŠ³ç¹ãããDB0-DB7ãã³ã«é¢å¿ããããŸãã ããã¯8ãããã®ããŒã¿ãã¹ã§ãããSSD1963ã«ããŒã¿ã転éããããã»ã¹ãå¶åŸ¡ããããã«äœ¿çšãããDCãRDãWRãCSãRESãã³ã§ãã
éä¿¡ãããããŒã¿ã®ãã©ãŒãããã«é¢ããŠã¯ããã®ãã£ã¹ãã¬ã€ã¯888ã®ãã©ãŒãããã䜿çšããŸããããã¯ã©ãããæå³ã§ããïŒ8ãã€ã-èµ€ã8ãã€ã-ç·ã8ãã€ã-éã ãã®ã¿ã€ãã®ãã£ã¹ãã¬ã€ã§ã¯ããªãã·ã§ã³555ã565ãªã©ãèŠã€ããããšãã§ããŸãããããã§ã¯ãããŸããã éä¿¡ãããããŒã¿ã®åœ¢åŒã¯å³ã«ç€ºãããŠããŸãã

ããŒã¿ã®æåã®ãã€ãããã¹ã«èšå®ããåã«ãCSãã³ãšWRãã³ã1ãã0ã«åãæ¿ããå¿
èŠããããŸãããŸããããŒã¿ãã€ããèšå®ããåŸãCSãšWRã0ãã1ã«åãæ¿ããå¿
èŠããããŸãã SSD1963ã³ã³ãããŒã©ãžã®ããŒã¿ã ä¿¡å·ã®ãã詳现ãªæ³¢åœ¢ã¯ãã³ã³ãããŒã©ãŒã®ããŒã¿ã·ãŒãã§ç¢ºèªã§ããŸãã
www.newhavendisplay.com/app_notes/SSD1963.pdfãœãŒã¹ã³ãŒãã§ã¯ãGPIOãã³ã®é
åãšã®ã€ã³ã¿ãŒãã§ã€ã¹ã«ã€ããŠèª¬æããŸãã
static unsigned int nhd_data_pin_config[] = { AT91_PIN_PE13, AT91_PIN_PE14, AT91_PIN_PE17, AT91_PIN_PE18, AT91_PIN_PE19, AT91_PIN_PE20, AT91_PIN_PE21, AT91_PIN_PE22 }; static unsigned int nhd_gpio_pin_config[] = { AT91_PIN_PE0,
ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã®ãã€ã転éæ©èœã¯æ¬¡ã®ãšããã§ãã
static void nhd_write_data(int command, unsigned short value) { int i; at91_set_gpio_output(AT91_PIN_PE12, 1);
ã芧ã®ãšããããã®æ©èœã䜿çšãããšãLCDã³ã³ãããŒã©ãŒã«ã³ãã³ããéä¿¡ããŠïŒããšãã°ããã£ã¹ãã¬ã€ãæ§æããïŒããã¯ã»ã«åœ¢åŒã®ããŒã¿ãéä¿¡ã§ããŸãã
ãã¬ãŒã ãããã¡ã³ã¢ã¢ãã«ãåãã®ãšãããLinuxã«ãŒãã«ã¯ãcharãã©ã€ããŒãblockãã©ã€ããŒãusbãã©ã€ããŒãªã©ãããŸããŸãªã¿ã€ãã®ããã€ã¹ãã©ã€ããŒçšã®ã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããŸãããã¬ãŒã ãããã¡ãŒãã©ã€ããŒã¯ãLinuxãã©ã€ããŒã¢ãã«ã®ç¬ç«ãããµãã·ã¹ãã ã§ããããŸãã FBãã©ã€ããŒãè¡šãããã«äœ¿çšãããäž»ãªæ§é ã¯ã
linux / fb.hã® struct fb_info ã§ãã ã¡ãªã¿ã«ããã®ããããŒãã¡ã€ã«ã«ã¯èå³æ·±ãå®çŸ©ãå«ãŸããŠãããããLinuxã«ãŒãã«ã³ãŒãã®ãŠãŒã¢ã¢æ奜家ã«ãšã£ãŠãèå³æ·±ããã®ã«ãªããŸãã
#define STUPID_ACCELF_TEXT_SHIT ã ååã¯ããèªäœãç©èªã£ãŠãããšæããŸãã ãããã
fb_infoæ§é ã«æ»ããŸãã
fb_var_screeninfoãš
fb_fix_screeninfoãå«ã2ã€ã®æ§é ã«èå³ããã
ãŸã ã ãã£ã¹ãã¬ã€ã®ãã©ã¡ãŒã¿ãŒã§ããããåæåããŸãã
static struct fb_fix_screeninfo ssd1963_fix __initdata = { .id = "SSD1963", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, .accel = FB_ACCEL_NONE, .line_length = 320 * 4, }; static struct fb_var_screeninfo ssd1963_var __initdata = { .xres = 320, .yres = 240, .xres_virtual = 320, .yres_virtual = 240, .width = 320, .height = 240, .bits_per_pixel = 32, .transp = {24, 8, 0}, .red = {16, 8, 0}, .green = {8, 8, 0}, .blue = {0, 8, 0}, .activate = FB_ACTIVATE_NOW, .vmode = FB_VMODE_NONINTERLACED, };
ãã®å Žåããã¯ã»ã«ã«4ãã€ããå²ãåœãŠãããŸãïŒ8-Redã8-Greenã8-Blueã8-Transparent
æ§é ãã£ãŒã«ãã®ããã€ãã«ã€ããŠèª¬æããŸãã
.typeã¯ãã¡ã¢ãªå
ã®ãã¯ã»ã«ãèšè¿°ããããããé
眮ããæ¹æ³ã§ãã ããã¯ããããã¯ã»ã«ãšã¯ããã®ãã€ããæå³ããŸãïŒãã®å Žåã8888ã¯æ¬¡ã
ã«é çªã«é
眮ãããŸãïŒã
.visual-衚瀺è²æ°ã ç§ãã¡ã®å Žåãããã¯ãã¥ã«ãŒã«ã©ãŒ-24ãããè²æ·±åºŠã§ã
.accel-ããŒããŠã§ã¢ã¢ã¯ã»ã©ã¬ãŒã·ã§ã³
.transpãredãgreenãblue -8,8,8,8圢åŒã3ã€ã®ãã£ãŒã«ãïŒ
offsetãlength ã
msb_rightïŒã®åœ¢åŒã§èšå®ããŸãã
ãŸããã«ãŒãã«ã«ãã©ã€ããŒãç»é²ããã«ã¯ãããã€ã¹ãšãã©ã€ããŒã®2ã€ã®ãšã³ãã£ãã£ãèšè¿°ããå¿
èŠããããŸãã ãããªã¡ã¢ãªã®ããŒãžïŒ
struct ss1963_page ïŒãå«ãFBããã€ã¹ïŒ
struct ssd1963 ïŒã«ã€ããŠèª¬æããŸãã
struct ssd1963_page { unsigned short x; unsigned short y; unsigned long *buffer; unsigned short len; int must_update; }; struct ssd1963 { struct device *dev; struct fb_info *info; unsigned int pages_count; struct ssd1963_page *pages; }; struct platform_driver ssd1963_driver = { .probe = ssd1963_probe, .remove = ssd1963_remove, .driver = { .name = "ssd1963" } };
åæåä»ã®Linuxã«ãŒãã«ã¢ãžã¥ãŒã«ãšåæ§ã«ãããã€ãã®init / removeé¢æ°ã«ã€ããŠèª¬æããŸãã initããå§ããŸãããã éåžžããã¬ãŒã ãããã¡ãŒãã©ã€ããŒã¯ã·ã¹ãã ã«
platform_driverãšããŠç»é²ãã
ãŸã ã
static int __init ssd1963_init(void) { int ret = 0; ret = platform_driver_register(&ssd1963_driver); if (ret) { pr_err("%s: unable to platform_driver_register\n", __func__); } return ret; } module_init(ssd1963_init);
ãã©ãããã©ãŒã ãã©ã€ããŒã¯ãç¹å®ã®ãã©ã€ããŒã®ãããŒãé¢æ°ãåŒã³åºããå¿
èŠãªãã¹ãŠã®æäœïŒã¡ã¢ãªã®å²ãåœãŠããªãœãŒã¹ã®äºçŽãæ§é ã®åæåãªã©ïŒãå®è¡ããŸãã
ssd1963_probeé¢æ°ã®äŸã次ã«
瀺ããŸãã
static int __init ssd1963_probe(struct platform_device *dev) { int ret = 0; struct ssd1963 *item; struct fb_info *info;
é¢æ°ã«é¢ããããã€ãã®ã³ã¡ã³ãã ããã«é çªã«ãããŸãïŒ
-ssd1963ããã€ã¹ã«ã¡ã¢ãªãå²ãåœãŠãŸã
-å€ãã®ãã©ã¡ãŒã¿ãŒãå€æŽããå¿
èŠããªããããæåã«ããã©ã«ãå€ïŒ
framebuffer_alloc ïŒã§ã¡ã¢ãªãå²ãåœãŠãŠfb_info
æ§é äœãåæåãã次ã«
fb_var_screeninfoãfb_fix_screeninfoããã³
fb_opsãªã©ã®ãã©ã€ããŒã®ç¹å®ã®å€ã䜿çšããŸãã
-ä»®æ³ã¡ã¢ãªå
ã®ãã¯ã»ã«ã®é£ç¶ãããã¡ã«ã¡ã¢ãªãå²ãåœãŠãŸããããã¯ããŠãŒã¶ãŒç©ºéããã»ã¹ã«ããèšé²ã«äœ¿çšãããŸãã
-ãã¬ãŒã ãããã¡ãŒä»®æ³ã¡ã¢ãªã®åããŒãžã«å¯ŸããŠ
ssd1963_pageãéžæããŸãã å
ssd1963_pageã«ã¯ãå
±æFBãããã¡ãŒã«é¢ããããŒãžãããã¡ãŒã®éå§ã¢ãã¬ã¹ãxãªãã»ãããyãªãã»ãããããã³ããŒãžãããã¡ãŒé·ãå«ãŸããŸãã ãã®å Žåããã¬ãŒã ãããã¡ã®å®¹é=
line_length * height = 320 * 4 * 240 = 307200ãã€ãã ãã®ãããªãããã¡å®¹éã®å Žåãline_length * height / PAGE_SIZE = 307200/4096 = 75ããŒãžãå¿
èŠã§ãã FBã¡ã¢ãªã§ã©ã®ããã«é
眮ããããã«æ³šæããŠãã ããã ãã®ããŒãžã¬ã€ã¢ãŠããç解ããããšã¯ãssd1963_copyé¢æ°ãå°ãåŸã§èŠããšãã«åœ¹ç«ã¡ãŸãã

-ã·ã¹ãã ã«FBãç»é²ãïŒ
register_framebuffer ïŒãé
延ããŒã¿æŽæ°ã®æé ãåæåããŸãïŒ
fb_deferred_io_init ïŒãããã«ã€ããŠã¯ãããã¬ãŒã ãããã¡ãŒã䜿çšããæäœãã»ã¯ã·ã§ã³ã§èª¬æããŸãã
-ssd1963_setupã¯ãAT91SAM9G45 CPUã§å¿
èŠãªGPIOãæ§æããLCDã³ã³ãããŒã©ãŒã®åæã»ããã¢ãããå®è¡ããŸãã ç¥ç§çãªãã€ãã®ã»ããã16é²æ°ã§éä¿¡ãã圢åŒã®åææ§æã¢ã«ãŽãªãºã ã¯ãSSD1963ã®ããã¥ã¡ã³ãããååŸãããŠãããããããã§ã¯æ©èœã®äžéšã®ã¿ã瀺ããŸãã
void ssd1963_setup(struct ssd1963 *item) { nhd_init_gpio_regs();
-ssd1963_update_allã¯ããã¹ãŠã®ããŒãžã«
must_update = 1ãã©ã°ãèšå®ãã
schedule_delayed_workïŒïŒitem-> info-> deferred_workãfbdefio-> delayïŒãåŒã³åºããŠãé
延ã³ã³ããã¹ãã§è¡šç€ºæŽæ°ã¡ã«ããºã ãéå§ããŸã
ããã®ãããinitãç解ããŸãããremoveé¢æ°ã¯ã¯ããã«åçŽã§ãå²ãåœãŠãããã¡ã¢ãªã解æŸããFBæ§é äœãã«ãŒãã«ã«è¿ããŸãã
static int ssd1963_remove(struct platform_device *device) { struct fb_info *info = platform_get_drvdata(device); struct ssd1963 *item = (struct ssd1963 *)info->par; if (info) { unregister_framebuffer(info); ssd1963_pages_free(item); ssd1963_video_free(item); framebuffer_release(info); kfree(item); } return 0; }
ãã¬ãŒã ãããã¡æäœããã§ã¯ã
fb_opsæ§é ãæ€èšã
ãŸã ã
static struct fb_ops ssd1963_fbops = { .owner = THIS_MODULE, .fb_read = fb_sys_read, .fb_write = ssd1963_write, .fb_fillrect = ssd1963_fillrect, .fb_copyarea = ssd1963_copyarea, .fb_imageblit = ssd1963_imageblit, .fb_setcolreg = ssd1963_setcolreg, .fb_blank = ssd1963_blank, };
ããã§ãã¹ãŠã®æ§é ã¡ãœãããæäŸããããã§ã¯ãããŸããã奜å¥å¿readerçãªèªè
ã¯ãã¢ãžã¥ãŒã«ã®ãœãŒã¹ã³ãŒããŸãã¯
ãã©ã€ããŒ/ãããªãã£ã¬ã¯ããªã®ã«ãŒãã«ã³ãŒãã®ä»ã®ãã©ã€ããŒã§ããããèŠã€ããããšãã§ããŸãã ãæ³åã®ãšãããfb_opsæ§é äœã¯ããã©ã€ããŒãå®è¡ã§ããã¢ã¯ã·ã§ã³ãèšè¿°ããŠããŸãã 幞ããªããšã«ãã«ãŒãã«éçºè
ã¯ãäŸãã°
fb_sys_readã®ããã«ã
sys_ãŸãã¯
fb_sysæ¥å°ŸèŸãæã€FBãæäœããããã®æšæºé¢æ°ãæäŸããããšã«ãããäœæ¥ãéšåçã«ä¿é²ã
ãŸãã ã
fb_ops ïŒ
ssd1963_readãssd1963_writeãªã©ïŒã®é¢æ°ã®å®è£
ã«æ©èœãè¿œå ããã ãã§ãå¿
èŠã«å¿ããŠå³åžãããªã¡ã¢ãªã®ããŒã¿ãæŽæ°ã§ããŸãã
ããšãã°ã
ssd1963_fillrecté¢æ°ã¯æ¬¡ã®ããã«ãªããŸãã
static void ssd1963_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { sys_fillrect(p, rect); ssd1963_touch(p, rect->dx, rect->dy, rect->width, rect->height); }
æããã«ã
fb_fillrectã·ã¹ãã ã³ãŒã«
ã¯ç»é¢ã®ç¹å®ã®é·æ¹åœ¢é åã®ãããªããŒã¿
ãæŽæ°ããããã
must_updateãã©ã°ã§ããŒã¯ãããããªã¡ã¢ãªæŽæ°ããã·ãŒãžã£ãæåã§åŒã³åºããŠãæŽæ°ããå¿
èŠãããããŒãžãæå®ããå¿
èŠããããŸãã
static void ssd1963_touch(struct fb_info *info, int x, int y, int w, int h) { struct fb_deferred_io *fbdefio = info->fbdefio; struct ssd1963 *item = (struct ssd1963 *)info->par; int i, ystart, yend; if (fbdefio) {
ãããªã¡ã¢ãªå
ã®ããŒã¿ã¯ãé
延ã³ã³ããã¹ããšããŠæŽæ°ãããŸãã ã°ã©ãã£ãã¯ã¹ã§åäœãããŠãŒã¶ãŒã¹ããŒã¹ã¢ããªã±ãŒã·ã§ã³ã¯ããããªã¡ã¢ãªã®åãã¬ãŒã ã®èšé²ãå®äºããã®ãåŸ
ã¡ãŸãããããã¯éåžžã«è«ççã§ãã
fb_infoã®é
延åŠçã¯ã
fb_deferred_ioæ§é ãšããŠå®çŸ©ãããŸãã
static struct fb_deferred_io ssd1963_defio = { .delay = HZ / 20, .deferred_io = &ssd1963_update, };
ãããã¿ã€ãã䜿çšãã
ssd1963_updateé¢æ°
void ssd1963_updateïŒstruct fb_info * infoãstruct list_head * pagelistïŒ;ãã¹ãŠã®ããŒãžã¯æŽæ°ãããŸãããããŠãŒã¶ãŒç©ºéããã»ã¹ã«ããæžãæãã®çµæãšããŠããŸãã¯
fb_fillrectãcompanyãªã©ã®ã·ã¹ãã ã³ãŒã«ã®çµæãšããŠå€æŽãããããŒãžã®ã¿ãæŽæ°ãããŸãã ãããã£ãŠãé¢æ°ã®åœ¢åŒã¯æ¬¡ã®ãšããã§ãã
static void ssd1963_update(struct fb_info *info, struct list_head *pagelist) { struct ssd1963 *item = (struct ssd1963 *)info->par; struct page *page; int i; list_for_each_entry(page, pagelist, lru) { item->pages[page->index].must_update=1; }
ãã®æç¹ã§ããããã
ssd1963_copyé¢æ°
ãäœãããã®ãçåã«æãã§ãããã ãããªã¡ã¢ãªããŒãžãã人çºçã«äœæããã8ãããGPIOããŒã¹ã®ãã¹ã«ããŒã¿ã転éãããšããæ±ãäœæ¥ããã¹ãŠè¡ããŸãã
ssd1963_copyé¢æ°ããã§ãã¡ã¢ãªå
ã®ããŒãžã衚瀺ãã¯ã»ã«ãšã©ã®ããã«å¯Ÿå¿ãããã瀺ãå³ãæãåºãå¿
èŠããããŸãã ããšãã°ã
ããŒãž[0]ã«ã¯ã320ãã¯ã»ã«ã®äžäœ3衚瀺è¡ã®æ
å ±ãšã4è¡ç®ã®64ãã¯ã»ã«ã®æ
å ±ãæ ŒçŽãããŠããŸãã ãã®ãããªããŒãžã75ããŒãžãããå³ã®åçããããæ°ã¥ãã®ã¯é£ãããããŸããã
ããŒãž[5]ã¯åãããã«èŠããŸã-320è¡ã®3è¡ãš64è¡ã®1è¡ããããã£ãŠãããŒãžã€ã³ããã¯ã¹ããã©ã¡ãŒã¿ãŒãšããŠåãé¢æ°ã«ã¯
switchïŒindexïŒ
5ïŒãããŠãç¹å®ã®åããŒãžã®ãªãã»ããã«å¿ããŠã衚瀺ã¡ã¢ãªã§ããã«å²ãåœãŠãããããŠã£ã³ããŠãã«ããŒã¿ãéä¿¡ããŸãã ãã®é¢æ°ã¯éåžžã«é·ãããããã®äžéšã®ã¿ãæäŸããŸãã
static void ssd1963_copy(struct ssd1963 *item, unsigned int index) { unsigned short x,y, startx, endx, starty, endy, offset; unsigned long *buffer; unsigned int len; unsigned int count; x = item->pages[index].x; y = item->pages[index].y; buffer = item->pages[index].buffer; len = item->pages[index].len; switch (index%5) { case 0: offset = 0; startx = x; starty = y; endx = 319; endy = y+2; len = 960; nhd_set_window(startx, endx, starty, endy); nhd_write_data(NHD_COMMAND, 0x2c); for (count = 0; count < len; count++) { nhd_write_data(NHD_DATA,(unsigned char)((buffer[count+offset])>>16));
ããã§ã¯ã
nhd_set_windowé¢æ°
㯠nhd_write_dataïŒNHD_COMMANDã...ïŒã䜿çšããŠæ§æãããŠã
ãŸãã ããŒã¿ïŒãã¯ã»ã«ïŒãèšé²ããã衚瀺é åã
nhd_write_dataïŒNHD_COMMANDã0x2cïŒ; -ããŒã¿ã¹ããªãŒã ãåŸã«ç¶ãLCDã³ã³ãããŒã©ãžã®ã³ãã³ãã
æåŸã«ããã£ã¹ãã¬ã€ä»ãã®ããã€ã¹äžã®tslibããã±ãŒãžã®ts_calibrateããã°ã©ã ã®ã¹ã¯ãªãŒã³ã·ã§ããã
誰ãæ°ã«ããªã-ã¢ãžã¥ãŒã«ã®å®å
šãªã³ãŒããéä¿¡ã§ããŸãïŒ
