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