linux/drivers/video/msm/mddi.c
<<
>>
Prefs
   1/*
   2 * MSM MDDI Transport
   3 *
   4 * Copyright (C) 2007 Google Incorporated
   5 * Copyright (C) 2007 QUALCOMM Incorporated
   6 *
   7 * This software is licensed under the terms of the GNU General Public
   8 * License version 2, as published by the Free Software Foundation, and
   9 * may be copied, distributed, and modified under those terms.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/kernel.h>
  20#include <linux/dma-mapping.h>
  21#include <linux/interrupt.h>
  22#include <linux/platform_device.h>
  23#include <linux/delay.h>
  24#include <linux/gfp.h>
  25#include <linux/spinlock.h>
  26#include <linux/clk.h>
  27#include <linux/io.h>
  28#include <linux/sched.h>
  29#include <linux/platform_data/video-msm_fb.h>
  30#include "mddi_hw.h"
  31
  32#define FLAG_DISABLE_HIBERNATION 0x0001
  33#define FLAG_HAVE_CAPS           0x0002
  34#define FLAG_HAS_VSYNC_IRQ       0x0004
  35#define FLAG_HAVE_STATUS         0x0008
  36
  37#define CMD_GET_CLIENT_CAP     0x0601
  38#define CMD_GET_CLIENT_STATUS  0x0602
  39
  40union mddi_rev {
  41        unsigned char raw[MDDI_REV_BUFFER_SIZE];
  42        struct mddi_rev_packet hdr;
  43        struct mddi_client_status status;
  44        struct mddi_client_caps caps;
  45        struct mddi_register_access reg;
  46};
  47
  48struct reg_read_info {
  49        struct completion done;
  50        uint32_t reg;
  51        uint32_t status;
  52        uint32_t result;
  53};
  54
  55struct mddi_info {
  56        uint16_t flags;
  57        uint16_t version;
  58        char __iomem *base;
  59        int irq;
  60        struct clk *clk;
  61        struct msm_mddi_client_data client_data;
  62
  63        /* buffer for rev encap packets */
  64        void *rev_data;
  65        dma_addr_t rev_addr;
  66        struct mddi_llentry *reg_write_data;
  67        dma_addr_t reg_write_addr;
  68        struct mddi_llentry *reg_read_data;
  69        dma_addr_t reg_read_addr;
  70        size_t rev_data_curr;
  71
  72        spinlock_t int_lock;
  73        uint32_t int_enable;
  74        uint32_t got_int;
  75        wait_queue_head_t int_wait;
  76
  77        struct mutex reg_write_lock;
  78        struct mutex reg_read_lock;
  79        struct reg_read_info *reg_read;
  80
  81        struct mddi_client_caps caps;
  82        struct mddi_client_status status;
  83
  84        void (*power_client)(struct msm_mddi_client_data *, int);
  85
  86        /* client device published to bind us to the
  87         * appropriate mddi_client driver
  88         */
  89        char client_name[20];
  90
  91        struct platform_device client_pdev;
  92};
  93
  94static void mddi_init_rev_encap(struct mddi_info *mddi);
  95
  96#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
  97#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
  98
  99void mddi_activate_link(struct msm_mddi_client_data *cdata)
 100{
 101        struct mddi_info *mddi = container_of(cdata, struct mddi_info,
 102                                              client_data);
 103
 104        mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
 105}
 106
 107static void mddi_handle_link_list_done(struct mddi_info *mddi)
 108{
 109}
 110
 111static void mddi_reset_rev_encap_ptr(struct mddi_info *mddi)
 112{
 113        printk(KERN_INFO "mddi: resetting rev ptr\n");
 114        mddi->rev_data_curr = 0;
 115        mddi_writel(mddi->rev_addr, REV_PTR);
 116        mddi_writel(mddi->rev_addr, REV_PTR);
 117        mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
 118}
 119
 120static void mddi_handle_rev_data(struct mddi_info *mddi, union mddi_rev *rev)
 121{
 122        int i;
 123        struct reg_read_info *ri;
 124
 125        if ((rev->hdr.length <= MDDI_REV_BUFFER_SIZE - 2) &&
 126           (rev->hdr.length >= sizeof(struct mddi_rev_packet) - 2)) {
 127
 128                switch (rev->hdr.type) {
 129                case TYPE_CLIENT_CAPS:
 130                        memcpy(&mddi->caps, &rev->caps,
 131                               sizeof(struct mddi_client_caps));
 132                        mddi->flags |= FLAG_HAVE_CAPS;
 133                        wake_up(&mddi->int_wait);
 134                        break;
 135                case TYPE_CLIENT_STATUS:
 136                        memcpy(&mddi->status, &rev->status,
 137                               sizeof(struct mddi_client_status));
 138                        mddi->flags |= FLAG_HAVE_STATUS;
 139                        wake_up(&mddi->int_wait);
 140                        break;
 141                case TYPE_REGISTER_ACCESS:
 142                        ri = mddi->reg_read;
 143                        if (ri == 0) {
 144                                printk(KERN_INFO "rev: got reg %x = %x without "
 145                                                 " pending read\n",
 146                                       rev->reg.register_address,
 147                                       rev->reg.register_data_list);
 148                                break;
 149                        }
 150                        if (ri->reg != rev->reg.register_address) {
 151                                printk(KERN_INFO "rev: got reg %x = %x for "
 152                                                 "wrong register, expected "
 153                                                 "%x\n",
 154                                       rev->reg.register_address,
 155                                       rev->reg.register_data_list, ri->reg);
 156                                break;
 157                        }
 158                        mddi->reg_read = NULL;
 159                        ri->status = 0;
 160                        ri->result = rev->reg.register_data_list;
 161                        complete(&ri->done);
 162                        break;
 163                default:
 164                        printk(KERN_INFO "rev: unknown reverse packet: "
 165                                         "len=%04x type=%04x CURR_REV_PTR=%x\n",
 166                               rev->hdr.length, rev->hdr.type,
 167                               mddi_readl(CURR_REV_PTR));
 168                        for (i = 0; i < rev->hdr.length + 2; i++) {
 169                                if ((i % 16) == 0)
 170                                        printk(KERN_INFO "\n");
 171                                printk(KERN_INFO " %02x", rev->raw[i]);
 172                        }
 173                        printk(KERN_INFO "\n");
 174                        mddi_reset_rev_encap_ptr(mddi);
 175                }
 176        } else {
 177                printk(KERN_INFO "bad rev length, %d, CURR_REV_PTR %x\n",
 178                       rev->hdr.length, mddi_readl(CURR_REV_PTR));
 179                mddi_reset_rev_encap_ptr(mddi);
 180        }
 181}
 182
 183static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
 184
 185static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
 186{
 187        uint32_t rev_data_count;
 188        uint32_t rev_crc_err_count;
 189        struct reg_read_info *ri;
 190        size_t prev_offset;
 191        uint16_t length;
 192
 193        union mddi_rev *crev = mddi->rev_data + mddi->rev_data_curr;
 194
 195        /* clear the interrupt */
 196        mddi_writel(MDDI_INT_REV_DATA_AVAIL, INT);
 197        rev_data_count = mddi_readl(REV_PKT_CNT);
 198        rev_crc_err_count = mddi_readl(REV_CRC_ERR);
 199        if (rev_data_count > 1)
 200                printk(KERN_INFO "rev_data_count %d\n", rev_data_count);
 201
 202        if (rev_crc_err_count) {
 203                printk(KERN_INFO "rev_crc_err_count %d, INT %x\n",
 204                       rev_crc_err_count,  mddi_readl(INT));
 205                ri = mddi->reg_read;
 206                if (ri == 0) {
 207                        printk(KERN_INFO "rev: got crc error without pending "
 208                               "read\n");
 209                } else {
 210                        mddi->reg_read = NULL;
 211                        ri->status = -EIO;
 212                        ri->result = -1;
 213                        complete(&ri->done);
 214                }
 215        }
 216
 217        if (rev_data_count == 0)
 218                return;
 219
 220        prev_offset = mddi->rev_data_curr;
 221
 222        length = *((uint8_t *)mddi->rev_data + mddi->rev_data_curr);
 223        mddi->rev_data_curr++;
 224        if (mddi->rev_data_curr == MDDI_REV_BUFFER_SIZE)
 225                mddi->rev_data_curr = 0;
 226        length += *((uint8_t *)mddi->rev_data + mddi->rev_data_curr) << 8;
 227        mddi->rev_data_curr += 1 + length;
 228        if (mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE)
 229                mddi->rev_data_curr =
 230                        mddi->rev_data_curr % MDDI_REV_BUFFER_SIZE;
 231
 232        if (length > MDDI_REV_BUFFER_SIZE - 2) {
 233                printk(KERN_INFO "mddi: rev data length greater than buffer"
 234                        "size\n");
 235                mddi_reset_rev_encap_ptr(mddi);
 236                return;
 237        }
 238
 239        if (prev_offset + 2 + length >= MDDI_REV_BUFFER_SIZE) {
 240                union mddi_rev tmprev;
 241                size_t rem = MDDI_REV_BUFFER_SIZE - prev_offset;
 242                memcpy(&tmprev.raw[0], mddi->rev_data + prev_offset, rem);
 243                memcpy(&tmprev.raw[rem], mddi->rev_data, 2 + length - rem);
 244                mddi_handle_rev_data(mddi, &tmprev);
 245        } else {
 246                mddi_handle_rev_data(mddi, crev);
 247        }
 248
 249        if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 &&
 250            mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) {
 251                mddi_writel(mddi->rev_addr, REV_PTR);
 252        }
 253}
 254
 255static irqreturn_t mddi_isr(int irq, void *data)
 256{
 257        struct msm_mddi_client_data *cdata = data;
 258        struct mddi_info *mddi = container_of(cdata, struct mddi_info,
 259                                              client_data);
 260        uint32_t active, status;
 261
 262        spin_lock(&mddi->int_lock);
 263
 264        active = mddi_readl(INT);
 265        status = mddi_readl(STAT);
 266
 267        mddi_writel(active, INT);
 268
 269        /* ignore any interrupts we have disabled */
 270        active &= mddi->int_enable;
 271
 272        mddi->got_int |= active;
 273        wake_up(&mddi->int_wait);
 274
 275        if (active & MDDI_INT_PRI_LINK_LIST_DONE) {
 276                mddi->int_enable &= (~MDDI_INT_PRI_LINK_LIST_DONE);
 277                mddi_handle_link_list_done(mddi);
 278        }
 279        if (active & MDDI_INT_REV_DATA_AVAIL)
 280                mddi_handle_rev_data_avail(mddi);
 281
 282        if (active & ~MDDI_INT_NEED_CLEAR)
 283                mddi->int_enable &= ~(active & ~MDDI_INT_NEED_CLEAR);
 284
 285        if (active & MDDI_INT_LINK_ACTIVE) {
 286                mddi->int_enable &= (~MDDI_INT_LINK_ACTIVE);
 287                mddi->int_enable |= MDDI_INT_IN_HIBERNATION;
 288        }
 289
 290        if (active & MDDI_INT_IN_HIBERNATION) {
 291                mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION);
 292                mddi->int_enable |= MDDI_INT_LINK_ACTIVE;
 293        }
 294
 295        mddi_writel(mddi->int_enable, INTEN);
 296        spin_unlock(&mddi->int_lock);
 297
 298        return IRQ_HANDLED;
 299}
 300
 301static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
 302                                        uint32_t intmask, int timeout)
 303{
 304        unsigned long irq_flags;
 305
 306        spin_lock_irqsave(&mddi->int_lock, irq_flags);
 307        mddi->got_int &= ~intmask;
 308        mddi->int_enable |= intmask;
 309        mddi_writel(mddi->int_enable, INTEN);
 310        spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
 311        return wait_event_timeout(mddi->int_wait, mddi->got_int & intmask,
 312                                  timeout);
 313}
 314
 315static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
 316{
 317        if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
 318                printk(KERN_INFO "mddi_wait_interrupt %d, timeout "
 319                       "waiting for %x, INT = %x, STAT = %x gotint = %x\n",
 320                       current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
 321                       mddi->got_int);
 322}
 323
 324static void mddi_init_rev_encap(struct mddi_info *mddi)
 325{
 326        memset(mddi->rev_data, 0xee, MDDI_REV_BUFFER_SIZE);
 327        mddi_writel(mddi->rev_addr, REV_PTR);
 328        mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
 329        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 330}
 331
 332void mddi_set_auto_hibernate(struct msm_mddi_client_data *cdata, int on)
 333{
 334        struct mddi_info *mddi = container_of(cdata, struct mddi_info,
 335                                              client_data);
 336        mddi_writel(MDDI_CMD_POWERDOWN, CMD);
 337        mddi_wait_interrupt(mddi, MDDI_INT_IN_HIBERNATION);
 338        mddi_writel(MDDI_CMD_HIBERNATE | !!on, CMD);
 339        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 340}
 341
 342
 343static uint16_t mddi_init_registers(struct mddi_info *mddi)
 344{
 345        mddi_writel(0x0001, VERSION);
 346        mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
 347        mddi_writel(0x0003, SPM); /* subframes per media */
 348        mddi_writel(0x0005, TA1_LEN);
 349        mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
 350        mddi_writel(0x0096, DRIVE_HI);
 351        /* 0x32 normal, 0x50 for Toshiba display */
 352        mddi_writel(0x0050, DRIVE_LO);
 353        mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
 354        mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
 355
 356        mddi_writel(MDDI_REV_BUFFER_SIZE, REV_SIZE);
 357        mddi_writel(MDDI_MAX_REV_PKT_SIZE, REV_ENCAP_SZ);
 358
 359        /* disable periodic rev encap */
 360        mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP, CMD);
 361        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 362
 363        if (mddi_readl(PAD_CTL) == 0) {
 364                /* If we are turning on band gap, need to wait 5us before
 365                 * turning on the rest of the PAD */
 366                mddi_writel(0x08000, PAD_CTL);
 367                udelay(5);
 368        }
 369
 370        /* Recommendation from PAD hw team */
 371        mddi_writel(0xa850f, PAD_CTL);
 372
 373
 374        /* Need an even number for counts */
 375        mddi_writel(0x60006, DRIVER_START_CNT);
 376
 377        mddi_set_auto_hibernate(&mddi->client_data, 0);
 378
 379        mddi_writel(MDDI_CMD_DISP_IGNORE, CMD);
 380        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 381
 382        mddi_init_rev_encap(mddi);
 383        return mddi_readl(CORE_VER) & 0xffff;
 384}
 385
 386static void mddi_suspend(struct msm_mddi_client_data *cdata)
 387{
 388        struct mddi_info *mddi = container_of(cdata, struct mddi_info,
 389                                              client_data);
 390        /* turn off the client */
 391        if (mddi->power_client)
 392                mddi->power_client(&mddi->client_data, 0);
 393        /* turn off the link */
 394        mddi_writel(MDDI_CMD_RESET, CMD);
 395        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 396        /* turn off the clock */
 397        clk_disable(mddi->clk);
 398}
 399
 400static void mddi_resume(struct msm_mddi_client_data *cdata)
 401{
 402        struct mddi_info *mddi = container_of(cdata, struct mddi_info,
 403                                              client_data);
 404        mddi_set_auto_hibernate(&mddi->client_data, 0);
 405        /* turn on the client */
 406        if (mddi->power_client)
 407                mddi->power_client(&mddi->client_data, 1);
 408        /* turn on the clock */
 409        clk_enable(mddi->clk);
 410        /* set up the local registers */
 411        mddi->rev_data_curr = 0;
 412        mddi_init_registers(mddi);
 413        mddi_writel(mddi->int_enable, INTEN);
 414        mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
 415        mddi_writel(MDDI_CMD_SEND_RTD, CMD);
 416        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 417        mddi_set_auto_hibernate(&mddi->client_data, 1);
 418}
 419
 420static int mddi_get_client_caps(struct mddi_info *mddi)
 421{
 422        int i, j;
 423
 424        /* clear any stale interrupts */
 425        mddi_writel(0xffffffff, INT);
 426
 427        mddi->int_enable = MDDI_INT_LINK_ACTIVE |
 428                           MDDI_INT_IN_HIBERNATION |
 429                           MDDI_INT_PRI_LINK_LIST_DONE |
 430                           MDDI_INT_REV_DATA_AVAIL |
 431                           MDDI_INT_REV_OVERFLOW |
 432                           MDDI_INT_REV_OVERWRITE |
 433                           MDDI_INT_RTD_FAILURE;
 434        mddi_writel(mddi->int_enable, INTEN);
 435
 436        mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
 437        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 438
 439        for (j = 0; j < 3; j++) {
 440                /* the toshiba vga panel does not respond to get
 441                 * caps unless you SEND_RTD, but the first SEND_RTD
 442                 * will fail...
 443                 */
 444                for (i = 0; i < 4; i++) {
 445                        uint32_t stat;
 446
 447                        mddi_writel(MDDI_CMD_SEND_RTD, CMD);
 448                        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 449                        stat = mddi_readl(STAT);
 450                        printk(KERN_INFO "mddi cmd send rtd: int %x, stat %x, "
 451                                        "rtd val %x\n", mddi_readl(INT), stat,
 452                                        mddi_readl(RTD_VAL));
 453                        if ((stat & MDDI_STAT_RTD_MEAS_FAIL) == 0)
 454                                break;
 455                        msleep(1);
 456                }
 457
 458                mddi_writel(CMD_GET_CLIENT_CAP, CMD);
 459                mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 460                wait_event_timeout(mddi->int_wait, mddi->flags & FLAG_HAVE_CAPS,
 461                                   HZ / 100);
 462
 463                if (mddi->flags & FLAG_HAVE_CAPS)
 464                        break;
 465                printk(KERN_INFO "mddi_init, timeout waiting for caps\n");
 466        }
 467        return mddi->flags & FLAG_HAVE_CAPS;
 468}
 469
 470/* link must be active when this is called */
 471int mddi_check_status(struct mddi_info *mddi)
 472{
 473        int ret = -1, retry = 3;
 474        mutex_lock(&mddi->reg_read_lock);
 475        mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
 476        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 477
 478        do {
 479                mddi->flags &= ~FLAG_HAVE_STATUS;
 480                mddi_writel(CMD_GET_CLIENT_STATUS, CMD);
 481                mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 482                wait_event_timeout(mddi->int_wait,
 483                                   mddi->flags & FLAG_HAVE_STATUS,
 484                                   HZ / 100);
 485
 486                if (mddi->flags & FLAG_HAVE_STATUS) {
 487                        if (mddi->status.crc_error_count)
 488                                printk(KERN_INFO "mddi status: crc_error "
 489                                        "count: %d\n",
 490                                        mddi->status.crc_error_count);
 491                        else
 492                                ret = 0;
 493                        break;
 494                } else
 495                        printk(KERN_INFO "mddi status: failed to get client "
 496                                "status\n");
 497                mddi_writel(MDDI_CMD_SEND_RTD, CMD);
 498                mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 499        } while (--retry);
 500
 501        mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
 502        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 503        mutex_unlock(&mddi->reg_read_lock);
 504        return ret;
 505}
 506
 507
 508void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val,
 509                       uint32_t reg)
 510{
 511        struct mddi_info *mddi = container_of(cdata, struct mddi_info,
 512                                              client_data);
 513        struct mddi_llentry *ll;
 514        struct mddi_register_access *ra;
 515
 516        mutex_lock(&mddi->reg_write_lock);
 517
 518        ll = mddi->reg_write_data;
 519
 520        ra = &(ll->u.r);
 521        ra->length = 14 + 4;
 522        ra->type = TYPE_REGISTER_ACCESS;
 523        ra->client_id = 0;
 524        ra->read_write_info = MDDI_WRITE | 1;
 525        ra->crc16 = 0;
 526
 527        ra->register_address = reg;
 528        ra->register_data_list = val;
 529
 530        ll->flags = 1;
 531        ll->header_count = 14;
 532        ll->data_count = 4;
 533        ll->data = mddi->reg_write_addr + offsetof(struct mddi_llentry,
 534                                                   u.r.register_data_list);
 535        ll->next = 0;
 536        ll->reserved = 0;
 537
 538        mddi_writel(mddi->reg_write_addr, PRI_PTR);
 539
 540        mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
 541        mutex_unlock(&mddi->reg_write_lock);
 542}
 543
 544uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
 545{
 546        struct mddi_info *mddi = container_of(cdata, struct mddi_info,
 547                                              client_data);
 548        struct mddi_llentry *ll;
 549        struct mddi_register_access *ra;
 550        struct reg_read_info ri;
 551        unsigned s;
 552        int retry_count = 2;
 553        unsigned long irq_flags;
 554
 555        mutex_lock(&mddi->reg_read_lock);
 556
 557        ll = mddi->reg_read_data;
 558
 559        ra = &(ll->u.r);
 560        ra->length = 14;
 561        ra->type = TYPE_REGISTER_ACCESS;
 562        ra->client_id = 0;
 563        ra->read_write_info = MDDI_READ | 1;
 564        ra->crc16 = 0;
 565
 566        ra->register_address = reg;
 567
 568        ll->flags = 0x11;
 569        ll->header_count = 14;
 570        ll->data_count = 0;
 571        ll->data = 0;
 572        ll->next = 0;
 573        ll->reserved = 0;
 574
 575        s = mddi_readl(STAT);
 576
 577        ri.reg = reg;
 578        ri.status = -1;
 579
 580        do {
 581                init_completion(&ri.done);
 582                mddi->reg_read = &ri;
 583                mddi_writel(mddi->reg_read_addr, PRI_PTR);
 584
 585                mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
 586
 587                /* Enable Periodic Reverse Encapsulation. */
 588                mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
 589                mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 590                if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
 591                    !ri.done.done) {
 592                        printk(KERN_INFO "mddi_remote_read(%x) timeout "
 593                                         "(%d %d %d)\n",
 594                               reg, ri.status, ri.result, ri.done.done);
 595                        spin_lock_irqsave(&mddi->int_lock, irq_flags);
 596                        mddi->reg_read = NULL;
 597                        spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
 598                        ri.status = -1;
 599                        ri.result = -1;
 600                }
 601                if (ri.status == 0)
 602                        break;
 603
 604                mddi_writel(MDDI_CMD_SEND_RTD, CMD);
 605                mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
 606                mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 607                printk(KERN_INFO "mddi_remote_read: failed, sent "
 608                       "MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
 609                       "curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
 610                       mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
 611        } while (retry_count-- > 0);
 612        /* Disable Periodic Reverse Encapsulation. */
 613        mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
 614        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 615        mddi->reg_read = NULL;
 616        mutex_unlock(&mddi->reg_read_lock);
 617        return ri.result;
 618}
 619
 620static struct mddi_info mddi_info[2];
 621
 622static int mddi_clk_setup(struct platform_device *pdev, struct mddi_info *mddi,
 623                          unsigned long clk_rate)
 624{
 625        int ret;
 626
 627        /* set up the clocks */
 628        mddi->clk = clk_get(&pdev->dev, "mddi_clk");
 629        if (IS_ERR(mddi->clk)) {
 630                printk(KERN_INFO "mddi: failed to get clock\n");
 631                return PTR_ERR(mddi->clk);
 632        }
 633        ret =  clk_enable(mddi->clk);
 634        if (ret)
 635                goto fail;
 636        ret = clk_set_rate(mddi->clk, clk_rate);
 637        if (ret)
 638                goto fail;
 639        return 0;
 640
 641fail:
 642        clk_put(mddi->clk);
 643        return ret;
 644}
 645
 646static int __init mddi_rev_data_setup(struct mddi_info *mddi)
 647{
 648        void *dma;
 649        dma_addr_t dma_addr;
 650
 651        /* set up dma buffer */
 652        dma = dma_alloc_coherent(NULL, 0x1000, &dma_addr, GFP_KERNEL);
 653        if (dma == 0)
 654                return -ENOMEM;
 655        mddi->rev_data = dma;
 656        mddi->rev_data_curr = 0;
 657        mddi->rev_addr = dma_addr;
 658        mddi->reg_write_data = dma + MDDI_REV_BUFFER_SIZE;
 659        mddi->reg_write_addr = dma_addr + MDDI_REV_BUFFER_SIZE;
 660        mddi->reg_read_data = mddi->reg_write_data + 1;
 661        mddi->reg_read_addr = mddi->reg_write_addr +
 662                              sizeof(*mddi->reg_write_data);
 663        return 0;
 664}
 665
 666static int mddi_probe(struct platform_device *pdev)
 667{
 668        struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
 669        struct mddi_info *mddi = &mddi_info[pdev->id];
 670        struct resource *resource;
 671        int ret, i;
 672
 673        resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 674        if (!resource) {
 675                printk(KERN_ERR "mddi: no associated mem resource!\n");
 676                return -ENOMEM;
 677        }
 678        mddi->base = ioremap(resource->start, resource_size(resource));
 679        if (!mddi->base) {
 680                printk(KERN_ERR "mddi: failed to remap base!\n");
 681                ret = -EINVAL;
 682                goto error_ioremap;
 683        }
 684        resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 685        if (!resource) {
 686                printk(KERN_ERR "mddi: no associated irq resource!\n");
 687                ret = -EINVAL;
 688                goto error_get_irq_resource;
 689        }
 690        mddi->irq = resource->start;
 691        printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
 692               mddi->irq);
 693        mddi->power_client = pdata->power_client;
 694
 695        mutex_init(&mddi->reg_write_lock);
 696        mutex_init(&mddi->reg_read_lock);
 697        spin_lock_init(&mddi->int_lock);
 698        init_waitqueue_head(&mddi->int_wait);
 699
 700        ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate);
 701        if (ret) {
 702                printk(KERN_ERR "mddi: failed to setup clock!\n");
 703                goto error_clk_setup;
 704        }
 705
 706        ret = mddi_rev_data_setup(mddi);
 707        if (ret) {
 708                printk(KERN_ERR "mddi: failed to setup rev data!\n");
 709                goto error_rev_data;
 710        }
 711
 712        mddi->int_enable = 0;
 713        mddi_writel(mddi->int_enable, INTEN);
 714        ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
 715                          &mddi->client_data);
 716        if (ret) {
 717                printk(KERN_ERR "mddi: failed to request enable irq!\n");
 718                goto error_request_irq;
 719        }
 720
 721        /* turn on the mddi client bridge chip */
 722        if (mddi->power_client)
 723                mddi->power_client(&mddi->client_data, 1);
 724
 725        /* initialize the mddi registers */
 726        mddi_set_auto_hibernate(&mddi->client_data, 0);
 727        mddi_writel(MDDI_CMD_RESET, CMD);
 728        mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
 729        mddi->version = mddi_init_registers(mddi);
 730        if (mddi->version < 0x20) {
 731                printk(KERN_ERR "mddi: unsupported version 0x%x\n",
 732                       mddi->version);
 733                ret = -ENODEV;
 734                goto error_mddi_version;
 735        }
 736
 737        /* read the capabilities off the client */
 738        if (!mddi_get_client_caps(mddi)) {
 739                printk(KERN_INFO "mddi: no client found\n");
 740                /* power down the panel */
 741                mddi_writel(MDDI_CMD_POWERDOWN, CMD);
 742                printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
 743                msleep(100);
 744                printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
 745                return 0;
 746        }
 747        mddi_set_auto_hibernate(&mddi->client_data, 1);
 748
 749        if (mddi->caps.Mfr_Name == 0 && mddi->caps.Product_Code == 0)
 750                pdata->fixup(&mddi->caps.Mfr_Name, &mddi->caps.Product_Code);
 751
 752        mddi->client_pdev.id = 0;
 753        for (i = 0; i < pdata->num_clients; i++) {
 754                if (pdata->client_platform_data[i].product_id ==
 755                    (mddi->caps.Mfr_Name << 16 | mddi->caps.Product_Code)) {
 756                        mddi->client_data.private_client_data =
 757                                pdata->client_platform_data[i].client_data;
 758                        mddi->client_pdev.name =
 759                                pdata->client_platform_data[i].name;
 760                        mddi->client_pdev.id =
 761                                pdata->client_platform_data[i].id;
 762                        /* XXX: possibly set clock */
 763                        break;
 764                }
 765        }
 766
 767        if (i >= pdata->num_clients)
 768                mddi->client_pdev.name = "mddi_c_dummy";
 769        printk(KERN_INFO "mddi: registering panel %s\n",
 770                mddi->client_pdev.name);
 771
 772        mddi->client_data.suspend = mddi_suspend;
 773        mddi->client_data.resume = mddi_resume;
 774        mddi->client_data.activate_link = mddi_activate_link;
 775        mddi->client_data.remote_write = mddi_remote_write;
 776        mddi->client_data.remote_read = mddi_remote_read;
 777        mddi->client_data.auto_hibernate = mddi_set_auto_hibernate;
 778        mddi->client_data.fb_resource = pdata->fb_resource;
 779        if (pdev->id == 0)
 780                mddi->client_data.interface_type = MSM_MDDI_PMDH_INTERFACE;
 781        else if (pdev->id == 1)
 782                mddi->client_data.interface_type = MSM_MDDI_EMDH_INTERFACE;
 783        else {
 784                printk(KERN_ERR "mddi: can not determine interface %d!\n",
 785                       pdev->id);
 786                ret = -EINVAL;
 787                goto error_mddi_interface;
 788        }
 789
 790        mddi->client_pdev.dev.platform_data = &mddi->client_data;
 791        printk(KERN_INFO "mddi: publish: %s\n", mddi->client_name);
 792        platform_device_register(&mddi->client_pdev);
 793        return 0;
 794
 795error_mddi_interface:
 796error_mddi_version:
 797        free_irq(mddi->irq, 0);
 798error_request_irq:
 799        dma_free_coherent(NULL, 0x1000, mddi->rev_data, mddi->rev_addr);
 800error_rev_data:
 801error_clk_setup:
 802error_get_irq_resource:
 803        iounmap(mddi->base);
 804error_ioremap:
 805
 806        printk(KERN_INFO "mddi: mddi_init() failed (%d)\n", ret);
 807        return ret;
 808}
 809
 810
 811static struct platform_driver mddi_driver = {
 812        .probe = mddi_probe,
 813        .driver = { .name = "msm_mddi" },
 814};
 815
 816static int __init _mddi_init(void)
 817{
 818        return platform_driver_register(&mddi_driver);
 819}
 820
 821module_init(_mddi_init);
 822
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.