GadgetSeed  0.9.6
hx8357d_lcd.c
[詳解]
1 /** @file
2  @brief HX8357D LCD GPIO 8bit接続 ドライバ
3  Kuman MAR3520(Kuman 3.5inch TFT LCD Shield)
4 
5  @date 2017.11.02
6  @author Takashi SHUDO
7 */
8 
9 #include "device.h"
10 #include "device/video_ioctl.h"
11 #include "device/vio_ioctl.h"
12 #include "timer.h"
13 #include "tkprintf.h"
14 #include "graphics.h"
15 
16 //#define DEBUGKBITS 0x03
17 #include "dkprintf.h"
18 
19 
20 #define LCD_WIDTH 480 // 幅
21 #define LCD_HEIGHT 320 // 高さ
22 
23 static struct st_device *gpio_dev;
24 static unsigned short lcd_width = LCD_WIDTH;
25 static unsigned short lcd_height = LCD_HEIGHT;
26 static unsigned short fore_color = 0;
27 static unsigned short back_color = 0;
28 
29 #define FMEM_NOP 0
30 #define FMEM_WRITE 1
31 #define FMEM_READ 2
32 static int fmem_stat = FMEM_NOP;
33 
34 #define HX8357_NOP 0x00
35 #define HX8357_SWRESET 0x01
36 #define HX8357_RDDID 0x04
37 #define HX8357_RDDST 0x09
38 
39 #define HX8357B_RDPOWMODE 0x0A
40 #define HX8357B_RDMADCTL 0x0B
41 #define HX8357B_RDCOLMOD 0x0C
42 #define HX8357B_RDDIM 0x0D
43 #define HX8357B_RDDSDR 0x0F
44 
45 #define HX8357_SLPIN 0x10
46 #define HX8357_SLPOUT 0x11
47 #define HX8357B_PTLON 0x12
48 #define HX8357B_NORON 0x13
49 
50 #define HX8357_INVOFF 0x20
51 #define HX8357_INVON 0x21
52 #define HX8357_DISPOFF 0x28
53 #define HX8357_DISPON 0x29
54 
55 #define HX8357_CASET 0x2A
56 #define HX8357_PASET 0x2B
57 #define HX8357_RAMWR 0x2C
58 #define HX8357_RAMRD 0x2E
59 
60 #define HX8357B_PTLAR 0x30
61 #define HX8357_TEON 0x35
62 #define HX8357_TEARLINE 0x44
63 #define HX8357_MADCTL 0x36
64 #define HX8357_COLMOD 0x3A
65 
66 #define HX8357_SETOSC 0xB0
67 #define HX8357_SETPWR1 0xB1
68 #define HX8357B_SETDISPLAY 0xB2
69 #define HX8357_SETRGB 0xB3
70 #define HX8357D_SETCOM 0xB6
71 
72 #define HX8357B_SETDISPMODE 0xB4
73 #define HX8357D_SETCYC 0xB4
74 #define HX8357B_SETOTP 0xB7
75 #define HX8357D_SETC 0xB9
76 
77 #define HX8357B_SET_PANEL_DRIVING 0xC0
78 #define HX8357D_SETSTBA 0xC0
79 #define HX8357B_SETDGC 0xC1
80 #define HX8357B_SETID 0xC3
81 #define HX8357B_SETDDB 0xC4
82 #define HX8357B_SETDISPLAYFRAME 0xC5
83 #define HX8357B_GAMMASET 0xC8
84 #define HX8357B_SETCABC 0xC9
85 #define HX8357_SETPANEL 0xCC
86 
87 
88 #define HX8357B_SETPOWER 0xD0
89 #define HX8357B_SETVCOM 0xD1
90 #define HX8357B_SETPWRNORMAL 0xD2
91 
92 #define HX8357B_RDID1 0xDA
93 #define HX8357B_RDID2 0xDB
94 #define HX8357B_RDID3 0xDC
95 #define HX8357B_RDID4 0xDD
96 
97 #define HX8357D_SETGAMMA 0xE0
98 
99 #define HX8357B_SETGAMMA 0xC8
100 #define HX8357B_SETPANELRELATED 0xE9
101 
102 #define HX8357B_MADCTL_MY 0x80
103 #define HX8357B_MADCTL_MX 0x40
104 #define HX8357B_MADCTL_MV 0x20
105 #define HX8357B_MADCTL_ML 0x10
106 #define HX8357B_MADCTL_RGB 0x00
107 #define HX8357B_MADCTL_BGR 0x08
108 #define HX8357B_MADCTL_MH 0x04
109 
110 static void set_cs(unsigned int cs)
111 {
112  ioctl_device(gpio_dev, IOCMD_VIO_SET_CS, cs, 0);
113 }
114 
115 static void reset_hx8357d(void)
116 {
117  ioctl_device(gpio_dev, IOCMD_VIO_SET_RESET, 0, 0);
118  wait_time(100);
119  ioctl_device(gpio_dev, IOCMD_VIO_SET_RESET, 1, 0);
120 }
121 
122 static inline void write_reg8(unsigned char addr, unsigned char data)
123 {
125  (((long)addr) << 16) | (long)(data & 0xff), 0);
126 }
127 
128 static inline void write_reg16(unsigned char addr, unsigned short data)
129 {
131  (((long)addr) << 16) | (long)(data & 0xffff), 0);
132 }
133 
134 static inline void write_reg(unsigned char addr, int len, unsigned char *data)
135 {
136  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, addr, 0);
137 
138  while(len) {
139  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_DATA8, *data, 0);
140  data ++;
141  len --;
142  }
143 }
144 
145 static inline void write_reg32(unsigned char addr, unsigned long data)
146 {
147  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, addr, 0);
148  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_DATA32, data, 0);
149 }
150 
151 static inline unsigned long read_reg32(unsigned char addr)
152 {
153  return ioctl_device(gpio_dev, IOCMD_VIO_READ_REG32, addr, 0);
154 }
155 
156 static void set_window(int x1, int y1, int x2, int y2)
157 {
158  DKPRINTF(0x01, "WO %3d %3d %3d %3d\n", x1, y1, x2, y2);
159 
160  set_cs(0);
161 
162  write_reg32(HX8357_CASET, ((x1<<16) | x2));
163  write_reg32(HX8357_PASET, ((y1<<16) | y2));
164 
165  set_cs(1);
166 }
167 
168 static void init_hx8357d(void)
169 {
170  reset_hx8357d();
171 
172  set_cs(0);
173 
174  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_SWRESET, 0);
175  static unsigned char setc[3] = { 0xFF, 0x83, 0x57 };
176  write_reg(HX8357D_SETC, 3, setc);
177  wait_time(250);
178  static unsigned char setrgb[4] = { 0x00, 0x00, 0x06, 0x06 };
179  write_reg(HX8357_SETRGB, 4, setrgb);
180  write_reg8(HX8357D_SETCOM, 0x25); // -1.52V
181  write_reg8(HX8357_SETOSC, 0x68); // Normal mode 70Hz, Idle mode 55 Hz
182  write_reg8(HX8357_SETPANEL, 0x05); // BGR, Gate direction swapped
183  static unsigned char setpwr1[6] = { 0x00, 0x15, 0x1C, 0x1C, 0x83, 0xAA };
184  write_reg(HX8357_SETPWR1, 6, setpwr1);
185  static unsigned char setstba[6] = { 0x50, 0x50, 0x01, 0x3C, 0x1E, 0x08 };
186  write_reg(HX8357D_SETSTBA, 6, setstba);
187  // MEME GAMMA HERE
188  static unsigned char setcyc[7] = { 0x02, 0x40, 0x00, 0x2A, 0x2A, 0x0D, 0x78 };
189  write_reg(HX8357D_SETCYC, 7, setcyc);
190  write_reg8(HX8357_COLMOD, 0x55);
191 // write_reg8(HX8357_MADCTL, 0xC0); // 320 x 480
192  write_reg8(HX8357_MADCTL, 0x60); // 480 x 320
193  write_reg8(HX8357_TEON, 0x00);
194  write_reg16(HX8357_TEARLINE, 0x0002);
195  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_SLPOUT, 0);
196  wait_time(150);
197  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_DISPON, 0);
198  wait_time(50);
199 
200  set_cs(1);
201 
202  set_window(0, 0, lcd_width - 1, lcd_height - 1);
203 }
204 
205 static void fill_screen(unsigned short color)
206 {
207  set_window(0, 0, lcd_width - 1, lcd_height - 1);
208 
209  ioctl_device(gpio_dev, IOCMD_VIO_SET_WRITEDATA0, (unsigned int)color, 0);
210 
211  set_cs(0);
212  fmem_stat = FMEM_WRITE;
213  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_RAMWR, 0);
214  ioctl_device(gpio_dev, IOCMD_VIO_REPEAT_DATA, (unsigned int)LCD_WIDTH * LCD_HEIGHT, 0);
215  set_cs(1);
216 }
217 
218 static int hx8357d_lcd_register(struct st_device *dev, char *param)
219 {
220  gpio_dev = open_device(param);
221  if(gpio_dev == 0) {
222  SYSERR_PRINT("Cannot open device \"%s\"\n", param);
223  return -1;
224  }
225 
226  init_hx8357d();
227 
228  fill_screen(0);
229 
230  return 0;
231 }
232 
233 static int hx8357d_lcd_read(struct st_device *dev, void *data, unsigned int size)
234 {
235  int rt;
236 
237  if(fmem_stat != FMEM_READ) {
238  set_cs(1);
239  set_cs(0);
240  fmem_stat = FMEM_READ;
241  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_RAMRD, 0);
242  ioctl_device(gpio_dev, IOCMD_VIO_READ_DATA8, 0, 0); // Dummy read
243  } else {
244  set_cs(0);
245  }
246 
247  rt = read_device(gpio_dev, data, size);
248 
249  set_cs(1);
250 
251  return rt;
252 }
253 
254 static int hx8357d_lcd_write(struct st_device *dev, const void *data, unsigned int size)
255 {
256  int rt;
257 
258  if(fmem_stat != FMEM_WRITE) {
259  set_cs(0);
260  fmem_stat = FMEM_WRITE;
261  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_RAMWR, 0);
262  } else {
263  set_cs(0);
264  }
265 
266  rt = write_device(gpio_dev, data, size);
267 
268  set_cs(1);
269 
270  return rt;
271 }
272 
273 static int hx8357d_lcd_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
274 {
275  DKFPRINTF(0x01, "com = %08X, arg = %08X\n", com, arg);
276 
277  switch(IOCTL(com)) {
279  ioctl_device(gpio_dev, IOCMD_VIO_LOCK_BUS, 0, 0);
280  break;
281 
283  ioctl_device(gpio_dev, IOCMD_VIO_UNLOCK_BUS, 0, 0);
284  break;
285 
286  case IOCMD_VIDEO_SETRECT:
287  {
288  struct st_rect *rect = (struct st_rect *)param;
289  DKPRINTF(0x01, "RECT %3d %3d %3d %3d\n", rect->left, rect->top, rect->right, rect->bottom);
290  set_window(rect->left, rect->top, rect->right, rect->bottom);
291  fmem_stat = FMEM_NOP;
292  return 0;
293  }
294  break;
295 
297  {
298  set_window(0, 0, lcd_width - 1, lcd_height - 1);
299  fmem_stat = FMEM_NOP;
300  return 0;
301  }
302  break;
303 
304  case IOCMD_VIDEO_CLEAR:
305  fill_screen(0);
306  return 0;
307  break;
308 
309  case IOCMD_VIDEO_FILL:
310  fill_screen(arg);
311  return 0;
312  break;
313 
315  break;
316 
318  {
319  DKPRINTF(0x01, "WORD %04X\n", arg);
320  if(fmem_stat != FMEM_WRITE) {
321  set_cs(0);
322  fmem_stat = FMEM_WRITE;
323  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_RAMWR, 0);
324  }
325  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_DATA16, arg & 0xffff, 0);
326  }
327  break;
328 
330  {
331  DKPRINTF(0x01, "WORD %04X\n", arg);
332  if(fmem_stat != FMEM_WRITE) {
333  set_cs(0);
334  fmem_stat = FMEM_WRITE;
335  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_RAMWR, 0);
336  }
337  ioctl_device(gpio_dev, IOCMD_VIO_NOLOCK_WRITE_DATA16, arg & 0xffff, 0);
338  }
339  break;
340 
342  {
343  fore_color = arg;
344  ioctl_device(gpio_dev, IOCMD_VIO_SET_WRITEDATA0, arg, 0);
345  }
346  break;
347 
349  {
350  back_color = arg;
351  ioctl_device(gpio_dev, IOCMD_VIO_SET_WRITEDATA1, arg, 0);
352  }
353  break;
354 
356  {
357  if(fmem_stat != FMEM_WRITE) {
358  set_cs(0);
359  fmem_stat = FMEM_WRITE;
360  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_RAMWR, 0);
361  }
362  ioctl_device(gpio_dev, IOCMD_VIO_REPEAT_DATA, arg, 0);
363  set_cs(1);
364  }
365  break;
366 
368  {
369  int x = ((arg >> 0) & 0xffff);
370  int y = ((arg >> 16) & 0xffff);
371  int dx;
372  int dy;
373 
374  DKPRINTF(0x01, "P %3d %3d\n", x, y);
375 
376  dx = x;
377  dy = y;
378 
379  set_window(dx, dy, lcd_width - 1, lcd_height - 1);
380  set_cs(0);
381  fmem_stat = FMEM_NOP;
382  write_reg16(HX8357_RAMWR, fore_color);
383  set_cs(1);
384  }
385  break;
386 
388  {
389  if(fmem_stat != FMEM_WRITE) {
390  set_cs(0);
391  fmem_stat = FMEM_WRITE;
392  ioctl_device(gpio_dev, IOCMD_VIO_WRITE_COMMAND, HX8357_RAMWR, 0);
393  }
394  ioctl_device(gpio_dev, IOCMD_VIO_REPEAT_BITS | (com & 0xffff), arg, param);
395  }
396  break;
397 
398  default:
399  SYSERR_PRINT("Unknow command %08lX arg %08lX\n", com, arg);
400  return -1;
401  }
402 
403  return 0;
404 }
405 
406 static int hx8357d_lcd_suspend(struct st_device *dev)
407 {
408  return 0;
409 }
410 
411 static int hx8357d_lcd_resume(struct st_device *dev)
412 {
413  return 0;
414 }
415 
416 static struct st_video_info lcd_info = {
418  .width = LCD_WIDTH,
419  .height = LCD_HEIGHT,
420  .color_depth = VCOLORDEP_16,
421 };
422 
423 const struct st_device hx8357d_lcd_device = {
425  .explan = "HX8357D(MAR3520) LCD",
426  .info = (void *)&lcd_info,
427  .register_dev = hx8357d_lcd_register,
428  .read = hx8357d_lcd_read,
429  .write = hx8357d_lcd_write,
430  .ioctl = hx8357d_lcd_ioctl,
431  .suspend = hx8357d_lcd_suspend,
432  .resume = hx8357d_lcd_resume,
433 };
#define IOCTL(ioctl)
ioctlコマンド
Definition: std_ioctl.h:29
#define IOCMD_VIDEO_NOLOCK_WRITE_WORD
2バイト表示データを転送する(MUTEXロックは無視)
Definition: video_ioctl.h:62
#define IOCMD_VIO_READ_DATA8
コントローラデバイスから8ビットデータを読み出す
Definition: vio_ioctl.h:31
#define IOCMD_VIO_WRITE_REG16
コントローラデバイスのレジスタに16ビットデータを書き込む
Definition: vio_ioctl.h:34
#define IOCMD_VIO_REPEAT_BITS
指定のビットデータを描画データ0、1で描画する
Definition: vio_ioctl.h:46
#define IOCMD_VIDEO_CLEAR
全画面初期化
Definition: video_ioctl.h:52
#define IOCMD_VIO_LOCK_BUS
バスをMUTEXロックする
Definition: vio_ioctl.h:18
#define IOCMD_VIO_WRITE_DATA16
コントローラデバイスに16ビットデータを書き込む
Definition: vio_ioctl.h:26
画像表示デバイスドライバ ioctl 用マクロ定義
#define IOCMD_VIDEO_UNLOCK_DEVICE
デバイスをMUTEXアンロックする
Definition: video_ioctl.h:45
#define IOCMD_VIO_SET_RESET
デバイスのリセットを設定する
Definition: vio_ioctl.h:21
#define IOCMD_VIDEO_SETRECT
描画データ転送範囲を矩形で設定する
Definition: video_ioctl.h:55
矩形
Definition: graphics.h:64
画像表示デバイス情報
Definition: video_ioctl.h:30
#define IOCMD_VIO_WRITE_COMMAND
コントローラデバイスにコマンドを書き込む
Definition: vio_ioctl.h:24
struct st_device * open_device(char *name)
デバイスをオープンする
Definition: device.c:262
#define IOCMD_VIDEO_REPEAT_DATA
指定ドット数分フォアカラーで描画する
Definition: video_ioctl.h:66
int write_device(struct st_device *dev, const void *buf, unsigned int count)
デバイスにデータを書き込む
Definition: device.c:451
int read_device(struct st_device *dev, void *buf, unsigned int count)
デバイスよりデータを読み出す
Definition: device.c:378
short top
左上頂点のY座標
Definition: graphics.h:66
short bottom
右下頂点のY座標
Definition: graphics.h:68
#define VIDEOTYPE_CMDDRAW
コマンドによる描画(フレームバッファなし)
Definition: video_ioctl.h:20
short left
左上頂点のX座標
Definition: graphics.h:65
#define IOCMD_VIO_READ_REG32
コントローラデバイスのレジスタより32ビットデータを読み出す
Definition: vio_ioctl.h:41
#define IOCMD_VIDEO_DRAW_PIXEL
フォアカラーで1ドット描画する
Definition: video_ioctl.h:67
#define IOCMD_VIDEO_DRAW_BITS
ビットパターンを描画する
Definition: video_ioctl.h:68
int suspend(void)
全デバイスを休止状態にする
Definition: device.c:634
#define IOCMD_VIO_REPEAT_DATA
描画データ0で指定ドット数描画する
Definition: vio_ioctl.h:45
カーネルタイマ
unsigned short type
ビデオデバイスタイプ(VIDEOTYPE_*)
Definition: video_ioctl.h:31
short right
右下頂点のX座標
Definition: graphics.h:67
カーネル用機能限定printf
#define IOCMD_VIO_SET_WRITEDATA0
描画データ0を設定する
Definition: vio_ioctl.h:43
#define IOCMD_VIO_NOLOCK_WRITE_DATA16
コントローラデバイスに16ビットデータを書き込む(ロックは無視)
Definition: vio_ioctl.h:29
#define IOCMD_VIO_SET_WRITEDATA1
描画データ1を設定する
Definition: vio_ioctl.h:44
#define IOCMD_VIO_SET_CS
CSを設定する
Definition: vio_ioctl.h:22
void wait_time(unsigned int time)
指定時間待つ
Definition: timer.c:216
#define IOCMD_VIO_WRITE_DATA32
コントローラデバイスに32ビットデータを書き込む
Definition: vio_ioctl.h:28
#define VCOLORDEP_16
16ビットカラー
Definition: video_ioctl.h:26
#define IOCMD_VIDEO_LOCK_DEVICE
デバイスをMUTEXロックする
Definition: video_ioctl.h:44
#define IOCMD_VIDEO_RESETRECT
描画データ転送範囲を全表示範囲にする
Definition: video_ioctl.h:56
#define IOCMD_VIDEO_SET_BACKCOLOR
バックカラーを設定する
Definition: video_ioctl.h:65
#define IOCMD_VIO_UNLOCK_BUS
バスをMUTEXアンロックする
Definition: vio_ioctl.h:19
#define IOCMD_VIO_WRITE_DATA8
コントローラデバイスに8ビットデータを書き込む
Definition: vio_ioctl.h:25
映像関連ドライバIO ioctl 用マクロ定義
int resume(void)
全デバイスを活性化する
Definition: device.c:655
#define DEF_DEV_NAME_VIDEO
標準ビデオデバイス名
Definition: video_ioctl.h:16
#define IOCMD_VIO_WRITE_REG8
コントローラデバイスのレジスタに8ビットデータを書き込む
Definition: vio_ioctl.h:33
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
カーネル、ドライバ(非タスク)デバッグ用マクロ
#define IOCMD_VIDEO_WRITE_WORD
2バイト表示データを転送する(未使用)
Definition: video_ioctl.h:59
int ioctl_device(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
デバイスを制御する
Definition: device.c:525
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
#define IOCMD_VIDEO_SET_FORECOLOR
フォアカラーを設定する
Definition: video_ioctl.h:64
グラフィックライブラリ
#define IOCMD_VIDEO_BCKLIGHT
バックライトを制御する(未使用)
Definition: video_ioctl.h:70
#define IOCMD_VIDEO_FILL
全画面を任意の色に描画する
Definition: video_ioctl.h:54