linux/drivers/media/pci/ivtv/ivtvfb.c
<<
>>
Prefs
   1/*
   2    On Screen Display cx23415 Framebuffer driver
   3
   4    This module presents the cx23415 OSD (onscreen display) framebuffer memory
   5    as a standard Linux /dev/fb style framebuffer device. The framebuffer has
   6    support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
   7    mode, there is a choice of a three color depths (12, 15 or 16 bits), but no
   8    local alpha. The colorspace is selectable between rgb & yuv.
   9    Depending on the TV standard configured in the ivtv module at load time,
  10    the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp.
  11    Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL)
  12    or 59.94 (NTSC)
  13
  14    Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com>
  15
  16    Derived from drivers/video/vesafb.c
  17    Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  18
  19    2.6 kernel port:
  20    Copyright (C) 2004 Matthias Badaire
  21
  22    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
  23
  24    Copyright (C) 2006  Ian Armstrong <ian@iarmst.demon.co.uk>
  25
  26    This program is free software; you can redistribute it and/or modify
  27    it under the terms of the GNU General Public License as published by
  28    the Free Software Foundation; either version 2 of the License, or
  29    (at your option) any later version.
  30
  31    This program is distributed in the hope that it will be useful,
  32    but WITHOUT ANY WARRANTY; without even the implied warranty of
  33    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  34    GNU General Public License for more details.
  35
  36    You should have received a copy of the GNU General Public License
  37    along with this program; if not, write to the Free Software
  38    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  39 */
  40
  41#include "ivtv-driver.h"
  42#include "ivtv-cards.h"
  43#include "ivtv-i2c.h"
  44#include "ivtv-udma.h"
  45#include "ivtv-mailbox.h"
  46#include "ivtv-firmware.h"
  47
  48#include <linux/fb.h>
  49#include <linux/ivtvfb.h>
  50
  51#ifdef CONFIG_X86_64
  52#include <asm/pat.h>
  53#endif
  54
  55/* card parameters */
  56static int ivtvfb_card_id = -1;
  57static int ivtvfb_debug = 0;
  58static bool osd_laced;
  59static int osd_depth;
  60static int osd_upper;
  61static int osd_left;
  62static int osd_yres;
  63static int osd_xres;
  64
  65module_param(ivtvfb_card_id, int, 0444);
  66module_param_named(debug,ivtvfb_debug, int, 0644);
  67module_param(osd_laced, bool, 0444);
  68module_param(osd_depth, int, 0444);
  69module_param(osd_upper, int, 0444);
  70module_param(osd_left, int, 0444);
  71module_param(osd_yres, int, 0444);
  72module_param(osd_xres, int, 0444);
  73
  74MODULE_PARM_DESC(ivtvfb_card_id,
  75                 "Only use framebuffer of the specified ivtv card (0-31)\n"
  76                 "\t\t\tdefault -1: initialize all available framebuffers");
  77
  78MODULE_PARM_DESC(debug,
  79                 "Debug level (bitmask). Default: errors only\n"
  80                 "\t\t\t(debug = 3 gives full debugging)");
  81
  82/* Why upper, left, xres, yres, depth, laced ? To match terminology used
  83   by fbset.
  84   Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
  85
  86MODULE_PARM_DESC(osd_laced,
  87                 "Interlaced mode\n"
  88                 "\t\t\t0=off\n"
  89                 "\t\t\t1=on\n"
  90                 "\t\t\tdefault off");
  91
  92MODULE_PARM_DESC(osd_depth,
  93                 "Bits per pixel - 8, 16, 32\n"
  94                 "\t\t\tdefault 8");
  95
  96MODULE_PARM_DESC(osd_upper,
  97                 "Vertical start position\n"
  98                 "\t\t\tdefault 0 (Centered)");
  99
 100MODULE_PARM_DESC(osd_left,
 101                 "Horizontal start position\n"
 102                 "\t\t\tdefault 0 (Centered)");
 103
 104MODULE_PARM_DESC(osd_yres,
 105                 "Display height\n"
 106                 "\t\t\tdefault 480 (PAL)\n"
 107                 "\t\t\t        400 (NTSC)");
 108
 109MODULE_PARM_DESC(osd_xres,
 110                 "Display width\n"
 111                 "\t\t\tdefault 640");
 112
 113MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
 114MODULE_LICENSE("GPL");
 115
 116/* --------------------------------------------------------------------- */
 117
 118#define IVTVFB_DBGFLG_WARN  (1 << 0)
 119#define IVTVFB_DBGFLG_INFO  (1 << 1)
 120
 121#define IVTVFB_DEBUG(x, type, fmt, args...) \
 122        do { \
 123                if ((x) & ivtvfb_debug) \
 124                        printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
 125        } while (0)
 126#define IVTVFB_DEBUG_WARN(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
 127#define IVTVFB_DEBUG_INFO(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
 128
 129/* Standard kernel messages */
 130#define IVTVFB_ERR(fmt, args...)   printk(KERN_ERR  "ivtvfb%d: " fmt, itv->instance , ## args)
 131#define IVTVFB_WARN(fmt, args...)  printk(KERN_WARNING  "ivtvfb%d: " fmt, itv->instance , ## args)
 132#define IVTVFB_INFO(fmt, args...)  printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
 133
 134/* --------------------------------------------------------------------- */
 135
 136#define IVTV_OSD_MAX_WIDTH  720
 137#define IVTV_OSD_MAX_HEIGHT 576
 138
 139#define IVTV_OSD_BPP_8      0x00
 140#define IVTV_OSD_BPP_16_444 0x03
 141#define IVTV_OSD_BPP_16_555 0x02
 142#define IVTV_OSD_BPP_16_565 0x01
 143#define IVTV_OSD_BPP_32     0x04
 144
 145struct osd_info {
 146        /* Physical base address */
 147        unsigned long video_pbase;
 148        /* Relative base address (relative to start of decoder memory) */
 149        u32 video_rbase;
 150        /* Mapped base address */
 151        volatile char __iomem *video_vbase;
 152        /* Buffer size */
 153        u32 video_buffer_size;
 154
 155        /* video_base rounded down as required by hardware MTRRs */
 156        unsigned long fb_start_aligned_physaddr;
 157        /* video_base rounded up as required by hardware MTRRs */
 158        unsigned long fb_end_aligned_physaddr;
 159        int wc_cookie;
 160
 161        /* Store the buffer offset */
 162        int set_osd_coords_x;
 163        int set_osd_coords_y;
 164
 165        /* Current dimensions (NOT VISIBLE SIZE!) */
 166        int display_width;
 167        int display_height;
 168        int display_byte_stride;
 169
 170        /* Current bits per pixel */
 171        int bits_per_pixel;
 172        int bytes_per_pixel;
 173
 174        /* Frame buffer stuff */
 175        struct fb_info ivtvfb_info;
 176        struct fb_var_screeninfo ivtvfb_defined;
 177        struct fb_fix_screeninfo ivtvfb_fix;
 178
 179        /* Used for a warm start */
 180        struct fb_var_screeninfo fbvar_cur;
 181        int blank_cur;
 182        u32 palette_cur[256];
 183        u32 pan_cur;
 184};
 185
 186struct ivtv_osd_coords {
 187        unsigned long offset;
 188        unsigned long max_offset;
 189        int pixel_stride;
 190        int lines;
 191        int x;
 192        int y;
 193};
 194
 195/* --------------------------------------------------------------------- */
 196
 197/* ivtv API calls for framebuffer related support */
 198
 199static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
 200                                       u32 *fblength)
 201{
 202        u32 data[CX2341X_MBOX_MAX_DATA];
 203        int rc;
 204
 205        ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
 206        rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
 207        *fbbase = data[0];
 208        *fblength = data[1];
 209        return rc;
 210}
 211
 212static int ivtvfb_get_osd_coords(struct ivtv *itv,
 213                                      struct ivtv_osd_coords *osd)
 214{
 215        struct osd_info *oi = itv->osd_info;
 216        u32 data[CX2341X_MBOX_MAX_DATA];
 217
 218        ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
 219
 220        osd->offset = data[0] - oi->video_rbase;
 221        osd->max_offset = oi->display_width * oi->display_height * 4;
 222        osd->pixel_stride = data[1];
 223        osd->lines = data[2];
 224        osd->x = data[3];
 225        osd->y = data[4];
 226        return 0;
 227}
 228
 229static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
 230{
 231        struct osd_info *oi = itv->osd_info;
 232
 233        oi->display_width = osd->pixel_stride;
 234        oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel;
 235        oi->set_osd_coords_x += osd->x;
 236        oi->set_osd_coords_y = osd->y;
 237
 238        return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
 239                        osd->offset + oi->video_rbase,
 240                        osd->pixel_stride,
 241                        osd->lines, osd->x, osd->y);
 242}
 243
 244static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
 245{
 246        int osd_height_limit = itv->is_out_50hz ? 576 : 480;
 247
 248        /* Only fail if resolution too high, otherwise fudge the start coords. */
 249        if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
 250                return -EINVAL;
 251
 252        /* Ensure we don't exceed display limits */
 253        if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
 254                IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
 255                        ivtv_window->top, ivtv_window->height);
 256                ivtv_window->top = osd_height_limit - ivtv_window->height;
 257        }
 258
 259        if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) {
 260                IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
 261                        ivtv_window->left, ivtv_window->width);
 262                ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
 263        }
 264
 265        /* Set the OSD origin */
 266        write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
 267
 268        /* How much to display */
 269        write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
 270
 271        /* Pass this info back the yuv handler */
 272        itv->yuv_info.osd_vis_w = ivtv_window->width;
 273        itv->yuv_info.osd_vis_h = ivtv_window->height;
 274        itv->yuv_info.osd_x_offset = ivtv_window->left;
 275        itv->yuv_info.osd_y_offset = ivtv_window->top;
 276
 277        return 0;
 278}
 279
 280static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
 281                                  unsigned long ivtv_dest_addr, void __user *userbuf,
 282                                  int size_in_bytes)
 283{
 284        DEFINE_WAIT(wait);
 285        int got_sig = 0;
 286
 287        mutex_lock(&itv->udma.lock);
 288        /* Map User DMA */
 289        if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
 290                mutex_unlock(&itv->udma.lock);
 291                IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with get_user_pages: %d bytes, %d pages returned\n",
 292                               size_in_bytes, itv->udma.page_count);
 293
 294                /* get_user_pages must have failed completely */
 295                return -EIO;
 296        }
 297
 298        IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
 299                       size_in_bytes, itv->udma.page_count);
 300
 301        ivtv_udma_prepare(itv);
 302        prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
 303        /* if no UDMA is pending and no UDMA is in progress, then the DMA
 304           is finished */
 305        while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
 306               test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
 307                /* don't interrupt if the DMA is in progress but break off
 308                   a still pending DMA. */
 309                got_sig = signal_pending(current);
 310                if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
 311                        break;
 312                got_sig = 0;
 313                schedule();
 314        }
 315        finish_wait(&itv->dma_waitq, &wait);
 316
 317        /* Unmap Last DMA Xfer */
 318        ivtv_udma_unmap(itv);
 319        mutex_unlock(&itv->udma.lock);
 320        if (got_sig) {
 321                IVTV_DEBUG_INFO("User stopped OSD\n");
 322                return -EINTR;
 323        }
 324
 325        return 0;
 326}
 327
 328static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
 329                              unsigned long dest_offset, int count)
 330{
 331        DEFINE_WAIT(wait);
 332        struct osd_info *oi = itv->osd_info;
 333
 334        /* Nothing to do */
 335        if (count == 0) {
 336                IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
 337                return -EINVAL;
 338        }
 339
 340        /* Check Total FB Size */
 341        if ((dest_offset + count) > oi->video_buffer_size) {
 342                IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
 343                        dest_offset + count, oi->video_buffer_size);
 344                return -E2BIG;
 345        }
 346
 347        /* Not fatal, but will have undesirable results */
 348        if ((unsigned long)source & 3)
 349                IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
 350                        (unsigned long)source);
 351
 352        if (dest_offset & 3)
 353                IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
 354
 355        if (count & 3)
 356                IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
 357
 358        /* Check Source */
 359        if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
 360                IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
 361                        (unsigned long)source);
 362
 363                IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
 364                        dest_offset, (unsigned long)source,
 365                        count);
 366                return -EINVAL;
 367        }
 368
 369        /* OSD Address to send DMA to */
 370        dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
 371
 372        /* Fill Buffers */
 373        return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
 374}
 375
 376static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
 377                                                size_t count, loff_t *ppos)
 378{
 379        unsigned long p = *ppos;
 380        void *dst;
 381        int err = 0;
 382        int dma_err;
 383        unsigned long total_size;
 384        struct ivtv *itv = (struct ivtv *) info->par;
 385        unsigned long dma_offset =
 386                        IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
 387        unsigned long dma_size;
 388        u16 lead = 0, tail = 0;
 389
 390        if (info->state != FBINFO_STATE_RUNNING)
 391                return -EPERM;
 392
 393        total_size = info->screen_size;
 394
 395        if (total_size == 0)
 396                total_size = info->fix.smem_len;
 397
 398        if (p > total_size)
 399                return -EFBIG;
 400
 401        if (count > total_size) {
 402                err = -EFBIG;
 403                count = total_size;
 404        }
 405
 406        if (count + p > total_size) {
 407                if (!err)
 408                        err = -ENOSPC;
 409                count = total_size - p;
 410        }
 411
 412        dst = (void __force *) (info->screen_base + p);
 413
 414        if (info->fbops->fb_sync)
 415                info->fbops->fb_sync(info);
 416
 417        /* If transfer size > threshold and both src/dst
 418        addresses are aligned, use DMA */
 419        if (count >= 4096 &&
 420            ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
 421                /* Odd address = can't DMA. Align */
 422                if ((unsigned long)dst & 3) {
 423                        lead = 4 - ((unsigned long)dst & 3);
 424                        if (copy_from_user(dst, buf, lead))
 425                                return -EFAULT;
 426                        buf += lead;
 427                        dst += lead;
 428                }
 429                /* DMA resolution is 32 bits */
 430                if ((count - lead) & 3)
 431                        tail = (count - lead) & 3;
 432                /* DMA the data */
 433                dma_size = count - lead - tail;
 434                dma_err = ivtvfb_prep_dec_dma_to_device(itv,
 435                       p + lead + dma_offset, (void __user *)buf, dma_size);
 436                if (dma_err)
 437                        return dma_err;
 438                dst += dma_size;
 439                buf += dma_size;
 440                /* Copy any leftover data */
 441                if (tail && copy_from_user(dst, buf, tail))
 442                        return -EFAULT;
 443        } else if (copy_from_user(dst, buf, count)) {
 444                return -EFAULT;
 445        }
 446
 447        if  (!err)
 448                *ppos += count;
 449
 450        return (err) ? err : count;
 451}
 452
 453static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 454{
 455        DEFINE_WAIT(wait);
 456        struct ivtv *itv = (struct ivtv *)info->par;
 457        int rc = 0;
 458
 459        switch (cmd) {
 460                case FBIOGET_VBLANK: {
 461                        struct fb_vblank vblank;
 462                        u32 trace;
 463
 464                        memset(&vblank, 0, sizeof(struct fb_vblank));
 465
 466                        vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
 467                                        FB_VBLANK_HAVE_VSYNC;
 468                        trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
 469                        if (itv->is_out_50hz && trace > 312)
 470                                trace -= 312;
 471                        else if (itv->is_out_60hz && trace > 262)
 472                                trace -= 262;
 473                        if (trace == 1)
 474                                vblank.flags |= FB_VBLANK_VSYNCING;
 475                        vblank.count = itv->last_vsync_field;
 476                        vblank.vcount = trace;
 477                        vblank.hcount = 0;
 478                        if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
 479                                return -EFAULT;
 480                        return 0;
 481                }
 482
 483                case FBIO_WAITFORVSYNC:
 484                        prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
 485                        if (!schedule_timeout(msecs_to_jiffies(50)))
 486                                rc = -ETIMEDOUT;
 487                        finish_wait(&itv->vsync_waitq, &wait);
 488                        return rc;
 489
 490                case IVTVFB_IOC_DMA_FRAME: {
 491                        struct ivtvfb_dma_frame args;
 492
 493                        IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
 494                        if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
 495                                return -EFAULT;
 496
 497                        return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
 498                }
 499
 500                default:
 501                        IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
 502                        return -EINVAL;
 503        }
 504        return 0;
 505}
 506
 507/* Framebuffer device handling */
 508
 509static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
 510{
 511        struct osd_info *oi = itv->osd_info;
 512        struct ivtv_osd_coords ivtv_osd;
 513        struct v4l2_rect ivtv_window;
 514        int osd_mode = -1;
 515
 516        IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
 517
 518        /* Select color space */
 519        if (var->nonstd) /* YUV */
 520                write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
 521        else /* RGB  */
 522                write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
 523
 524        /* Set the color mode */
 525        switch (var->bits_per_pixel) {
 526                case 8:
 527                        osd_mode = IVTV_OSD_BPP_8;
 528                        break;
 529                case 32:
 530                        osd_mode = IVTV_OSD_BPP_32;
 531                        break;
 532                case 16:
 533                        switch (var->green.length) {
 534                        case 4:
 535                                osd_mode = IVTV_OSD_BPP_16_444;
 536                                break;
 537                        case 5:
 538                                osd_mode = IVTV_OSD_BPP_16_555;
 539                                break;
 540                        case 6:
 541                                osd_mode = IVTV_OSD_BPP_16_565;
 542                                break;
 543                        default:
 544                                IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
 545                        }
 546                        break;
 547                default:
 548                        IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
 549        }
 550
 551        /* Set video mode. Although rare, the display can become scrambled even
 552           if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
 553        if (osd_mode != -1) {
 554                ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
 555                ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
 556        }
 557
 558        oi->bits_per_pixel = var->bits_per_pixel;
 559        oi->bytes_per_pixel = var->bits_per_pixel / 8;
 560
 561        /* Set the flicker filter */
 562        switch (var->vmode & FB_VMODE_MASK) {
 563                case FB_VMODE_NONINTERLACED: /* Filter on */
 564                        ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
 565                        break;
 566                case FB_VMODE_INTERLACED: /* Filter off */
 567                        ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
 568                        break;
 569                default:
 570                        IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
 571        }
 572
 573        /* Read the current osd info */
 574        ivtvfb_get_osd_coords(itv, &ivtv_osd);
 575
 576        /* Now set the OSD to the size we want */
 577        ivtv_osd.pixel_stride = var->xres_virtual;
 578        ivtv_osd.lines = var->yres_virtual;
 579        ivtv_osd.x = 0;
 580        ivtv_osd.y = 0;
 581        ivtvfb_set_osd_coords(itv, &ivtv_osd);
 582
 583        /* Can't seem to find the right API combo for this.
 584           Use another function which does what we need through direct register access. */
 585        ivtv_window.width = var->xres;
 586        ivtv_window.height = var->yres;
 587
 588        /* Minimum margin cannot be 0, as X won't allow such a mode */
 589        if (!var->upper_margin)
 590                var->upper_margin++;
 591        if (!var->left_margin)
 592                var->left_margin++;
 593        ivtv_window.top = var->upper_margin - 1;
 594        ivtv_window.left = var->left_margin - 1;
 595
 596        ivtvfb_set_display_window(itv, &ivtv_window);
 597
 598        /* Pass screen size back to yuv handler */
 599        itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
 600        itv->yuv_info.osd_full_h = ivtv_osd.lines;
 601
 602        /* Force update of yuv registers */
 603        itv->yuv_info.yuv_forced_update = 1;
 604
 605        /* Keep a copy of these settings */
 606        memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
 607
 608        IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
 609                      var->xres, var->yres,
 610                      var->xres_virtual, var->yres_virtual,
 611                      var->bits_per_pixel);
 612
 613        IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
 614                      var->left_margin, var->upper_margin);
 615
 616        IVTVFB_DEBUG_INFO("Display filter: %s\n",
 617                        (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
 618        IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
 619
 620        return 0;
 621}
 622
 623static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
 624{
 625        struct osd_info *oi = itv->osd_info;
 626
 627        IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
 628        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 629        strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
 630        fix->smem_start = oi->video_pbase;
 631        fix->smem_len = oi->video_buffer_size;
 632        fix->type = FB_TYPE_PACKED_PIXELS;
 633        fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 634        fix->xpanstep = 1;
 635        fix->ypanstep = 1;
 636        fix->ywrapstep = 0;
 637        fix->line_length = oi->display_byte_stride;
 638        fix->accel = FB_ACCEL_NONE;
 639        return 0;
 640}
 641
 642/* Check the requested display mode, returning -EINVAL if we can't
 643   handle it. */
 644
 645static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
 646{
 647        struct osd_info *oi = itv->osd_info;
 648        int osd_height_limit;
 649        u32 pixclock, hlimit, vlimit;
 650
 651        IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
 652
 653        /* Set base references for mode calcs. */
 654        if (itv->is_out_50hz) {
 655                pixclock = 84316;
 656                hlimit = 776;
 657                vlimit = 591;
 658                osd_height_limit = 576;
 659        }
 660        else {
 661                pixclock = 83926;
 662                hlimit = 776;
 663                vlimit = 495;
 664                osd_height_limit = 480;
 665        }
 666
 667        if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
 668                var->transp.offset = 24;
 669                var->transp.length = 8;
 670                var->red.offset = 16;
 671                var->red.length = 8;
 672                var->green.offset = 8;
 673                var->green.length = 8;
 674                var->blue.offset = 0;
 675                var->blue.length = 8;
 676        }
 677        else if (var->bits_per_pixel == 16) {
 678                /* To find out the true mode, check green length */
 679                switch (var->green.length) {
 680                        case 4:
 681                                var->red.offset = 8;
 682                                var->red.length = 4;
 683                                var->green.offset = 4;
 684                                var->green.length = 4;
 685                                var->blue.offset = 0;
 686                                var->blue.length = 4;
 687                                var->transp.offset = 12;
 688                                var->transp.length = 1;
 689                                break;
 690                        case 5:
 691                                var->red.offset = 10;
 692                                var->red.length = 5;
 693                                var->green.offset = 5;
 694                                var->green.length = 5;
 695                                var->blue.offset = 0;
 696                                var->blue.length = 5;
 697                                var->transp.offset = 15;
 698                                var->transp.length = 1;
 699                                break;
 700                        default:
 701                                var->red.offset = 11;
 702                                var->red.length = 5;
 703                                var->green.offset = 5;
 704                                var->green.length = 6;
 705                                var->blue.offset = 0;
 706                                var->blue.length = 5;
 707                                var->transp.offset = 0;
 708                                var->transp.length = 0;
 709                                break;
 710                }
 711        }
 712        else {
 713                IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
 714                return -EINVAL;
 715        }
 716
 717        /* Check the resolution */
 718        if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
 719                IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
 720                                var->xres, var->yres);
 721                return -EINVAL;
 722        }
 723
 724        /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
 725        if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
 726            var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
 727            var->xres_virtual < var->xres ||
 728            var->yres_virtual < var->yres) {
 729                IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
 730                        var->xres_virtual, var->yres_virtual);
 731                return -EINVAL;
 732        }
 733
 734        /* Some extra checks if in 8 bit mode */
 735        if (var->bits_per_pixel == 8) {
 736                /* Width must be a multiple of 4 */
 737                if (var->xres & 3) {
 738                        IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
 739                        return -EINVAL;
 740                }
 741                if (var->xres_virtual & 3) {
 742                        IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
 743                        return -EINVAL;
 744                }
 745        }
 746        else if (var->bits_per_pixel == 16) {
 747                /* Width must be a multiple of 2 */
 748                if (var->xres & 1) {
 749                        IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
 750                        return -EINVAL;
 751                }
 752                if (var->xres_virtual & 1) {
 753                        IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
 754                        return -EINVAL;
 755                }
 756        }
 757
 758        /* Now check the offsets */
 759        if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
 760                IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
 761                        var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
 762                return -EINVAL;
 763        }
 764
 765        /* Check pixel format */
 766        if (var->nonstd > 1) {
 767                IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
 768                return -EINVAL;
 769        }
 770
 771        /* Check video mode */
 772        if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
 773                ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
 774                IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
 775                return -EINVAL;
 776        }
 777
 778        /* Check the left & upper margins
 779           If the margins are too large, just center the screen
 780           (enforcing margins causes too many problems) */
 781
 782        if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
 783                var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
 784
 785        if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
 786                var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
 787                        var->yres) / 2);
 788
 789        /* Maintain overall 'size' for a constant refresh rate */
 790        var->right_margin = hlimit - var->left_margin - var->xres;
 791        var->lower_margin = vlimit - var->upper_margin - var->yres;
 792
 793        /* Fixed sync times */
 794        var->hsync_len = 24;
 795        var->vsync_len = 2;
 796
 797        /* Non-interlaced / interlaced mode is used to switch the OSD filter
 798           on or off. Adjust the clock timings to maintain a constant
 799           vertical refresh rate. */
 800        if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
 801                var->pixclock = pixclock / 2;
 802        else
 803                var->pixclock = pixclock;
 804
 805        itv->osd_rect.width = var->xres;
 806        itv->osd_rect.height = var->yres;
 807
 808        IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
 809                      var->xres, var->yres,
 810                      var->xres_virtual, var->yres_virtual,
 811                      var->bits_per_pixel);
 812
 813        IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
 814                      var->left_margin, var->upper_margin);
 815
 816        IVTVFB_DEBUG_INFO("Display filter: %s\n",
 817                        (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
 818        IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
 819        return 0;
 820}
 821
 822static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 823{
 824        struct ivtv *itv = (struct ivtv *) info->par;
 825        IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
 826        return _ivtvfb_check_var(var, itv);
 827}
 828
 829static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 830{
 831        u32 osd_pan_index;
 832        struct ivtv *itv = (struct ivtv *) info->par;
 833
 834        if (var->yoffset + info->var.yres > info->var.yres_virtual ||
 835            var->xoffset + info->var.xres > info->var.xres_virtual)
 836                return -EINVAL;
 837
 838        osd_pan_index = var->yoffset * info->fix.line_length
 839                      + var->xoffset * info->var.bits_per_pixel / 8;
 840        write_reg(osd_pan_index, 0x02A0C);
 841
 842        /* Pass this info back the yuv handler */
 843        itv->yuv_info.osd_x_pan = var->xoffset;
 844        itv->yuv_info.osd_y_pan = var->yoffset;
 845        /* Force update of yuv registers */
 846        itv->yuv_info.yuv_forced_update = 1;
 847        /* Remember this value */
 848        itv->osd_info->pan_cur = osd_pan_index;
 849        return 0;
 850}
 851
 852static int ivtvfb_set_par(struct fb_info *info)
 853{
 854        int rc = 0;
 855        struct ivtv *itv = (struct ivtv *) info->par;
 856
 857        IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
 858
 859        rc = ivtvfb_set_var(itv, &info->var);
 860        ivtvfb_pan_display(&info->var, info);
 861        ivtvfb_get_fix(itv, &info->fix);
 862        ivtv_firmware_check(itv, "ivtvfb_set_par");
 863        return rc;
 864}
 865
 866static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 867                                unsigned blue, unsigned transp,
 868                                struct fb_info *info)
 869{
 870        u32 color, *palette;
 871        struct ivtv *itv = (struct ivtv *)info->par;
 872
 873        if (regno >= info->cmap.len)
 874                return -EINVAL;
 875
 876        color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
 877        if (info->var.bits_per_pixel <= 8) {
 878                write_reg(regno, 0x02a30);
 879                write_reg(color, 0x02a34);
 880                itv->osd_info->palette_cur[regno] = color;
 881                return 0;
 882        }
 883        if (regno >= 16)
 884                return -EINVAL;
 885
 886        palette = info->pseudo_palette;
 887        if (info->var.bits_per_pixel == 16) {
 888                switch (info->var.green.length) {
 889                        case 4:
 890                                color = ((red & 0xf000) >> 4) |
 891                                        ((green & 0xf000) >> 8) |
 892                                        ((blue & 0xf000) >> 12);
 893                                break;
 894                        case 5:
 895                                color = ((red & 0xf800) >> 1) |
 896                                        ((green & 0xf800) >> 6) |
 897                                        ((blue & 0xf800) >> 11);
 898                                break;
 899                        case 6:
 900                                color = (red & 0xf800 ) |
 901                                        ((green & 0xfc00) >> 5) |
 902                                        ((blue & 0xf800) >> 11);
 903                                break;
 904                }
 905        }
 906        palette[regno] = color;
 907        return 0;
 908}
 909
 910/* We don't really support blanking. All this does is enable or
 911   disable the OSD. */
 912static int ivtvfb_blank(int blank_mode, struct fb_info *info)
 913{
 914        struct ivtv *itv = (struct ivtv *)info->par;
 915
 916        IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
 917        switch (blank_mode) {
 918        case FB_BLANK_UNBLANK:
 919                ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
 920                ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
 921                break;
 922        case FB_BLANK_NORMAL:
 923        case FB_BLANK_HSYNC_SUSPEND:
 924        case FB_BLANK_VSYNC_SUSPEND:
 925                ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
 926                ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
 927                break;
 928        case FB_BLANK_POWERDOWN:
 929                ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
 930                ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
 931                break;
 932        }
 933        itv->osd_info->blank_cur = blank_mode;
 934        return 0;
 935}
 936
 937static struct fb_ops ivtvfb_ops = {
 938        .owner = THIS_MODULE,
 939        .fb_write       = ivtvfb_write,
 940        .fb_check_var   = ivtvfb_check_var,
 941        .fb_set_par     = ivtvfb_set_par,
 942        .fb_setcolreg   = ivtvfb_setcolreg,
 943        .fb_fillrect    = cfb_fillrect,
 944        .fb_copyarea    = cfb_copyarea,
 945        .fb_imageblit   = cfb_imageblit,
 946        .fb_cursor      = NULL,
 947        .fb_ioctl       = ivtvfb_ioctl,
 948        .fb_pan_display = ivtvfb_pan_display,
 949        .fb_blank       = ivtvfb_blank,
 950};
 951
 952/* Restore hardware after firmware restart */
 953static void ivtvfb_restore(struct ivtv *itv)
 954{
 955        struct osd_info *oi = itv->osd_info;
 956        int i;
 957
 958        ivtvfb_set_var(itv, &oi->fbvar_cur);
 959        ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
 960        for (i = 0; i < 256; i++) {
 961                write_reg(i, 0x02a30);
 962                write_reg(oi->palette_cur[i], 0x02a34);
 963        }
 964        write_reg(oi->pan_cur, 0x02a0c);
 965}
 966
 967/* Initialization */
 968
 969
 970/* Setup our initial video mode */
 971static int ivtvfb_init_vidmode(struct ivtv *itv)
 972{
 973        struct osd_info *oi = itv->osd_info;
 974        struct v4l2_rect start_window;
 975        int max_height;
 976
 977        /* Color mode */
 978
 979        if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
 980                osd_depth = 8;
 981        oi->bits_per_pixel = osd_depth;
 982        oi->bytes_per_pixel = oi->bits_per_pixel / 8;
 983
 984        /* Horizontal size & position */
 985
 986        if (osd_xres > 720)
 987                osd_xres = 720;
 988
 989        /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
 990        if (osd_depth == 8)
 991                osd_xres &= ~3;
 992        else if (osd_depth == 16)
 993                osd_xres &= ~1;
 994
 995        start_window.width = osd_xres ? osd_xres : 640;
 996
 997        /* Check horizontal start (osd_left). */
 998        if (osd_left && osd_left + start_window.width > 721) {
 999                IVTVFB_ERR("Invalid osd_left - assuming default\n");
1000                osd_left = 0;
1001        }
1002
1003        /* Hardware coords start at 0, user coords start at 1. */
1004        osd_left--;
1005
1006        start_window.left = osd_left >= 0 ?
1007                 osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
1008
1009        oi->display_byte_stride =
1010                        start_window.width * oi->bytes_per_pixel;
1011
1012        /* Vertical size & position */
1013
1014        max_height = itv->is_out_50hz ? 576 : 480;
1015
1016        if (osd_yres > max_height)
1017                osd_yres = max_height;
1018
1019        start_window.height = osd_yres ?
1020                osd_yres : itv->is_out_50hz ? 480 : 400;
1021
1022        /* Check vertical start (osd_upper). */
1023        if (osd_upper + start_window.height > max_height + 1) {
1024                IVTVFB_ERR("Invalid osd_upper - assuming default\n");
1025                osd_upper = 0;
1026        }
1027
1028        /* Hardware coords start at 0, user coords start at 1. */
1029        osd_upper--;
1030
1031        start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
1032
1033        oi->display_width = start_window.width;
1034        oi->display_height = start_window.height;
1035
1036        /* Generate a valid fb_var_screeninfo */
1037
1038        oi->ivtvfb_defined.xres = oi->display_width;
1039        oi->ivtvfb_defined.yres = oi->display_height;
1040        oi->ivtvfb_defined.xres_virtual = oi->display_width;
1041        oi->ivtvfb_defined.yres_virtual = oi->display_height;
1042        oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
1043        oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
1044        oi->ivtvfb_defined.left_margin = start_window.left + 1;
1045        oi->ivtvfb_defined.upper_margin = start_window.top + 1;
1046        oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
1047        oi->ivtvfb_defined.nonstd = 0;
1048
1049        /* We've filled in the most data, let the usual mode check
1050           routine fill in the rest. */
1051        _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1052
1053        /* Generate valid fb_fix_screeninfo */
1054
1055        ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1056
1057        /* Generate valid fb_info */
1058
1059        oi->ivtvfb_info.node = -1;
1060        oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
1061        oi->ivtvfb_info.fbops = &ivtvfb_ops;
1062        oi->ivtvfb_info.par = itv;
1063        oi->ivtvfb_info.var = oi->ivtvfb_defined;
1064        oi->ivtvfb_info.fix = oi->ivtvfb_fix;
1065        oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
1066        oi->ivtvfb_info.fbops = &ivtvfb_ops;
1067
1068        /* Supply some monitor specs. Bogus values will do for now */
1069        oi->ivtvfb_info.monspecs.hfmin = 8000;
1070        oi->ivtvfb_info.monspecs.hfmax = 70000;
1071        oi->ivtvfb_info.monspecs.vfmin = 10;
1072        oi->ivtvfb_info.monspecs.vfmax = 100;
1073
1074        /* Allocate color map */
1075        if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1076                IVTVFB_ERR("abort, unable to alloc cmap\n");
1077                return -ENOMEM;
1078        }
1079
1080        /* Allocate the pseudo palette */
1081        oi->ivtvfb_info.pseudo_palette =
1082                kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
1083
1084        if (!oi->ivtvfb_info.pseudo_palette) {
1085                IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
1086                return -ENOMEM;
1087        }
1088
1089        return 0;
1090}
1091
1092/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1093
1094static int ivtvfb_init_io(struct ivtv *itv)
1095{
1096        struct osd_info *oi = itv->osd_info;
1097        /* Find the largest power of two that maps the whole buffer */
1098        int size_shift = 31;
1099
1100        mutex_lock(&itv->serialize_lock);
1101        if (ivtv_init_on_first_open(itv)) {
1102                mutex_unlock(&itv->serialize_lock);
1103                IVTVFB_ERR("Failed to initialize ivtv\n");
1104                return -ENXIO;
1105        }
1106        mutex_unlock(&itv->serialize_lock);
1107
1108        if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
1109                                        &oi->video_buffer_size) < 0) {
1110                IVTVFB_ERR("Firmware failed to respond\n");
1111                return -EIO;
1112        }
1113
1114        /* The osd buffer size depends on the number of video buffers allocated
1115           on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1116           size to prevent any overlap. */
1117        oi->video_buffer_size = 1704960;
1118
1119        oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1120        oi->video_vbase = itv->dec_mem + oi->video_rbase;
1121
1122        if (!oi->video_vbase) {
1123                IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1124                     oi->video_buffer_size, oi->video_pbase);
1125                return -EIO;
1126        }
1127
1128        IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1129                        oi->video_pbase, oi->video_vbase,
1130                        oi->video_buffer_size / 1024);
1131
1132        while (!(oi->video_buffer_size & (1 << size_shift)))
1133                size_shift--;
1134        size_shift++;
1135        oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1136        oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1137        oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1138        oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1139        oi->wc_cookie = arch_phys_wc_add(oi->fb_start_aligned_physaddr,
1140                                         oi->fb_end_aligned_physaddr -
1141                                         oi->fb_start_aligned_physaddr);
1142        /* Blank the entire osd. */
1143        memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1144
1145        return 0;
1146}
1147
1148/* Release any memory we've grabbed & remove mtrr entry */
1149static void ivtvfb_release_buffers (struct ivtv *itv)
1150{
1151        struct osd_info *oi = itv->osd_info;
1152
1153        /* Release cmap */
1154        if (oi->ivtvfb_info.cmap.len)
1155                fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1156
1157        /* Release pseudo palette */
1158        kfree(oi->ivtvfb_info.pseudo_palette);
1159        arch_phys_wc_del(oi->wc_cookie);
1160        kfree(oi);
1161        itv->osd_info = NULL;
1162}
1163
1164/* Initialize the specified card */
1165
1166static int ivtvfb_init_card(struct ivtv *itv)
1167{
1168        int rc;
1169
1170#ifdef CONFIG_X86_64
1171        if (pat_enabled()) {
1172                pr_warn("ivtvfb needs PAT disabled, boot with nopat kernel parameter\n");
1173                return -ENODEV;
1174        }
1175#endif
1176
1177        if (itv->osd_info) {
1178                IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1179                return -EBUSY;
1180        }
1181
1182        itv->osd_info = kzalloc(sizeof(struct osd_info),
1183                                        GFP_ATOMIC|__GFP_NOWARN);
1184        if (itv->osd_info == NULL) {
1185                IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1186                return -ENOMEM;
1187        }
1188
1189        /* Find & setup the OSD buffer */
1190        rc = ivtvfb_init_io(itv);
1191        if (rc) {
1192                ivtvfb_release_buffers(itv);
1193                return rc;
1194        }
1195
1196        /* Set the startup video mode information */
1197        if ((rc = ivtvfb_init_vidmode(itv))) {
1198                ivtvfb_release_buffers(itv);
1199                return rc;
1200        }
1201
1202        /* Register the framebuffer */
1203        if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1204                ivtvfb_release_buffers(itv);
1205                return -EINVAL;
1206        }
1207
1208        itv->osd_video_pbase = itv->osd_info->video_pbase;
1209
1210        /* Set the card to the requested mode */
1211        ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1212
1213        /* Set color 0 to black */
1214        write_reg(0, 0x02a30);
1215        write_reg(0, 0x02a34);
1216
1217        /* Enable the osd */
1218        ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1219
1220        /* Enable restart */
1221        itv->ivtvfb_restore = ivtvfb_restore;
1222
1223        /* Allocate DMA */
1224        ivtv_udma_alloc(itv);
1225        return 0;
1226
1227}
1228
1229static int __init ivtvfb_callback_init(struct device *dev, void *p)
1230{
1231        struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1232        struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1233
1234        if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1235                if (ivtvfb_init_card(itv) == 0) {
1236                        IVTVFB_INFO("Framebuffer registered on %s\n",
1237                                        itv->v4l2_dev.name);
1238                        (*(int *)p)++;
1239                }
1240        }
1241        return 0;
1242}
1243
1244static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1245{
1246        struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1247        struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1248        struct osd_info *oi = itv->osd_info;
1249
1250        if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1251                if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1252                        IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
1253                                       itv->instance);
1254                        return 0;
1255                }
1256                IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1257                itv->ivtvfb_restore = NULL;
1258                ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1259                ivtvfb_release_buffers(itv);
1260                itv->osd_video_pbase = 0;
1261        }
1262        return 0;
1263}
1264
1265static int __init ivtvfb_init(void)
1266{
1267        struct device_driver *drv;
1268        int registered = 0;
1269        int err;
1270
1271
1272        if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1273                pr_err("ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1274                     IVTV_MAX_CARDS - 1);
1275                return -EINVAL;
1276        }
1277
1278        drv = driver_find("ivtv", &pci_bus_type);
1279        err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
1280        (void)err;      /* suppress compiler warning */
1281        if (!registered) {
1282                pr_err("no cards found\n");
1283                return -ENODEV;
1284        }
1285        return 0;
1286}
1287
1288static void ivtvfb_cleanup(void)
1289{
1290        struct device_driver *drv;
1291        int err;
1292
1293        pr_info("Unloading framebuffer module\n");
1294
1295        drv = driver_find("ivtv", &pci_bus_type);
1296        err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
1297        (void)err;      /* suppress compiler warning */
1298}
1299
1300module_init(ivtvfb_init);
1301module_exit(ivtvfb_cleanup);
1302