1 /*
2  * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c
3  * active panel using spi interface to do init
4  *
5  * Copyright (C) 2012 Marvell Technology Group Ltd.
6  * Authors:  Guoqing Li <ligq@marvell.com>
7  *          Lisa Du <cldu@marvell.com>
8  *          Zhou Zhu <zzhu3@marvell.com>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2 of the License, or (at your
13  * option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  * more details.
19  *
20  * You should have received a copy of the GNU General Public License along with
21  * this program.  If not, see <http://www.gnu.org/licenses/>.
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 
36 static 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 
79 static u16 poweroff[] = {
80 	0x07d9,
81 };
82 
83 struct tpohvga_plat_data {
84 	void (*plat_onoff)(int status);
85 	struct spi_device *spi;
86 };
87 
88 static 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 
108 static 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 
125 static int tpohvga_get_modelist(struct mmp_panel *panel,
126 		struct mmp_mode **modelist)
127 {
128 	*modelist = mmp_modes_tpohvga;
129 	return 1;
130 }
131 
132 static 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 
139 static 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 	/* get configs from platform data */
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 	/* setup spi related info */
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 
175 static struct spi_driver panel_tpohvga_driver = {
176 	.driver		= {
177 		.name	= "tpo-hvga",
178 	},
179 	.probe		= tpohvga_probe,
180 };
181 module_spi_driver(panel_tpohvga_driver);
182 
183 MODULE_AUTHOR("Lisa Du<cldu@marvell.com>");
184 MODULE_DESCRIPTION("Panel driver for tpohvga");
185 MODULE_LICENSE("GPL");
186