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