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