2006-10-26 15:49:39

by Miguel Ojeda

[permalink] [raw]
Subject: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

Andrew, here it is a small update for the
drivers-add-lcd-support patch at -mm2. Please apply.

Franck Bui-Huu, thanks for pointing out the lack of mmaping support.
---

- Adds mmaping support for the cfag12864bfb.
- Exchange the wiring drawing URL to a local ASCII drawing
at Documentation/auxdisplay/cfag12864b.

Documentation/auxdisplay/cfag12864b | 37 +++++++++++++++++++++-----
drivers/auxdisplay/Kconfig | 7 ----
drivers/auxdisplay/cfag12864b.c | 22 +++++++++------
drivers/auxdisplay/cfag12864bfb.c | 37 +++++++++++++++++++++++---
4 files changed, 80 insertions(+), 23 deletions(-)

miguelojeda-2.6.19-rc1-drivers-add-LCD-support-4-mmaping-and-ascii-drawing.patch
Signed-off-by: Miguel Ojeda Sandonis <[email protected]>
---
diff -uprN -X dontdiff linux-2.6.19-rc1-modified/Documentation/auxdisplay/cfag12864b linux/Documentation/auxdisplay/cfag12864b
--- linux-2.6.19-rc1-modified/Documentation/auxdisplay/cfag12864b 2006-10-26 16:57:38.000000000 +0000
+++ linux/Documentation/auxdisplay/cfag12864b 2006-10-26 16:38:54.000000000 +0000
@@ -4,7 +4,7 @@

License: GPLv2
Author & Maintainer: Miguel Ojeda Sandonis <[email protected]>
-Date: 2006-10-11
+Date: 2006-10-26



@@ -51,12 +51,37 @@ Addresses: 64 each page

The cfag12864b LCD Series don't have official wiring.

-The common wiring is done to the parallel port:
-
-http://www.skippari.net/lcd/sekalaista/crystalfontz_cfag12864B-TMI-V.png
-
-You can get help at Crystalfontz and LCDInfo forums.
+The common wiring is done to the parallel port as shown:

+Parallel Port cfag12864b
+
+ Name Pin# Pin# Name
+
+Strobe ( 1)------------------------------(17) Enable
+Data 0 ( 2)------------------------------( 4) Data 0
+Data 1 ( 3)------------------------------( 5) Data 1
+Data 2 ( 4)------------------------------( 6) Data 2
+Data 3 ( 5)------------------------------( 7) Data 3
+Data 4 ( 6)------------------------------( 8) Data 4
+Data 5 ( 7)------------------------------( 9) Data 5
+Data 6 ( 8)------------------------------(10) Data 6
+Data 7 ( 9)------------------------------(11) Data 7
+ (10) [+5v]---( 1) Vdd
+ (11) [GND]---( 2) Ground
+ (12) [+5v]---(14) Reset
+ (13) [GND]---(15) Read / Write
+ Line (14)------------------------------(13) Controller Select 1
+ (15)
+ Init (16)------------------------------(12) Controller Select 2
+Select (17)------------------------------(16) Data / Instruction
+Ground (18)---[GND] [+5v]---(19) LED +
+Ground (19)---[GND]
+Ground (20)---[GND] E A Values:
+Ground (21)---[GND] [GND]---[P1]---(18) Vee ? R = Resistor = 22 ohm
+Ground (22)---[GND] | ? P1 = Preset = 10 Kohm
+Ground (23)---[GND] ---- S ------( 3) V0 ? P2 = Preset = 1 Kohm
+Ground (24)---[GND] | |
+Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED -


------------------------
diff -uprN -X dontdiff linux-2.6.19-rc1-modified/drivers/auxdisplay/cfag12864b.c linux/drivers/auxdisplay/cfag12864b.c
--- linux-2.6.19-rc1-modified/drivers/auxdisplay/cfag12864b.c 2006-10-26 16:57:38.000000000 +0000
+++ linux/drivers/auxdisplay/cfag12864b.c 2006-10-26 16:48:36.000000000 +0000
@@ -6,7 +6,7 @@
* Depends: ks0108
*
* Author: Copyright (C) Miguel Ojeda Sandonis <[email protected]>
- * Date: 2006-10-13
+ * Date: 2006-10-26
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -182,7 +182,7 @@ static void cfag12864b_nop(void)
* cfag12864b Internal Commands
*/

-unsigned char *cfag12864b_cache;
+static unsigned char *cfag12864b_cache;
unsigned char *cfag12864b_buffer;
EXPORT_SYMBOL_GPL(cfag12864b_buffer);

@@ -264,12 +264,18 @@ static int __init cfag12864b_init(void)
{
int ret = -EINVAL;

- cfag12864b_buffer = vmalloc(sizeof(unsigned char) *
- CFAG12864B_SIZE);
+ if(PAGE_SIZE < CFAG12864B_SIZE) {
+ printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
+ "page size (%i) < cfag12864b size (%i)\n",
+ (unsigned int)PAGE_SIZE, CFAG12864B_SIZE);
+ ret = -ENOMEM;
+ goto none;
+ }
+
+ cfag12864b_buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
if (cfag12864b_buffer == NULL) {
printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
- "can't v-alloc buffer (%i bytes)\n",
- CFAG12864B_SIZE);
+ "can't get a free page\n");
ret = -ENOMEM;
goto none;
}
@@ -302,7 +308,7 @@ cachealloced:
kfree(cfag12864b_cache);

bufferalloced:
- vfree(cfag12864b_buffer);
+ free_page((unsigned long) cfag12864b_buffer);

none:
return ret;
@@ -317,7 +323,7 @@ static void __exit cfag12864b_exit(void)
cfag12864b_off();

kfree(cfag12864b_cache);
- vfree(cfag12864b_buffer);
+ free_page((unsigned long) cfag12864b_buffer);
}

module_init(cfag12864b_init);
diff -uprN -X dontdiff linux-2.6.19-rc1-modified/drivers/auxdisplay/cfag12864bfb.c linux/drivers/auxdisplay/cfag12864bfb.c
--- linux-2.6.19-rc1-modified/drivers/auxdisplay/cfag12864bfb.c 2006-10-26 16:57:38.000000000 +0000
+++ linux/drivers/auxdisplay/cfag12864bfb.c 2006-10-26 16:22:42.000000000 +0000
@@ -6,7 +6,7 @@
* Depends: cfag12864b
*
* Author: Copyright (C) Miguel Ojeda Sandonis <[email protected]>
- * Date: 2006-10-13
+ * Date: 2006-10-26
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,12 +35,13 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/cfag12864b.h>
+#include <asm/semaphore.h>
#include <asm/uaccess.h>

#define CFAG12864BFB_NAME "cfag12864bfb"

static struct fb_fix_screeninfo cfag12864bfb_fix __initdata = {
- .id = "cfag12864b",
+ .id = "cfag12864b",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_MONO10,
.xpanstep = 0,
@@ -66,11 +67,41 @@ static struct fb_var_screeninfo cfag1286
.vmode = FB_VMODE_NONINTERLACED,
};

+DECLARE_MUTEX(cfag12864bfb_sem);
+
+struct page *cfag12864bfb_vma_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ struct page *page;
+ down(&cfag12864bfb_sem);
+
+ page = virt_to_page(cfag12864b_buffer);
+ get_page(page);
+
+ if(type)
+ *type = VM_FAULT_MINOR;
+
+ up(&cfag12864bfb_sem);
+ return page;
+}
+
+static struct vm_operations_struct cfag12864bfb_vm_ops = {
+ .nopage = cfag12864bfb_vma_nopage,
+};
+
+static int cfag12864bfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ vma->vm_ops = &cfag12864bfb_vm_ops;
+ vma->vm_flags |= VM_RESERVED;
+ return 0;
+}
+
static struct fb_ops cfag12864bfb_ops = {
.owner = THIS_MODULE,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
+ .fb_mmap = cfag12864bfb_mmap,
};

static int __init cfag12864bfb_probe(struct platform_device *device)
@@ -81,7 +112,7 @@ static int __init cfag12864bfb_probe(str
if (!info)
goto none;

- info->screen_base = (char __iomem *)cfag12864b_buffer;
+ info->screen_base = (char __iomem *) cfag12864b_buffer;
info->screen_size = CFAG12864B_SIZE;
info->fbops = &cfag12864bfb_ops;
info->fix = cfag12864bfb_fix;
diff -uprN -X dontdiff linux-2.6.19-rc1-modified/drivers/auxdisplay/Kconfig linux/drivers/auxdisplay/Kconfig
--- linux-2.6.19-rc1-modified/drivers/auxdisplay/Kconfig 2006-10-26 17:01:26.000000000 +0000
+++ linux/drivers/auxdisplay/Kconfig 2006-10-26 17:39:57.000000000 +0000
@@ -71,12 +71,7 @@ config CFAG12864B
say Y. You also need the ks0108 LCD Controller driver.

For help about how to wire your LCD to the parallel port,
- check this image:
-
- http://www.skippari.net/lcd/sekalaista/crystalfontz_cfag12864B-TMI-V.png
-
- Also, you can find help in Crystalfontz and LCDStudio forums.
- Check Documentation/lcddisplay/cfag12864b for more information.
+ check Documentation/auxdisplay/cfag12864b

The LCD framebuffer driver can be attached to a console.
It will work fine. However, you can't attach it to the fbdev driver


2006-10-27 05:07:09

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

On Thu, 26 Oct 2006 17:48:58 +0000
Miguel Ojeda Sandonis <[email protected]> wrote:

>
> +DECLARE_MUTEX(cfag12864bfb_sem);

Mutexes are preferred - please only use semaphores if their counting
feature is required.

This lock can have static scope.

> +struct page *cfag12864bfb_vma_nopage(struct vm_area_struct *vma,
> + unsigned long address, int *type)

This function can have static scope.

> +{
> + struct page *page;
> + down(&cfag12864bfb_sem);
> +
> + page = virt_to_page(cfag12864b_buffer);
> + get_page(page);
> +
> + if(type)
> + *type = VM_FAULT_MINOR;
> +
> + up(&cfag12864bfb_sem);
> + return page;
> +}

What's the semaphore actually needed for?

2006-10-27 12:42:42

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

On 10/27/06, Andrew Morton <[email protected]> wrote:
> On Thu, 26 Oct 2006 17:48:58 +0000
> Miguel Ojeda Sandonis <[email protected]> wrote:
>
> >
> > +DECLARE_MUTEX(cfag12864bfb_sem);
>
> Mutexes are preferred - please only use semaphores if their counting
> feature is required.
>
> This lock can have static scope.
>
> > +struct page *cfag12864bfb_vma_nopage(struct vm_area_struct *vma,
> > + unsigned long address, int *type)
>
> This function can have static scope.
>
> > +{
> > + struct page *page;
> > + down(&cfag12864bfb_sem);
> > +
> > + page = virt_to_page(cfag12864b_buffer);
> > + get_page(page);
> > +
> > + if(type)
> > + *type = VM_FAULT_MINOR;
> > +
> > + up(&cfag12864bfb_sem);
> > + return page;
> > +}
>
> What's the semaphore actually needed for?
>

Hum, the code is based on LDD3, I just adapted it removing a few
lines. I thought this code also needed lock protection as the LDD3
example. I'm sending a new patch in a few moments with this 3 things
fixed.

Thanks you,
Miguel Ojeda

2006-10-30 09:34:53

by Franck Bui-Huu

[permalink] [raw]
Subject: Re: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

Andrew,

Andrew Morton wrote:
> On Thu, 26 Oct 2006 17:48:58 +0000
> Miguel Ojeda Sandonis <[email protected]> wrote:
>
[snip]
>
>> +struct page *cfag12864bfb_vma_nopage(struct vm_area_struct *vma,
>> + unsigned long address, int *type)
>
> This function can have static scope.
>
>> +{
>> + struct page *page;
>> + down(&cfag12864bfb_sem);
>> +
>> + page = virt_to_page(cfag12864b_buffer);
>> + get_page(page);
>> +
>> + if(type)
>> + *type = VM_FAULT_MINOR;
>> +
>> + up(&cfag12864bfb_sem);
>> + return page;
>> +}
>

Any idea why LDD3 states:

An interesting limitation of remap_pfn_range is that it gives
access only to reserved pages and physical addresses above the
top of physical memory.

Is that true we can't do:

buf = (char *)__get_free_page(...);
pfn = PFN_DOWN(virt_to_phys(buf));
remap_pfn_range(vma, vma->vm_start, pfn, PAGE_SIZE, vma->vm_page_prot);

Thanks
Franck

2006-10-30 13:53:18

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

On 10/30/06, Franck Bui-Huu <[email protected]> wrote:
> Andrew,
>
> Andrew Morton wrote:
> > On Thu, 26 Oct 2006 17:48:58 +0000
> > Miguel Ojeda Sandonis <[email protected]> wrote:
> >
> [snip]
> >
> >> +struct page *cfag12864bfb_vma_nopage(struct vm_area_struct *vma,
> >> + unsigned long address, int *type)
> >
> > This function can have static scope.
> >
> >> +{
> >> + struct page *page;
> >> + down(&cfag12864bfb_sem);
> >> +
> >> + page = virt_to_page(cfag12864b_buffer);
> >> + get_page(page);
> >> +
> >> + if(type)
> >> + *type = VM_FAULT_MINOR;
> >> +
> >> + up(&cfag12864bfb_sem);
> >> + return page;
> >> +}
> >
>
> Any idea why LDD3 states:
>
> An interesting limitation of remap_pfn_range is that it gives
> access only to reserved pages and physical addresses above the
> top of physical memory.
>
> Is that true we can't do:
>
> buf = (char *)__get_free_page(...);
> pfn = PFN_DOWN(virt_to_phys(buf));
> remap_pfn_range(vma, vma->vm_start, pfn, PAGE_SIZE, vma->vm_page_prot);
>
> Thanks
> Franck
>

Again: Please read LDD3. It explains it well. Read all the "Remapping
RAM" chapter and you will understand what I've done, or just try to
remap RAM yourself with remap_pfn_range. (I really tried it using
different ways and I couldn't map it with remap_pfn_range, it returns
you a place full with zeros, as LDD3 states).

2006-10-30 14:24:51

by Hugh Dickins

[permalink] [raw]
Subject: Re: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

On Mon, 30 Oct 2006, Franck Bui-Huu wrote:
>
> Any idea why LDD3 states:
>
> An interesting limitation of remap_pfn_range is that it gives
> access only to reserved pages and physical addresses above the
> top of physical memory.

It was true until 2.6.15, when VM_PFNMAP removed that restriction to
PageReserved (or struct-page-less) pages.

Hugh

2006-10-31 08:47:25

by Franck Bui-Huu

[permalink] [raw]
Subject: Re: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

Miguel Ojeda wrote:
> Again: Please read LDD3. It explains it well. Read all the "Remapping
> RAM" chapter and you will understand what I've done, or just try to
> remap RAM yourself with remap_pfn_range.

Well, I'm trying to get an explanation here and here is what I get
from you:

MO > LDD3 states it must work like this. (Note: it doesn't explain
why though)
FBH > Weird I read the implementation of remap_pfn_range() and it
doesn't seem to have such restriction, I'm wondering how
things work...
MO > Again it's stated in LDD3, read again.

Do you really think you explain anything with such replies ?

Fortunately, Hugh Dickins gives a hint and it appears that the
restriction doesn't hold anymore.

> (I really tried it using
> different ways and I couldn't map it with remap_pfn_range, it returns
> you a place full with zeros, as LDD3 states).

I'm really wondering how did you test the thing... ;)

bye
Franck

2006-10-31 13:58:55

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH 2.6.19-rc1 update4] drivers: add LCD support

On 10/31/06, Franck Bui-Huu <[email protected]> wrote:
> Miguel Ojeda wrote:
> > Again: Please read LDD3. It explains it well. Read all the "Remapping
> > RAM" chapter and you will understand what I've done, or just try to
> > remap RAM yourself with remap_pfn_range.
>
> Well, I'm trying to get an explanation here and here is what I get
> from you:
>
> MO > LDD3 states it must work like this. (Note: it doesn't explain
> why though)
> FBH > Weird I read the implementation of remap_pfn_range() and it
> doesn't seem to have such restriction, I'm wondering how
> things work...
> MO > Again it's stated in LDD3, read again.
>
> Do you really think you explain anything with such replies ?
>

Do you really think I have to explain anything with my replies? I was
just trying to help you telling where I found the answer.

Anyway, isn't it explained in LDD3? isn't it stated in LDD3? I think
it is (yep, not deeply, but enough: other books cover that points
better and a device driver programmer doesn't have to know about
implementations, right?). Sure, neither the book or I didn't know
about the VM_PFNMAP change, but that doesn't change that I was trying
to encourage you to read such chapter, the same way I found the answer
there.

>
> Fortunately, Hugh Dickins gives a hint and it appears that the
> restriction doesn't hold anymore.
>
> > (I really tried it using
> > different ways and I couldn't map it with remap_pfn_range, it returns
> > you a place full with zeros, as LDD3 states).
>
> I'm really wondering how did you test the thing... ;)
>

And I still say I tried it, many ways, using remap_pfn_range() and
other weird things also. Finally, I thought something was wrong, so I
read LDD3 and I found the explanation about why my code mmap couldn't
mmap RAM. Also, my area was full of zeros, as LDD3 states. So I read a
little further and I did what "Remapping RAM" explains.

Anything else?

Bye,
Miguel Ojeda