MOD Nokia 3310 LCD am WRT54g

Post new topic   Reply to topic    DD-WRT Forum Index -> Broadcom SoC basierende Hardware
Author Message
topcam
DD-WRT Novice


Joined: 27 Nov 2006
Posts: 40

PostPosted: Fri Dec 15, 2006 17:06    Post subject: MOD Nokia 3310 LCD am WRT54g Reply with quote
Hast sich schon mal einer das MOD gewagt das LCD vom Nokia 3310
in den Router einzubauen ?


Habe alles zusammen, nur der Treiber fehlt noch.


Topcam
Sponsor
daa531
DD-WRT User


Joined: 26 Sep 2006
Posts: 112

PostPosted: Fri Dec 15, 2006 17:30    Post subject: Reply with quote
Haste ein Schaltplan wie man was anschliesst?

Gruss Olli.




Joined: 01 Jan 1970
Posts:

PostPosted: Fri Dec 15, 2006 18:08    Post subject: Re: MOD Nokia 3310 LCD am WRT54g Reply with quote
topcam wrote:
Habe alles zusammen, nur der Treiber fehlt noch.
LCD4Linux ?

LCD4Linux liegt bereits als OpenWrt Paket vor.
soundy
DD-WRT User


Joined: 20 Jul 2006
Posts: 64

PostPosted: Fri Dec 15, 2006 18:40    Post subject: Reply with quote
Hallo,

Ich denke es geht um dies hier:
http://nanl.de/blog/howtos/lcd-mod-fur-linksys-wrt54gs/

Was ich mich dabei frage ist nur, ob man da auch einstellen kann, was angezeigt wird bzw. wo man nähere Infos zur Ansteuerung des Displays findet. Interessant für mich wäre:

1. Traffic seit letztem Reboot (oder) Uptime des Routers
2. Zeile: Aktueller Datendurchsatz (Traffic) als Zahl
3. Zeile: Grafische horizontale (Bargraphanzeige) des aktuellen Traffics

Ob dies umsetzbar ist bzw. wie...
Noch tappe ich ein wenig im dunkeln! :roll:

Lg Soundy
topcam
DD-WRT Novice


Joined: 27 Nov 2006
Posts: 40

PostPosted: Mon Dec 18, 2006 10:47    Post subject: Reply with quote
Hier gibt es info zum Nokia 3310 Display :

http://www.amontec.com/lcd_nokia_3310.shtml


Belegung zum anschluss unter

http://nanl.de/blog/howtos/lcd-mod-fur-linksys-wrt54gs/

Hier braucht mann ein Gutes Auge da die Bilder nicht so astrein sind.

Her der Treiber:

Code:
/*
 * fb.c - Frame-buffer driver for Nokia 3310 LCD
 *
 */

#include <linux/config.h>
#include <linux/module.h>

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/proc_fs.h>

#include <asm/io.h>
#include <asm/uaccess.h>

#include <video/fbcon.h>
#include <video/fbcon-mfb.h>

#define LCD_WIDTH 84
#define LCD_HEIGHT 48

/* allow for 1bpp */
static unsigned char *lcd_scr;

#define SD_DI 0x20
#define SD_DO 0x10
#define SD_CLK 0x08
#define SD_CS 0x80

typedef unsigned int uint32;
static unsigned char port_state = 0x00;
static volatile uint32 *gpioaddr_input = (uint32 *)0xb8000060;
static volatile uint32 *gpioaddr_output = (uint32 *)0xb8000064;
static volatile uint32 *gpioaddr_enable = (uint32 *)0xb8000068;
static volatile uint32 *gpioaddr_control = (uint32 *)0xb800006c;

static inline void lcd_spi_cs_low(void)
{
  port_state &= ~(SD_CS);
  *gpioaddr_output = port_state;
}

static inline void lcd_spi_cs_high(void)
{
  port_state |= SD_CS;
  *gpioaddr_output = port_state;
}

static inline void lcd_data_mode(void)
{
  port_state |= SD_DO;
  *gpioaddr_output = port_state;
}

static inline void lcd_command_mode(void)
{
  port_state &= ~(SD_DO);
  *gpioaddr_output = port_state;
}

static unsigned char lcd_spi_io(unsigned char data_out)
{
  int i;
  unsigned char result = 0, tmp_data = 0;
 
  for(i=0; i<8; i++) {
     if(data_out & (0x01 << (7-i)))
        port_state |= SD_DI;
     else
        port_state &= ~SD_DI;
    
     *gpioaddr_output = port_state;
     port_state |= SD_CLK;
     *gpioaddr_output = port_state;
    
     tmp_data = *gpioaddr_input;
    
     port_state &= ~SD_CLK;
     *gpioaddr_output = port_state;
    
     result <<= 1;
    
     if(tmp_data & SD_DO)
        result |= 1;
  }
 
  return(result);
}

#if 0
static void lcd_out(int x, int y, const char c)
{
   lcd_command_mode();

   lcd_spi_io(x | 0x80);
   lcd_spi_io(y | 0x40);

   lcd_data_mode();

   lcd_spi_io(c);
}
#endif

static void lcd_clear(void)
{
   int p, q;
   port_state &= ~(SD_DI);
   *gpioaddr_output = port_state;   

   lcd_data_mode();

   lcd_spi_cs_low();

   for(p=0; p<6; p++) {
      for(q=0; q<84; q++) {
         lcd_spi_io(0);
      }
   }
}


/* initialise the LCD */
static void
init_lcd(void)
{
   *gpioaddr_enable |= SD_DI | SD_CLK | SD_CS | SD_DO;

   port_state = *gpioaddr_output;
   port_state &= ~(SD_CLK | SD_DI | SD_CS);
   *gpioaddr_output = port_state;

   lcd_spi_cs_low();
   lcd_command_mode();

   lcd_spi_io(0x21);
   lcd_spi_io(0xc5);
   lcd_spi_io(0x06);
   lcd_spi_io(0x13);
   lcd_spi_io(0x20);
   lcd_spi_io(0x0c);

   lcd_clear();

   lcd_spi_cs_high();
}

static void lcd_detect(void)
{

}

static void lcd_update_display(struct display *p, int sx, int sy, int mx, int my)
{
   int x, y, i, bit;

   *gpioaddr_enable |= SD_DI | SD_CLK | SD_CS | SD_DO;
   port_state = *gpioaddr_output;

   lcd_spi_cs_low();

   unsigned char *scr = lcd_scr;

   lcd_command_mode();

   lcd_spi_io(0x80);
   lcd_spi_io(0x40);

   lcd_data_mode();

   // For now we just do braindead updating of the entire screen
   for(y = 0; y<LCD_HEIGHT/8; y++) {
      for(x = 0; x < (LCD_WIDTH+4)/8; x++) {
         for(bit = (x == LCD_WIDTH/8) ? 0x8 : 0x80;
             bit != 0;
             bit >>= 1) {
            for(i=7; i>=0; i--) {
               if(scr[x+(LCD_WIDTH+4)*i/8] & bit)
                  port_state |= SD_DI;
               else
                  port_state &= ~SD_DI;
               
               *gpioaddr_output = port_state;
               
               *gpioaddr_output = port_state | SD_CLK;
               *gpioaddr_output = port_state;
            }
         }
      }
      scr+=(LCD_WIDTH+4);
   }

   lcd_spi_cs_high();
}

struct lcdfb_info {
   struct fb_info_gen gen;
};


struct lcdfb_par {
   /*
    *  The hardware specific data in this structure uniquely defines a video
    *  mode.
    *
    *  If your hardware supports only one video mode, you can leave it empty.
    */
};


void lcd_fb_setup(struct display *p)
{
   fbcon_mfb.setup(p);
}

void lcd_fb_bmove(struct display *p, int sy, int sx, int dy, int dx,
           int height, int width)
{
   fbcon_mfb.bmove(p, sy, sx, dy, dx, height, width);
   lcd_update_display(p, 0, 0, LCD_WIDTH/8, LCD_HEIGHT/fontheight(p));
}

void lcd_fb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
           int height, int width)
{
   fbcon_mfb.clear(conp, p, sy, sx, height, width);
   lcd_update_display(p, sx, sy, sx+width, sy+height);
}

void lcd_fb_putc(struct vc_data *conp, struct display *p, int c, int yy,
          int xx)
{
   fbcon_mfb.putc(conp, p, c, yy, xx);
   lcd_update_display(p, xx, yy, xx+1, yy+1);
}

void lcd_fb_putcs(struct vc_data *conp, struct display *p,
           const unsigned short *s, int count, int yy, int xx)
{
   fbcon_mfb.putcs(conp, p, s, count, yy, xx);
   lcd_update_display(p, xx, yy, xx+count, yy+1);
}

void lcd_fb_revc(struct display *p, int xx, int yy)
{
   fbcon_mfb.revc(p, xx, yy);
   lcd_update_display(p, xx, yy, xx+1, yy+1);
}

void lcd_fb_clear_margins(struct vc_data *conp, struct display *p,
           int bottom_only)
{
   fbcon_mfb.clear_margins(conp, p, bottom_only);
   lcd_update_display(p, 0, 0, LCD_WIDTH, LCD_HEIGHT);
}

/*
 *  `switch' for the low level operations
 */

struct display_switch fbcon_lcd = {
   setup:      lcd_fb_setup,
   bmove:      lcd_fb_bmove,
   clear:      lcd_fb_clear,
   putc:      lcd_fb_putc,
   putcs:      lcd_fb_putcs,
   revc:      lcd_fb_revc,
   clear_margins:  lcd_fb_clear_margins,
   fontwidthmask:   FONTWIDTH(8)
};

static struct lcdfb_info fb_info;
static struct lcdfb_par current_par;
static int current_par_valid = 0;
static struct display disp;

int lcdfb_init(void);
int lcdfb_setup(char*);

static int lcd_encode_fix(struct fb_fix_screeninfo *fix, struct lcdfb_par *par,
           const struct fb_info *info)
{
   /*
    *  This function should fill in the 'fix' structure based on the values
    *  in the `par' structure.
    */


   memset(fix, 0x0, sizeof(*fix));

   strcpy(fix->id, "lcd");
   /* required for mmap() */
   fix->smem_start = lcd_scr;
   fix->smem_len = LCD_HEIGHT * (LCD_WIDTH+4)/8;

   fix->type= FB_TYPE_PACKED_PIXELS;

   fix->visual = FB_VISUAL_MONO10;   /* fixed visual */
   fix->line_length = (LCD_WIDTH+4) / 8;

   fix->xpanstep = 0;   /* no hardware panning */
   fix->ypanstep = 0;   /* no hardware panning */
   fix->ywrapstep = 0;   /* */

   fix->accel = FB_ACCEL_NONE;

   return 0;
}

static int lcd_decode_var(struct fb_var_screeninfo *var, struct lcdfb_par *par,
           const struct fb_info *info)
{
   /*
    *  Get the video params out of 'var'. If a value doesn't fit, round it up,
    *  if it's too big, return -EINVAL.
    *
    *  Suggestion: Round up in the following order: bits_per_pixel, xres,
    *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
    *  bitfields, horizontal timing, vertical timing.
    */


   if ( var->xres > LCD_WIDTH ||
      var->yres > LCD_HEIGHT ||
      var->xres_virtual != var->xres ||
      var->yres_virtual != var->yres ||
      var->xoffset != 0 ||
      var->yoffset != 0 ) {
      return -EINVAL;
   }

   if ( var->bits_per_pixel != 1 ) {
      return -EINVAL;
   }


   return 0;
}

static int lcd_encode_var(struct fb_var_screeninfo *var, struct lcdfb_par *par,
           const struct fb_info *info)
{

   /*
    *  Fill the 'var' structure based on the values in 'par' and maybe other
    *  values read out of the hardware.
    */

   var->xres = LCD_WIDTH;
   var->yres = LCD_HEIGHT;
   var->xres_virtual = var->xres;
   var->yres_virtual = var->yres;
   var->xoffset = 0;
   var->yoffset = 0;

   var->bits_per_pixel = 1;
   var->grayscale = 1;

   return 0;
}

static void lcd_get_par(struct lcdfb_par *par, const struct fb_info *info)
{
   /*
    *  Fill the hardware's 'par' structure.
    */

   if ( current_par_valid ) {
      *par = current_par;
   }
   else {
      /* ... */
   }
}

static void lcd_set_par(struct lcdfb_par *par, const struct fb_info *info)
{
   /*
    *  Set the hardware according to 'par'.
    */

   current_par = *par;
   current_par_valid = 1;

   /* ... */
}

static int lcd_getcolreg(unsigned regno, unsigned *red, unsigned *green,
          unsigned *blue, unsigned *transp,
          const struct fb_info *info)
{
   /*
    *  Read a single color register and split it into colors/transparent.
    *  The return values must have a 16 bit magnitude.
    *  Return != 0 for invalid regno.
    */

   /* ... */
   return 0;
}

static int lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
          unsigned blue, unsigned transp,
          const struct fb_info *info)
{
   /*
    *  Set a single color register. The values supplied have a 16 bit
    *  magnitude.
    *  Return != 0 for invalid regno.
    */

   /* ... */
   return 0;
}

static int lcd_pan_display(struct fb_var_screeninfo *var,
            struct lcdfb_par *par, const struct fb_info *info)
{
   /*
    *  Pan (or wrap, depending on the `vmode' field) the display using the
    *  `xoffset' and `yoffset' fields of the `var' structure.
    *  If the values don't fit, return -EINVAL.
    */

   /* ... */
   return -EINVAL;
}

static int lcd_blank(int blank_mode, const struct fb_info *info)
{

   switch (blank_mode) {
   case VESA_NO_BLANKING:
      break;

   case VESA_VSYNC_SUSPEND:
   case VESA_HSYNC_SUSPEND:
      break;

   case VESA_POWERDOWN:
      break;

   default:
      /* printk(KERN_ERR "unknown blank value %d\n", blank_mode); */
      return -EINVAL;
   }

   return 0;
}

static void lcd_set_disp(const void *par, struct display *disp,
          struct fb_info_gen *info)
{

   /*
    *  Fill in a pointer with the virtual address of the mapped frame buffer.
    *  Fill in a pointer to appropriate low level text console operations (and
    *  optionally a pointer to help data) for the video mode `par' of your
    *  video hardware. These can be generic software routines, or hardware
    *  accelerated routines specifically tailored for your hardware.
    *  If you don't have any appropriate operations, you must fill in a
    *  pointer to dummy operations, and there will be no text output.
    */

   disp->screen_base = lcd_scr;
   disp->dispsw = &fbcon_lcd;
}


/* ------------ Interfaces to hardware functions ------------ */

struct fbgen_hwswitch lcd_switch = {
   detect:      lcd_detect,
   encode_fix:   lcd_encode_fix,
   decode_var:   lcd_decode_var,
   encode_var:   lcd_encode_var,
   get_par:   lcd_get_par,
   set_par:   lcd_set_par,
   getcolreg:   lcd_getcolreg,
   setcolreg:   lcd_setcolreg,
   pan_display:   lcd_pan_display,
   blank:      lcd_blank,
   set_disp:   lcd_set_disp,
};


/* ------------------------------------------------------------------------- */


/*
 *  Frame buffer operations
 */

static int lcd_fp_open(const struct fb_info *info, int user)
{

   return 0;
}

static int lcd_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
   u_long arg, int con, struct fb_info *info)

{
   return -EINVAL;
}


/*
 *  In most cases the `generic' routines (fbgen_*) should be satisfactory.
 *  However, you're free to fill in your own replacements.
 */

static struct fb_ops lcdfb_ops = {
   owner:      THIS_MODULE,
   fb_open:   lcd_fp_open,
   fb_get_fix:   fbgen_get_fix,
   fb_get_var:   fbgen_get_var,
   fb_set_var:   fbgen_set_var,
   fb_get_cmap:   fbgen_get_cmap,
   fb_set_cmap:   fbgen_set_cmap,
   fb_pan_display:   fbgen_pan_display,
   fb_ioctl:   lcd_fb_ioctl,
};


/* ------------ Hardware Independent Functions ------------ */


/*
 *  Initialization
 */

int read_proc(char *buf, char **start, off_t offset, int count,
           int *eof, void *data)
{
   int length = sprintf(buf, "No debug at this point\n");

   /* housekeeping */
   if (length <= offset + count)
      *eof = 1;
   *start = buf + offset;
   length -= offset;
   if (length > count)
      length = count;
   if (length < 0)
      length = 0;

   return length;
}


int __init lcdfb_init(void)
{
   lcd_scr = kmalloc(LCD_HEIGHT * (LCD_WIDTH+4)/8, GFP_KERNEL);
   if(lcd_scr == NULL)
      return -EINVAL;

   memset(lcd_scr, 0, LCD_HEIGHT * (LCD_WIDTH+4)/8);

        if (!create_proc_read_entry("lcdfb", 0, 0, read_proc, NULL)) {
      // Too bad
   }

   fb_info.gen.fbhw = &lcd_switch;

   fb_info.gen.fbhw->detect();

   strcpy(fb_info.gen.info.modename, "lcd");

   fb_info.gen.info.changevar = NULL;
   fb_info.gen.info.node = -1;
   fb_info.gen.info.fbops = &lcdfb_ops;
   fb_info.gen.info.disp = &disp;
   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);
   fbgen_install_cmap(0, &fb_info.gen);

   if ( register_framebuffer(&fb_info.gen.info) < 0 ) {
      kfree(lcd_scr);
      return -EINVAL;
   }

   init_lcd();

   printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);

   /* uncomment this if your driver cannot be unloaded */
   /* MOD_INC_USE_COUNT; */
   return 0;
}


/*
 *  Cleanup
 */

void lcdfb_cleanup(struct fb_info *info)
{
   /*
    *  If your driver supports multiple boards, you should unregister and
    *  clean up all instances.
    */

   unregister_framebuffer(info);
   kfree(lcd_scr);

   /* ... */
}


/*
 *  Setup
 */

int __init lcdfb_setup(char *options)
{
   /* Parse user speficied options (`video=lcdfb:') */
   return 0;
}

#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
   return lcdfb_init();
}

void cleanup_module(void)
{
   
}

#endif /* MODULE */


Hier das fb-lcd-patch

Code:
diff -urN -X dontdiff linux-vanilla/drivers/char/console.c linux/drivers/char/console.c
--- linux-vanilla/drivers/char/console.c   2003-07-04 10:11:31.000000000 +0200
+++ linux/drivers/char/console.c   2005-03-16 19:34:17.000000000 +0100
@@ -110,7 +110,7 @@
 #include "console_macros.h"
 
 
-const struct consw *conswitchp;
+const struct consw *conswitchp = &dummy_con;
 
 /* A bitmap for codes <32. A bit of 1 indicates that the code
  * corresponding to that bit number invokes some special action
@@ -161,7 +161,7 @@
 int console_blanked;
 
 static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
-static int blankinterval = 10*60*HZ;
+static int blankinterval = 0;
 static int vesa_off_interval;
 
 static struct tq_struct console_callback_tq = {
diff -urN -X dontdiff linux-vanilla/drivers/video/Config.in linux/drivers/video/Config.in
--- linux-vanilla/drivers/video/Config.in   2003-07-04 10:12:02.000000000 +0200
+++ linux/drivers/video/Config.in   2005-03-06 11:22:01.000000000 +0100
@@ -9,6 +9,7 @@
 
 if [ "$CONFIG_FB" = "y" ]; then
    define_bool CONFIG_DUMMY_CONSOLE y
+   define_bool CONFIG_FB_LCD y
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       if [ "$CONFIG_PCI" = "y" ]; then
          tristate '  nVidia Riva support (EXPERIMENTAL)' CONFIG_FB_RIVA
diff -urN -X dontdiff linux-vanilla/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- linux-vanilla/drivers/video/fbcon.c   2003-07-04 10:12:03.000000000 +0200
+++ linux/drivers/video/fbcon.c   2005-03-16 19:35:16.000000000 +0100
@@ -572,8 +572,8 @@
     int i, charcnt = 256;
     struct fbcon_font_desc *font;
     
-    if (con != fg_console || (p->fb_info->flags & FBINFO_FLAG_MODULE) ||
-        p->type == FB_TYPE_TEXT)
+    /*    if (con != fg_console || (p->fb_info->flags & FBINFO_FLAG_MODULE) ||
+     p->type == FB_TYPE_TEXT) */
        logo = 0;
 
     p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
diff -urN -X dontdiff linux-vanilla/drivers/video/fb-lcd.c linux/drivers/video/fb-lcd.c
--- linux-vanilla/drivers/video/fb-lcd.c   1970-01-01 01:00:00.000000000 +0100
+++ linux/drivers/video/fb-lcd.c   2005-03-13 21:26:57.000000000 +0100
@@ -0,0 +1,647 @@
+/*
+ * fb.c - Frame-buffer driver for Nokia 3310 LCD
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/proc_fs.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+
+#define LCD_WIDTH 84
+#define LCD_HEIGHT 48
+
+/* allow for 1bpp */
+static unsigned char *lcd_scr;
+
+#define SD_DI 0x20
+#define SD_DO 0x10
+#define SD_CLK 0x08
+#define SD_CS 0x80
+
+typedef unsigned int uint32;
+static unsigned char port_state = 0x00;
+static volatile uint32 *gpioaddr_input = (uint32 *)0xb8000060;
+static volatile uint32 *gpioaddr_output = (uint32 *)0xb8000064;
+static volatile uint32 *gpioaddr_enable = (uint32 *)0xb8000068;
+static volatile uint32 *gpioaddr_control = (uint32 *)0xb800006c;
+
+static inline void lcd_spi_cs_low(void)
+{
+  port_state &= ~(SD_CS);
+  *gpioaddr_output = port_state;
+}
+
+static inline void lcd_spi_cs_high(void)
+{
+  port_state |= SD_CS;
+  *gpioaddr_output = port_state;
+}
+
+static inline void lcd_data_mode(void)
+{
+  port_state |= SD_DO;
+  *gpioaddr_output = port_state;
+}
+
+static inline void lcd_command_mode(void)
+{
+  port_state &= ~(SD_DO);
+  *gpioaddr_output = port_state;
+}
+
+static unsigned char lcd_spi_io(unsigned char data_out)
+{
+  int i;
+  unsigned char result = 0, tmp_data = 0;

+  for(i=0; i<8; i++) {
+     if(data_out & (0x01 << (7-i)))
+        port_state |= SD_DI;
+     else
+        port_state &= ~SD_DI;
+    
+     *gpioaddr_output = port_state;
+     port_state |= SD_CLK;
+     *gpioaddr_output = port_state;
+    
+     tmp_data = *gpioaddr_input;
+    
+     port_state &= ~SD_CLK;
+     *gpioaddr_output = port_state;
+    
+     result <<= 1;
+    
+     if(tmp_data & SD_DO)
+        result |= 1;
+  }

+  return(result);
+}
+
+#if 0
+static void lcd_out(int x, int y, const char c)
+{
+   lcd_command_mode();
+
+   lcd_spi_io(x | 0x80);
+   lcd_spi_io(y | 0x40);
+
+   lcd_data_mode();
+
+   lcd_spi_io(c);
+}
+#endif
+
+static void lcd_clear(void)
+{
+   int p, q;
+   port_state &= ~(SD_DI);
+   *gpioaddr_output = port_state;   
+
+   lcd_data_mode();
+
+   lcd_spi_cs_low();
+
+   for(p=0; p<6; p++) {
+      for(q=0; q<84; q++) {
+         lcd_spi_io(0);
+      }
+   }
+}
+
+
+/* initialise the LCD */
+static void
+init_lcd(void)
+{
+   *gpioaddr_enable |= SD_DI | SD_CLK | SD_CS | SD_DO;
+
+   port_state = *gpioaddr_output;
+   port_state &= ~(SD_CLK | SD_DI | SD_CS);
+   *gpioaddr_output = port_state;
+
+   lcd_spi_cs_low();
+   lcd_command_mode();
+
+   lcd_spi_io(0x21);
+   lcd_spi_io(0xc5);
+   lcd_spi_io(0x06);
+   lcd_spi_io(0x13);
+   lcd_spi_io(0x20);
+   lcd_spi_io(0x0c);
+
+   lcd_clear();
+
+   lcd_spi_cs_high();
+}
+
+static void lcd_detect(void)
+{
+
+}
+
+static void lcd_update_display(struct display *p, int sx, int sy, int mx, int my)
+{
+   int x, y, i, bit;
+
+   *gpioaddr_enable |= SD_DI | SD_CLK | SD_CS | SD_DO;
+   port_state = *gpioaddr_output;
+
+   lcd_spi_cs_low();
+
+   unsigned char *scr = lcd_scr;
+
+   lcd_command_mode();
+
+   lcd_spi_io(0x80);
+   lcd_spi_io(0x40);
+
+   lcd_data_mode();
+
+   // For now we just do braindead updating of the entire screen
+   for(y = 0; y<LCD_HEIGHT/8; y++) {
+      for(x = 0; x < (LCD_WIDTH+4)/8; x++) {
+         for(bit = (x == LCD_WIDTH/8) ? 0x8 : 0x80;
+             bit != 0;
+             bit >>= 1) {
+            for(i=7; i>=0; i--) {
+               if(scr[x+(LCD_WIDTH+4)*i/8] & bit)
+                  port_state |= SD_DI;
+               else
+                  port_state &= ~SD_DI;
+               
+               *gpioaddr_output = port_state;
+               
+               *gpioaddr_output = port_state | SD_CLK;
+               *gpioaddr_output = port_state;
+            }
+         }
+      }
+      scr+=(LCD_WIDTH+4);
+   }
+
+   lcd_spi_cs_high();
+}
+
+struct lcdfb_info {
+   struct fb_info_gen gen;
+};
+
+
+struct lcdfb_par {
+   /*
+    *  The hardware specific data in this structure uniquely defines a video
+    *  mode.
+    *
+    *  If your hardware supports only one video mode, you can leave it empty.
+    */
+};
+
+
+void lcd_fb_setup(struct display *p)
+{
+   fbcon_mfb.setup(p);
+}
+
+void lcd_fb_bmove(struct display *p, int sy, int sx, int dy, int dx,
+           int height, int width)
+{
+   fbcon_mfb.bmove(p, sy, sx, dy, dx, height, width);
+   lcd_update_display(p, 0, 0, LCD_WIDTH/8, LCD_HEIGHT/fontheight(p));
+}
+
+void lcd_fb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+           int height, int width)
+{
+   fbcon_mfb.clear(conp, p, sy, sx, height, width);
+   lcd_update_display(p, sx, sy, sx+width, sy+height);
+}
+
+void lcd_fb_putc(struct vc_data *conp, struct display *p, int c, int yy,
+          int xx)
+{
+   fbcon_mfb.putc(conp, p, c, yy, xx);
+   lcd_update_display(p, xx, yy, xx+1, yy+1);
+}
+
+void lcd_fb_putcs(struct vc_data *conp, struct display *p,
+           const unsigned short *s, int count, int yy, int xx)
+{
+   fbcon_mfb.putcs(conp, p, s, count, yy, xx);
+   lcd_update_display(p, xx, yy, xx+count, yy+1);
+}
+
+void lcd_fb_revc(struct display *p, int xx, int yy)
+{
+   fbcon_mfb.revc(p, xx, yy);
+   lcd_update_display(p, xx, yy, xx+1, yy+1);
+}
+
+void lcd_fb_clear_margins(struct vc_data *conp, struct display *p,
+           int bottom_only)
+{
+   fbcon_mfb.clear_margins(conp, p, bottom_only);
+   lcd_update_display(p, 0, 0, LCD_WIDTH, LCD_HEIGHT);
+}
+
+/*
+ *  `switch' for the low level operations
+ */
+
+struct display_switch fbcon_lcd = {
+   setup:      lcd_fb_setup,
+   bmove:      lcd_fb_bmove,
+   clear:      lcd_fb_clear,
+   putc:      lcd_fb_putc,
+   putcs:      lcd_fb_putcs,
+   revc:      lcd_fb_revc,
+   clear_margins:  lcd_fb_clear_margins,
+   fontwidthmask:   FONTWIDTH(8)
+};
+
+static struct lcdfb_info fb_info;
+static struct lcdfb_par current_par;
+static int current_par_valid = 0;
+static struct display disp;
+
+int lcdfb_init(void);
+int lcdfb_setup(char*);
+
+static int lcd_encode_fix(struct fb_fix_screeninfo *fix, struct lcdfb_par *par,
+           const struct fb_info *info)
+{
+   /*
+    *  This function should fill in the 'fix' structure based on the values
+    *  in the `par' structure.
+    */
+
+
+   memset(fix, 0x0, sizeof(*fix));
+
+   strcpy(fix->id, "lcd");
+   /* required for mmap() */
+   fix->smem_start = lcd_scr;
+   fix->smem_len = LCD_HEIGHT * (LCD_WIDTH+4)/8;
+
+   fix->type= FB_TYPE_PACKED_PIXELS;
+
+   fix->visual = FB_VISUAL_MONO10;   /* fixed visual */
+   fix->line_length = (LCD_WIDTH+4) / 8;
+
+   fix->xpanstep = 0;   /* no hardware panning */
+   fix->ypanstep = 0;   /* no hardware panning */
+   fix->ywrapstep = 0;   /* */
+
+   fix->accel = FB_ACCEL_NONE;
+
+   return 0;
+}
+
+static int lcd_decode_var(struct fb_var_screeninfo *var, struct lcdfb_par *par,
+           const struct fb_info *info)
+{
+   /*
+    *  Get the video params out of 'var'. If a value doesn't fit, round it up,
+    *  if it's too big, return -EINVAL.
+    *
+    *  Suggestion: Round up in the following order: bits_per_pixel, xres,
+    *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+    *  bitfields, horizontal timing, vertical timing.
+    */
+
+
+   if ( var->xres > LCD_WIDTH ||
+      var->yres > LCD_HEIGHT ||
+      var->xres_virtual != var->xres ||
+      var->yres_virtual != var->yres ||
+      var->xoffset != 0 ||
+      var->yoffset != 0 ) {
+      return -EINVAL;
+   }
+
+   if ( var->bits_per_pixel != 1 ) {
+      return -EINVAL;
+   }
+
+
+   return 0;
+}
+
+static int lcd_encode_var(struct fb_var_screeninfo *var, struct lcdfb_par *par,
+           const struct fb_info *info)
+{
+
+   /*
+    *  Fill the 'var' structure based on the values in 'par' and maybe other
+    *  values read out of the hardware.
+    */
+
+   var->xres = LCD_WIDTH;
+   var->yres = LCD_HEIGHT;
+   var->xres_virtual = var->xres;
+   var->yres_virtual = var->yres;
+   var->xoffset = 0;
+   var->yoffset = 0;
+
+   var->bits_per_pixel = 1;
+   var->grayscale = 1;
+
+   return 0;
+}
+
+static void lcd_get_par(struct lcdfb_par *par, const struct fb_info *info)
+{
+   /*
+    *  Fill the hardware's 'par' structure.
+    */
+
+   if ( current_par_valid ) {
+      *par = current_par;
+   }
+   else {
+      /* ... */
+   }
+}
+
+static void lcd_set_par(struct lcdfb_par *par, const struct fb_info *info)
+{
+   /*
+    *  Set the hardware according to 'par'.
+    */
+
+   current_par = *par;
+   current_par_valid = 1;
+
+   /* ... */
+}
+
+static int lcd_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+          unsigned *blue, unsigned *transp,
+          const struct fb_info *info)
+{
+   /*
+    *  Read a single color register and split it into colors/transparent.
+    *  The return values must have a 16 bit magnitude.
+    *  Return != 0 for invalid regno.
+    */
+
+   /* ... */
+   return 0;
+}
+
+static int lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
+          unsigned blue, unsigned transp,
+          const struct fb_info *info)
+{
+   /*
+    *  Set a single color register. The values supplied have a 16 bit
+    *  magnitude.
+    *  Return != 0 for invalid regno.
+    */
+
+   /* ... */
+   return 0;
+}
+
+static int lcd_pan_display(struct fb_var_screeninfo *var,
+            struct lcdfb_par *par, const struct fb_info *info)
+{
+   /*
+    *  Pan (or wrap, depending on the `vmode' field) the display using the
+    *  `xoffset' and `yoffset' fields of the `var' structure.
+    *  If the values don't fit, return -EINVAL.
+    */
+
+   /* ... */
+   return -EINVAL;
+}
+
+static int lcd_blank(int blank_mode, const struct fb_info *info)
+{
+
+   switch (blank_mode) {
+   case VESA_NO_BLANKING:
+      break;
+
+   case VESA_VSYNC_SUSPEND:
+   case VESA_HSYNC_SUSPEND:
+      break;
+
+   case VESA_POWERDOWN:
+      break;
+
+   default:
+      /* printk(KERN_ERR "unknown blank value %d\n", blank_mode); */
+      return -EINVAL;
+   }
+
+   return 0;
+}
+
+static void lcd_set_disp(const void *par, struct display *disp,
+          struct fb_info_gen *info)
+{
+
+   /*
+    *  Fill in a pointer with the virtual address of the mapped frame buffer.
+    *  Fill in a pointer to appropriate low level text console operations (and
+    *  optionally a pointer to help data) for the video mode `par' of your
+    *  video hardware. These can be generic software routines, or hardware
+    *  accelerated routines specifically tailored for your hardware.
+    *  If you don't have any appropriate operations, you must fill in a
+    *  pointer to dummy operations, and there will be no text output.
+    */
+
+   disp->screen_base = lcd_scr;
+   disp->dispsw = &fbcon_lcd;
+}
+
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+struct fbgen_hwswitch lcd_switch = {
+   detect:      lcd_detect,
+   encode_fix:   lcd_encode_fix,
+   decode_var:   lcd_decode_var,
+   encode_var:   lcd_encode_var,
+   get_par:   lcd_get_par,
+   set_par:   lcd_set_par,
+   getcolreg:   lcd_getcolreg,
+   setcolreg:   lcd_setcolreg,
+   pan_display:   lcd_pan_display,
+   blank:      lcd_blank,
+   set_disp:   lcd_set_disp,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/*
+ *  Frame buffer operations
+ */
+
+static int lcd_fp_open(const struct fb_info *info, int user)
+{
+
+   return 0;
+}
+
+static int lcd_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+   u_long arg, int con, struct fb_info *info)
+
+{
+   return -EINVAL;
+}
+
+
+/*
+ *  In most cases the `generic' routines (fbgen_*) should be satisfactory.
+ *  However, you're free to fill in your own replacements.
+ */
+
+static struct fb_ops lcdfb_ops = {
+   owner:      THIS_MODULE,
+   fb_open:   lcd_fp_open,
+   fb_get_fix:   fbgen_get_fix,
+   fb_get_var:   fbgen_get_var,
+   fb_set_var:   fbgen_set_var,
+   fb_get_cmap:   fbgen_get_cmap,
+   fb_set_cmap:   fbgen_set_cmap,
+   fb_pan_display:   fbgen_pan_display,
+   fb_ioctl:   lcd_fb_ioctl,
+};
+
+
+/* ------------ Hardware Independent Functions ------------ */
+
+
+/*
+ *  Initialization
+ */
+
+int read_proc(char *buf, char **start, off_t offset, int count,
+           int *eof, void *data)
+{
+   int length = sprintf(buf, "No debug at this point\n");
+
+   /* housekeeping */
+   if (length <= offset + count)
+      *eof = 1;
+   *start = buf + offset;
+   length -= offset;
+   if (length > count)
+      length = count;
+   if (length < 0)
+      length = 0;
+
+   return length;
+}
+
+
+int __init lcdfb_init(void)
+{
+   lcd_scr = kmalloc(LCD_HEIGHT * (LCD_WIDTH+4)/8, GFP_KERNEL);
+   if(lcd_scr == NULL)
+      return -EINVAL;
+
+   memset(lcd_scr, 0, LCD_HEIGHT * (LCD_WIDTH+4)/8);
+
+        if (!create_proc_read_entry("lcdfb", 0, 0, read_proc, NULL)) {
+      // Too bad
+   }
+
+   fb_info.gen.fbhw = &lcd_switch;
+
+   fb_info.gen.fbhw->detect();
+
+   strcpy(fb_info.gen.info.modename, "lcd");
+
+   fb_info.gen.info.changevar = NULL;
+   fb_info.gen.info.node = -1;
+   fb_info.gen.info.fbops = &lcdfb_ops;
+   fb_info.gen.info.disp = &disp;
+   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);
+   fbgen_install_cmap(0, &fb_info.gen);
+
+   if ( register_framebuffer(&fb_info.gen.info) < 0 ) {
+      kfree(lcd_scr);
+      return -EINVAL;
+   }
+
+   init_lcd();
+
+   printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
+
+   /* uncomment this if your driver cannot be unloaded */
+   /* MOD_INC_USE_COUNT; */
+   return 0;
+}
+
+
+/*
+ *  Cleanup
+ */
+
+void lcdfb_cleanup(struct fb_info *info)
+{
+   /*
+    *  If your driver supports multiple boards, you should unregister and
+    *  clean up all instances.
+    */
+
+   unregister_framebuffer(info);
+   kfree(lcd_scr);
+
+   /* ... */
+}
+
+
+/*
+ *  Setup
+ */
+
+int __init lcdfb_setup(char *options)
+{
+   /* Parse user speficied options (`video=lcdfb:') */
+   return 0;
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+int init_module(void)
+{
+   return lcdfb_init();
+}
+
+void cleanup_module(void)
+{
+   
+}
+
+#endif /* MODULE */
diff -urN -X dontdiff linux-vanilla/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- linux-vanilla/drivers/video/fbmem.c   2003-07-04 10:12:03.000000000 +0200
+++ linux/drivers/video/fbmem.c   2005-03-07 20:50:24.000000000 +0100
@@ -140,6 +140,8 @@
 extern int pvr2fb_setup(char*);
 extern int sstfb_init(void);
 extern int sstfb_setup(char*);
+extern int lcdfb_init(void);
+extern int lcdfb_setup(char*);
 
 static struct {
    const char *name;
@@ -189,6 +191,9 @@
 #ifdef CONFIG_FB_ATY128
    { "aty128fb", aty128fb_init, aty128fb_setup },
 #endif
+#ifdef CONFIG_FB_LCD
+   { "lcd", lcdfb_init, lcdfb_setup },
+#endif
 #ifdef CONFIG_FB_NEOMAGIC
    { "neo", neofb_init, neofb_setup },
 #endif


Kann leider keiner Treiber erstellen mir fehlt Linux und das DD-wrt pack.

Habe die sache mal nach plan zusammen gelötet, nur wenn ich alles anschließe habe ich keine MMC mehr, Kann sein da ich den Treiber nicht mitlade.

Topcam
gerd
DD-WRT Novice


Joined: 10 Jun 2006
Posts: 23

PostPosted: Thu Dec 21, 2006 13:12    Post subject: Reply with quote
hallo !

Kann es sein das LCD und MMC die selben GPIO's nutzen ?

Ciao Gerd
BrainSlayer
Site Admin


Joined: 06 Jun 2006
Posts: 7492
Location: Dresden, Germany

PostPosted: Thu Dec 21, 2006 23:59    Post subject: Reply with quote
klar. so viele freie gpio's hat der wrt ja nicht. und was ich da sehe sieht dannach aus als ob die mmc gpio's genutzt werden
_________________
"So you tried to use the computer and it started smoking? Sounds like a Mac to me.." - Louis Rossmann https://www.youtube.com/watch?v=eL_5YDRWqGE&t=60s
vSaAmTp
DD-WRT User


Joined: 04 Nov 2006
Posts: 91

PostPosted: Sat Dec 23, 2006 21:25    Post subject: Reply with quote
http://www.dd-wrt.com/phpBB2/viewtopic.php?p=48862#48862

dort hab ich wegen dem display mod schon gepostet. ne anleitung ist als link auch dabei
gabontz
DD-WRT Novice


Joined: 24 Jun 2012
Posts: 5

PostPosted: Sun Jun 24, 2012 17:07    Post subject: help Reply with quote
Hi, does anyone have the schematics from this page?
http://nanl.de/blog/howtos/lcd-mod-fur-linksys-wrt54gs/
The page is not working anymore and i need them.

Thanks in advance
gabontz
DD-WRT Novice


Joined: 24 Jun 2012
Posts: 5

PostPosted: Sun Jun 24, 2012 19:26    Post subject: Reply with quote
Thanks !!!!
Now i just need to adapt it for wrt54gl, and i think i must give up to sd mod.
Display posts from previous:    Page 1 of 1
Post new topic   Reply to topic    DD-WRT Forum Index -> Broadcom SoC basierende Hardware All times are GMT

Navigation

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum