4
4
#include "printf.h"
5
5
#include "serial.h"
6
6
#include "fernvale-lcd.h"
7
+ #include "fernvale-gpio.h"
8
+ #include "fernvale-clockgate.h"
7
9
8
10
// local implementation of strncmp() because we don't have it as a lib in fernly
9
11
static int my_strncmp (const char * s1 , const char * s2 , size_t n )
@@ -17,10 +19,115 @@ static int my_strncmp(const char* s1, const char* s2, size_t n)
17
19
return 0 ;
18
20
}
19
21
22
+ static void usleep (uint32_t usecs ) {
23
+ uint32_t i , j ;
24
+ for (i = 0 ; i < usecs ; i ++ ) {
25
+ for (j = 0 ; j < 73 ; j ++ ) {
26
+ asm("nop" );
27
+ }
28
+ }
29
+ }
30
+
31
+ static void msleep (uint32_t msecs ) {
32
+ uint32_t i , j ;
33
+ for (i = 0 ; i < msecs ; i ++ ) {
34
+ for (j = 0 ; j < 73000 ; j ++ ) {
35
+ asm("nop" );
36
+ }
37
+ }
38
+ }
39
+
40
+ #define USE_DMA 0
41
+ #if USE_DMA // needs debuggin'
42
+ void flush_dma ( uint8_t q ) {
43
+ while (* ((volatile uint16_t * ) LCD_STATUS_REG ) & LCD_STATUS_BUSY_BIT )
44
+ ;
45
+
46
+ * ((volatile uint16_t * ) LCD_INT_ENA_REG ) &= ~LCD_INT_ENA_TRIG_BIT ;
47
+ * ((volatile uint32_t * ) LCD_MEMMAP_CTRL_REG ) &= 0x0FFFFFFF ; // disable all layers
48
+ * ((volatile uint32_t * ) LCD_MEMMAP_CTRL_REG ) &= 0xFFFFE0FF ; // clear command count
49
+ * ((volatile uint32_t * ) LCD_MEMMAP_CTRL_REG ) |= (q << 8 ); // enter command count
50
+ * ((volatile uint32_t * ) LCD_MEMMAP_CTRL_REG ) |= 0x8000 ; // enable commands to be sent first
51
+ * ((volatile uint32_t * )LCD_MEMMAP_SIZE_REG ) = 0x0 ;
52
+ * ((volatile uint16_t * )LCD_RUN_REG ) = 0 ;
53
+ * ((volatile uint16_t * )LCD_RUN_REG ) = LCD_RUN_BIT ;
54
+ usleep (1 );
55
+
56
+ while (* ((volatile uint16_t * ) LCD_STATUS_REG ) & LCD_STATUS_BUSY_BIT )
57
+ ;
58
+
59
+ * ((volatile uint32_t * )LCD_MEMMAP_SIZE_REG ) = 0x014000F0 ;
60
+ }
61
+
62
+ void lcd_cmd ( uint16_t cmd ) {
63
+ * ((volatile uint32_t * )LCD_CMD_LIST_ADDR ) = 0x800000 | cmd ;
64
+ flush_dma (1 );
65
+ }
66
+
67
+ void lcd_dat ( uint16_t dat ) {
68
+ * ((volatile uint32_t * )LCD_CMD_LIST_ADDR ) = dat ;
69
+ flush_dma (1 );
70
+ }
71
+
72
+ // note these don't flush the DMA, you have to do this yourself explicitly later on
73
+ void lcd_cmd_slot ( uint16_t cmd , uint8_t slot ) { // slot is the order to execute
74
+ * ((volatile uint32_t * ) (LCD_CMD_LIST_ADDR + (slot << 2 ))) = 0x800000 | cmd ;
75
+ }
76
+ void lcd_dat_slot ( uint16_t dat , uint8_t slot ) { // slot is the order to execute
77
+ * ((volatile uint32_t * ) (LCD_CMD_LIST_ADDR + (slot << 2 ))) = dat ;
78
+ }
79
+ #else
80
+
81
+ #define lcd_cmd (_cmd_ ) *((volatile uint16_t *)LCD_PAR0_CMD_PORT_REG) = (uint16_t) _cmd_
82
+ #define lcd_dat (_dat_ ) *((volatile uint16_t *)LCD_PAR0_DAT_PORT_REG) = (uint16_t) _dat_
83
+
84
+ #endif
85
+
86
+
87
+ void setup_lcd_gpio () {
88
+ // LPCE0, LPTE0, LPRSTB
89
+ * ((volatile uint32_t * ) GPIO_CTRL_MODE5 ) &= ~( GPIO_CTRL_MODE5_IO40_MASK |
90
+ GPIO_CTRL_MODE5_IO46_MASK |
91
+ GPIO_CTRL_MODE5_IO45_MASK );
92
+ * ((volatile uint32_t * ) GPIO_CTRL_MODE5 ) |= ( GPIO_CTRL_MODE5_IO40_LPCE0B |
93
+ GPIO_CTRL_MODE5_IO45_LPTE0 |
94
+ GPIO_CTRL_MODE5_IO46_LPRSTB );
95
+
96
+ // NLD0-4, LWRB, LRDB, LPA0
97
+ * ((volatile uint32_t * ) GPIO_CTRL_MODE4 ) &= ~( GPIO_CTRL_MODE4_IO32_MASK |
98
+ GPIO_CTRL_MODE4_IO33_MASK |
99
+ GPIO_CTRL_MODE4_IO34_MASK |
100
+ GPIO_CTRL_MODE4_IO35_MASK |
101
+ GPIO_CTRL_MODE4_IO36_MASK |
102
+ GPIO_CTRL_MODE4_IO37_MASK |
103
+ GPIO_CTRL_MODE4_IO38_MASK |
104
+ GPIO_CTRL_MODE4_IO39_MASK );
105
+ * ((volatile uint32_t * ) GPIO_CTRL_MODE4 ) |= ( GPIO_CTRL_MODE4_IO32_NLD4 |
106
+ GPIO_CTRL_MODE4_IO33_NLD3 |
107
+ GPIO_CTRL_MODE4_IO34_NLD2 |
108
+ GPIO_CTRL_MODE4_IO35_NLD1 |
109
+ GPIO_CTRL_MODE4_IO36_NLD0 |
110
+ GPIO_CTRL_MODE4_IO37_LWRB |
111
+ GPIO_CTRL_MODE4_IO38_LRDB |
112
+ GPIO_CTRL_MODE4_IO39_LPA0 );
113
+
114
+ // NLD5-8
115
+ * ((volatile uint32_t * ) GPIO_CTRL_MODE3 ) &= ~( GPIO_CTRL_MODE3_IO28_MASK |
116
+ GPIO_CTRL_MODE3_IO29_MASK |
117
+ GPIO_CTRL_MODE3_IO30_MASK |
118
+ GPIO_CTRL_MODE3_IO31_MASK );
119
+ * ((volatile uint32_t * ) GPIO_CTRL_MODE3 ) |= ( GPIO_CTRL_MODE3_IO28_NLD8 |
120
+ GPIO_CTRL_MODE3_IO29_NLD7 |
121
+ GPIO_CTRL_MODE3_IO30_NLD6 |
122
+ GPIO_CTRL_MODE3_IO31_NLD5 );
123
+
124
+ }
125
+
20
126
int cmd_lcd (int argc , char * * argv )
21
127
{
22
128
uint32_t genarg = 0 ;
23
129
char * subcmd ;
130
+ int i ;
24
131
25
132
if (argc < 1 ) {
26
133
printf ("Usage: lcd [subcmd] [arg0]\n" );
@@ -35,25 +142,150 @@ int cmd_lcd(int argc, char **argv)
35
142
36
143
printf ( "command got: %s\n" , subcmd );
37
144
if ( my_strncmp ( subcmd , "su" , 8 ) == 0 ) {
145
+ setup_lcd_gpio ();
146
+
147
+ * ((volatile uint32_t * ) CLKGATE_SYS_CTL0_CLR ) = CLKGATE_CTL0_LCD ; // power up the LCD block
148
+ msleep (1 );
149
+
38
150
// execute setup command
39
- printf ( "nothing for now.\n" );
151
+ // we're on CS0
152
+ // our internal bus period is 166 MHz, or 6.25ns
153
+ // write cycle = 66ns = 11 cycles - 1 = 10
154
+ // write c22write su (tcs) = 15ns = 3 cycles
155
+ // write ce2write hold (tdht) = 10ns = 2 cycles - 1 = 1
156
+ // read latency = 450 ns = 72 cycles, crop at 63 cycles
157
+ // read ce2read su (trdl - trcs) = 45-45 = 0 ns = 0 cycles
158
+ // read th = 90ns = 15 cycles (not quite clear, but best guess)
159
+ * ((volatile uint32_t * )LCD_PAR0_CFG_REG ) =
160
+ (10 << LCD_PAR_CFG_WR_WAIT_CYC_BIT ) |
161
+ (3 << LCD_PAR_CFG_WR_TSU_BIT ) |
162
+ (1 << LCD_PAR_CFG_WR_TH_BIT ) |
163
+ (63 << LCD_PAR_CFG_RD_LATENCY_CYC_BIT ) | // this might need to be shorter??
164
+ (0 << LCD_PAR_CFG_RD_TSU_BIT ) |
165
+ (15 << LCD_PAR_CFG_RD_TH_BIT );
166
+
167
+ // 9 bit width, tchw is 0 for this chipset (back2back writes allowed)
168
+ * ((volatile uint32_t * )LCD_PAR_DATA_WIDTH_REG ) =
169
+ (0 << LCD_PAR_W2W_WAIT0_BIT ) |
170
+ (LCD_PAR_BUS_WIDTH_9BIT << LCD_PAR_BUS_WIDTH0_BIT );
171
+
172
+ * ((volatile uint32_t * )LCD_AUTOCOPY_CTRL_REG ) = 0 ; // AUTOCOPY off initially
173
+
174
+ } else if ( my_strncmp ( subcmd , "auto" , 8 ) == 0 ) {
175
+ * ((volatile uint32_t * )LCD_LAYER0_CTRL_REG ) = 0 ;
176
+ * ((volatile uint32_t * )LCD_LAYER0_OFFSET_REG ) = 0 ;
177
+ * ((volatile uint32_t * )LCD_LAYER0_BUFF_ADDR_REG ) = 0 ;
178
+ * ((volatile uint32_t * )LCD_LAYER0_SIZE_REG ) = 0x014000f0 ;
179
+ * ((volatile uint32_t * )LCD_LAYER0_MEM_OFFSET_REG ) = 0x0 ;
180
+ * ((volatile uint32_t * )LCD_LAYER0_MEM_PITCH_REG ) = 0x1e0 ;
181
+
182
+ * ((volatile uint32_t * )LCD_AUTOCOPY_OFFSET_REG ) = 0 ;
183
+ * ((volatile uint16_t * )LCD_AUTOCOPY_CMD_ADDR_REG ) = 0x4000 ;
184
+ * ((volatile uint16_t * )LCD_AUTOCOPY_DATA_ADDR_REG ) = 0x4100 ;
185
+ * ((volatile uint32_t * )LCD_AUTOCOPY_SIZE_REG ) = 0x014000F0 ;
186
+ * ((volatile uint32_t * )LCD_AUTOCOPY_BG_COLOR_REG ) = 0x80008000 ;
187
+
188
+ * ((volatile uint32_t * )LCD_AUTOCOPY_CTRL_REG ) = 0x85020094 ;
189
+
40
190
} else if ( my_strncmp ( subcmd , "dump" , 8 ) == 0 ) {
41
191
// dump registers
42
- printf ( "LCD_PAR0_CMD_PORT_REG: %08x \n" , * ((volatile uint32_t * ) LCD_PAR0_CMD_PORT_REG ) );
43
- printf ( "LCD_PAR0_DAT_PORT_REG: %08x \n" , * ((volatile uint32_t * ) LCD_PAR0_DAT_PORT_REG ) );
44
- printf ( "LCD_PAR1_CMD_PORT_REG: %08x \n" , * ((volatile uint32_t * ) LCD_PAR1_CMD_PORT_REG ) );
45
- printf ( "LCD_PAR1_DAT_PORT_REG: %08x \n" , * ((volatile uint32_t * ) LCD_PAR1_DAT_PORT_REG ) );
192
+ printf ( "LCD_PAR0_CMD_PORT_REG: %04x \n" , * ((volatile uint16_t * ) LCD_PAR0_CMD_PORT_REG ) );
193
+ printf ( "LCD_PAR0_DAT_PORT_REG: %04x \n" , * ((volatile uint16_t * ) LCD_PAR0_DAT_PORT_REG ) );
194
+ printf ( "LCD_PAR1_CMD_PORT_REG: %04x \n" , * ((volatile uint16_t * ) LCD_PAR1_CMD_PORT_REG ) );
195
+ printf ( "LCD_PAR1_DAT_PORT_REG: %04x \n" , * ((volatile uint16_t * ) LCD_PAR1_DAT_PORT_REG ) );
46
196
printf ( "LCD_PAR0_CFG_REG: %08x\n" , * ((volatile uint32_t * ) LCD_PAR0_CFG_REG ) );
47
197
printf ( "LCD_PAR1_CFG_REG: %08x\n" , * ((volatile uint32_t * ) LCD_PAR1_CFG_REG ) );
48
- printf ( "LCD_STATUS_REG: %08x \n" , * ((volatile uint32_t * ) LCD_STATUS_REG ) );
49
- printf ( "LCD_INT_ENA_REG: %08x \n" , * ((volatile uint32_t * ) LCD_INT_ENA_REG ) );
50
- printf ( "LCD_INT_STAT_REG: %08x \n" , * ((volatile uint32_t * ) LCD_INT_STAT_REG ) );
51
- printf ( "LCD_RUN_REG: %08x \n" , * ((volatile uint32_t * ) LCD_RUN_REG ) );
52
- printf ( "LCD_RESET_REG: %08x \n" , * ((volatile uint32_t * ) LCD_RESET_REG ) );
198
+ printf ( "LCD_STATUS_REG: %04x \n" , * ((volatile uint16_t * ) LCD_STATUS_REG ) );
199
+ printf ( "LCD_INT_ENA_REG: %04x \n" , * ((volatile uint16_t * ) LCD_INT_ENA_REG ) );
200
+ printf ( "LCD_INT_STAT_REG: %04x \n" , * ((volatile uint16_t * ) LCD_INT_STAT_REG ) );
201
+ printf ( "LCD_RUN_REG: %04x \n" , * ((volatile uint16_t * ) LCD_RUN_REG ) );
202
+ printf ( "LCD_RESET_REG: %04x \n" , * ((volatile uint16_t * ) LCD_RESET_REG ) );
53
203
printf ( "LCD_PAR_DATA_WIDTH_REG: %08x\n" , * ((volatile uint32_t * ) LCD_PAR_DATA_WIDTH_REG ) );
54
204
printf ( "LCD_TEARING_CON_REG: %08x\n" , * ((volatile uint32_t * ) LCD_TEARING_CON_REG ) );
205
+ printf ( "LCD_AUTOCOPY_CTRL_REG: %08x\n" , * ((volatile uint32_t * ) LCD_AUTOCOPY_CTRL_REG ) );
206
+ } else if ( my_strncmp ( subcmd , "run" , 8 ) == 0 ) {
207
+ // cause the interface to run
208
+ * ((volatile uint16_t * )LCD_RUN_REG ) = 0 ;
209
+ * ((volatile uint16_t * )LCD_RUN_REG ) = LCD_RUN_BIT ;
210
+ } else if ( my_strncmp ( subcmd , "stop" , 8 ) == 0 ) {
211
+ // cause the interface to stop
212
+ * ((volatile uint16_t * )LCD_RUN_REG ) = 0 ;
213
+ } else if ( my_strncmp ( subcmd , "init" , 8 ) == 0 ) {
214
+ * ((volatile uint16_t * )LCD_RESET_REG ) = 1 ;
215
+ usleep (20000 );
216
+ * ((volatile uint16_t * )LCD_RESET_REG ) = 0 ; // turn on reset
217
+ msleep (20 );
218
+ * ((volatile uint16_t * )LCD_RESET_REG ) = 1 ; // turn off reset
219
+ msleep (150 );
220
+
221
+ lcd_cmd (0x11 ); //Exit Sleep
222
+ msleep (50 ); // Delay 50ms
223
+ lcd_cmd (0xC0 ); //Power control
224
+ lcd_dat (0x26 );
225
+ lcd_cmd (0xC1 ); //Power control
226
+ lcd_dat (0x11 ); //SAP[2:0];BT[3:0]
227
+ lcd_cmd (0xC5 ); //VCM control
228
+ lcd_dat (0x35 );
229
+ lcd_dat (0x3E );
230
+ lcd_cmd (0xc7 );
231
+ lcd_dat (0xbe );
232
+
233
+ lcd_cmd (0x36 ); // Memory Access Control
234
+ lcd_dat (0x48 );
235
+
236
+ lcd_cmd (0x3a ); // pixel format set
237
+ lcd_dat (0x55 ); // 16bpp
238
+
239
+ lcd_cmd (0xB1 ); // Frame Rate Control
240
+ lcd_dat (0x00 );
241
+ lcd_dat (0x1b );
242
+
243
+ //--------------ddram ---------------------
244
+ lcd_cmd (0x2a ); // column set
245
+ lcd_dat (0x00 );
246
+ lcd_dat (0x00 );
247
+ lcd_dat (0x00 );
248
+ lcd_dat (0xEF );
249
+ lcd_cmd (0x2b ); // page address set
250
+ lcd_dat (0x00 );
251
+ lcd_dat (0x00 );
252
+ lcd_dat (0x01 );
253
+ lcd_dat (0x3F );
254
+ lcd_cmd (0x34 ); // tearing effect off
255
+ //lcd_cmd(0x35); // tearing effect on
256
+ //lcd_cmd(0xb4); // display inversion
257
+ //lcd_dat(0x00,0x00);
258
+ lcd_cmd (0xb7 ); //entry mode set
259
+ lcd_dat (0x07 );
260
+ //-----------------display---------------------
261
+ lcd_cmd (0xb6 ); // display function control
262
+ lcd_dat (0x0a );
263
+ lcd_dat (0x82 );
264
+ lcd_dat (0x27 );
265
+ lcd_dat (0x00 );
266
+ lcd_cmd (0x11 ); //sleep out
267
+ msleep (100 );
268
+ lcd_cmd (0x29 ); // display on
269
+ msleep (100 );
270
+ lcd_cmd (0x2c ); //memory write
271
+ } else if ( my_strncmp ( subcmd , "tp1" , 8 ) == 0 ) {
272
+ lcd_cmd (0x2a ); // column set
273
+ lcd_dat (0x00 );
274
+ lcd_dat (0x00 );
275
+ lcd_dat (0x00 );
276
+ lcd_dat (0xEF );
277
+ lcd_cmd (0x2b ); // page address set
278
+ lcd_dat (0x00 );
279
+ lcd_dat (0x00 );
280
+ lcd_dat (0x01 );
281
+ lcd_dat (0x3F );
282
+
283
+ lcd_cmd (0x2c ); //memory write
284
+ for ( i = 0 ; i < 16384 ; i ++ ) {
285
+ lcd_dat ((uint16_t ) i );
286
+ }
55
287
} else {
56
- printf ( "lcd commands: su (setup timing), dump (dump registers)\n" );
288
+ printf ( "lcd commands: su (setup timing), dump (dump registers), run, stop, init, tp1 \n" );
57
289
}
58
290
59
291
return 0 ;
0 commit comments