ALSA: hda - Add position_fix quirk for Biostar mobo
[pandora-kernel.git] / drivers / video / omap2 / displays / panel-tpo-td043mtea1.c
1 /*
2  * LCD panel driver for TPO TD043MTEA1
3  *
4  * Author: Gražvydas Ignotas <notasas@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <linux/module.h>
13 #include <linux/delay.h>
14 #include <linux/spi/spi.h>
15 #include <linux/regulator/consumer.h>
16 #include <linux/gpio.h>
17 #include <linux/err.h>
18
19 #include <plat/display.h>
20
21 #define TPO_R02_MODE(x)         ((x) & 7)
22 #define TPO_R02_MODE_800x480    7
23 #define TPO_R02_NCLK_RISING     BIT(3)
24 #define TPO_R02_HSYNC_HIGH      BIT(4)
25 #define TPO_R02_VSYNC_HIGH      BIT(5)
26
27 #define TPO_R03_NSTANDBY        BIT(0)
28 #define TPO_R03_EN_CP_CLK       BIT(1)
29 #define TPO_R03_EN_VGL_PUMP     BIT(2)
30 #define TPO_R03_EN_PWM          BIT(3)
31 #define TPO_R03_DRIVING_CAP_100 BIT(4)
32 #define TPO_R03_EN_PRE_CHARGE   BIT(6)
33 #define TPO_R03_SOFTWARE_CTL    BIT(7)
34
35 #define TPO_R04_NFLIP_H         BIT(0)
36 #define TPO_R04_NFLIP_V         BIT(1)
37 #define TPO_R04_CP_CLK_FREQ_1H  BIT(2)
38 #define TPO_R04_VGL_FREQ_1H     BIT(4)
39
40 #define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
41                         TPO_R03_EN_VGL_PUMP |  TPO_R03_EN_PWM | \
42                         TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
43                         TPO_R03_SOFTWARE_CTL)
44
45 #define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
46                         TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
47
48 static const u16 tpo_td043_def_gamma[12] = {
49         106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020
50 };
51
52 struct tpo_td043_device {
53         struct spi_device *spi;
54         struct regulator *vcc_reg;
55         u16 gamma[12];
56         u32 mode;
57         u32 hmirror:1;
58         u32 vmirror:1;
59 };
60
61 static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
62 {
63         struct spi_message      m;
64         struct spi_transfer     xfer;
65         u16                     w;
66         int                     r;
67
68         spi_message_init(&m);
69
70         memset(&xfer, 0, sizeof(xfer));
71
72         w = ((u16)addr << 10) | (1 << 8) | data;
73         xfer.tx_buf = &w;
74         xfer.bits_per_word = 16;
75         xfer.len = 2;
76         spi_message_add_tail(&xfer, &m);
77
78         r = spi_sync(spi, &m);
79         if (r < 0)
80                 dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
81         return r;
82 }
83
84 static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
85 {
86         u8 i, val;
87
88         /* gamma bits [9:8] */
89         for (val = i = 0; i < 4; i++)
90                 val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
91         tpo_td043_write(spi, 0x11, val);
92
93         for (val = i = 0; i < 4; i++)
94                 val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
95         tpo_td043_write(spi, 0x12, val);
96
97         for (val = i = 0; i < 4; i++)
98                 val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
99         tpo_td043_write(spi, 0x13, val);
100
101         /* gamma bits [7:0] */
102         for (val = i = 0; i < 12; i++)
103                 tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
104 }
105
106 static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
107 {
108         u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V | \
109                 TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
110         if (h)
111                 reg4 &= ~TPO_R04_NFLIP_H;
112         if (v)
113                 reg4 &= ~TPO_R04_NFLIP_V;
114
115         return tpo_td043_write(spi, 4, reg4);
116 }
117
118 static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
119 {
120         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
121
122         tpo_td043->hmirror = enable;
123         return tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
124                         tpo_td043->vmirror);
125 }
126
127 static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
128 {
129         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
130
131         return tpo_td043->hmirror;
132 }
133
134 static ssize_t tpo_td043_vmirror_show(struct device *dev,
135         struct device_attribute *attr, char *buf)
136 {
137         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
138
139         return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->vmirror);
140 }
141
142 static ssize_t tpo_td043_vmirror_store(struct device *dev,
143         struct device_attribute *attr, const char *buf, size_t count)
144 {
145         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
146         long val;
147         int ret;
148
149         ret = strict_strtol(buf, 0, &val);
150         if (ret < 0)
151                 return ret;
152
153         ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val);
154         if (ret < 0)
155                 return ret;
156
157         tpo_td043->vmirror = val;
158
159         return count;
160 }
161
162 static ssize_t tpo_td043_mode_show(struct device *dev,
163         struct device_attribute *attr, char *buf)
164 {
165         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
166
167         return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->mode);
168 }
169
170 static ssize_t tpo_td043_mode_store(struct device *dev,
171         struct device_attribute *attr, const char *buf, size_t count)
172 {
173         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
174         long val;
175         int ret;
176
177         ret = strict_strtol(buf, 0, &val);
178         if (ret != 0 || val & ~7)
179                 return -EINVAL;
180
181         tpo_td043->mode = val;
182
183         val |= TPO_R02_NCLK_RISING;
184         tpo_td043_write(tpo_td043->spi, 2, val);
185
186         return count;
187 }
188
189 static ssize_t tpo_td043_gamma_show(struct device *dev,
190         struct device_attribute *attr, char *buf)
191 {
192         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
193         ssize_t len = 0;
194         int ret;
195         int i;
196
197         for (i = 0; i < ARRAY_SIZE(tpo_td043->gamma); i++) {
198                 ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
199                                 tpo_td043->gamma[i]);
200                 if (ret < 0)
201                         return ret;
202                 len += ret;
203         }
204         buf[len - 1] = '\n';
205
206         return len;
207 }
208
209 static ssize_t tpo_td043_gamma_store(struct device *dev,
210         struct device_attribute *attr, const char *buf, size_t count)
211 {
212         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
213         unsigned int g[12];
214         int ret;
215         int i;
216
217         ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
218                         &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
219                         &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
220
221         if (ret != 12)
222                 return -EINVAL;
223
224         for (i = 0; i < 12; i++)
225                 tpo_td043->gamma[i] = g[i];
226
227         tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
228
229         return count;
230 }
231
232 static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
233                 tpo_td043_vmirror_show, tpo_td043_vmirror_store);
234 static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
235                 tpo_td043_mode_show, tpo_td043_mode_store);
236 static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
237                 tpo_td043_gamma_show, tpo_td043_gamma_store);
238
239 static struct attribute *tpo_td043_attrs[] = {
240         &dev_attr_vmirror.attr,
241         &dev_attr_mode.attr,
242         &dev_attr_gamma.attr,
243         NULL,
244 };
245
246 static struct attribute_group tpo_td043_attr_group = {
247         .attrs = tpo_td043_attrs,
248 };
249
250 static const struct omap_video_timings tpo_td043_timings = {
251         .x_res          = 800,
252         .y_res          = 480,
253
254         .pixel_clock    = 36000,
255
256         .hsw            = 1,
257         .hfp            = 68,
258         .hbp            = 214,
259
260         .vsw            = 1,
261         .vfp            = 39,
262         .vbp            = 34,
263 };
264
265 static int tpo_td043_power_on(struct omap_dss_device *dssdev)
266 {
267         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
268         int nreset_gpio = dssdev->reset_gpio;
269         int r;
270
271         r = omapdss_dpi_display_enable(dssdev);
272         if (r)
273                 goto err0;
274
275         if (dssdev->platform_enable) {
276                 r = dssdev->platform_enable(dssdev);
277                 if (r)
278                         goto err1;
279         }
280
281         regulator_enable(tpo_td043->vcc_reg);
282
283         /* wait for power up */
284         msleep(160);
285
286         if (gpio_is_valid(nreset_gpio))
287                 gpio_set_value(nreset_gpio, 1);
288
289         tpo_td043_write(tpo_td043->spi, 2,
290                         TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
291         tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_NORMAL);
292         tpo_td043_write(tpo_td043->spi, 0x20, 0xf0);
293         tpo_td043_write(tpo_td043->spi, 0x21, 0xf0);
294         tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
295                         tpo_td043->vmirror);
296         tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
297
298         return 0;
299 err1:
300         omapdss_dpi_display_disable(dssdev);
301 err0:
302         return r;
303 }
304
305 static void tpo_td043_power_off(struct omap_dss_device *dssdev)
306 {
307         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
308         int nreset_gpio = dssdev->reset_gpio;
309
310         tpo_td043_write(tpo_td043->spi, 3,
311                         TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
312
313         if (gpio_is_valid(nreset_gpio))
314                 gpio_set_value(nreset_gpio, 0);
315
316         /* wait for at least 2 vsyncs before cutting off power */
317         msleep(50);
318
319         tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_STANDBY);
320
321         regulator_disable(tpo_td043->vcc_reg);
322
323         if (dssdev->platform_disable)
324                 dssdev->platform_disable(dssdev);
325
326         omapdss_dpi_display_disable(dssdev);
327 }
328
329 static int tpo_td043_enable(struct omap_dss_device *dssdev)
330 {
331         int ret;
332
333         dev_dbg(&dssdev->dev, "enable\n");
334
335         ret = tpo_td043_power_on(dssdev);
336         if (ret)
337                 return ret;
338
339         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
340
341         return 0;
342 }
343
344 static void tpo_td043_disable(struct omap_dss_device *dssdev)
345 {
346         dev_dbg(&dssdev->dev, "disable\n");
347
348         tpo_td043_power_off(dssdev);
349
350         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
351 }
352
353 static int tpo_td043_suspend(struct omap_dss_device *dssdev)
354 {
355         tpo_td043_power_off(dssdev);
356         dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
357         return 0;
358 }
359
360 static int tpo_td043_resume(struct omap_dss_device *dssdev)
361 {
362         int r = 0;
363
364         r = tpo_td043_power_on(dssdev);
365         if (r)
366                 return r;
367
368         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
369
370         return 0;
371 }
372
373 static int tpo_td043_probe(struct omap_dss_device *dssdev)
374 {
375         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
376         int nreset_gpio = dssdev->reset_gpio;
377         int ret = 0;
378
379         dev_dbg(&dssdev->dev, "probe\n");
380
381         if (tpo_td043 == NULL) {
382                 dev_err(&dssdev->dev, "missing tpo_td043_device\n");
383                 return -ENODEV;
384         }
385
386         dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS |
387                                 OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IPC;
388         dssdev->panel.timings = tpo_td043_timings;
389         dssdev->ctrl.pixel_size = 24;
390
391         tpo_td043->mode = TPO_R02_MODE_800x480;
392         memcpy(tpo_td043->gamma, tpo_td043_def_gamma, sizeof(tpo_td043->gamma));
393
394         tpo_td043->vcc_reg = regulator_get(&dssdev->dev, "vcc");
395         if (IS_ERR(tpo_td043->vcc_reg)) {
396                 dev_err(&dssdev->dev, "failed to get LCD VCC regulator\n");
397                 ret = PTR_ERR(tpo_td043->vcc_reg);
398                 goto fail_regulator;
399         }
400
401         if (gpio_is_valid(nreset_gpio)) {
402                 ret = gpio_request(nreset_gpio, "lcd reset");
403                 if (ret < 0) {
404                         dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
405                         goto fail_gpio_req;
406                 }
407
408                 ret = gpio_direction_output(nreset_gpio, 0);
409                 if (ret < 0) {
410                         dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
411                         goto fail_gpio_direction;
412                 }
413         }
414
415         ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
416         if (ret)
417                 dev_warn(&dssdev->dev, "failed to create sysfs files\n");
418
419         return 0;
420
421 fail_gpio_direction:
422         gpio_free(nreset_gpio);
423 fail_gpio_req:
424         regulator_put(tpo_td043->vcc_reg);
425 fail_regulator:
426         kfree(tpo_td043);
427         return ret;
428 }
429
430 static void tpo_td043_remove(struct omap_dss_device *dssdev)
431 {
432         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
433         int nreset_gpio = dssdev->reset_gpio;
434
435         dev_dbg(&dssdev->dev, "remove\n");
436
437         sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
438         regulator_put(tpo_td043->vcc_reg);
439         if (gpio_is_valid(nreset_gpio))
440                 gpio_free(nreset_gpio);
441 }
442
443 static struct omap_dss_driver tpo_td043_driver = {
444         .probe          = tpo_td043_probe,
445         .remove         = tpo_td043_remove,
446
447         .enable         = tpo_td043_enable,
448         .disable        = tpo_td043_disable,
449         .suspend        = tpo_td043_suspend,
450         .resume         = tpo_td043_resume,
451         .set_mirror     = tpo_td043_set_hmirror,
452         .get_mirror     = tpo_td043_get_hmirror,
453
454         .driver         = {
455                 .name   = "tpo_td043mtea1_panel",
456                 .owner  = THIS_MODULE,
457         },
458 };
459
460 static int tpo_td043_spi_probe(struct spi_device *spi)
461 {
462         struct omap_dss_device *dssdev = spi->dev.platform_data;
463         struct tpo_td043_device *tpo_td043;
464         int ret;
465
466         if (dssdev == NULL) {
467                 dev_err(&spi->dev, "missing dssdev\n");
468                 return -ENODEV;
469         }
470
471         spi->bits_per_word = 16;
472         spi->mode = SPI_MODE_0;
473
474         ret = spi_setup(spi);
475         if (ret < 0) {
476                 dev_err(&spi->dev, "spi_setup failed: %d\n", ret);
477                 return ret;
478         }
479
480         tpo_td043 = kzalloc(sizeof(*tpo_td043), GFP_KERNEL);
481         if (tpo_td043 == NULL)
482                 return -ENOMEM;
483
484         tpo_td043->spi = spi;
485         dev_set_drvdata(&spi->dev, tpo_td043);
486         dev_set_drvdata(&dssdev->dev, tpo_td043);
487
488         omap_dss_register_driver(&tpo_td043_driver);
489
490         return 0;
491 }
492
493 static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
494 {
495         struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev);
496
497         omap_dss_unregister_driver(&tpo_td043_driver);
498         kfree(tpo_td043);
499
500         return 0;
501 }
502
503 static struct spi_driver tpo_td043_spi_driver = {
504         .driver = {
505                 .name   = "tpo_td043mtea1_panel_spi",
506                 .bus    = &spi_bus_type,
507                 .owner  = THIS_MODULE,
508         },
509         .probe  = tpo_td043_spi_probe,
510         .remove = __devexit_p(tpo_td043_spi_remove),
511 };
512
513 static int __init tpo_td043_init(void)
514 {
515         return spi_register_driver(&tpo_td043_spi_driver);
516 }
517
518 static void __exit tpo_td043_exit(void)
519 {
520         spi_unregister_driver(&tpo_td043_spi_driver);
521 }
522
523 module_init(tpo_td043_init);
524 module_exit(tpo_td043_exit);
525
526 MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
527 MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
528 MODULE_LICENSE("GPL");