1 /*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <boot/boot.h>
30 #include <boot/board.h>
31 #include <msm7k/mddi.h>
32
33 unsigned fb_width = 0;
34 unsigned fb_height = 0;
35
36 static unsigned short *FB;
37 static mddi_llentry *mlist;
38
wr32(void * _dst,unsigned n)39 void wr32(void *_dst, unsigned n)
40 {
41 unsigned char *src = (unsigned char*) &n;
42 unsigned char *dst = _dst;
43
44 dst[0] = src[0];
45 dst[1] = src[1];
46 dst[2] = src[2];
47 dst[3] = src[3];
48 };
49
printcaps(mddi_client_caps * c)50 void printcaps(mddi_client_caps *c)
51 {
52 if((c->length != 0x4a) || (c->type != 0x42)) {
53 dprintf("bad caps header\n");
54 memset(c, 0, sizeof(*c));
55 return;
56 }
57
58 dprintf("mddi: bm: %d,%d win %d,%d rgb %x\n",
59 c->bitmap_width, c->bitmap_height,
60 c->display_window_width, c->display_window_height,
61 c->rgb_cap);
62 dprintf("mddi: vend %x prod %x\n",
63 c->manufacturer_name, c->product_code);
64
65 fb_width = c->bitmap_width;
66 fb_height = c->bitmap_height;
67
68 panel_init(c);
69 }
70
71 mddi_llentry *mlist_remote_write = 0;
72
mddi_remote_write(unsigned val,unsigned reg)73 void mddi_remote_write(unsigned val, unsigned reg)
74 {
75 mddi_llentry *ll;
76 mddi_register_access *ra;
77 unsigned s;
78
79 if(mlist_remote_write == 0) {
80 mlist_remote_write = alloc(sizeof(mddi_llentry));
81 }
82
83 ll = mlist_remote_write;
84
85 ra = &(ll->u.r);
86 ra->length = 14 + 4;
87 ra->type = TYPE_REGISTER_ACCESS;
88 ra->client_id = 0;
89 ra->rw_info = MDDI_WRITE | 1;
90 ra->crc = 0;
91
92 wr32(&ra->reg_addr, reg);
93 wr32(&ra->reg_data, val);
94
95 ll->flags = 1;
96 ll->header_count = 14;
97 ll->data_count = 4;
98 wr32(&ll->data, (unsigned) &ra->reg_data);
99 wr32(&ll->next, 0);
100 ll->reserved = 0;
101
102 writel((unsigned) ll, MDDI_PRI_PTR);
103
104 s = readl(MDDI_STAT);
105 while((s & 0x20) == 0){
106 s = readl(MDDI_STAT);
107 }
108 }
109
mddi_start_update(void)110 void mddi_start_update(void)
111 {
112 writel((unsigned) mlist, MDDI_PRI_PTR);
113 }
114
mddi_update_done(void)115 int mddi_update_done(void)
116 {
117 return !!(readl(MDDI_STAT) & MDDI_STAT_PRI_LINK_LIST_DONE);
118 }
119
mddi_do_cmd(unsigned cmd)120 void mddi_do_cmd(unsigned cmd)
121 {
122 writel(cmd, MDDI_CMD);
123
124 while (!(readl(MDDI_INT) & MDDI_INT_NO_REQ_PKTS_PENDING)) ;
125 }
126
127 unsigned char *rev_pkt_buf;
128
mddi_get_caps(void)129 void mddi_get_caps(void)
130 {
131 unsigned timeout = 100000;
132 unsigned n;
133
134 memset(rev_pkt_buf, 0xee, 256);
135
136 // writel(CMD_HIBERNATE, MDDI_CMD);
137 // writel(CMD_LINK_ACTIVE, MDDI_CMD);
138
139 writel(256, MDDI_REV_SIZE);
140 writel((unsigned) rev_pkt_buf, MDDI_REV_PTR);
141 mddi_do_cmd(CMD_FORCE_NEW_REV_PTR);
142
143 /* sometimes this will fail -- do it three times for luck... */
144 mddi_do_cmd(CMD_RTD_MEASURE);
145 mdelay(1);
146
147 mddi_do_cmd(CMD_RTD_MEASURE);
148 mdelay(1);
149
150 mddi_do_cmd(CMD_RTD_MEASURE);
151 mdelay(1);
152
153 mddi_do_cmd(CMD_GET_CLIENT_CAP);
154
155 do {
156 n = readl(MDDI_INT);
157 } while(!(n & MDDI_INT_REV_DATA_AVAIL) && (--timeout));
158
159 if(timeout == 0) dprintf("timeout\n");
160 printcaps((mddi_client_caps*) rev_pkt_buf);
161 }
162
163
mddi_init(void)164 void mddi_init(void)
165 {
166 unsigned n;
167
168 // dprintf("mddi_init()\n");
169
170 rev_pkt_buf = alloc(256);
171
172 mddi_do_cmd(CMD_RESET);
173
174 /* disable periodic rev encap */
175 mddi_do_cmd(CMD_PERIODIC_REV_ENC | 0);
176
177 writel(0x0001, MDDI_VERSION);
178 writel(0x3C00, MDDI_BPS);
179 writel(0x0003, MDDI_SPM);
180
181 writel(0x0005, MDDI_TA1_LEN);
182 writel(0x000C, MDDI_TA2_LEN);
183 writel(0x0096, MDDI_DRIVE_HI);
184 writel(0x0050, MDDI_DRIVE_LO);
185 writel(0x003C, MDDI_DISP_WAKE);
186 writel(0x0002, MDDI_REV_RATE_DIV);
187
188 /* needs to settle for 5uS */
189 if (readl(MDDI_PAD_CTL) == 0) {
190 writel(0x08000, MDDI_PAD_CTL);
191 udelay(5);
192 }
193
194 writel(0xA850F, MDDI_PAD_CTL);
195 writel(0x60006, MDDI_DRIVER_START_CNT);
196
197 writel((unsigned) rev_pkt_buf, MDDI_REV_PTR);
198 writel(256, MDDI_REV_SIZE);
199 writel(256, MDDI_REV_ENCAP_SZ);
200
201 mddi_do_cmd(CMD_FORCE_NEW_REV_PTR);
202
203 /* disable hibernate */
204 mddi_do_cmd(CMD_HIBERNATE | 0);
205
206 panel_backlight(0);
207
208 panel_poweron();
209
210 mddi_do_cmd(CMD_LINK_ACTIVE);
211
212 do {
213 n = readl(MDDI_STAT);
214 } while(!(n & MDDI_STAT_LINK_ACTIVE));
215
216 /* v > 8? v > 8 && < 0x19 ? */
217 writel(2, MDDI_TEST);
218
219 // writel(CMD_PERIODIC_REV_ENC | 0, MDDI_CMD); /* disable */
220
221 mddi_get_caps();
222
223 #if 0
224 writel(0x5666, MDDI_MDP_VID_FMT_DES);
225 writel(0x00C3, MDDI_MDP_VID_PIX_ATTR);
226 writel(0x0000, MDDI_MDP_CLIENTID);
227 #endif
228
229 dprintf("panel is %d x %d\n", fb_width, fb_height);
230
231 FB = alloc(2 * fb_width * fb_height);
232 mlist = alloc(sizeof(mddi_llentry) * (fb_height / 8));
233
234 // dprintf("FB @ %x mlist @ %x\n", (unsigned) FB, (unsigned) mlist);
235
236 for(n = 0; n < (fb_height / 8); n++) {
237 unsigned y = n * 8;
238 unsigned pixels = fb_width * 8;
239 mddi_video_stream *vs = &(mlist[n].u.v);
240
241 vs->length = sizeof(mddi_video_stream) - 2 + (pixels * 2);
242 vs->type = TYPE_VIDEO_STREAM;
243 vs->client_id = 0;
244 vs->format = 0x5565; // FORMAT_16BPP;
245 vs->pixattr = PIXATTR_BOTH_EYES | PIXATTR_TO_ALL;
246
247 vs->left = 0;
248 vs->right = fb_width - 1;
249 vs->top = y;
250 vs->bottom = y + 7;
251
252 vs->start_x = 0;
253 vs->start_y = y;
254
255 vs->pixels = pixels;
256 vs->crc = 0;
257 vs->reserved = 0;
258
259 mlist[n].header_count = sizeof(mddi_video_stream) - 2;
260 mlist[n].data_count = pixels * 2;
261 mlist[n].reserved = 0;
262 wr32(&mlist[n].data, ((unsigned) FB) + (y * fb_width * 2));
263
264 mlist[n].flags = 0;
265 wr32(&mlist[n].next, (unsigned) (mlist + n + 1));
266 }
267
268 mlist[n-1].flags = 1;
269 wr32(&mlist[n-1].next, 0);
270
271 writel(CMD_HIBERNATE, MDDI_CMD);
272 writel(CMD_LINK_ACTIVE, MDDI_CMD);
273
274 for(n = 0; n < (fb_width * fb_height); n++) FB[n] = 0;
275
276 mddi_start_update();
277
278 panel_backlight(1);
279 }
280
mddi_framebuffer(void)281 void *mddi_framebuffer(void)
282 {
283 return FB;
284 }
285
286