Re: [PATCH 2.6.18 real-V5] drivers: add lcd display support
- From: Andrew Morton <akpm@xxxxxxxx>
- Date: Tue, 26 Sep 2006 12:08:21 -0700
On Fri, 22 Sep 2006 22:03:46 +0200
Miguel Ojeda Sandonis <maxextreme@xxxxxxxxx> wrote:
miguelojeda-2.6.18-add-lcd-display-support.patch
...
diff -uprN -X dontdiff linux-2.6.18-vanilla/include/linux/device.h linux-2.6.18/include/linux/device.h
--- linux-2.6.18-vanilla/include/linux/device.h 2006-09-20 14:52:00.000000000 +0200
+++ linux-2.6.18/include/linux/device.h 2006-09-20 14:55:56.000000000 +0200
@@ -271,7 +271,7 @@ struct class_interface {
extern int class_interface_register(struct class_interface *);
extern void class_interface_unregister(struct class_interface *);
-extern struct class *class_create(struct module *owner, char *name);
+extern struct class *class_create(struct module *owner, const char *name);
Please prepare a separate patch for this, send to Greg.
--- linux-2.6.18-vanilla/drivers/lcddisplay/cfag12864b.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.18/drivers/lcddisplay/cfag12864b.c 2006-09-22 21:46:52.000000000 +0200
@@ -0,0 +1,529 @@
+/*
+ * Filename: cfag12864b.c
+ * Version: 0.1.0
+ * Description: cfag12864b LCD Display Driver
+ * License: GPLv2
+ * Depends: lcddisplay ks0108
+ *
+ * Author: Miguel Ojeda Sandonis <maxextreme@xxxxxxxxx>
+ * Date: 2006-09-21
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/lcddisplay.h>
+#include <linux/ks0108.h>
+#include <linux/cfag12864b.h>
+#include <asm/uaccess.h>
+
+#define NAME "cfag12864b"
+#define PRINTK_PREFIX KERN_INFO NAME ": "
In numerous places the driver uses PRINTK_PREFIX for reporting errors. It
should use KERN_ERR. I suggest that PRINTK_PREFIX be removed and that you
open-code all the printk facility levels, make sure that the appropriate
level is being used at each site.
+
+
+/*
+ * Device
+ */
+
+static const unsigned int cfag12864b_firstminor;
+static const unsigned int cfag12864b_ndevices = 1;
+static const char * cfag12864b_name = NAME;
The more usual kernel style is to not put a space after the `*':
static const char *cfag12864b_name = NAME;
(this affects the entire patch).
Suggest that cfag12864b_name be removed - just use NAME at the single place
where this variable is used.
+static int cfag12864b_major;
+static int cfag12864b_minor;
+static dev_t cfag12864b_device;
+struct cdev cfag12864b_chardevice;
+
+
+
+
One blank line is sufficient (there are many instances of this)
+/*
+ * cfag12864b Commands
+ */
+
+static const unsigned int cfag12864b_bits = 8;
+static const unsigned int cfag12864b_width = CFAG12864B_WIDTH;
+static const unsigned int cfag12864b_height = CFAG12864B_HEIGHT;
+static const unsigned int cfag12864b_matrixsize = CFAG12864B_MATRIXSIZE;
+static const unsigned int cfag12864b_controllers = CFAG12864B_CONTROLLERS;
+static const unsigned int cfag12864b_pages = CFAG12864B_PAGES;
+static const unsigned int cfag12864b_addresses = CFAG12864B_ADDRESSES;
+static const unsigned int cfag12864b_size = CFAG12864B_SIZE;
+static unsigned char cfag12864b_state;
+
+static void cfag12864b_set(void)
+{
+ ks0108_writecontrol(cfag12864b_state);
+}
+
+static void cfag12864b_setbit(unsigned char state, unsigned char bit)
+{
+ if (state)
+ set_bit(bit, (void*)&cfag12864b_state);
+ else
+ clear_bit(bit, (void*)&cfag12864b_state);
+ cfag12864b_set();
+}
bitops are defined on an unsigned long only. This trick is as ugly as sin
and is buggy on big-endian CPUs. Suggest that cfag12864b_state be
converted to unsigned long.
+{
+ cfag12864b_startline(0);
+}
+
+
+
blank lines
+/*
+ * Auxiliary
+ */
+
+static void normalizeoffset(unsigned int * offset)
coding style.
+{
+ if (*offset >= cfag12864b_pages*cfag12864b_addresses)
+ *offset -= cfag12864b_pages*cfag12864b_addresses;
+}
Ths usual kernel style is to put a single space around arithmetic operators
and around comparison operators. This affects the entire patch, please.
+void cfag12864b_clear(void)
+{
+ unsigned char page,address;
+
+ cfag12864b_setcontrollers(1, 1);
+ for (page=0; page<cfag12864b_pages; ++page) {
For example,
for (page = 0; page < cfag12864b_pages; page++) {
would be more kernelish.
The use of the identifier `page' here is unfortunate. We usually expect
such a thing to have type `struct page *'. I understand that "Each
controller is divided into 8 pages", but it'd be nice if some different
nomenclature could be used here. If nothing else comes to mind, we can
live with it as-is.
+void cfag12864b_write(
+ unsigned short offset,
+ const unsigned char * buffer,
+ unsigned short count)
+{
It is more usual to do
void cfag12864b_write(unsigned short offset, const unsigned char *buffer,
unsigned short count)
{
+ for (controller=0; controller < cfag12864b_controllers; ++controller)
+ for (page=0; page < cfag12864b_pages; ++page)
+ for (address=0; address < cfag12864b_addresses; ++address) {
+ dest[(controller*cfag12864b_pages+page)*cfag12864b_addresses+address]=0;
+ for (bit=0; bit < cfag12864b_bits; ++bit)
+ if (src[controller*cfag12864b_addresses+address+(page*cfag12864b_bits+bit)*cfag12864b_width])
+ set_bit(bit, (void*)(dest+(controller*cfag12864b_pages+page)*cfag12864b_addresses+address));
+ }
That's rather ugly-looking.
It's also probably-incorrect on big-endian CPUs. Perhaps you should not
use bitops at all for this driver, use open-coded | and &/~ instead?
The driver doesn't have any locking. Is it racy on SMP and/or
CONFIG_PREEMPT?
+static int cfag12864b_fopioctlformat(void __user * arg)
+{
+ int result;
+ int ret = -ENOTTY;
+
+ unsigned char * tmpbuffer;
+
+ tmpbuffer = kmalloc(
+ sizeof(unsigned char)*cfag12864b_matrixsize,GFP_KERNEL);
+ if (tmpbuffer == NULL) {
+ printk(PRINTK_PREFIX "FOP ioctl: ERROR: "
+ "can't alloc memory %i bytes\n",
+ sizeof(unsigned char)*cfag12864b_matrixsize);
+ goto none;
+ }
+
+ result = copy_from_user(
+ tmpbuffer,
+ arg,
+ sizeof(unsigned char)*cfag12864b_matrixsize);
result = copy_from_user(tmpbuffer, arg, cfag12864b_matrixsize);
+ if (result != 0) {
+ printk(PRINTK_PREFIX "FOP ioctl: ERROR: "
+ "can't copy memory from user\n");
+ goto bufferalloced;
+ }
+
+ cfag12864b_format(tmpbuffer);
+
+ ret = 0;
+
+bufferalloced:
+ kfree(tmpbuffer);
+
+none:
+ return ret;
+}
+
...
+
+static struct file_operations cfag12864b_fops =
`static const struct'
+
+ class_device_create(
+ lcddisplay_class,NULL,
+ cfag12864b_device,
+ NULL,"cfag12864b%d", cfag12864b_minor);
class_device_create() can fail.
+void ks0108_writecontrol(unsigned char byte)
+{
+ const unsigned int ecycledelay = 2;
+ udelay(ecycledelay);
+ parport_write_control(ks0108_parport, byte^(bit(3)|bit(1)|bit(0)));
+}
udelay(2) would be clearer.
+void ks0108_displaystate(unsigned char state)
+{
+ unsigned char cmd = bit(1) | bit(2) | bit(3) | bit(4) | bit(5);
+ if (state)
+ set_bit(0, (void*)&cmd);
argh. Even if this driver will only ever run on big-endian hardware,
please don't do this.
+void ks0108_startline(unsigned char startline)
+{
+ const unsigned char maxstartline = 63;
+ unsigned char cmd = bit(6) | bit(7);
+ if (startline > maxstartline)
+ startline = maxstartline;
There are a lot of open-coded min() and max() operations in this driver.
Suggest it be changed to use min() and max().
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
- Follow-Ups:
- Re: [PATCH 2.6.18 real-V5] drivers: add lcd display support
- From: Miguel Ojeda
- Re: [PATCH 2.6.18 real-V5] drivers: add lcd display support
- References:
- [PATCH 2.6.18 real-V5] drivers: add lcd display support
- From: Miguel Ojeda Sandonis
- [PATCH 2.6.18 real-V5] drivers: add lcd display support
- Prev by Date: Re: Bad page state with x86_64
- Next by Date: Re: [PATCH] Linux Kernel Markers 0.13 for 2.6.17
- Previous by thread: [PATCH 2.6.18 real-V5] drivers: add lcd display support
- Next by thread: Re: [PATCH 2.6.18 real-V5] drivers: add lcd display support
- Index(es):