Home | History | Annotate | Download | only in arch_msm7k
      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