1fc1a79d9SHeiko Schocher /*
2fc1a79d9SHeiko Schocher * LCD: LG4573, TFT 4.3", 480x800, RGB24
3fc1a79d9SHeiko Schocher * LCD initialization via SPI
4fc1a79d9SHeiko Schocher *
5fc1a79d9SHeiko Schocher * SPDX-License-Identifier: GPL-2.0
6fc1a79d9SHeiko Schocher *
7fc1a79d9SHeiko Schocher */
8fc1a79d9SHeiko Schocher #include <common.h>
9fc1a79d9SHeiko Schocher #include <errno.h>
10fc1a79d9SHeiko Schocher #include <spi.h>
11fc1a79d9SHeiko Schocher
12fc1a79d9SHeiko Schocher #define PWR_ON_DELAY_MSECS 120
13fc1a79d9SHeiko Schocher
lb043wv_spi_write_u16(struct spi_slave * spi,u16 val)14fc1a79d9SHeiko Schocher static int lb043wv_spi_write_u16(struct spi_slave *spi, u16 val)
15fc1a79d9SHeiko Schocher {
16fc1a79d9SHeiko Schocher unsigned long flags = SPI_XFER_BEGIN;
17fc1a79d9SHeiko Schocher unsigned short buf16 = htons(val);
18fc1a79d9SHeiko Schocher int ret = 0;
19fc1a79d9SHeiko Schocher
20fc1a79d9SHeiko Schocher flags |= SPI_XFER_END;
21fc1a79d9SHeiko Schocher
22fc1a79d9SHeiko Schocher ret = spi_xfer(spi, 16, &buf16, NULL, flags);
23fc1a79d9SHeiko Schocher if (ret)
24fc1a79d9SHeiko Schocher debug("%s: Failed to send: %d\n", __func__, ret);
25fc1a79d9SHeiko Schocher
26fc1a79d9SHeiko Schocher return ret;
27fc1a79d9SHeiko Schocher }
28fc1a79d9SHeiko Schocher
lb043wv_spi_write_u16_array(struct spi_slave * spi,u16 * buff,int size)29fc1a79d9SHeiko Schocher static void lb043wv_spi_write_u16_array(struct spi_slave *spi, u16 *buff,
30fc1a79d9SHeiko Schocher int size)
31fc1a79d9SHeiko Schocher {
32fc1a79d9SHeiko Schocher int i;
33fc1a79d9SHeiko Schocher
34fc1a79d9SHeiko Schocher for (i = 0; i < size; i++)
35fc1a79d9SHeiko Schocher lb043wv_spi_write_u16(spi, buff[i]);
36fc1a79d9SHeiko Schocher }
37fc1a79d9SHeiko Schocher
lb043wv_display_mode_settings(struct spi_slave * spi)38fc1a79d9SHeiko Schocher static void lb043wv_display_mode_settings(struct spi_slave *spi)
39fc1a79d9SHeiko Schocher {
40fc1a79d9SHeiko Schocher static u16 display_mode_settings[] = {
41fc1a79d9SHeiko Schocher 0x703A,
42fc1a79d9SHeiko Schocher 0x7270,
43fc1a79d9SHeiko Schocher 0x70B1,
44fc1a79d9SHeiko Schocher 0x7208,
45fc1a79d9SHeiko Schocher 0x723B,
46fc1a79d9SHeiko Schocher 0x720F,
47fc1a79d9SHeiko Schocher 0x70B2,
48fc1a79d9SHeiko Schocher 0x7200,
49fc1a79d9SHeiko Schocher 0x72C8,
50fc1a79d9SHeiko Schocher 0x70B3,
51fc1a79d9SHeiko Schocher 0x7200,
52fc1a79d9SHeiko Schocher 0x70B4,
53fc1a79d9SHeiko Schocher 0x7200,
54fc1a79d9SHeiko Schocher 0x70B5,
55fc1a79d9SHeiko Schocher 0x7242,
56fc1a79d9SHeiko Schocher 0x7210,
57fc1a79d9SHeiko Schocher 0x7210,
58fc1a79d9SHeiko Schocher 0x7200,
59fc1a79d9SHeiko Schocher 0x7220,
60fc1a79d9SHeiko Schocher 0x70B6,
61fc1a79d9SHeiko Schocher 0x720B,
62fc1a79d9SHeiko Schocher 0x720F,
63fc1a79d9SHeiko Schocher 0x723C,
64fc1a79d9SHeiko Schocher 0x7213,
65fc1a79d9SHeiko Schocher 0x7213,
66fc1a79d9SHeiko Schocher 0x72E8,
67fc1a79d9SHeiko Schocher 0x70B7,
68fc1a79d9SHeiko Schocher 0x7246,
69fc1a79d9SHeiko Schocher 0x7206,
70fc1a79d9SHeiko Schocher 0x720C,
71fc1a79d9SHeiko Schocher 0x7200,
72fc1a79d9SHeiko Schocher 0x7200,
73fc1a79d9SHeiko Schocher };
74fc1a79d9SHeiko Schocher
75fc1a79d9SHeiko Schocher debug("transfer display mode settings\n");
76fc1a79d9SHeiko Schocher lb043wv_spi_write_u16_array(spi, display_mode_settings,
77fc1a79d9SHeiko Schocher ARRAY_SIZE(display_mode_settings));
78fc1a79d9SHeiko Schocher }
79fc1a79d9SHeiko Schocher
lb043wv_power_settings(struct spi_slave * spi)80fc1a79d9SHeiko Schocher static void lb043wv_power_settings(struct spi_slave *spi)
81fc1a79d9SHeiko Schocher {
82fc1a79d9SHeiko Schocher static u16 power_settings[] = {
83fc1a79d9SHeiko Schocher 0x70C0,
84fc1a79d9SHeiko Schocher 0x7201,
85fc1a79d9SHeiko Schocher 0x7211,
86fc1a79d9SHeiko Schocher 0x70C3,
87fc1a79d9SHeiko Schocher 0x7207,
88fc1a79d9SHeiko Schocher 0x7203,
89fc1a79d9SHeiko Schocher 0x7204,
90fc1a79d9SHeiko Schocher 0x7204,
91fc1a79d9SHeiko Schocher 0x7204,
92fc1a79d9SHeiko Schocher 0x70C4,
93fc1a79d9SHeiko Schocher 0x7212,
94fc1a79d9SHeiko Schocher 0x7224,
95fc1a79d9SHeiko Schocher 0x7218,
96fc1a79d9SHeiko Schocher 0x7218,
97fc1a79d9SHeiko Schocher 0x7202,
98fc1a79d9SHeiko Schocher 0x7249,
99fc1a79d9SHeiko Schocher 0x70C5,
100fc1a79d9SHeiko Schocher 0x726F,
101fc1a79d9SHeiko Schocher 0x70C6,
102fc1a79d9SHeiko Schocher 0x7241,
103fc1a79d9SHeiko Schocher 0x7263,
104fc1a79d9SHeiko Schocher };
105fc1a79d9SHeiko Schocher
106fc1a79d9SHeiko Schocher debug("transfer power settings\n");
107fc1a79d9SHeiko Schocher lb043wv_spi_write_u16_array(spi, power_settings,
108fc1a79d9SHeiko Schocher ARRAY_SIZE(power_settings));
109fc1a79d9SHeiko Schocher }
110fc1a79d9SHeiko Schocher
lb043wv_gamma_settings(struct spi_slave * spi)111fc1a79d9SHeiko Schocher static void lb043wv_gamma_settings(struct spi_slave *spi)
112fc1a79d9SHeiko Schocher {
113fc1a79d9SHeiko Schocher static u16 gamma_settings[] = {
114fc1a79d9SHeiko Schocher 0x70D0,
115fc1a79d9SHeiko Schocher 0x7203,
116fc1a79d9SHeiko Schocher 0x7207,
117fc1a79d9SHeiko Schocher 0x7273,
118fc1a79d9SHeiko Schocher 0x7235,
119fc1a79d9SHeiko Schocher 0x7200,
120fc1a79d9SHeiko Schocher 0x7201,
121fc1a79d9SHeiko Schocher 0x7220,
122fc1a79d9SHeiko Schocher 0x7200,
123fc1a79d9SHeiko Schocher 0x7203,
124fc1a79d9SHeiko Schocher 0x70D1,
125fc1a79d9SHeiko Schocher 0x7203,
126fc1a79d9SHeiko Schocher 0x7207,
127fc1a79d9SHeiko Schocher 0x7273,
128fc1a79d9SHeiko Schocher 0x7235,
129fc1a79d9SHeiko Schocher 0x7200,
130fc1a79d9SHeiko Schocher 0x7201,
131fc1a79d9SHeiko Schocher 0x7220,
132fc1a79d9SHeiko Schocher 0x7200,
133fc1a79d9SHeiko Schocher 0x7203,
134fc1a79d9SHeiko Schocher 0x70D2,
135fc1a79d9SHeiko Schocher 0x7203,
136fc1a79d9SHeiko Schocher 0x7207,
137fc1a79d9SHeiko Schocher 0x7273,
138fc1a79d9SHeiko Schocher 0x7235,
139fc1a79d9SHeiko Schocher 0x7200,
140fc1a79d9SHeiko Schocher 0x7201,
141fc1a79d9SHeiko Schocher 0x7220,
142fc1a79d9SHeiko Schocher 0x7200,
143fc1a79d9SHeiko Schocher 0x7203,
144fc1a79d9SHeiko Schocher 0x70D3,
145fc1a79d9SHeiko Schocher 0x7203,
146fc1a79d9SHeiko Schocher 0x7207,
147fc1a79d9SHeiko Schocher 0x7273,
148fc1a79d9SHeiko Schocher 0x7235,
149fc1a79d9SHeiko Schocher 0x7200,
150fc1a79d9SHeiko Schocher 0x7201,
151fc1a79d9SHeiko Schocher 0x7220,
152fc1a79d9SHeiko Schocher 0x7200,
153fc1a79d9SHeiko Schocher 0x7203,
154fc1a79d9SHeiko Schocher 0x70D4,
155fc1a79d9SHeiko Schocher 0x7203,
156fc1a79d9SHeiko Schocher 0x7207,
157fc1a79d9SHeiko Schocher 0x7273,
158fc1a79d9SHeiko Schocher 0x7235,
159fc1a79d9SHeiko Schocher 0x7200,
160fc1a79d9SHeiko Schocher 0x7201,
161fc1a79d9SHeiko Schocher 0x7220,
162fc1a79d9SHeiko Schocher 0x7200,
163fc1a79d9SHeiko Schocher 0x7203,
164fc1a79d9SHeiko Schocher 0x70D5,
165fc1a79d9SHeiko Schocher 0x7203,
166fc1a79d9SHeiko Schocher 0x7207,
167fc1a79d9SHeiko Schocher 0x7273,
168fc1a79d9SHeiko Schocher 0x7235,
169fc1a79d9SHeiko Schocher 0x7200,
170fc1a79d9SHeiko Schocher 0x7201,
171fc1a79d9SHeiko Schocher 0x7220,
172fc1a79d9SHeiko Schocher 0x7200,
173fc1a79d9SHeiko Schocher 0x7203,
174fc1a79d9SHeiko Schocher };
175fc1a79d9SHeiko Schocher
176fc1a79d9SHeiko Schocher debug("transfer gamma settings\n");
177fc1a79d9SHeiko Schocher lb043wv_spi_write_u16_array(spi, gamma_settings,
178fc1a79d9SHeiko Schocher ARRAY_SIZE(gamma_settings));
179fc1a79d9SHeiko Schocher }
180fc1a79d9SHeiko Schocher
lb043wv_display_on(struct spi_slave * spi)181fc1a79d9SHeiko Schocher static void lb043wv_display_on(struct spi_slave *spi)
182fc1a79d9SHeiko Schocher {
183fc1a79d9SHeiko Schocher static u16 sleep_out = 0x7011;
184fc1a79d9SHeiko Schocher static u16 display_on = 0x7029;
185fc1a79d9SHeiko Schocher
186fc1a79d9SHeiko Schocher lb043wv_spi_write_u16(spi, sleep_out);
187fc1a79d9SHeiko Schocher mdelay(PWR_ON_DELAY_MSECS);
188fc1a79d9SHeiko Schocher lb043wv_spi_write_u16(spi, display_on);
189fc1a79d9SHeiko Schocher }
190fc1a79d9SHeiko Schocher
lg4573_spi_startup(unsigned int bus,unsigned int cs,unsigned int max_hz,unsigned int spi_mode)191fc1a79d9SHeiko Schocher int lg4573_spi_startup(unsigned int bus, unsigned int cs,
192fc1a79d9SHeiko Schocher unsigned int max_hz, unsigned int spi_mode)
193fc1a79d9SHeiko Schocher {
194fc1a79d9SHeiko Schocher struct spi_slave *spi;
195fc1a79d9SHeiko Schocher int ret;
196fc1a79d9SHeiko Schocher
197fc1a79d9SHeiko Schocher spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
198fc1a79d9SHeiko Schocher if (!spi) {
199fc1a79d9SHeiko Schocher debug("%s: Failed to set up slave\n", __func__);
200fc1a79d9SHeiko Schocher return -1;
201fc1a79d9SHeiko Schocher }
202fc1a79d9SHeiko Schocher
203fc1a79d9SHeiko Schocher ret = spi_claim_bus(spi);
204fc1a79d9SHeiko Schocher if (ret) {
205fc1a79d9SHeiko Schocher debug("%s: Failed to claim SPI bus: %d\n", __func__, ret);
206fc1a79d9SHeiko Schocher goto err_claim_bus;
207fc1a79d9SHeiko Schocher }
208fc1a79d9SHeiko Schocher
209fc1a79d9SHeiko Schocher lb043wv_display_mode_settings(spi);
210fc1a79d9SHeiko Schocher lb043wv_power_settings(spi);
211fc1a79d9SHeiko Schocher lb043wv_gamma_settings(spi);
212fc1a79d9SHeiko Schocher
213fc1a79d9SHeiko Schocher lb043wv_display_on(spi);
214fc1a79d9SHeiko Schocher return 0;
215fc1a79d9SHeiko Schocher err_claim_bus:
216fc1a79d9SHeiko Schocher spi_free_slave(spi);
217fc1a79d9SHeiko Schocher return -1;
218fc1a79d9SHeiko Schocher }
219fc1a79d9SHeiko Schocher
do_lgset(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])220fc1a79d9SHeiko Schocher static int do_lgset(cmd_tbl_t *cmdtp, int flag, int argc,
221fc1a79d9SHeiko Schocher char * const argv[])
222fc1a79d9SHeiko Schocher {
223*c4e498d9SHeiko Schocher lg4573_spi_startup(CONFIG_LG4573_BUS, CONFIG_LG4573_CS, 10000000,
224*c4e498d9SHeiko Schocher SPI_MODE_0);
225fc1a79d9SHeiko Schocher return 0;
226fc1a79d9SHeiko Schocher }
227fc1a79d9SHeiko Schocher
228fc1a79d9SHeiko Schocher U_BOOT_CMD(
229fc1a79d9SHeiko Schocher lgset, 2, 1, do_lgset,
230fc1a79d9SHeiko Schocher "set lgdisplay",
231fc1a79d9SHeiko Schocher ""
232fc1a79d9SHeiko Schocher );
233