0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/types.h>
0012
0013 #define BT431_CURSOR_SIZE 64
0014
0015
0016
0017
0018
0019 struct bt431_regs {
0020 volatile u16 addr_lo;
0021 u16 pad0;
0022 volatile u16 addr_hi;
0023 u16 pad1;
0024 volatile u16 addr_cmap;
0025 u16 pad2;
0026 volatile u16 addr_reg;
0027 u16 pad3;
0028 };
0029
0030 static inline u16 bt431_set_value(u8 val)
0031 {
0032 return ((val << 8) | (val & 0xff)) & 0xffff;
0033 }
0034
0035 static inline u8 bt431_get_value(u16 val)
0036 {
0037 return val & 0xff;
0038 }
0039
0040
0041
0042
0043 #define BT431_REG_CMD 0x0000
0044 #define BT431_REG_CXLO 0x0001
0045 #define BT431_REG_CXHI 0x0002
0046 #define BT431_REG_CYLO 0x0003
0047 #define BT431_REG_CYHI 0x0004
0048 #define BT431_REG_WXLO 0x0005
0049 #define BT431_REG_WXHI 0x0006
0050 #define BT431_REG_WYLO 0x0007
0051 #define BT431_REG_WYHI 0x0008
0052 #define BT431_REG_WWLO 0x0009
0053 #define BT431_REG_WWHI 0x000a
0054 #define BT431_REG_WHLO 0x000b
0055 #define BT431_REG_WHHI 0x000c
0056
0057 #define BT431_REG_CRAM_BASE 0x0000
0058 #define BT431_REG_CRAM_END 0x01ff
0059
0060
0061
0062
0063 #define BT431_CMD_CURS_ENABLE 0x40
0064 #define BT431_CMD_XHAIR_ENABLE 0x20
0065 #define BT431_CMD_OR_CURSORS 0x10
0066 #define BT431_CMD_XOR_CURSORS 0x00
0067 #define BT431_CMD_1_1_MUX 0x00
0068 #define BT431_CMD_4_1_MUX 0x04
0069 #define BT431_CMD_5_1_MUX 0x08
0070 #define BT431_CMD_xxx_MUX 0x0c
0071 #define BT431_CMD_THICK_1 0x00
0072 #define BT431_CMD_THICK_3 0x01
0073 #define BT431_CMD_THICK_5 0x02
0074 #define BT431_CMD_THICK_7 0x03
0075
0076 static inline void bt431_select_reg(struct bt431_regs *regs, int ir)
0077 {
0078
0079
0080
0081
0082 volatile u16 *lo = &(regs->addr_lo);
0083 volatile u16 *hi = &(regs->addr_hi);
0084
0085 mb();
0086 *lo = bt431_set_value(ir & 0xff);
0087 wmb();
0088 *hi = bt431_set_value((ir >> 8) & 0xff);
0089 }
0090
0091
0092 static inline u8 bt431_read_reg_inc(struct bt431_regs *regs)
0093 {
0094
0095
0096
0097
0098 volatile u16 *r = &(regs->addr_reg);
0099
0100 mb();
0101 return bt431_get_value(*r);
0102 }
0103
0104 static inline void bt431_write_reg_inc(struct bt431_regs *regs, u8 value)
0105 {
0106
0107
0108
0109
0110 volatile u16 *r = &(regs->addr_reg);
0111
0112 mb();
0113 *r = bt431_set_value(value);
0114 }
0115
0116 static inline u8 bt431_read_reg(struct bt431_regs *regs, int ir)
0117 {
0118 bt431_select_reg(regs, ir);
0119 return bt431_read_reg_inc(regs);
0120 }
0121
0122 static inline void bt431_write_reg(struct bt431_regs *regs, int ir, u8 value)
0123 {
0124 bt431_select_reg(regs, ir);
0125 bt431_write_reg_inc(regs, value);
0126 }
0127
0128
0129 static inline u16 bt431_read_cmap_inc(struct bt431_regs *regs)
0130 {
0131
0132
0133
0134
0135 volatile u16 *r = &(regs->addr_cmap);
0136
0137 mb();
0138 return *r;
0139 }
0140
0141 static inline void bt431_write_cmap_inc(struct bt431_regs *regs, u16 value)
0142 {
0143
0144
0145
0146
0147 volatile u16 *r = &(regs->addr_cmap);
0148
0149 mb();
0150 *r = value;
0151 }
0152
0153 static inline u16 bt431_read_cmap(struct bt431_regs *regs, int cr)
0154 {
0155 bt431_select_reg(regs, cr);
0156 return bt431_read_cmap_inc(regs);
0157 }
0158
0159 static inline void bt431_write_cmap(struct bt431_regs *regs, int cr, u16 value)
0160 {
0161 bt431_select_reg(regs, cr);
0162 bt431_write_cmap_inc(regs, value);
0163 }
0164
0165 static inline void bt431_enable_cursor(struct bt431_regs *regs)
0166 {
0167 bt431_write_reg(regs, BT431_REG_CMD,
0168 BT431_CMD_CURS_ENABLE | BT431_CMD_OR_CURSORS
0169 | BT431_CMD_4_1_MUX | BT431_CMD_THICK_1);
0170 }
0171
0172 static inline void bt431_erase_cursor(struct bt431_regs *regs)
0173 {
0174 bt431_write_reg(regs, BT431_REG_CMD, BT431_CMD_4_1_MUX);
0175 }
0176
0177 static inline void bt431_position_cursor(struct bt431_regs *regs, u16 x, u16 y)
0178 {
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 x += 412 - 52;
0192 y += 68 - 32;
0193
0194
0195 bt431_select_reg(regs, BT431_REG_CXLO);
0196 bt431_write_reg_inc(regs, x & 0xff);
0197 bt431_write_reg_inc(regs, (x >> 8) & 0x0f);
0198 bt431_write_reg_inc(regs, y & 0xff);
0199 bt431_write_reg_inc(regs, (y >> 8) & 0x0f);
0200 }
0201
0202 static inline void bt431_set_cursor(struct bt431_regs *regs,
0203 const char *data, const char *mask,
0204 u16 rop, u16 width, u16 height)
0205 {
0206 u16 x, y;
0207 int i;
0208
0209 i = 0;
0210 width = DIV_ROUND_UP(width, 8);
0211 bt431_select_reg(regs, BT431_REG_CRAM_BASE);
0212 for (y = 0; y < BT431_CURSOR_SIZE; y++)
0213 for (x = 0; x < BT431_CURSOR_SIZE / 8; x++) {
0214 u16 val = 0;
0215
0216 if (y < height && x < width) {
0217 val = mask[i];
0218 if (rop == ROP_XOR)
0219 val = (val << 8) | (val ^ data[i]);
0220 else
0221 val = (val << 8) | (val & data[i]);
0222 i++;
0223 }
0224 bt431_write_cmap_inc(regs, val);
0225 }
0226 }
0227
0228 static inline void bt431_init_cursor(struct bt431_regs *regs)
0229 {
0230
0231 bt431_select_reg(regs, BT431_REG_WXLO);
0232 bt431_write_reg_inc(regs, 0x00);
0233 bt431_write_reg_inc(regs, 0x00);
0234 bt431_write_reg_inc(regs, 0x00);
0235 bt431_write_reg_inc(regs, 0x00);
0236 bt431_write_reg_inc(regs, 0x00);
0237 bt431_write_reg_inc(regs, 0x00);
0238 bt431_write_reg_inc(regs, 0x00);
0239 bt431_write_reg_inc(regs, 0x00);
0240 }