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 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 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 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 110 void mddi_start_update(void) 111 { 112 writel((unsigned) mlist, MDDI_PRI_PTR); 113 } 114 115 int mddi_update_done(void) 116 { 117 return !!(readl(MDDI_STAT) & MDDI_STAT_PRI_LINK_LIST_DONE); 118 } 119 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 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 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 281 void *mddi_framebuffer(void) 282 { 283 return FB; 284 } 285 286