diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/backlight/Kconfig | 4 | ||||
-rw-r--r-- | drivers/video/backlight/tdo24m.c | 94 |
2 files changed, 88 insertions, 10 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 4a4dd9adc328..7ee2313ed6b8 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -52,11 +52,11 @@ config LCD_ILI9320 | |||
52 | then say y to include a power driver for it. | 52 | then say y to include a power driver for it. |
53 | 53 | ||
54 | config LCD_TDO24M | 54 | config LCD_TDO24M |
55 | tristate "Toppoly TDO24M LCD Panels support" | 55 | tristate "Toppoly TDO24M and TDO35S LCD Panels support" |
56 | depends on LCD_CLASS_DEVICE && SPI_MASTER | 56 | depends on LCD_CLASS_DEVICE && SPI_MASTER |
57 | default n | 57 | default n |
58 | help | 58 | help |
59 | If you have a Toppoly TDO24M series LCD panel, say y here to | 59 | If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to |
60 | include the support for it. | 60 | include the support for it. |
61 | 61 | ||
62 | config LCD_VGG2432A4 | 62 | config LCD_VGG2432A4 |
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 8427669162ea..1dae7f8f3c6b 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/spi/spi.h> | 16 | #include <linux/spi/spi.h> |
17 | #include <linux/spi/tdo24m.h> | ||
17 | #include <linux/fb.h> | 18 | #include <linux/fb.h> |
18 | #include <linux/lcd.h> | 19 | #include <linux/lcd.h> |
19 | 20 | ||
@@ -31,6 +32,9 @@ struct tdo24m { | |||
31 | struct spi_transfer xfer; | 32 | struct spi_transfer xfer; |
32 | uint8_t *buf; | 33 | uint8_t *buf; |
33 | 34 | ||
35 | int (*adj_mode)(struct tdo24m *lcd, int mode); | ||
36 | int color_invert; | ||
37 | |||
34 | int power; | 38 | int power; |
35 | int mode; | 39 | int mode; |
36 | }; | 40 | }; |
@@ -66,7 +70,7 @@ static uint32_t lcd_panel_off[] = { | |||
66 | CMD_NULL, | 70 | CMD_NULL, |
67 | }; | 71 | }; |
68 | 72 | ||
69 | static uint32_t lcd_vga_pass_through[] = { | 73 | static uint32_t lcd_vga_pass_through_tdo24m[] = { |
70 | CMD1(0xB0, 0x16), | 74 | CMD1(0xB0, 0x16), |
71 | CMD1(0xBC, 0x80), | 75 | CMD1(0xBC, 0x80), |
72 | CMD1(0xE1, 0x00), | 76 | CMD1(0xE1, 0x00), |
@@ -75,7 +79,7 @@ static uint32_t lcd_vga_pass_through[] = { | |||
75 | CMD_NULL, | 79 | CMD_NULL, |
76 | }; | 80 | }; |
77 | 81 | ||
78 | static uint32_t lcd_qvga_pass_through[] = { | 82 | static uint32_t lcd_qvga_pass_through_tdo24m[] = { |
79 | CMD1(0xB0, 0x16), | 83 | CMD1(0xB0, 0x16), |
80 | CMD1(0xBC, 0x81), | 84 | CMD1(0xBC, 0x81), |
81 | CMD1(0xE1, 0x00), | 85 | CMD1(0xE1, 0x00), |
@@ -84,7 +88,7 @@ static uint32_t lcd_qvga_pass_through[] = { | |||
84 | CMD_NULL, | 88 | CMD_NULL, |
85 | }; | 89 | }; |
86 | 90 | ||
87 | static uint32_t lcd_vga_transfer[] = { | 91 | static uint32_t lcd_vga_transfer_tdo24m[] = { |
88 | CMD1(0xcf, 0x02), /* Blanking period control (1) */ | 92 | CMD1(0xcf, 0x02), /* Blanking period control (1) */ |
89 | CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ | 93 | CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ |
90 | CMD1(0xd1, 0x01), /* CKV timing control on/off */ | 94 | CMD1(0xd1, 0x01), /* CKV timing control on/off */ |
@@ -110,6 +114,35 @@ static uint32_t lcd_qvga_transfer[] = { | |||
110 | CMD_NULL, | 114 | CMD_NULL, |
111 | }; | 115 | }; |
112 | 116 | ||
117 | static uint32_t lcd_vga_pass_through_tdo35s[] = { | ||
118 | CMD1(0xB0, 0x16), | ||
119 | CMD1(0xBC, 0x80), | ||
120 | CMD1(0xE1, 0x00), | ||
121 | CMD1(0x3B, 0x00), | ||
122 | CMD_NULL, | ||
123 | }; | ||
124 | |||
125 | static uint32_t lcd_qvga_pass_through_tdo35s[] = { | ||
126 | CMD1(0xB0, 0x16), | ||
127 | CMD1(0xBC, 0x81), | ||
128 | CMD1(0xE1, 0x00), | ||
129 | CMD1(0x3B, 0x22), | ||
130 | CMD_NULL, | ||
131 | }; | ||
132 | |||
133 | static uint32_t lcd_vga_transfer_tdo35s[] = { | ||
134 | CMD1(0xcf, 0x02), /* Blanking period control (1) */ | ||
135 | CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ | ||
136 | CMD1(0xd1, 0x01), /* CKV timing control on/off */ | ||
137 | CMD2(0xd2, 0x00, 0x1e), /* CKV 1,2 timing control */ | ||
138 | CMD2(0xd3, 0x14, 0x28), /* OEV timing control */ | ||
139 | CMD2(0xd4, 0x28, 0x64), /* ASW timing control (1) */ | ||
140 | CMD1(0xd5, 0x28), /* ASW timing control (2) */ | ||
141 | CMD0(0x21), /* Invert for normally black display */ | ||
142 | CMD0(0x29), /* Display on */ | ||
143 | CMD_NULL, | ||
144 | }; | ||
145 | |||
113 | static uint32_t lcd_panel_config[] = { | 146 | static uint32_t lcd_panel_config[] = { |
114 | CMD2(0xb8, 0xff, 0xf9), /* Output control */ | 147 | CMD2(0xb8, 0xff, 0xf9), /* Output control */ |
115 | CMD0(0x11), /* sleep out */ | 148 | CMD0(0x11), /* sleep out */ |
@@ -148,6 +181,8 @@ static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array) | |||
148 | int nparams, err = 0; | 181 | int nparams, err = 0; |
149 | 182 | ||
150 | for (; *p != CMD_NULL; p++) { | 183 | for (; *p != CMD_NULL; p++) { |
184 | if (!lcd->color_invert && *p == CMD0(0x21)) | ||
185 | continue; | ||
151 | 186 | ||
152 | nparams = (*p >> 30) & 0x3; | 187 | nparams = (*p >> 30) & 0x3; |
153 | 188 | ||
@@ -184,12 +219,33 @@ static int tdo24m_adj_mode(struct tdo24m *lcd, int mode) | |||
184 | { | 219 | { |
185 | switch (mode) { | 220 | switch (mode) { |
186 | case MODE_VGA: | 221 | case MODE_VGA: |
187 | tdo24m_writes(lcd, lcd_vga_pass_through); | 222 | tdo24m_writes(lcd, lcd_vga_pass_through_tdo24m); |
188 | tdo24m_writes(lcd, lcd_panel_config); | 223 | tdo24m_writes(lcd, lcd_panel_config); |
189 | tdo24m_writes(lcd, lcd_vga_transfer); | 224 | tdo24m_writes(lcd, lcd_vga_transfer_tdo24m); |
190 | break; | 225 | break; |
191 | case MODE_QVGA: | 226 | case MODE_QVGA: |
192 | tdo24m_writes(lcd, lcd_qvga_pass_through); | 227 | tdo24m_writes(lcd, lcd_qvga_pass_through_tdo24m); |
228 | tdo24m_writes(lcd, lcd_panel_config); | ||
229 | tdo24m_writes(lcd, lcd_qvga_transfer); | ||
230 | break; | ||
231 | default: | ||
232 | return -EINVAL; | ||
233 | } | ||
234 | |||
235 | lcd->mode = mode; | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int tdo35s_adj_mode(struct tdo24m *lcd, int mode) | ||
240 | { | ||
241 | switch (mode) { | ||
242 | case MODE_VGA: | ||
243 | tdo24m_writes(lcd, lcd_vga_pass_through_tdo35s); | ||
244 | tdo24m_writes(lcd, lcd_panel_config); | ||
245 | tdo24m_writes(lcd, lcd_vga_transfer_tdo35s); | ||
246 | break; | ||
247 | case MODE_QVGA: | ||
248 | tdo24m_writes(lcd, lcd_qvga_pass_through_tdo35s); | ||
193 | tdo24m_writes(lcd, lcd_panel_config); | 249 | tdo24m_writes(lcd, lcd_panel_config); |
194 | tdo24m_writes(lcd, lcd_qvga_transfer); | 250 | tdo24m_writes(lcd, lcd_qvga_transfer); |
195 | break; | 251 | break; |
@@ -213,7 +269,7 @@ static int tdo24m_power_on(struct tdo24m *lcd) | |||
213 | if (err) | 269 | if (err) |
214 | goto out; | 270 | goto out; |
215 | 271 | ||
216 | err = tdo24m_adj_mode(lcd, lcd->mode); | 272 | err = lcd->adj_mode(lcd, lcd->mode); |
217 | out: | 273 | out: |
218 | return err; | 274 | return err; |
219 | } | 275 | } |
@@ -262,7 +318,7 @@ static int tdo24m_set_mode(struct lcd_device *ld, struct fb_videomode *m) | |||
262 | if (lcd->mode == mode) | 318 | if (lcd->mode == mode) |
263 | return 0; | 319 | return 0; |
264 | 320 | ||
265 | return tdo24m_adj_mode(lcd, mode); | 321 | return lcd->adj_mode(lcd, mode); |
266 | } | 322 | } |
267 | 323 | ||
268 | static struct lcd_ops tdo24m_ops = { | 324 | static struct lcd_ops tdo24m_ops = { |
@@ -276,8 +332,16 @@ static int __devinit tdo24m_probe(struct spi_device *spi) | |||
276 | struct tdo24m *lcd; | 332 | struct tdo24m *lcd; |
277 | struct spi_message *m; | 333 | struct spi_message *m; |
278 | struct spi_transfer *x; | 334 | struct spi_transfer *x; |
335 | struct tdo24m_platform_data *pdata; | ||
336 | enum tdo24m_model model; | ||
279 | int err; | 337 | int err; |
280 | 338 | ||
339 | pdata = spi->dev.platform_data; | ||
340 | if (pdata) | ||
341 | model = pdata->model; | ||
342 | else | ||
343 | model = TDO24M; | ||
344 | |||
281 | spi->bits_per_word = 8; | 345 | spi->bits_per_word = 8; |
282 | spi->mode = SPI_MODE_3; | 346 | spi->mode = SPI_MODE_3; |
283 | err = spi_setup(spi); | 347 | err = spi_setup(spi); |
@@ -306,6 +370,20 @@ static int __devinit tdo24m_probe(struct spi_device *spi) | |||
306 | x->tx_buf = &lcd->buf[0]; | 370 | x->tx_buf = &lcd->buf[0]; |
307 | spi_message_add_tail(x, m); | 371 | spi_message_add_tail(x, m); |
308 | 372 | ||
373 | switch (model) { | ||
374 | case TDO24M: | ||
375 | lcd->color_invert = 1; | ||
376 | lcd->adj_mode = tdo24m_adj_mode; | ||
377 | break; | ||
378 | case TDO35S: | ||
379 | lcd->adj_mode = tdo35s_adj_mode; | ||
380 | lcd->color_invert = 0; | ||
381 | break; | ||
382 | default: | ||
383 | dev_err(&spi->dev, "Unsupported model"); | ||
384 | goto out_free; | ||
385 | } | ||
386 | |||
309 | lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev, | 387 | lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev, |
310 | lcd, &tdo24m_ops); | 388 | lcd, &tdo24m_ops); |
311 | if (IS_ERR(lcd->lcd_dev)) { | 389 | if (IS_ERR(lcd->lcd_dev)) { |