#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sspscreen.h" #define DEVICE_NAME "screen" #define SCREEN_BAUD (0x001 << 8) #define DSS_9 8 #define FRF_SPI 0 #define SSE_ENABLED (1 << 7) #define SPO (1 << 3) #define SPH (1 << 4) //********************************************************************** // NSSP lines and GPIOs static int gNSSPClk = 81; //NSSP_CLOCK static int gNSSPCS = 82; //NSSP_FRAME static int gNSSPData = 83; //NSSP_TXD MOSI static int gGPIOReset = 84; //NSSP_RXD MISO struct ssp_dev gSpiDevice; //********************************************************************** // DELAY static void screen_delay(int n) { int time_to_stop = get_jiffies_64() + n; int time_now; do { time_now = get_jiffies_64(); cpu_relax(); //printk("n: %d now: %d stop: %d\n", n, time_now, time_to_stop); }while(time_now < time_to_stop); } //********************************************************************** // SET/CLEAR static void set_gpio(int gpio) { GPSR(gpio) = GPIO_bit(gpio); } static void clear_gpio(int gpio) { GPCR(gpio) = GPIO_bit(gpio); } //********************************************************************** // SEND BIT/DATA/COMMAND void send_cmd(unsigned char b) { int value; u32 readOut; readOut=0; value = b; // Write data ssp_write_word(&gSpiDevice, value); // Read to keep SPI happy! ssp_read_word(&gSpiDevice, &readOut); } void send_data(unsigned char b) { int value; u32 readOut; readOut=0; value = b | 0x100; // Write data ssp_write_word(&gSpiDevice, value); // Read to keep SPI happy! ssp_read_word(&gSpiDevice,&readOut); } //********************************************************************** // PUT PIXEL void put_pixel(unsigned char color, unsigned char x, unsigned char y) { send_cmd(PASET); // page start/end ram send_data(x);// for some reason starts at 2 send_data(x + 1); send_cmd(CASET); // column start/end ram send_data(y); // for some reason starts at 2 send_data(y + 1); send_cmd(RAMWR); // write something send_data(color); } //********************************************************************** // FILE OPERATIONS struct file_operations screen_fops = { owner: THIS_MODULE, // ioctl: whatever, // open: jogwheel_open, // release: jogwheel_release, // read: jogwheel_read, }; //********************************************************************** // INIT static int __init screen_init( void ) { int rc; int i; int speed = SCREEN_BAUD; int mode = DSS_9 | FRF_SPI | SSE_ENABLED; int flags = SPO | SPH; int result=0; printk("screen: init called\n"); // register our device with Linux if (( rc = register_chrdev( SCREEN_MAJOR, DEVICE_NAME, &screen_fops )) < 0 ) { printk( KERN_WARNING "screen: register_chrdev failed for major %d\n", SCREEN_MAJOR ); return rc; } printk("screen: init GPIO pins\n"); // Pin functions and directions pxa_gpio_mode( gNSSPData | GPIO_ALT_FN_1_OUT ); pxa_gpio_mode( gNSSPClk | GPIO_ALT_FN_1_OUT ); pxa_gpio_mode( gNSSPCS | GPIO_ALT_FN_1_OUT ); pxa_gpio_mode( gGPIOReset | GPIO_OUT ); // Setup GPIO levels set_gpio(gGPIOReset); printk("screen: init NSSP\n"); result=ssp_init(&gSpiDevice, 2,flags); if (result) { printk("ssp_init() failed!\n"); } printk("ssp_init() success!%d\n",result); /* configure NSSP port parameters */ ssp_config(&gSpiDevice, mode, flags, 0, speed); ssp_enable(&gSpiDevice); printk("screen: display reset\n"); // Reset the display clear_gpio(gGPIOReset); screen_delay(10); set_gpio(gGPIOReset); screen_delay(10); printk("screen: display reset : control\n"); // display control send_cmd(DISCTL); printk("screen: display reset : send_cmd(DISCTL)\n"); send_data(0x03); printk("screen: display reset : d1\n"); send_data(0x20); printk("screen: display reset : d2\n"); send_data(0x0C); //send_data(0x00); // EH? printk("screen: display reset : comscn\n"); // comscn send_cmd(COMSCN); send_data(0x01); printk("screen: display reset : oscon\n"); // oscon send_cmd(OSCON); // sleep out printk("screen: sleep out\n"); send_cmd(SLPOUT); screen_delay(10); // electronic volume, this is kinda contrast/brightness // this might be different for individual LCDs send_cmd(VOLCTR); send_data(0x05); send_data(0x01); send_cmd(VOLDOWN); send_cmd(VOLDOWN); send_cmd(TMPGRD); send_data(0); send_data(0); send_data(0); send_data(0); send_data(0); // power ctrl //everything on, no external reference resistors send_cmd(PWRCTR); send_data(0x0f); screen_delay(10); //send_cmd(PTLOUT); //send_cmd(RMWOUT); // Scroll area //send_cmd(ASCSET); //send_data(0x00); //send_data(0x00); //send_data(0x00); //send_data(0x03); // Whole screen //send_cmd(SCSTART); //send_data(0x00); // display mode send_cmd(DISINV); // datctl send_cmd(DATCTL); send_data(0x00); send_data(0x00); send_data(0x01); printk("screen: color LUT\n"); // setup color lookup table send_cmd(RGBSET8); // color table //RED send_data(0); send_data(2); send_data(4); send_data(6); send_data(8); send_data(10); send_data(12); send_data(15); // GREEN send_data(0); send_data(2); send_data(4); send_data(6); send_data(8); send_data(10); send_data(12); send_data(15); //BLUE send_data(0); send_data(4); send_data(9); send_data(15); // nop send_cmd(NOP); // display on screen_delay(100); printk("screen: display on\n"); send_cmd(DISON); screen_delay(10); // this loop adjusts the contrast, change the number of iterations to get // desired contrast. this might be different for individual LCDs printk("screen: contrast loop\n"); for (i = 0; i < 50; i++) { send_cmd(VOLUP); } // page start/end ram send_cmd(PASET); // for some reason starts at 2 send_data(0x00); send_data(0x83); // column start/end ram send_cmd(CASET); send_data(0x00); send_data(0x83); // write some stuff (background) send_cmd(RAMWR); for (i = 0; i < 17424; i++) { if(i % 200 == 0) printk("screen: background: %d\r", i); send_data(i % 0x100); //if(i == 200) // send_data(0xE0); // 1C is green E0 is red 03 is blue //else if(i % 3 == 1) // send_data(0x1C); // 1C is green E0 is red 03 is blue //else // send_data(0x03); // 1C is green E0 is red 03 is blue } printk("screen: background: %d\n", i); // draw a multi-colored square in the center of screen int x, y, c; for (i = 0; i < 4096; i++) { if(i % 50 == 0) printk("screen: square: %d\r", i); x = (i % 64) + 32; y = (i / 64) + 32; if(x <= 63 && y <= 63) c = 0xE0; else if(x > 63 && y <= 63) c = 0x1C; else if(x <= 63 && y > 63) c = 0x03; else c = 0xE3; put_pixel(c, x, y); } printk("screen: square: %d\n", i); return 0; } //********************************************************************** // EXIT static void __exit screen_exit( void ) { printk("screen: exit called\n"); send_cmd(SLPIN); screen_delay(10); send_cmd(DISOFF); screen_delay(10); ssp_exit(&gSpiDevice); unregister_chrdev( SCREEN_MAJOR, DEVICE_NAME ); } //********************************************************************** // MODULE SETUP module_init(screen_init); module_exit(screen_exit); MODULE_AUTHOR("Dan Taylor"); MODULE_DESCRIPTION("Screen Driver"); MODULE_LICENSE("GPL");