linux/arch/arm/mach-pxa/am300epd.c
<<
>>
Prefs
   1/*
   2 * am300epd.c -- Platform device for AM300 EPD kit
   3 *
   4 * Copyright (C) 2008, Jaya Kumar
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License. See the file COPYING in the main directory of this archive for
   8 * more details.
   9 *
  10 * This work was made possible by help and equipment support from E-Ink
  11 * Corporation. http://support.eink.com/community
  12 *
  13 * This driver is written to be used with the Broadsheet display controller.
  14 * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600
  15 * Vizplex EPD on a Gumstix board using the Broadsheet interface board.
  16 *
  17 */
  18
  19#include <linux/module.h>
  20#include <linux/kernel.h>
  21#include <linux/errno.h>
  22#include <linux/string.h>
  23#include <linux/delay.h>
  24#include <linux/interrupt.h>
  25#include <linux/fb.h>
  26#include <linux/init.h>
  27#include <linux/platform_device.h>
  28#include <linux/irq.h>
  29#include <linux/gpio.h>
  30
  31#include <mach/gumstix.h>
  32#include <mach/mfp-pxa25x.h>
  33#include <linux/platform_data/video-pxafb.h>
  34
  35#include "generic.h"
  36
  37#include <video/broadsheetfb.h>
  38
  39static unsigned int panel_type = 6;
  40static struct platform_device *am300_device;
  41static struct broadsheet_board am300_board;
  42
  43static unsigned long am300_pin_config[] __initdata = {
  44        GPIO16_GPIO,
  45        GPIO17_GPIO,
  46        GPIO32_GPIO,
  47        GPIO48_GPIO,
  48        GPIO49_GPIO,
  49        GPIO51_GPIO,
  50        GPIO74_GPIO,
  51        GPIO75_GPIO,
  52        GPIO76_GPIO,
  53        GPIO77_GPIO,
  54
  55        /* this is the 16-bit hdb bus 58-73 */
  56        GPIO58_GPIO,
  57        GPIO59_GPIO,
  58        GPIO60_GPIO,
  59        GPIO61_GPIO,
  60
  61        GPIO62_GPIO,
  62        GPIO63_GPIO,
  63        GPIO64_GPIO,
  64        GPIO65_GPIO,
  65
  66        GPIO66_GPIO,
  67        GPIO67_GPIO,
  68        GPIO68_GPIO,
  69        GPIO69_GPIO,
  70
  71        GPIO70_GPIO,
  72        GPIO71_GPIO,
  73        GPIO72_GPIO,
  74        GPIO73_GPIO,
  75};
  76
  77/* register offsets for gpio control */
  78#define PWR_GPIO_PIN    16
  79#define CFG_GPIO_PIN    17
  80#define RDY_GPIO_PIN    32
  81#define DC_GPIO_PIN     48
  82#define RST_GPIO_PIN    49
  83#define LED_GPIO_PIN    51
  84#define RD_GPIO_PIN     74
  85#define WR_GPIO_PIN     75
  86#define CS_GPIO_PIN     76
  87#define IRQ_GPIO_PIN    77
  88
  89/* hdb bus */
  90#define DB0_GPIO_PIN    58
  91#define DB15_GPIO_PIN   73
  92
  93static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
  94                        RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
  95                        IRQ_GPIO_PIN, LED_GPIO_PIN };
  96static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
  97                                "CS", "IRQ", "LED" };
  98
  99static int am300_wait_event(struct broadsheetfb_par *par)
 100{
 101        /* todo: improve err recovery */
 102        wait_event(par->waitq, gpio_get_value(RDY_GPIO_PIN));
 103        return 0;
 104}
 105
 106static int am300_init_gpio_regs(struct broadsheetfb_par *par)
 107{
 108        int i;
 109        int err;
 110        char dbname[8];
 111
 112        for (i = 0; i < ARRAY_SIZE(gpios); i++) {
 113                err = gpio_request(gpios[i], gpio_names[i]);
 114                if (err) {
 115                        dev_err(&am300_device->dev, "failed requesting "
 116                                "gpio %s, err=%d\n", gpio_names[i], err);
 117                        goto err_req_gpio;
 118                }
 119        }
 120
 121        /* we also need to take care of the hdb bus */
 122        for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
 123                sprintf(dbname, "DB%d", i);
 124                err = gpio_request(i, dbname);
 125                if (err) {
 126                        dev_err(&am300_device->dev, "failed requesting "
 127                                "gpio %d, err=%d\n", i, err);
 128                        goto err_req_gpio2;
 129                }
 130        }
 131
 132        /* setup the outputs and init values */
 133        gpio_direction_output(PWR_GPIO_PIN, 0);
 134        gpio_direction_output(CFG_GPIO_PIN, 1);
 135        gpio_direction_output(DC_GPIO_PIN, 0);
 136        gpio_direction_output(RD_GPIO_PIN, 1);
 137        gpio_direction_output(WR_GPIO_PIN, 1);
 138        gpio_direction_output(CS_GPIO_PIN, 1);
 139        gpio_direction_output(RST_GPIO_PIN, 0);
 140
 141        /* setup the inputs */
 142        gpio_direction_input(RDY_GPIO_PIN);
 143        gpio_direction_input(IRQ_GPIO_PIN);
 144
 145        /* start the hdb bus as an input */
 146        for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
 147                gpio_direction_output(i, 0);
 148
 149        /* go into command mode */
 150        gpio_set_value(CFG_GPIO_PIN, 1);
 151        gpio_set_value(RST_GPIO_PIN, 0);
 152        msleep(10);
 153        gpio_set_value(RST_GPIO_PIN, 1);
 154        msleep(10);
 155        am300_wait_event(par);
 156
 157        return 0;
 158
 159err_req_gpio2:
 160        while (--i >= DB0_GPIO_PIN)
 161                gpio_free(i);
 162        i = ARRAY_SIZE(gpios);
 163err_req_gpio:
 164        while (--i >= 0)
 165                gpio_free(gpios[i]);
 166
 167        return err;
 168}
 169
 170static int am300_init_board(struct broadsheetfb_par *par)
 171{
 172        return am300_init_gpio_regs(par);
 173}
 174
 175static void am300_cleanup(struct broadsheetfb_par *par)
 176{
 177        int i;
 178
 179        free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par);
 180
 181        for (i = 0; i < ARRAY_SIZE(gpios); i++)
 182                gpio_free(gpios[i]);
 183
 184        for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
 185                gpio_free(i);
 186
 187}
 188
 189static u16 am300_get_hdb(struct broadsheetfb_par *par)
 190{
 191        u16 res = 0;
 192        int i;
 193
 194        for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
 195                res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;
 196
 197        return res;
 198}
 199
 200static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
 201{
 202        int i;
 203
 204        for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
 205                gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
 206}
 207
 208
 209static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
 210                                u8 state)
 211{
 212        switch (bit) {
 213        case BS_CS:
 214                gpio_set_value(CS_GPIO_PIN, state);
 215                break;
 216        case BS_DC:
 217                gpio_set_value(DC_GPIO_PIN, state);
 218                break;
 219        case BS_WR:
 220                gpio_set_value(WR_GPIO_PIN, state);
 221                break;
 222        }
 223}
 224
 225static int am300_get_panel_type(void)
 226{
 227        return panel_type;
 228}
 229
 230static irqreturn_t am300_handle_irq(int irq, void *dev_id)
 231{
 232        struct broadsheetfb_par *par = dev_id;
 233
 234        wake_up(&par->waitq);
 235        return IRQ_HANDLED;
 236}
 237
 238static int am300_setup_irq(struct fb_info *info)
 239{
 240        int ret;
 241        struct broadsheetfb_par *par = info->par;
 242
 243        ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am300_handle_irq,
 244                                IRQF_DISABLED|IRQF_TRIGGER_RISING,
 245                                "AM300", par);
 246        if (ret)
 247                dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
 248
 249        return ret;
 250}
 251
 252static struct broadsheet_board am300_board = {
 253        .owner                  = THIS_MODULE,
 254        .init                   = am300_init_board,
 255        .cleanup                = am300_cleanup,
 256        .set_hdb                = am300_set_hdb,
 257        .get_hdb                = am300_get_hdb,
 258        .set_ctl                = am300_set_ctl,
 259        .wait_for_rdy           = am300_wait_event,
 260        .get_panel_type         = am300_get_panel_type,
 261        .setup_irq              = am300_setup_irq,
 262};
 263
 264int __init am300_init(void)
 265{
 266        int ret;
 267
 268        pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config));
 269
 270        /* request our platform independent driver */
 271        request_module("broadsheetfb");
 272
 273        am300_device = platform_device_alloc("broadsheetfb", -1);
 274        if (!am300_device)
 275                return -ENOMEM;
 276
 277        /* the am300_board that will be seen by broadsheetfb is a copy */
 278        platform_device_add_data(am300_device, &am300_board,
 279                                        sizeof(am300_board));
 280
 281        ret = platform_device_add(am300_device);
 282
 283        if (ret) {
 284                platform_device_put(am300_device);
 285                return ret;
 286        }
 287
 288        return 0;
 289}
 290
 291module_param(panel_type, uint, 0);
 292MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");
 293
 294MODULE_DESCRIPTION("board driver for am300 epd kit");
 295MODULE_AUTHOR("Jaya Kumar");
 296MODULE_LICENSE("GPL");
 297