linux/drivers/video/omap/blizzard.c
<<
>>
Prefs
   1/*
   2 * Epson Blizzard LCD controller driver
   3 *
   4 * Copyright (C) 2004-2005 Nokia Corporation
   5 * Authors:     Juha Yrjola   <juha.yrjola@nokia.com>
   6 *              Imre Deak     <imre.deak@nokia.com>
   7 * YUV support: Jussi Laako   <jussi.laako@nokia.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms of the GNU General Public License as published by the
  11 * Free Software Foundation; either version 2 of the License, or (at your
  12 * option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful, but
  15 * WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License along
  20 * with this program; if not, write to the Free Software Foundation, Inc.,
  21 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22 */
  23#include <linux/module.h>
  24#include <linux/mm.h>
  25#include <linux/fb.h>
  26#include <linux/delay.h>
  27#include <linux/clk.h>
  28
  29#include <mach/dma.h>
  30#include <mach/omapfb.h>
  31#include <mach/blizzard.h>
  32
  33#include "dispc.h"
  34
  35#define MODULE_NAME                             "blizzard"
  36
  37#define BLIZZARD_REV_CODE                       0x00
  38#define BLIZZARD_CONFIG                         0x02
  39#define BLIZZARD_PLL_DIV                        0x04
  40#define BLIZZARD_PLL_LOCK_RANGE                 0x06
  41#define BLIZZARD_PLL_CLOCK_SYNTH_0              0x08
  42#define BLIZZARD_PLL_CLOCK_SYNTH_1              0x0a
  43#define BLIZZARD_PLL_MODE                       0x0c
  44#define BLIZZARD_CLK_SRC                        0x0e
  45#define BLIZZARD_MEM_BANK0_ACTIVATE             0x10
  46#define BLIZZARD_MEM_BANK0_STATUS               0x14
  47#define BLIZZARD_HDISP                          0x2a
  48#define BLIZZARD_HNDP                           0x2c
  49#define BLIZZARD_VDISP0                         0x2e
  50#define BLIZZARD_VDISP1                         0x30
  51#define BLIZZARD_VNDP                           0x32
  52#define BLIZZARD_HSW                            0x34
  53#define BLIZZARD_VSW                            0x38
  54#define BLIZZARD_DISPLAY_MODE                   0x68
  55#define BLIZZARD_INPUT_WIN_X_START_0            0x6c
  56#define BLIZZARD_DATA_SOURCE_SELECT             0x8e
  57#define BLIZZARD_DISP_MEM_DATA_PORT             0x90
  58#define BLIZZARD_DISP_MEM_READ_ADDR0            0x92
  59#define BLIZZARD_POWER_SAVE                     0xE6
  60#define BLIZZARD_NDISP_CTRL_STATUS              0xE8
  61
  62/* Data source select */
  63/* For S1D13745 */
  64#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND       0x00
  65#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE      0x01
  66#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE       0x04
  67#define BLIZZARD_SRC_DISABLE_OVERLAY            0x05
  68/* For S1D13744 */
  69#define BLIZZARD_SRC_WRITE_LCD                  0x00
  70#define BLIZZARD_SRC_BLT_LCD                    0x06
  71
  72#define BLIZZARD_COLOR_RGB565                   0x01
  73#define BLIZZARD_COLOR_YUV420                   0x09
  74
  75#define BLIZZARD_VERSION_S1D13745               0x01    /* Hailstorm */
  76#define BLIZZARD_VERSION_S1D13744               0x02    /* Blizzard */
  77
  78#define BLIZZARD_AUTO_UPDATE_TIME               (HZ / 20)
  79
  80/* Reserve 4 request slots for requests in irq context */
  81#define REQ_POOL_SIZE                   24
  82#define IRQ_REQ_POOL_SIZE               4
  83
  84#define REQ_FROM_IRQ_POOL 0x01
  85
  86#define REQ_COMPLETE    0
  87#define REQ_PENDING     1
  88
  89struct blizzard_reg_list {
  90        int     start;
  91        int     end;
  92};
  93
  94/* These need to be saved / restored separately from the rest. */
  95static struct blizzard_reg_list blizzard_pll_regs[] = {
  96        {
  97                .start  = 0x04,         /* Don't save PLL ctrl (0x0C) */
  98                .end    = 0x0a,
  99        },
 100        {
 101                .start  = 0x0e,         /* Clock configuration */
 102                .end    = 0x0e,
 103        },
 104};
 105
 106static struct blizzard_reg_list blizzard_gen_regs[] = {
 107        {
 108                .start  = 0x18,         /* SDRAM control */
 109                .end    = 0x20,
 110        },
 111        {
 112                .start  = 0x28,         /* LCD Panel configuration */
 113                .end    = 0x5a,         /* HSSI interface, TV configuration */
 114        },
 115};
 116
 117static u8 blizzard_reg_cache[0x5a / 2];
 118
 119struct update_param {
 120        int     plane;
 121        int     x, y, width, height;
 122        int     out_x, out_y;
 123        int     out_width, out_height;
 124        int     color_mode;
 125        int     bpp;
 126        int     flags;
 127};
 128
 129struct blizzard_request {
 130        struct list_head entry;
 131        unsigned int     flags;
 132
 133        int              (*handler)(struct blizzard_request *req);
 134        void             (*complete)(void *data);
 135        void             *complete_data;
 136
 137        union {
 138                struct update_param     update;
 139                struct completion       *sync;
 140        } par;
 141};
 142
 143struct plane_info {
 144        unsigned long offset;
 145        int pos_x, pos_y;
 146        int width, height;
 147        int out_width, out_height;
 148        int scr_width;
 149        int color_mode;
 150        int bpp;
 151};
 152
 153struct blizzard_struct {
 154        enum omapfb_update_mode update_mode;
 155        enum omapfb_update_mode update_mode_before_suspend;
 156
 157        struct timer_list       auto_update_timer;
 158        int                     stop_auto_update;
 159        struct omapfb_update_window     auto_update_window;
 160        int                     enabled_planes;
 161        int                     vid_nonstd_color;
 162        int                     vid_scaled;
 163        int                     last_color_mode;
 164        int                     zoom_on;
 165        int                     screen_width;
 166        int                     screen_height;
 167        unsigned                te_connected:1;
 168        unsigned                vsync_only:1;
 169
 170        struct plane_info       plane[OMAPFB_PLANE_NUM];
 171
 172        struct blizzard_request req_pool[REQ_POOL_SIZE];
 173        struct list_head        pending_req_list;
 174        struct list_head        free_req_list;
 175        struct semaphore        req_sema;
 176        spinlock_t              req_lock;
 177
 178        unsigned long           sys_ck_rate;
 179        struct extif_timings    reg_timings, lut_timings;
 180
 181        u32                     max_transmit_size;
 182        u32                     extif_clk_period;
 183        int                     extif_clk_div;
 184        unsigned long           pix_tx_time;
 185        unsigned long           line_upd_time;
 186
 187        struct omapfb_device    *fbdev;
 188        struct lcd_ctrl_extif   *extif;
 189        struct lcd_ctrl         *int_ctrl;
 190
 191        void                    (*power_up)(struct device *dev);
 192        void                    (*power_down)(struct device *dev);
 193
 194        int                     version;
 195} blizzard;
 196
 197struct lcd_ctrl blizzard_ctrl;
 198
 199static u8 blizzard_read_reg(u8 reg)
 200{
 201        u8 data;
 202
 203        blizzard.extif->set_bits_per_cycle(8);
 204        blizzard.extif->write_command(&reg, 1);
 205        blizzard.extif->read_data(&data, 1);
 206
 207        return data;
 208}
 209
 210static void blizzard_write_reg(u8 reg, u8 val)
 211{
 212        blizzard.extif->set_bits_per_cycle(8);
 213        blizzard.extif->write_command(&reg, 1);
 214        blizzard.extif->write_data(&val, 1);
 215}
 216
 217static void blizzard_restart_sdram(void)
 218{
 219        unsigned long tmo;
 220
 221        blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
 222        udelay(50);
 223        blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1);
 224        tmo = jiffies + msecs_to_jiffies(200);
 225        while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {
 226                if (time_after(jiffies, tmo)) {
 227                        dev_err(blizzard.fbdev->dev,
 228                                        "s1d1374x: SDRAM not ready\n");
 229                        break;
 230                }
 231                msleep(1);
 232        }
 233}
 234
 235static void blizzard_stop_sdram(void)
 236{
 237        blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
 238}
 239
 240/* Wait until the last window was completely written into the controllers
 241 * SDRAM and we can start transferring the next window.
 242 */
 243static void blizzard_wait_line_buffer(void)
 244{
 245        unsigned long tmo = jiffies + msecs_to_jiffies(30);
 246
 247        while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) {
 248                if (time_after(jiffies, tmo)) {
 249                        if (printk_ratelimit())
 250                                dev_err(blizzard.fbdev->dev,
 251                                        "s1d1374x: line buffer not ready\n");
 252                        break;
 253                }
 254        }
 255}
 256
 257/* Wait until the YYC color space converter is idle. */
 258static void blizzard_wait_yyc(void)
 259{
 260        unsigned long tmo = jiffies + msecs_to_jiffies(30);
 261
 262        while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) {
 263                if (time_after(jiffies, tmo)) {
 264                        if (printk_ratelimit())
 265                                dev_err(blizzard.fbdev->dev,
 266                                        "s1d1374x: YYC not ready\n");
 267                        break;
 268                }
 269        }
 270}
 271
 272static void disable_overlay(void)
 273{
 274        blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT,
 275                                BLIZZARD_SRC_DISABLE_OVERLAY);
 276}
 277
 278static void set_window_regs(int x_start, int y_start, int x_end, int y_end,
 279                            int x_out_start, int y_out_start,
 280                            int x_out_end, int y_out_end, int color_mode,
 281                            int zoom_off, int flags)
 282{
 283        u8 tmp[18];
 284        u8 cmd;
 285
 286        x_end--;
 287        y_end--;
 288        tmp[0] = x_start;
 289        tmp[1] = x_start >> 8;
 290        tmp[2] = y_start;
 291        tmp[3] = y_start >> 8;
 292        tmp[4] = x_end;
 293        tmp[5] = x_end >> 8;
 294        tmp[6] = y_end;
 295        tmp[7] = y_end >> 8;
 296
 297        x_out_end--;
 298        y_out_end--;
 299        tmp[8]  = x_out_start;
 300        tmp[9]  = x_out_start >> 8;
 301        tmp[10] = y_out_start;
 302        tmp[11] = y_out_start >> 8;
 303        tmp[12] = x_out_end;
 304        tmp[13] = x_out_end >> 8;
 305        tmp[14] = y_out_end;
 306        tmp[15] = y_out_end >> 8;
 307
 308        tmp[16] = color_mode;
 309        if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745)
 310                tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
 311        else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY)
 312                tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE;
 313        else
 314                tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
 315                                BLIZZARD_SRC_WRITE_LCD :
 316                                BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
 317
 318        blizzard.extif->set_bits_per_cycle(8);
 319        cmd = BLIZZARD_INPUT_WIN_X_START_0;
 320        blizzard.extif->write_command(&cmd, 1);
 321        blizzard.extif->write_data(tmp, 18);
 322}
 323
 324static void enable_tearsync(int y, int width, int height, int screen_height,
 325                            int out_height, int force_vsync)
 326{
 327        u8 b;
 328
 329        b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
 330        b |= 1 << 3;
 331        blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
 332
 333        if (likely(blizzard.vsync_only || force_vsync)) {
 334                blizzard.extif->enable_tearsync(1, 0);
 335                return;
 336        }
 337
 338        if (width * blizzard.pix_tx_time < blizzard.line_upd_time) {
 339                blizzard.extif->enable_tearsync(1, 0);
 340                return;
 341        }
 342
 343        if ((width * blizzard.pix_tx_time / 1000) * height <
 344            (y + out_height) * (blizzard.line_upd_time / 1000)) {
 345                blizzard.extif->enable_tearsync(1, 0);
 346                return;
 347        }
 348
 349        blizzard.extif->enable_tearsync(1, y + 1);
 350}
 351
 352static void disable_tearsync(void)
 353{
 354        u8 b;
 355
 356        blizzard.extif->enable_tearsync(0, 0);
 357        b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
 358        b &= ~(1 << 3);
 359        blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
 360        b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
 361}
 362
 363static inline void set_extif_timings(const struct extif_timings *t);
 364
 365static inline struct blizzard_request *alloc_req(void)
 366{
 367        unsigned long flags;
 368        struct blizzard_request *req;
 369        int req_flags = 0;
 370
 371        if (!in_interrupt())
 372                down(&blizzard.req_sema);
 373        else
 374                req_flags = REQ_FROM_IRQ_POOL;
 375
 376        spin_lock_irqsave(&blizzard.req_lock, flags);
 377        BUG_ON(list_empty(&blizzard.free_req_list));
 378        req = list_entry(blizzard.free_req_list.next,
 379                         struct blizzard_request, entry);
 380        list_del(&req->entry);
 381        spin_unlock_irqrestore(&blizzard.req_lock, flags);
 382
 383        INIT_LIST_HEAD(&req->entry);
 384        req->flags = req_flags;
 385
 386        return req;
 387}
 388
 389static inline void free_req(struct blizzard_request *req)
 390{
 391        unsigned long flags;
 392
 393        spin_lock_irqsave(&blizzard.req_lock, flags);
 394
 395        list_del(&req->entry);
 396        list_add(&req->entry, &blizzard.free_req_list);
 397        if (!(req->flags & REQ_FROM_IRQ_POOL))
 398                up(&blizzard.req_sema);
 399
 400        spin_unlock_irqrestore(&blizzard.req_lock, flags);
 401}
 402
 403static void process_pending_requests(void)
 404{
 405        unsigned long flags;
 406
 407        spin_lock_irqsave(&blizzard.req_lock, flags);
 408
 409        while (!list_empty(&blizzard.pending_req_list)) {
 410                struct blizzard_request *req;
 411                void (*complete)(void *);
 412                void *complete_data;
 413
 414                req = list_entry(blizzard.pending_req_list.next,
 415                                 struct blizzard_request, entry);
 416                spin_unlock_irqrestore(&blizzard.req_lock, flags);
 417
 418                if (req->handler(req) == REQ_PENDING)
 419                        return;
 420
 421                complete = req->complete;
 422                complete_data = req->complete_data;
 423                free_req(req);
 424
 425                if (complete)
 426                        complete(complete_data);
 427
 428                spin_lock_irqsave(&blizzard.req_lock, flags);
 429        }
 430
 431        spin_unlock_irqrestore(&blizzard.req_lock, flags);
 432}
 433
 434static void submit_req_list(struct list_head *head)
 435{
 436        unsigned long flags;
 437        int process = 1;
 438
 439        spin_lock_irqsave(&blizzard.req_lock, flags);
 440        if (likely(!list_empty(&blizzard.pending_req_list)))
 441                process = 0;
 442        list_splice_init(head, blizzard.pending_req_list.prev);
 443        spin_unlock_irqrestore(&blizzard.req_lock, flags);
 444
 445        if (process)
 446                process_pending_requests();
 447}
 448
 449static void request_complete(void *data)
 450{
 451        struct blizzard_request *req = (struct blizzard_request *)data;
 452        void                    (*complete)(void *);
 453        void                    *complete_data;
 454
 455        complete = req->complete;
 456        complete_data = req->complete_data;
 457
 458        free_req(req);
 459
 460        if (complete)
 461                complete(complete_data);
 462
 463        process_pending_requests();
 464}
 465
 466
 467static int do_full_screen_update(struct blizzard_request *req)
 468{
 469        int i;
 470        int flags;
 471
 472        for (i = 0; i < 3; i++) {
 473                struct plane_info *p = &blizzard.plane[i];
 474                if (!(blizzard.enabled_planes & (1 << i))) {
 475                        blizzard.int_ctrl->enable_plane(i, 0);
 476                        continue;
 477                }
 478                dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n",
 479                        p->width, p->height);
 480                blizzard.int_ctrl->setup_plane(i,
 481                                OMAPFB_CHANNEL_OUT_LCD, p->offset,
 482                                p->scr_width, p->pos_x, p->pos_y,
 483                                p->width, p->height,
 484                                p->color_mode);
 485                blizzard.int_ctrl->enable_plane(i, 1);
 486        }
 487
 488        dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n",
 489                blizzard.screen_width, blizzard.screen_height);
 490        blizzard_wait_line_buffer();
 491        flags = req->par.update.flags;
 492        if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
 493                enable_tearsync(0, blizzard.screen_width,
 494                                blizzard.screen_height,
 495                                blizzard.screen_height,
 496                                blizzard.screen_height,
 497                                flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
 498        else
 499                disable_tearsync();
 500
 501        set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height,
 502                        0, 0, blizzard.screen_width, blizzard.screen_height,
 503                        BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags);
 504        blizzard.zoom_on = 0;
 505
 506        blizzard.extif->set_bits_per_cycle(16);
 507        /* set_window_regs has left the register index at the right
 508         * place, so no need to set it here.
 509         */
 510        blizzard.extif->transfer_area(blizzard.screen_width,
 511                                      blizzard.screen_height,
 512                                      request_complete, req);
 513        return REQ_PENDING;
 514}
 515
 516/* Setup all planes with an overlapping area with the update window. */
 517static int do_partial_update(struct blizzard_request *req, int plane,
 518                             int x, int y, int w, int h,
 519                             int x_out, int y_out, int w_out, int h_out,
 520                             int wnd_color_mode, int bpp)
 521{
 522        int i;
 523        int gx1, gy1, gx2, gy2;
 524        int gx1_out, gy1_out, gx2_out, gy2_out;
 525        int color_mode;
 526        int flags;
 527        int zoom_off;
 528
 529        /* Global coordinates, relative to pixel 0,0 of the LCD */
 530        gx1 = x + blizzard.plane[plane].pos_x;
 531        gy1 = y + blizzard.plane[plane].pos_y;
 532        gx2 = gx1 + w;
 533        gy2 = gy1 + h;
 534
 535        flags = req->par.update.flags;
 536        if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
 537                gx1_out = gx1;
 538                gy1_out = gy1;
 539                gx2_out = gx1 + w * 2;
 540                gy2_out = gy1 + h * 2;
 541        } else {
 542                gx1_out = x_out + blizzard.plane[plane].pos_x;
 543                gy1_out = y_out + blizzard.plane[plane].pos_y;
 544                gx2_out = gx1_out + w_out;
 545                gy2_out = gy1_out + h_out;
 546        }
 547        zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 &&
 548                w == blizzard.screen_width && h == blizzard.screen_height;
 549        blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) ||
 550                           (w < w_out || h < h_out);
 551
 552        for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
 553                struct plane_info *p = &blizzard.plane[i];
 554                int px1, py1;
 555                int px2, py2;
 556                int pw, ph;
 557                int pposx, pposy;
 558                unsigned long offset;
 559
 560                if (!(blizzard.enabled_planes & (1 << i))  ||
 561                    (wnd_color_mode && i != plane)) {
 562                        blizzard.int_ctrl->enable_plane(i, 0);
 563                        continue;
 564                }
 565                /* Plane coordinates */
 566                if (i == plane) {
 567                        /* Plane in which we are doing the update.
 568                         * Local coordinates are the one in the update
 569                         * request.
 570                         */
 571                        px1 = x;
 572                        py1 = y;
 573                        px2 = x + w;
 574                        py2 = y + h;
 575                        pposx = 0;
 576                        pposy = 0;
 577                } else {
 578                        /* Check if this plane has an overlapping part */
 579                        px1 = gx1 - p->pos_x;
 580                        py1 = gy1 - p->pos_y;
 581                        px2 = gx2 - p->pos_x;
 582                        py2 = gy2 - p->pos_y;
 583                        if (px1 >= p->width || py1 >= p->height ||
 584                            px2 <= 0 || py2 <= 0) {
 585                                blizzard.int_ctrl->enable_plane(i, 0);
 586                                continue;
 587                        }
 588                        /* Calculate the coordinates for the overlapping
 589                         * part in the plane's local coordinates.
 590                         */
 591                        pposx = -px1;
 592                        pposy = -py1;
 593                        if (px1 < 0)
 594                                px1 = 0;
 595                        if (py1 < 0)
 596                                py1 = 0;
 597                        if (px2 > p->width)
 598                                px2 = p->width;
 599                        if (py2 > p->height)
 600                                py2 = p->height;
 601                        if (pposx < 0)
 602                                pposx = 0;
 603                        if (pposy < 0)
 604                                pposy = 0;
 605                }
 606                pw = px2 - px1;
 607                ph = py2 - py1;
 608                offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8;
 609                if (wnd_color_mode)
 610                        /* Window embedded in the plane with a differing
 611                         * color mode / bpp. Calculate the number of DMA
 612                         * transfer elements in terms of the plane's bpp.
 613                         */
 614                        pw = (pw + 1) * bpp / p->bpp;
 615#ifdef VERBOSE
 616                dev_dbg(blizzard.fbdev->dev,
 617                        "plane %d offset %#08lx pposx %d pposy %d "
 618                        "px1 %d py1 %d pw %d ph %d\n",
 619                        i, offset, pposx, pposy, px1, py1, pw, ph);
 620#endif
 621                blizzard.int_ctrl->setup_plane(i,
 622                                OMAPFB_CHANNEL_OUT_LCD, offset,
 623                                p->scr_width,
 624                                pposx, pposy, pw, ph,
 625                                p->color_mode);
 626
 627                blizzard.int_ctrl->enable_plane(i, 1);
 628        }
 629
 630        switch (wnd_color_mode) {
 631        case OMAPFB_COLOR_YUV420:
 632                color_mode = BLIZZARD_COLOR_YUV420;
 633                /* Currently only the 16 bits/pixel cycle format is
 634                 * supported on the external interface. Adjust the number
 635                 * of transfer elements per line for 12bpp format.
 636                 */
 637                w = (w + 1) * 3 / 4;
 638                break;
 639        default:
 640                color_mode = BLIZZARD_COLOR_RGB565;
 641                break;
 642        }
 643
 644        blizzard_wait_line_buffer();
 645        if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420)
 646                blizzard_wait_yyc();
 647        blizzard.last_color_mode = color_mode;
 648        if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
 649                enable_tearsync(gy1, w, h,
 650                                blizzard.screen_height,
 651                                h_out,
 652                                flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
 653        else
 654                disable_tearsync();
 655
 656        set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
 657                        color_mode, zoom_off, flags);
 658
 659        blizzard.extif->set_bits_per_cycle(16);
 660        /* set_window_regs has left the register index at the right
 661         * place, so no need to set it here.
 662         */
 663        blizzard.extif->transfer_area(w, h, request_complete, req);
 664
 665        return REQ_PENDING;
 666}
 667
 668static int send_frame_handler(struct blizzard_request *req)
 669{
 670        struct update_param *par = &req->par.update;
 671        int plane = par->plane;
 672
 673#ifdef VERBOSE
 674        dev_dbg(blizzard.fbdev->dev,
 675                "send_frame: x %d y %d w %d h %d "
 676                "x_out %d y_out %d w_out %d h_out %d "
 677                "color_mode %04x flags %04x planes %01x\n",
 678                par->x, par->y, par->width, par->height,
 679                par->out_x, par->out_y, par->out_width, par->out_height,
 680                par->color_mode, par->flags, blizzard.enabled_planes);
 681#endif
 682        if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY)
 683                disable_overlay();
 684
 685        if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) ||
 686             (blizzard.enabled_planes & blizzard.vid_scaled))
 687                return do_full_screen_update(req);
 688
 689        return do_partial_update(req, plane, par->x, par->y,
 690                                 par->width, par->height,
 691                                 par->out_x, par->out_y,
 692                                 par->out_width, par->out_height,
 693                                 par->color_mode, par->bpp);
 694}
 695
 696static void send_frame_complete(void *data)
 697{
 698}
 699
 700#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do {   \
 701        req = alloc_req();                      \
 702        req->handler    = send_frame_handler;   \
 703        req->complete   = send_frame_complete;  \
 704        req->par.update.plane = plane_idx;      \
 705        req->par.update.x = _x;                 \
 706        req->par.update.y = _y;                 \
 707        req->par.update.width  = _w;            \
 708        req->par.update.height = _h;            \
 709        req->par.update.out_x = _x_out;         \
 710        req->par.update.out_y = _y_out;         \
 711        req->par.update.out_width = _w_out;     \
 712        req->par.update.out_height = _h_out;    \
 713        req->par.update.bpp = bpp;              \
 714        req->par.update.color_mode = color_mode;\
 715        req->par.update.flags     = flags;      \
 716        list_add_tail(&req->entry, req_head);   \
 717} while(0)
 718
 719static void create_req_list(int plane_idx,
 720                            struct omapfb_update_window *win,
 721                            struct list_head *req_head)
 722{
 723        struct blizzard_request *req;
 724        int x = win->x;
 725        int y = win->y;
 726        int width = win->width;
 727        int height = win->height;
 728        int x_out = win->out_x;
 729        int y_out = win->out_y;
 730        int width_out = win->out_width;
 731        int height_out = win->out_height;
 732        int color_mode;
 733        int bpp;
 734        int flags;
 735        unsigned int ystart = y;
 736        unsigned int yspan = height;
 737        unsigned int ystart_out = y_out;
 738        unsigned int yspan_out = height_out;
 739
 740        flags = win->format & ~OMAPFB_FORMAT_MASK;
 741        color_mode = win->format & OMAPFB_FORMAT_MASK;
 742        switch (color_mode) {
 743        case OMAPFB_COLOR_YUV420:
 744                /* Embedded window with different color mode */
 745                bpp = 12;
 746                /* X, Y, height must be aligned at 2, width at 4 pixels */
 747                x &= ~1;
 748                y &= ~1;
 749                height = yspan = height & ~1;
 750                width = width & ~3;
 751                break;
 752        default:
 753                /* Same as the plane color mode */
 754                bpp = blizzard.plane[plane_idx].bpp;
 755                break;
 756        }
 757        if (width * height * bpp / 8 > blizzard.max_transmit_size) {
 758                yspan = blizzard.max_transmit_size / (width * bpp / 8);
 759                yspan_out = yspan * height_out / height;
 760                ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
 761                         width_out, yspan_out);
 762                ystart += yspan;
 763                ystart_out += yspan_out;
 764                yspan = height - yspan;
 765                yspan_out = height_out - yspan_out;
 766                flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
 767        }
 768
 769        ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
 770                 width_out, yspan_out);
 771}
 772
 773static void auto_update_complete(void *data)
 774{
 775        if (!blizzard.stop_auto_update)
 776                mod_timer(&blizzard.auto_update_timer,
 777                          jiffies + BLIZZARD_AUTO_UPDATE_TIME);
 778}
 779
 780static void blizzard_update_window_auto(unsigned long arg)
 781{
 782        LIST_HEAD(req_list);
 783        struct blizzard_request *last;
 784        struct omapfb_plane_struct *plane;
 785
 786        plane = blizzard.fbdev->fb_info[0]->par;
 787        create_req_list(plane->idx,
 788                        &blizzard.auto_update_window, &req_list);
 789        last = list_entry(req_list.prev, struct blizzard_request, entry);
 790
 791        last->complete = auto_update_complete;
 792        last->complete_data = NULL;
 793
 794        submit_req_list(&req_list);
 795}
 796
 797int blizzard_update_window_async(struct fb_info *fbi,
 798                                 struct omapfb_update_window *win,
 799                                 void (*complete_callback)(void *arg),
 800                                 void *complete_callback_data)
 801{
 802        LIST_HEAD(req_list);
 803        struct blizzard_request *last;
 804        struct omapfb_plane_struct *plane = fbi->par;
 805
 806        if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE))
 807                return -EINVAL;
 808        if (unlikely(!blizzard.te_connected &&
 809                     (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC)))
 810                return -EINVAL;
 811
 812        create_req_list(plane->idx, win, &req_list);
 813        last = list_entry(req_list.prev, struct blizzard_request, entry);
 814
 815        last->complete = complete_callback;
 816        last->complete_data = (void *)complete_callback_data;
 817
 818        submit_req_list(&req_list);
 819
 820        return 0;
 821}
 822EXPORT_SYMBOL(blizzard_update_window_async);
 823
 824static int update_full_screen(void)
 825{
 826        return blizzard_update_window_async(blizzard.fbdev->fb_info[0],
 827                                     &blizzard.auto_update_window, NULL, NULL);
 828
 829}
 830
 831static int blizzard_setup_plane(int plane, int channel_out,
 832                                  unsigned long offset, int screen_width,
 833                                  int pos_x, int pos_y, int width, int height,
 834                                  int color_mode)
 835{
 836        struct plane_info *p;
 837
 838#ifdef VERBOSE
 839        dev_dbg(blizzard.fbdev->dev,
 840                    "plane %d ch_out %d offset %#08lx scr_width %d "
 841                    "pos_x %d pos_y %d width %d height %d color_mode %d\n",
 842                    plane, channel_out, offset, screen_width,
 843                    pos_x, pos_y, width, height, color_mode);
 844#endif
 845        if ((unsigned)plane > OMAPFB_PLANE_NUM)
 846                return -EINVAL;
 847        p = &blizzard.plane[plane];
 848
 849        switch (color_mode) {
 850        case OMAPFB_COLOR_YUV422:
 851        case OMAPFB_COLOR_YUY422:
 852                p->bpp = 16;
 853                blizzard.vid_nonstd_color &= ~(1 << plane);
 854                break;
 855        case OMAPFB_COLOR_YUV420:
 856                p->bpp = 12;
 857                blizzard.vid_nonstd_color |= 1 << plane;
 858                break;
 859        case OMAPFB_COLOR_RGB565:
 860                p->bpp = 16;
 861                blizzard.vid_nonstd_color &= ~(1 << plane);
 862                break;
 863        default:
 864                return -EINVAL;
 865        }
 866
 867        p->offset = offset;
 868        p->pos_x = pos_x;
 869        p->pos_y = pos_y;
 870        p->width = width;
 871        p->height = height;
 872        p->scr_width = screen_width;
 873        if (!p->out_width)
 874                p->out_width = width;
 875        if (!p->out_height)
 876                p->out_height = height;
 877
 878        p->color_mode = color_mode;
 879
 880        return 0;
 881}
 882
 883static int blizzard_set_scale(int plane, int orig_w, int orig_h,
 884                              int out_w, int out_h)
 885{
 886        struct plane_info *p = &blizzard.plane[plane];
 887        int r;
 888
 889        dev_dbg(blizzard.fbdev->dev,
 890                "plane %d orig_w %d orig_h %d out_w %d out_h %d\n",
 891                plane, orig_w, orig_h, out_w, out_h);
 892        if ((unsigned)plane > OMAPFB_PLANE_NUM)
 893                return -ENODEV;
 894
 895        r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h);
 896        if (r < 0)
 897                return r;
 898
 899        p->width = orig_w;
 900        p->height = orig_h;
 901        p->out_width = out_w;
 902        p->out_height = out_h;
 903        if (orig_w == out_w && orig_h == out_h)
 904                blizzard.vid_scaled &= ~(1 << plane);
 905        else
 906                blizzard.vid_scaled |= 1 << plane;
 907
 908        return 0;
 909}
 910
 911static int blizzard_enable_plane(int plane, int enable)
 912{
 913        if (enable)
 914                blizzard.enabled_planes |= 1 << plane;
 915        else
 916                blizzard.enabled_planes &= ~(1 << plane);
 917
 918        return 0;
 919}
 920
 921static int sync_handler(struct blizzard_request *req)
 922{
 923        complete(req->par.sync);
 924        return REQ_COMPLETE;
 925}
 926
 927static void blizzard_sync(void)
 928{
 929        LIST_HEAD(req_list);
 930        struct blizzard_request *req;
 931        struct completion comp;
 932
 933        req = alloc_req();
 934
 935        req->handler = sync_handler;
 936        req->complete = NULL;
 937        init_completion(&comp);
 938        req->par.sync = &comp;
 939
 940        list_add(&req->entry, &req_list);
 941        submit_req_list(&req_list);
 942
 943        wait_for_completion(&comp);
 944}
 945
 946
 947static void blizzard_bind_client(struct omapfb_notifier_block *nb)
 948{
 949        if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) {
 950                omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
 951        }
 952}
 953
 954static int blizzard_set_update_mode(enum omapfb_update_mode mode)
 955{
 956        if (unlikely(mode != OMAPFB_MANUAL_UPDATE &&
 957                     mode != OMAPFB_AUTO_UPDATE &&
 958                     mode != OMAPFB_UPDATE_DISABLED))
 959                return -EINVAL;
 960
 961        if (mode == blizzard.update_mode)
 962                return 0;
 963
 964        dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n",
 965                        mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
 966                        (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
 967
 968        switch (blizzard.update_mode) {
 969        case OMAPFB_MANUAL_UPDATE:
 970                omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED);
 971                break;
 972        case OMAPFB_AUTO_UPDATE:
 973                blizzard.stop_auto_update = 1;
 974                del_timer_sync(&blizzard.auto_update_timer);
 975                break;
 976        case OMAPFB_UPDATE_DISABLED:
 977                break;
 978        }
 979
 980        blizzard.update_mode = mode;
 981        blizzard_sync();
 982        blizzard.stop_auto_update = 0;
 983
 984        switch (mode) {
 985        case OMAPFB_MANUAL_UPDATE:
 986                omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
 987                break;
 988        case OMAPFB_AUTO_UPDATE:
 989                blizzard_update_window_auto(0);
 990                break;
 991        case OMAPFB_UPDATE_DISABLED:
 992                break;
 993        }
 994
 995        return 0;
 996}
 997
 998static enum omapfb_update_mode blizzard_get_update_mode(void)
 999{
1000        return blizzard.update_mode;
1001}
1002
1003static inline void set_extif_timings(const struct extif_timings *t)
1004{
1005        blizzard.extif->set_timings(t);
1006}
1007
1008static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
1009{
1010        int bus_tick = blizzard.extif_clk_period * div;
1011        return (ps + bus_tick - 1) / bus_tick * bus_tick;
1012}
1013
1014static int calc_reg_timing(unsigned long sysclk, int div)
1015{
1016        struct extif_timings *t;
1017        unsigned long systim;
1018
1019        /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
1020         * AccessTime 2 ns + 12.2 ns (regs),
1021         * WEOffTime = WEOnTime + 1 ns,
1022         * REOffTime = REOnTime + 12 ns (regs),
1023         * CSOffTime = REOffTime + 1 ns
1024         * ReadCycle = 2ns + 2*SYSCLK  (regs),
1025         * WriteCycle = 2*SYSCLK + 2 ns,
1026         * CSPulseWidth = 10 ns */
1027
1028        systim = 1000000000 / (sysclk / 1000);
1029        dev_dbg(blizzard.fbdev->dev,
1030                  "Blizzard systim %lu ps extif_clk_period %u div %d\n",
1031                  systim, blizzard.extif_clk_period, div);
1032
1033        t = &blizzard.reg_timings;
1034        memset(t, 0, sizeof(*t));
1035
1036        t->clk_div = div;
1037
1038        t->cs_on_time = 0;
1039        t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1040        t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1041        t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
1042        t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
1043        t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div);
1044        t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
1045        t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1046        if (t->we_cycle_time < t->we_off_time)
1047                t->we_cycle_time = t->we_off_time;
1048        t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1049        if (t->re_cycle_time < t->re_off_time)
1050                t->re_cycle_time = t->re_off_time;
1051        t->cs_pulse_width = 0;
1052
1053        dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
1054                 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
1055        dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
1056                 t->we_on_time, t->we_off_time, t->re_cycle_time,
1057                 t->we_cycle_time);
1058        dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
1059                 t->access_time, t->cs_pulse_width);
1060
1061        return blizzard.extif->convert_timings(t);
1062}
1063
1064static int calc_lut_timing(unsigned long sysclk, int div)
1065{
1066        struct extif_timings *t;
1067        unsigned long systim;
1068
1069        /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
1070         * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
1071         * WEOffTime = WEOnTime + 1 ns,
1072         * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
1073         * CSOffTime = REOffTime + 1 ns
1074         * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
1075         * WriteCycle = 2*SYSCLK + 2 ns,
1076         * CSPulseWidth = 10 ns */
1077
1078        systim = 1000000000 / (sysclk / 1000);
1079        dev_dbg(blizzard.fbdev->dev,
1080                "Blizzard systim %lu ps extif_clk_period %u div %d\n",
1081                systim, blizzard.extif_clk_period, div);
1082
1083        t = &blizzard.lut_timings;
1084        memset(t, 0, sizeof(*t));
1085
1086        t->clk_div = div;
1087
1088        t->cs_on_time = 0;
1089        t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1090        t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1091        t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
1092                                              26000, div);
1093        t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
1094        t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
1095                                              26000, div);
1096        t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
1097        t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1098        if (t->we_cycle_time < t->we_off_time)
1099                t->we_cycle_time = t->we_off_time;
1100        t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
1101        if (t->re_cycle_time < t->re_off_time)
1102                t->re_cycle_time = t->re_off_time;
1103        t->cs_pulse_width = 0;
1104
1105        dev_dbg(blizzard.fbdev->dev,
1106                 "[lut]cson %d csoff %d reon %d reoff %d\n",
1107                 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
1108        dev_dbg(blizzard.fbdev->dev,
1109                 "[lut]weon %d weoff %d recyc %d wecyc %d\n",
1110                 t->we_on_time, t->we_off_time, t->re_cycle_time,
1111                 t->we_cycle_time);
1112        dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
1113                 t->access_time, t->cs_pulse_width);
1114
1115        return blizzard.extif->convert_timings(t);
1116}
1117
1118static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
1119{
1120        int max_clk_div;
1121        int div;
1122
1123        blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div);
1124        for (div = 1; div <= max_clk_div; div++) {
1125                if (calc_reg_timing(sysclk, div) == 0)
1126                        break;
1127        }
1128        if (div > max_clk_div) {
1129                dev_dbg(blizzard.fbdev->dev, "reg timing failed\n");
1130                goto err;
1131        }
1132        *extif_mem_div = div;
1133
1134        for (div = 1; div <= max_clk_div; div++) {
1135                if (calc_lut_timing(sysclk, div) == 0)
1136                        break;
1137        }
1138
1139        if (div > max_clk_div)
1140                goto err;
1141
1142        blizzard.extif_clk_div = div;
1143
1144        return 0;
1145err:
1146        dev_err(blizzard.fbdev->dev, "can't setup timings\n");
1147        return -1;
1148}
1149
1150static void calc_blizzard_clk_rates(unsigned long ext_clk,
1151                                unsigned long *sys_clk, unsigned long *pix_clk)
1152{
1153        int pix_clk_src;
1154        int sys_div = 0, sys_mul = 0;
1155        int pix_div;
1156
1157        pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC);
1158        pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
1159        if ((pix_clk_src & (0x3 << 1)) == 0) {
1160                /* Source is the PLL */
1161                sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1;
1162                sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0);
1163                sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1)
1164                                & 0x0f) << 11);
1165                *sys_clk = ext_clk * sys_mul / sys_div;
1166        } else  /* else source is ext clk, or oscillator */
1167                *sys_clk = ext_clk;
1168
1169        *pix_clk = *sys_clk / pix_div;                  /* HZ */
1170        dev_dbg(blizzard.fbdev->dev,
1171                "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
1172                ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
1173        dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
1174                *sys_clk, *pix_clk);
1175}
1176
1177static int setup_tearsync(unsigned long pix_clk, int extif_div)
1178{
1179        int hdisp, vdisp;
1180        int hndp, vndp;
1181        int hsw, vsw;
1182        int hs, vs;
1183        int hs_pol_inv, vs_pol_inv;
1184        int use_hsvs, use_ndp;
1185        u8  b;
1186
1187        hsw = blizzard_read_reg(BLIZZARD_HSW);
1188        vsw = blizzard_read_reg(BLIZZARD_VSW);
1189        hs_pol_inv = !(hsw & 0x80);
1190        vs_pol_inv = !(vsw & 0x80);
1191        hsw = hsw & 0x7f;
1192        vsw = vsw & 0x3f;
1193
1194        hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8;
1195        vdisp = blizzard_read_reg(BLIZZARD_VDISP0) +
1196                ((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8);
1197
1198        hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f;
1199        vndp = blizzard_read_reg(BLIZZARD_VNDP);
1200
1201        /* time to transfer one pixel (16bpp) in ps */
1202        blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time;
1203        if (blizzard.extif->get_max_tx_rate != NULL) {
1204                /* The external interface might have a rate limitation,
1205                 * if so, we have to maximize our transfer rate.
1206                 */
1207                unsigned long min_tx_time;
1208                unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate();
1209
1210                dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n",
1211                        max_tx_rate);
1212                min_tx_time = 1000000000 / (max_tx_rate / 1000);  /* ps */
1213                if (blizzard.pix_tx_time < min_tx_time)
1214                        blizzard.pix_tx_time = min_tx_time;
1215        }
1216
1217        /* time to update one line in ps */
1218        blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
1219        blizzard.line_upd_time *= 1000;
1220        if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time)
1221                /* transfer speed too low, we might have to use both
1222                 * HS and VS */
1223                use_hsvs = 1;
1224        else
1225                /* decent transfer speed, we'll always use only VS */
1226                use_hsvs = 0;
1227
1228        if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
1229                /* HS or'ed with VS doesn't work, use the active high
1230                 * TE signal based on HNDP / VNDP */
1231                use_ndp = 1;
1232                hs_pol_inv = 0;
1233                vs_pol_inv = 0;
1234                hs = hndp;
1235                vs = vndp;
1236        } else {
1237                /* Use HS or'ed with VS as a TE signal if both are needed
1238                 * or VNDP if only vsync is needed. */
1239                use_ndp = 0;
1240                hs = hsw;
1241                vs = vsw;
1242                if (!use_hsvs) {
1243                        hs_pol_inv = 0;
1244                        vs_pol_inv = 0;
1245                }
1246        }
1247
1248        hs = hs * 1000000 / (pix_clk / 1000);             /* ps */
1249        hs *= 1000;
1250
1251        vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
1252        vs *= 1000;
1253
1254        if (vs <= hs)
1255                return -EDOM;
1256        /* set VS to 120% of HS to minimize VS detection time */
1257        vs = hs * 12 / 10;
1258        /* minimize HS too */
1259        if (hs > 10000)
1260                hs = 10000;
1261
1262        b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
1263        b &= ~0x3;
1264        b |= use_hsvs ? 1 : 0;
1265        b |= (use_ndp && use_hsvs) ? 0 : 2;
1266        blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
1267
1268        blizzard.vsync_only = !use_hsvs;
1269
1270        dev_dbg(blizzard.fbdev->dev,
1271                "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
1272                pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time);
1273        dev_dbg(blizzard.fbdev->dev,
1274                "hs %d ps vs %d ps mode %d vsync_only %d\n",
1275                hs, vs, b & 0x3, !use_hsvs);
1276
1277        return blizzard.extif->setup_tearsync(1, hs, vs,
1278                                              hs_pol_inv, vs_pol_inv,
1279                                              extif_div);
1280}
1281
1282static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
1283{
1284        blizzard.int_ctrl->get_caps(plane, caps);
1285        caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
1286                OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
1287                OMAPFB_CAPS_WINDOW_SCALE |
1288                OMAPFB_CAPS_WINDOW_OVERLAY;
1289        if (blizzard.te_connected)
1290                caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
1291        caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
1292                           (1 << OMAPFB_COLOR_YUV420);
1293}
1294
1295static void _save_regs(struct blizzard_reg_list *list, int cnt)
1296{
1297        int i;
1298
1299        for (i = 0; i < cnt; i++, list++) {
1300                int reg;
1301                for (reg = list->start; reg <= list->end; reg += 2)
1302                        blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg);
1303        }
1304}
1305
1306static void _restore_regs(struct blizzard_reg_list *list, int cnt)
1307{
1308        int i;
1309
1310        for (i = 0; i < cnt; i++, list++) {
1311                int reg;
1312                for (reg = list->start; reg <= list->end; reg += 2)
1313                        blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]);
1314        }
1315}
1316
1317static void blizzard_save_all_regs(void)
1318{
1319        _save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
1320        _save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
1321}
1322
1323static void blizzard_restore_pll_regs(void)
1324{
1325        _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
1326}
1327
1328static void blizzard_restore_gen_regs(void)
1329{
1330        _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
1331}
1332
1333static void blizzard_suspend(void)
1334{
1335        u32 l;
1336        unsigned long tmo;
1337
1338        if (blizzard.last_color_mode) {
1339                update_full_screen();
1340                blizzard_sync();
1341        }
1342        blizzard.update_mode_before_suspend = blizzard.update_mode;
1343        /* the following will disable clocks as well */
1344        blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
1345
1346        blizzard_save_all_regs();
1347
1348        blizzard_stop_sdram();
1349
1350        l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
1351        /* Standby, Sleep. We assume we use an external clock. */
1352        l |= 0x03;
1353        blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
1354
1355        tmo = jiffies + msecs_to_jiffies(100);
1356        while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) {
1357                if (time_after(jiffies, tmo)) {
1358                        dev_err(blizzard.fbdev->dev,
1359                                "s1d1374x: sleep timeout, stopping PLL manually\n");
1360                        l = blizzard_read_reg(BLIZZARD_PLL_MODE);
1361                        l &= ~0x03;
1362                        /* Disable PLL, counter function */
1363                        l |= 0x2;
1364                        blizzard_write_reg(BLIZZARD_PLL_MODE, l);
1365                        break;
1366                }
1367                msleep(1);
1368        }
1369
1370        if (blizzard.power_down != NULL)
1371                blizzard.power_down(blizzard.fbdev->dev);
1372}
1373
1374static void blizzard_resume(void)
1375{
1376        u32 l;
1377
1378        if (blizzard.power_up != NULL)
1379                blizzard.power_up(blizzard.fbdev->dev);
1380
1381        l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
1382        /* Standby, Sleep */
1383        l &= ~0x03;
1384        blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
1385
1386        blizzard_restore_pll_regs();
1387        l = blizzard_read_reg(BLIZZARD_PLL_MODE);
1388        l &= ~0x03;
1389        /* Enable PLL, counter function */
1390        l |= 0x1;
1391        blizzard_write_reg(BLIZZARD_PLL_MODE, l);
1392
1393        while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7)))
1394                msleep(1);
1395
1396        blizzard_restart_sdram();
1397
1398        blizzard_restore_gen_regs();
1399
1400        /* Enable display */
1401        blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01);
1402
1403        /* the following will enable clocks as necessary */
1404        blizzard_set_update_mode(blizzard.update_mode_before_suspend);
1405
1406        /* Force a background update */
1407        blizzard.zoom_on = 1;
1408        update_full_screen();
1409        blizzard_sync();
1410}
1411
1412static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
1413                         struct omapfb_mem_desc *req_vram)
1414{
1415        int r = 0, i;
1416        u8 rev, conf;
1417        unsigned long ext_clk;
1418        int extif_div;
1419        unsigned long sys_clk, pix_clk;
1420        struct omapfb_platform_data *omapfb_conf;
1421        struct blizzard_platform_data *ctrl_conf;
1422
1423        blizzard.fbdev = fbdev;
1424
1425        BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
1426
1427        blizzard.fbdev = fbdev;
1428        blizzard.extif = fbdev->ext_if;
1429        blizzard.int_ctrl = fbdev->int_ctrl;
1430
1431        omapfb_conf = fbdev->dev->platform_data;
1432        ctrl_conf = omapfb_conf->ctrl_platform_data;
1433        if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
1434                dev_err(fbdev->dev, "s1d1374x: missing platform data\n");
1435                r = -ENOENT;
1436                goto err1;
1437        }
1438
1439        blizzard.power_down = ctrl_conf->power_down;
1440        blizzard.power_up = ctrl_conf->power_up;
1441
1442        spin_lock_init(&blizzard.req_lock);
1443
1444        if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0)
1445                goto err1;
1446
1447        if ((r = blizzard.extif->init(fbdev)) < 0)
1448                goto err2;
1449
1450        blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key;
1451        blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key;
1452        blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem;
1453        blizzard_ctrl.mmap = blizzard.int_ctrl->mmap;
1454
1455        ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
1456        if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0)
1457                goto err3;
1458
1459        set_extif_timings(&blizzard.reg_timings);
1460
1461        if (blizzard.power_up != NULL)
1462                blizzard.power_up(fbdev->dev);
1463
1464        calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk);
1465
1466        if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0)
1467                goto err3;
1468        set_extif_timings(&blizzard.reg_timings);
1469
1470        if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) {
1471                dev_err(fbdev->dev,
1472                        "controller not initialized by the bootloader\n");
1473                r = -ENODEV;
1474                goto err3;
1475        }
1476
1477        if (ctrl_conf->te_connected) {
1478                if ((r = setup_tearsync(pix_clk, extif_div)) < 0)
1479                        goto err3;
1480                blizzard.te_connected = 1;
1481        }
1482
1483        rev = blizzard_read_reg(BLIZZARD_REV_CODE);
1484        conf = blizzard_read_reg(BLIZZARD_CONFIG);
1485
1486        switch (rev & 0xfc) {
1487        case 0x9c:
1488                blizzard.version = BLIZZARD_VERSION_S1D13744;
1489                pr_info("omapfb: s1d13744 LCD controller rev %d "
1490                        "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
1491                break;
1492        case 0xa4:
1493                blizzard.version = BLIZZARD_VERSION_S1D13745;
1494                pr_info("omapfb: s1d13745 LCD controller rev %d "
1495                        "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
1496                break;
1497        default:
1498                dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n",
1499                        rev);
1500                r = -ENODEV;
1501                goto err3;
1502        }
1503
1504        blizzard.max_transmit_size = blizzard.extif->max_transmit_size;
1505
1506        blizzard.update_mode = OMAPFB_UPDATE_DISABLED;
1507
1508        blizzard.auto_update_window.x = 0;
1509        blizzard.auto_update_window.y = 0;
1510        blizzard.auto_update_window.width = fbdev->panel->x_res;
1511        blizzard.auto_update_window.height = fbdev->panel->y_res;
1512        blizzard.auto_update_window.out_x = 0;
1513        blizzard.auto_update_window.out_x = 0;
1514        blizzard.auto_update_window.out_width = fbdev->panel->x_res;
1515        blizzard.auto_update_window.out_height = fbdev->panel->y_res;
1516        blizzard.auto_update_window.format = 0;
1517
1518        blizzard.screen_width = fbdev->panel->x_res;
1519        blizzard.screen_height = fbdev->panel->y_res;
1520
1521        init_timer(&blizzard.auto_update_timer);
1522        blizzard.auto_update_timer.function = blizzard_update_window_auto;
1523        blizzard.auto_update_timer.data = 0;
1524
1525        INIT_LIST_HEAD(&blizzard.free_req_list);
1526        INIT_LIST_HEAD(&blizzard.pending_req_list);
1527        for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++)
1528                list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list);
1529        BUG_ON(i <= IRQ_REQ_POOL_SIZE);
1530        sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE);
1531
1532        return 0;
1533err3:
1534        if (blizzard.power_down != NULL)
1535                blizzard.power_down(fbdev->dev);
1536        blizzard.extif->cleanup();
1537err2:
1538        blizzard.int_ctrl->cleanup();
1539err1:
1540        return r;
1541}
1542
1543static void blizzard_cleanup(void)
1544{
1545        blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
1546        blizzard.extif->cleanup();
1547        blizzard.int_ctrl->cleanup();
1548        if (blizzard.power_down != NULL)
1549                blizzard.power_down(blizzard.fbdev->dev);
1550}
1551
1552struct lcd_ctrl blizzard_ctrl = {
1553        .name                   = "blizzard",
1554        .init                   = blizzard_init,
1555        .cleanup                = blizzard_cleanup,
1556        .bind_client            = blizzard_bind_client,
1557        .get_caps               = blizzard_get_caps,
1558        .set_update_mode        = blizzard_set_update_mode,
1559        .get_update_mode        = blizzard_get_update_mode,
1560        .setup_plane            = blizzard_setup_plane,
1561        .set_scale              = blizzard_set_scale,
1562        .enable_plane           = blizzard_enable_plane,
1563        .update_window          = blizzard_update_window_async,
1564        .sync                   = blizzard_sync,
1565        .suspend                = blizzard_suspend,
1566        .resume                 = blizzard_resume,
1567};
1568
1569
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.