linux/arch/mips/lasat/picvue.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Picvue PVC160206 display driver
   4 *
   5 * Brian Murphy <brian@murphy.dk>
   6 *
   7 */
   8#include <linux/kernel.h>
   9#include <linux/delay.h>
  10#include <asm/bootinfo.h>
  11#include <asm/lasat/lasat.h>
  12#include <linux/module.h>
  13#include <linux/errno.h>
  14#include <linux/string.h>
  15
  16#include "picvue.h"
  17
  18#define PVC_BUSY                0x80
  19#define PVC_NLINES              2
  20#define PVC_DISPMEM             80
  21#define PVC_LINELEN             PVC_DISPMEM / PVC_NLINES
  22
  23struct pvc_defs *picvue;
  24
  25static void pvc_reg_write(u32 val)
  26{
  27        *picvue->reg = val;
  28}
  29
  30static u32 pvc_reg_read(void)
  31{
  32        u32 tmp = *picvue->reg;
  33        return tmp;
  34}
  35
  36static void pvc_write_byte(u32 data, u8 byte)
  37{
  38        data |= picvue->e;
  39        pvc_reg_write(data);
  40        data &= ~picvue->data_mask;
  41        data |= byte << picvue->data_shift;
  42        pvc_reg_write(data);
  43        ndelay(220);
  44        pvc_reg_write(data & ~picvue->e);
  45        ndelay(220);
  46}
  47
  48static u8 pvc_read_byte(u32 data)
  49{
  50        u8 byte;
  51
  52        data |= picvue->e;
  53        pvc_reg_write(data);
  54        ndelay(220);
  55        byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift;
  56        data &= ~picvue->e;
  57        pvc_reg_write(data);
  58        ndelay(220);
  59        return byte;
  60}
  61
  62static u8 pvc_read_data(void)
  63{
  64        u32 data = pvc_reg_read();
  65        u8 byte;
  66        data |= picvue->rw;
  67        data &= ~picvue->rs;
  68        pvc_reg_write(data);
  69        ndelay(40);
  70        byte = pvc_read_byte(data);
  71        data |= picvue->rs;
  72        pvc_reg_write(data);
  73        return byte;
  74}
  75
  76#define TIMEOUT 1000
  77static int pvc_wait(void)
  78{
  79        int i = TIMEOUT;
  80        int err = 0;
  81
  82        while ((pvc_read_data() & PVC_BUSY) && i)
  83                i--;
  84        if (i == 0)
  85                err = -ETIME;
  86
  87        return err;
  88}
  89
  90#define MODE_INST 0
  91#define MODE_DATA 1
  92static void pvc_write(u8 byte, int mode)
  93{
  94        u32 data = pvc_reg_read();
  95        data &= ~picvue->rw;
  96        if (mode == MODE_DATA)
  97                data |= picvue->rs;
  98        else
  99                data &= ~picvue->rs;
 100        pvc_reg_write(data);
 101        ndelay(40);
 102        pvc_write_byte(data, byte);
 103        if (mode == MODE_DATA)
 104                data &= ~picvue->rs;
 105        else
 106                data |= picvue->rs;
 107        pvc_reg_write(data);
 108        pvc_wait();
 109}
 110
 111void pvc_write_string(const unsigned char *str, u8 addr, int line)
 112{
 113        int i = 0;
 114
 115        if (line > 0 && (PVC_NLINES > 1))
 116                addr += 0x40 * line;
 117        pvc_write(0x80 | addr, MODE_INST);
 118
 119        while (*str != 0 && i < PVC_LINELEN) {
 120                pvc_write(*str++, MODE_DATA);
 121                i++;
 122        }
 123}
 124
 125void pvc_write_string_centered(const unsigned char *str, int line)
 126{
 127        int len = strlen(str);
 128        u8 addr;
 129
 130        if (len > PVC_VISIBLE_CHARS)
 131                addr = 0;
 132        else
 133                addr = (PVC_VISIBLE_CHARS - strlen(str))/2;
 134
 135        pvc_write_string(str, addr, line);
 136}
 137
 138void pvc_dump_string(const unsigned char *str)
 139{
 140        int len = strlen(str);
 141
 142        pvc_write_string(str, 0, 0);
 143        if (len > PVC_VISIBLE_CHARS)
 144                pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1);
 145}
 146
 147#define BM_SIZE                 8
 148#define MAX_PROGRAMMABLE_CHARS  8
 149int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE])
 150{
 151        int i;
 152        int addr;
 153
 154        if (charnum > MAX_PROGRAMMABLE_CHARS)
 155                return -ENOENT;
 156
 157        addr = charnum * 8;
 158        pvc_write(0x40 | addr, MODE_INST);
 159
 160        for (i = 0; i < BM_SIZE; i++)
 161                pvc_write(bitmap[i], MODE_DATA);
 162        return 0;
 163}
 164
 165#define FUNC_SET_CMD    0x20
 166#define  EIGHT_BYTE     (1 << 4)
 167#define  FOUR_BYTE      0
 168#define  TWO_LINES      (1 << 3)
 169#define  ONE_LINE       0
 170#define  LARGE_FONT     (1 << 2)
 171#define  SMALL_FONT     0
 172
 173static void pvc_funcset(u8 cmd)
 174{
 175        pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)),
 176                  MODE_INST);
 177}
 178
 179#define ENTRYMODE_CMD           0x4
 180#define  AUTO_INC               (1 << 1)
 181#define  AUTO_DEC               0
 182#define  CURSOR_FOLLOWS_DISP    (1 << 0)
 183
 184static void pvc_entrymode(u8 cmd)
 185{
 186        pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)),
 187                  MODE_INST);
 188}
 189
 190#define DISP_CNT_CMD    0x08
 191#define  DISP_OFF       0
 192#define  DISP_ON        (1 << 2)
 193#define  CUR_ON         (1 << 1)
 194#define  CUR_BLINK      (1 << 0)
 195void pvc_dispcnt(u8 cmd)
 196{
 197        pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST);
 198}
 199
 200#define MOVE_CMD        0x10
 201#define  DISPLAY        (1 << 3)
 202#define  CURSOR         0
 203#define  RIGHT          (1 << 2)
 204#define  LEFT           0
 205void pvc_move(u8 cmd)
 206{
 207        pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
 208}
 209
 210#define CLEAR_CMD       0x1
 211void pvc_clear(void)
 212{
 213        pvc_write(CLEAR_CMD, MODE_INST);
 214}
 215
 216#define HOME_CMD        0x2
 217void pvc_home(void)
 218{
 219        pvc_write(HOME_CMD, MODE_INST);
 220}
 221
 222int pvc_init(void)
 223{
 224        u8 cmd = EIGHT_BYTE;
 225
 226        if (PVC_NLINES == 2)
 227                cmd |= (SMALL_FONT|TWO_LINES);
 228        else
 229                cmd |= (LARGE_FONT|ONE_LINE);
 230        pvc_funcset(cmd);
 231        pvc_dispcnt(DISP_ON);
 232        pvc_entrymode(AUTO_INC);
 233
 234        pvc_clear();
 235        pvc_write_string_centered("Display", 0);
 236        pvc_write_string_centered("Initialized", 1);
 237
 238        return 0;
 239}
 240
 241module_init(pvc_init);
 242MODULE_LICENSE("GPL");
 243