1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/kernel.h>
28#include <linux/errno.h>
29#include <linux/string.h>
30#include <linux/delay.h>
31#include <linux/platform_device.h>
32#include <linux/err.h>
33#include <linux/spi/spi.h>
34#include <video/mmp_disp.h>
35
36static u16 init[] = {
37 0x0801,
38 0x0800,
39 0x0200,
40 0x0304,
41 0x040e,
42 0x0903,
43 0x0b18,
44 0x0c53,
45 0x0d01,
46 0x0ee0,
47 0x0f01,
48 0x1058,
49 0x201e,
50 0x210a,
51 0x220a,
52 0x231e,
53 0x2400,
54 0x2532,
55 0x2600,
56 0x27ac,
57 0x2904,
58 0x2aa2,
59 0x2b45,
60 0x2c45,
61 0x2d15,
62 0x2e5a,
63 0x2fff,
64 0x306b,
65 0x310d,
66 0x3248,
67 0x3382,
68 0x34bd,
69 0x35e7,
70 0x3618,
71 0x3794,
72 0x3801,
73 0x395d,
74 0x3aae,
75 0x3bff,
76 0x07c9,
77};
78
79static u16 poweroff[] = {
80 0x07d9,
81};
82
83struct tpohvga_plat_data {
84 void (*plat_onoff)(int status);
85 struct spi_device *spi;
86};
87
88static void tpohvga_onoff(struct mmp_panel *panel, int status)
89{
90 struct tpohvga_plat_data *plat = panel->plat_data;
91 int ret;
92
93 if (status) {
94 plat->plat_onoff(1);
95
96 ret = spi_write(plat->spi, init, sizeof(init));
97 if (ret < 0)
98 dev_warn(panel->dev, "init cmd failed(%d)\n", ret);
99 } else {
100 ret = spi_write(plat->spi, poweroff, sizeof(poweroff));
101 if (ret < 0)
102 dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret);
103
104 plat->plat_onoff(0);
105 }
106}
107
108static struct mmp_mode mmp_modes_tpohvga[] = {
109 [0] = {
110 .pixclock_freq = 10394400,
111 .refresh = 60,
112 .xres = 320,
113 .yres = 480,
114 .hsync_len = 10,
115 .left_margin = 15,
116 .right_margin = 10,
117 .vsync_len = 2,
118 .upper_margin = 4,
119 .lower_margin = 2,
120 .invert_pixclock = 1,
121 .pix_fmt_out = PIXFMT_RGB565,
122 },
123};
124
125static int tpohvga_get_modelist(struct mmp_panel *panel,
126 struct mmp_mode **modelist)
127{
128 *modelist = mmp_modes_tpohvga;
129 return 1;
130}
131
132static struct mmp_panel panel_tpohvga = {
133 .name = "tpohvga",
134 .panel_type = PANELTYPE_ACTIVE,
135 .get_modelist = tpohvga_get_modelist,
136 .set_onoff = tpohvga_onoff,
137};
138
139static int tpohvga_probe(struct spi_device *spi)
140{
141 struct mmp_mach_panel_info *mi;
142 int ret;
143 struct tpohvga_plat_data *plat_data;
144
145
146 mi = spi->dev.platform_data;
147 if (mi == NULL) {
148 dev_err(&spi->dev, "%s: no platform data defined\n", __func__);
149 return -EINVAL;
150 }
151
152
153 spi->bits_per_word = 16;
154 ret = spi_setup(spi);
155 if (ret < 0) {
156 dev_err(&spi->dev, "spi setup failed %d", ret);
157 return ret;
158 }
159
160 plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL);
161 if (plat_data == NULL)
162 return -ENOMEM;
163
164 plat_data->spi = spi;
165 plat_data->plat_onoff = mi->plat_set_onoff;
166 panel_tpohvga.plat_data = plat_data;
167 panel_tpohvga.plat_path_name = mi->plat_path_name;
168 panel_tpohvga.dev = &spi->dev;
169
170 mmp_register_panel(&panel_tpohvga);
171
172 return 0;
173}
174
175static struct spi_driver panel_tpohvga_driver = {
176 .driver = {
177 .name = "tpo-hvga",
178 .owner = THIS_MODULE,
179 },
180 .probe = tpohvga_probe,
181};
182module_spi_driver(panel_tpohvga_driver);
183
184MODULE_AUTHOR("Lisa Du<cldu@marvell.com>");
185MODULE_DESCRIPTION("Panel driver for tpohvga");
186MODULE_LICENSE("GPL");
187