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 (%p)\n",
 350                            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 %p\n", source);
 361
 362                IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source %p count %d\n",
 363                                  dest_offset, source, count);
 364                return -EINVAL;
 365        }
 366
 367        /* OSD Address to send DMA to */
 368        dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
 369
 370        /* Fill Buffers */
 371        return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
 372}
 373
 374static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
 375                                                size_t count, loff_t *ppos)
 376{
 377        unsigned long p = *ppos;
 378        void *dst;
 379        int err = 0;
 380        int dma_err;
 381        unsigned long total_size;
 382        struct ivtv *itv = (struct ivtv *) info->par;
 383        unsigned long dma_offset =
 384                        IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
 385        unsigned long dma_size;
 386        u16 lead = 0, tail = 0;
 387
 388        if (info->state != FBINFO_STATE_RUNNING)
 389                return -EPERM;
 390
 391        total_size = info->screen_size;
 392
 393        if (total_size == 0)
 394                total_size = info->fix.smem_len;
 395
 396        if (p > total_size)
 397                return -EFBIG;
 398
 399        if (count > total_size) {
 400                err = -EFBIG;
 401                count = total_size;
 402        }
 403
 404        if (count + p > total_size) {
 405                if (!err)
 406                        err = -ENOSPC;
 407                count = total_size - p;
 408        }
 409
 410        dst = (void __force *) (info->screen_base + p);
 411
 412        if (info->fbops->fb_sync)
 413                info->fbops->fb_sync(info);
 414
 415        /* If transfer size > threshold and both src/dst
 416        addresses are aligned, use DMA */
 417        if (count >= 4096 &&
 418            ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
 419                /* Odd address = can't DMA. Align */
 420                if ((unsigned long)dst & 3) {
 421                        lead = 4 - ((unsigned long)dst & 3);
 422                        if (copy_from_user(dst, buf, lead))
 423                                return -EFAULT;
 424                        buf += lead;
 425                        dst += lead;
 426                }
 427                /* DMA resolution is 32 bits */
 428                if ((count - lead) & 3)
 429                        tail = (count - lead) & 3;
 430                /* DMA the data */
 431                dma_size = count - lead - tail;
 432                dma_err = ivtvfb_prep_dec_dma_to_device(itv,
 433                       p + lead + dma_offset, (void __user *)buf, dma_size);
 434                if (dma_err)
 435                        return dma_err;
 436                dst += dma_size;
 437                buf += dma_size;
 438                /* Copy any leftover data */
 439                if (tail && copy_from_user(dst, buf, tail))
 440                        return -EFAULT;
 441        } else if (copy_from_user(dst, buf, count)) {
 442                return -EFAULT;
 443        }
 444
 445        if  (!err)
 446                *ppos += count;
 447
 448        return (err) ? err : count;
 449}
 450
 451static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 452{
 453        DEFINE_WAIT(wait);
 454        struct ivtv *itv = (struct ivtv *)info->par;
 455        int rc = 0;
 456
 457        switch (cmd) {
 458                case FBIOGET_VBLANK: {
 459                        struct fb_vblank vblank;
 460                        u32 trace;
 461
 462                        memset(&vblank, 0, sizeof(struct fb_vblank));
 463
 464                        vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
 465                                        FB_VBLANK_HAVE_VSYNC;
 466                        trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
 467                        if (itv->is_out_50hz && trace > 312)
 468                                trace -= 312;
 469                        else if (itv->is_out_60hz && trace > 262)
 470                                trace -= 262;
 471                        if (trace == 1)
 472                                vblank.flags |= FB_VBLANK_VSYNCING;
 473                        vblank.count = itv->last_vsync_field;
 474                        vblank.vcount = trace;
 475                        vblank.hcount = 0;
 476                        if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
 477                                return -EFAULT;
 478                        return 0;
 479                }
 480
 481                case FBIO_WAITFORVSYNC:
 482                        prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
 483                        if (!schedule_timeout(msecs_to_jiffies(50)))
 484                                rc = -ETIMEDOUT;
 485                        finish_wait(&itv->vsync_waitq, &wait);
 486                        return rc;
 487
 488                case IVTVFB_IOC_DMA_FRAME: {
 489                        struct ivtvfb_dma_frame args;
 490
 491                        IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
 492                        if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
 493                                return -EFAULT;
 494
 495                        return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
 496                }
 497
 498                default:
 499                        IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
 500                        return -EINVAL;
 501        }
 502        return 0;
 503}
 504
 505/* Framebuffer device handling */
 506
 507static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
 508{
 509        struct osd_info *oi = itv->osd_info;
 510        struct ivtv_osd_coords ivtv_osd;
 511        struct v4l2_rect ivtv_window;
 512        int osd_mode = -1;
 513
 514        IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
 515
 516        /* Select color space */
 517        if (var->nonstd) /* YUV */
 518                write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
 519        else /* RGB  */
 520                write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
 521
 522        /* Set the color mode */
 523        switch (var->bits_per_pixel) {
 524                case 8:
 525                        osd_mode = IVTV_OSD_BPP_8;
 526                        break;
 527                case 32:
 528                        osd_mode = IVTV_OSD_BPP_32;
 529                        break;
 530                case 16:
 531                        switch (var->green.length) {
 532                        case 4:
 533                                osd_mode = IVTV_OSD_BPP_16_444;
 534                                break;
 535                        case 5:
 536                                osd_mode = IVTV_OSD_BPP_16_555;
 537                                break;
 538                        case 6:
 539                                osd_mode = IVTV_OSD_BPP_16_565;
 540                                break;
 541                        default:
 542                                IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
 543                        }
 544                        break;
 545                default:
 546                        IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
 547        }
 548
 549        /* Set video mode. Although rare, the display can become scrambled even
 550           if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
 551        if (osd_mode != -1) {
 552                ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
 553                ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
 554        }
 555
 556        oi->bits_per_pixel = var->bits_per_pixel;
 557        oi->bytes_per_pixel = var->bits_per_pixel / 8;
 558
 559        /* Set the flicker filter */
 560        switch (var->vmode & FB_VMODE_MASK) {
 561                case FB_VMODE_NONINTERLACED: /* Filter on */
 562                        ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
 563                        break;
 564                case FB_VMODE_INTERLACED: /* Filter off */
 565                        ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
 566                        break;
 567                default:
 568                        IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
 569        }
 570
 571        /* Read the current osd info */
 572        ivtvfb_get_osd_coords(itv, &ivtv_osd);
 573
 574        /* Now set the OSD to the size we want */
 575        ivtv_osd.pixel_stride = var->xres_virtual;
 576        ivtv_osd.lines = var->yres_virtual;
 577        ivtv_osd.x = 0;
 578        ivtv_osd.y = 0;
 579        ivtvfb_set_osd_coords(itv, &ivtv_osd);
 580
 581        /* Can't seem to find the right API combo for this.
 582           Use another function which does what we need through direct register access. */
 583        ivtv_window.width = var->xres;
 584        ivtv_window.height = var->yres;
 585
 586        /* Minimum margin cannot be 0, as X won't allow such a mode */
 587        if (!var->upper_margin)
 588                var->upper_margin++;
 589        if (!var->left_margin)
 590                var->left_margin++;
 591        ivtv_window.top = var->upper_margin - 1;
 592        ivtv_window.left = var->left_margin - 1;
 593
 594        ivtvfb_set_display_window(itv, &ivtv_window);
 595
 596        /* Pass screen size back to yuv handler */
 597        itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
 598        itv->yuv_info.osd_full_h = ivtv_osd.lines;
 599
 600        /* Force update of yuv registers */
 601        itv->yuv_info.yuv_forced_update = 1;
 602
 603        /* Keep a copy of these settings */
 604        memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
 605
 606        IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
 607                      var->xres, var->yres,
 608                      var->xres_virtual, var->yres_virtual,
 609                      var->bits_per_pixel);
 610
 611        IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
 612                      var->left_margin, var->upper_margin);
 613
 614        IVTVFB_DEBUG_INFO("Display filter: %s\n",
 615                        (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
 616        IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
 617
 618        return 0;
 619}
 620
 621static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
 622{
 623        struct osd_info *oi = itv->osd_info;
 624
 625        IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
 626        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 627        strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
 628        fix->smem_start = oi->video_pbase;
 629        fix->smem_len = oi->video_buffer_size;
 630        fix->type = FB_TYPE_PACKED_PIXELS;
 631        fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 632        fix->xpanstep = 1;
 633        fix->ypanstep = 1;
 634        fix->ywrapstep = 0;
 635        fix->line_length = oi->display_byte_stride;
 636        fix->accel = FB_ACCEL_NONE;
 637        return 0;
 638}
 639
 640/* Check the requested display mode, returning -EINVAL if we can't
 641   handle it. */
 642
 643static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
 644{
 645        struct osd_info *oi = itv->osd_info;
 646        int osd_height_limit;
 647        u32 pixclock, hlimit, vlimit;
 648
 649        IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
 650
 651        /* Set base references for mode calcs. */
 652        if (itv->is_out_50hz) {
 653                pixclock = 84316;
 654                hlimit = 776;
 655                vlimit = 591;
 656                osd_height_limit = 576;
 657        }
 658        else {
 659                pixclock = 83926;
 660                hlimit = 776;
 661                vlimit = 495;
 662                osd_height_limit = 480;
 663        }
 664
 665        if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
 666                var->transp.offset = 24;
 667                var->transp.length = 8;
 668                var->red.offset = 16;
 669                var->red.length = 8;
 670                var->green.offset = 8;
 671                var->green.length = 8;
 672                var->blue.offset = 0;
 673                var->blue.length = 8;
 674        }
 675        else if (var->bits_per_pixel == 16) {
 676                /* To find out the true mode, check green length */
 677                switch (var->green.length) {
 678                        case 4:
 679                                var->red.offset = 8;
 680                                var->red.length = 4;
 681                                var->green.offset = 4;
 682                                var->green.length = 4;
 683                                var->blue.offset = 0;
 684                                var->blue.length = 4;
 685                                var->transp.offset = 12;
 686                                var->transp.length = 1;
 687                                break;
 688                        case 5:
 689                                var->red.offset = 10;
 690                                var->red.length = 5;
 691                                var->green.offset = 5;
 692                                var->green.length = 5;
 693                                var->blue.offset = 0;
 694                                var->blue.length = 5;
 695                                var->transp.offset = 15;
 696                                var->transp.length = 1;
 697                                break;
 698                        default:
 699                                var->red.offset = 11;
 700                                var->red.length = 5;
 701                                var->green.offset = 5;
 702                                var->green.length = 6;
 703                                var->blue.offset = 0;
 704                                var->blue.length = 5;
 705                                var->transp.offset = 0;
 706                                var->transp.length = 0;
 707                                break;
 708                }
 709        }
 710        else {
 711                IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
 712                return -EINVAL;
 713        }
 714
 715        /* Check the resolution */
 716        if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
 717                IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
 718                                var->xres, var->yres);
 719                return -EINVAL;
 720        }
 721
 722        /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
 723        if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
 724            var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
 725            var->xres_virtual < var->xres ||
 726            var->yres_virtual < var->yres) {
 727                IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
 728                        var->xres_virtual, var->yres_virtual);
 729                return -EINVAL;
 730        }
 731
 732        /* Some extra checks if in 8 bit mode */
 733        if (var->bits_per_pixel == 8) {
 734                /* Width must be a multiple of 4 */
 735                if (var->xres & 3) {
 736                        IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
 737                        return -EINVAL;
 738                }
 739                if (var->xres_virtual & 3) {
 740                        IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
 741                        return -EINVAL;
 742                }
 743        }
 744        else if (var->bits_per_pixel == 16) {
 745                /* Width must be a multiple of 2 */
 746                if (var->xres & 1) {
 747                        IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
 748                        return -EINVAL;
 749                }
 750                if (var->xres_virtual & 1) {
 751                        IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
 752                        return -EINVAL;
 753                }
 754        }
 755
 756        /* Now check the offsets */
 757        if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
 758                IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
 759                        var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
 760                return -EINVAL;
 761        }
 762
 763        /* Check pixel format */
 764        if (var->nonstd > 1) {
 765                IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
 766                return -EINVAL;
 767        }
 768
 769        /* Check video mode */
 770        if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
 771                ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
 772                IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
 773                return -EINVAL;
 774        }
 775
 776        /* Check the left & upper margins
 777           If the margins are too large, just center the screen
 778           (enforcing margins causes too many problems) */
 779
 780        if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
 781                var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
 782
 783        if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
 784                var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
 785                        var->yres) / 2);
 786
 787        /* Maintain overall 'size' for a constant refresh rate */
 788        var->right_margin = hlimit - var->left_margin - var->xres;
 789        var->lower_margin = vlimit - var->upper_margin - var->yres;
 790
 791        /* Fixed sync times */
 792        var->hsync_len = 24;
 793        var->vsync_len = 2;
 794
 795        /* Non-interlaced / interlaced mode is used to switch the OSD filter
 796           on or off. Adjust the clock timings to maintain a constant
 797           vertical refresh rate. */
 798        if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
 799                var->pixclock = pixclock / 2;
 800        else
 801                var->pixclock = pixclock;
 802
 803        itv->osd_rect.width = var->xres;
 804        itv->osd_rect.height = var->yres;
 805
 806        IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
 807                      var->xres, var->yres,
 808                      var->xres_virtual, var->yres_virtual,
 809                      var->bits_per_pixel);
 810
 811        IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
 812                      var->left_margin, var->upper_margin);
 813
 814        IVTVFB_DEBUG_INFO("Display filter: %s\n",
 815                        (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
 816        IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
 817        return 0;
 818}
 819
 820static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 821{
 822        struct ivtv *itv = (struct ivtv *) info->par;
 823        IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
 824        return _ivtvfb_check_var(var, itv);
 825}
 826
 827static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 828{
 829        u32 osd_pan_index;
 830        struct ivtv *itv = (struct ivtv *) info->par;
 831
 832        if (var->yoffset + info->var.yres > info->var.yres_virtual ||
 833            var->xoffset + info->var.xres > info->var.xres_virtual)
 834                return -EINVAL;
 835
 836        osd_pan_index = var->yoffset * info->fix.line_length
 837                      + var->xoffset * info->var.bits_per_pixel / 8;
 838        write_reg(osd_pan_index, 0x02A0C);
 839
 840        /* Pass this info back the yuv handler */
 841        itv->yuv_info.osd_x_pan = var->xoffset;
 842        itv->yuv_info.osd_y_pan = var->yoffset;
 843        /* Force update of yuv registers */
 844        itv->yuv_info.yuv_forced_update = 1;
 845        /* Remember this value */
 846        itv->osd_info->pan_cur = osd_pan_index;
 847        return 0;
 848}
 849
 850static int ivtvfb_set_par(struct fb_info *info)
 851{
 852        int rc = 0;
 853        struct ivtv *itv = (struct ivtv *) info->par;
 854
 855        IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
 856
 857        rc = ivtvfb_set_var(itv, &info->var);
 858        ivtvfb_pan_display(&info->var, info);
 859        ivtvfb_get_fix(itv, &info->fix);
 860        ivtv_firmware_check(itv, "ivtvfb_set_par");
 861        return rc;
 862}
 863
 864static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 865                                unsigned blue, unsigned transp,
 866                                struct fb_info *info)
 867{
 868        u32 color, *palette;
 869        struct ivtv *itv = (struct ivtv *)info->par;
 870
 871        if (regno >= info->cmap.len)
 872                return -EINVAL;
 873
 874        color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
 875        if (info->var.bits_per_pixel <= 8) {
 876                write_reg(regno, 0x02a30);
 877                write_reg(color, 0x02a34);
 878                itv->osd_info->palette_cur[regno] = color;
 879                return 0;
 880        }
 881        if (regno >= 16)
 882                return -EINVAL;
 883
 884        palette = info->pseudo_palette;
 885        if (info->var.bits_per_pixel == 16) {
 886                switch (info->var.green.length) {
 887                        case 4:
 888                                color = ((red & 0xf000) >> 4) |
 889                                        ((green & 0xf000) >> 8) |
 890                                        ((blue & 0xf000) >> 12);
 891                                break;
 892                        case 5:
 893                                color = ((red & 0xf800) >> 1) |
 894                                        ((green & 0xf800) >> 6) |
 895                                        ((blue & 0xf800) >> 11);
 896                                break;
 897                        case 6:
 898                                color = (red & 0xf800 ) |
 899                                        ((green & 0xfc00) >> 5) |
 900                                        ((blue & 0xf800) >> 11);
 901                                break;
 902                }
 903        }
 904        palette[regno] = color;
 905        return 0;
 906}
 907
 908/* We don't really support blanking. All this does is enable or
 909   disable the OSD. */
 910static int ivtvfb_blank(int blank_mode, struct fb_info *info)
 911{
 912        struct ivtv *itv = (struct ivtv *)info->par;
 913
 914        IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
 915        switch (blank_mode) {
 916        case FB_BLANK_UNBLANK:
 917                ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
 918                ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
 919                break;
 920        case FB_BLANK_NORMAL:
 921        case FB_BLANK_HSYNC_SUSPEND:
 922        case FB_BLANK_VSYNC_SUSPEND:
 923                ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
 924                ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
 925                break;
 926        case FB_BLANK_POWERDOWN:
 927                ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
 928                ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
 929                break;
 930        }
 931        itv->osd_info->blank_cur = blank_mode;
 932        return 0;
 933}
 934
 935static struct fb_ops ivtvfb_ops = {
 936        .owner = THIS_MODULE,
 937        .fb_write       = ivtvfb_write,
 938        .fb_check_var   = ivtvfb_check_var,
 939        .fb_set_par     = ivtvfb_set_par,
 940        .fb_setcolreg   = ivtvfb_setcolreg,
 941        .fb_fillrect    = cfb_fillrect,
 942        .fb_copyarea    = cfb_copyarea,
 943        .fb_imageblit   = cfb_imageblit,
 944        .fb_cursor      = NULL,
 945        .fb_ioctl       = ivtvfb_ioctl,
 946        .fb_pan_display = ivtvfb_pan_display,
 947        .fb_blank       = ivtvfb_blank,
 948};
 949
 950/* Restore hardware after firmware restart */
 951static void ivtvfb_restore(struct ivtv *itv)
 952{
 953        struct osd_info *oi = itv->osd_info;
 954        int i;
 955
 956        ivtvfb_set_var(itv, &oi->fbvar_cur);
 957        ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
 958        for (i = 0; i < 256; i++) {
 959                write_reg(i, 0x02a30);
 960                write_reg(oi->palette_cur[i], 0x02a34);
 961        }
 962        write_reg(oi->pan_cur, 0x02a0c);
 963}
 964
 965/* Initialization */
 966
 967
 968/* Setup our initial video mode */
 969static int ivtvfb_init_vidmode(struct ivtv *itv)
 970{
 971        struct osd_info *oi = itv->osd_info;
 972        struct v4l2_rect start_window;
 973        int max_height;
 974
 975        /* Color mode */
 976
 977        if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
 978                osd_depth = 8;
 979        oi->bits_per_pixel = osd_depth;
 980        oi->bytes_per_pixel = oi->bits_per_pixel / 8;
 981
 982        /* Horizontal size & position */
 983
 984        if (osd_xres > 720)
 985                osd_xres = 720;
 986
 987        /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
 988        if (osd_depth == 8)
 989                osd_xres &= ~3;
 990        else if (osd_depth == 16)
 991                osd_xres &= ~1;
 992
 993        start_window.width = osd_xres ? osd_xres : 640;
 994
 995        /* Check horizontal start (osd_left). */
 996        if (osd_left && osd_left + start_window.width > 721) {
 997                IVTVFB_ERR("Invalid osd_left - assuming default\n");
 998                osd_left = 0;
 999        }
1000
1001        /* Hardware coords start at 0, user coords start at 1. */
1002        osd_left--;
1003
1004        start_window.left = osd_left >= 0 ?
1005                 osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
1006
1007        oi->display_byte_stride =
1008                        start_window.width * oi->bytes_per_pixel;
1009
1010        /* Vertical size & position */
1011
1012        max_height = itv->is_out_50hz ? 576 : 480;
1013
1014        if (osd_yres > max_height)
1015                osd_yres = max_height;
1016
1017        start_window.height = osd_yres ?
1018                osd_yres : itv->is_out_50hz ? 480 : 400;
1019
1020        /* Check vertical start (osd_upper). */
1021        if (osd_upper + start_window.height > max_height + 1) {
1022                IVTVFB_ERR("Invalid osd_upper - assuming default\n");
1023                osd_upper = 0;
1024        }
1025
1026        /* Hardware coords start at 0, user coords start at 1. */
1027        osd_upper--;
1028
1029        start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
1030
1031        oi->display_width = start_window.width;
1032        oi->display_height = start_window.height;
1033
1034        /* Generate a valid fb_var_screeninfo */
1035
1036        oi->ivtvfb_defined.xres = oi->display_width;
1037        oi->ivtvfb_defined.yres = oi->display_height;
1038        oi->ivtvfb_defined.xres_virtual = oi->display_width;
1039        oi->ivtvfb_defined.yres_virtual = oi->display_height;
1040        oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
1041        oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
1042        oi->ivtvfb_defined.left_margin = start_window.left + 1;
1043        oi->ivtvfb_defined.upper_margin = start_window.top + 1;
1044        oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
1045        oi->ivtvfb_defined.nonstd = 0;
1046
1047        /* We've filled in the most data, let the usual mode check
1048           routine fill in the rest. */
1049        _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1050
1051        /* Generate valid fb_fix_screeninfo */
1052
1053        ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1054
1055        /* Generate valid fb_info */
1056
1057        oi->ivtvfb_info.node = -1;
1058        oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
1059        oi->ivtvfb_info.fbops = &ivtvfb_ops;
1060        oi->ivtvfb_info.par = itv;
1061        oi->ivtvfb_info.var = oi->ivtvfb_defined;
1062        oi->ivtvfb_info.fix = oi->ivtvfb_fix;
1063        oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
1064        oi->ivtvfb_info.fbops = &ivtvfb_ops;
1065
1066        /* Supply some monitor specs. Bogus values will do for now */
1067        oi->ivtvfb_info.monspecs.hfmin = 8000;
1068        oi->ivtvfb_info.monspecs.hfmax = 70000;
1069        oi->ivtvfb_info.monspecs.vfmin = 10;
1070        oi->ivtvfb_info.monspecs.vfmax = 100;
1071
1072        /* Allocate color map */
1073        if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1074                IVTVFB_ERR("abort, unable to alloc cmap\n");
1075                return -ENOMEM;
1076        }
1077
1078        /* Allocate the pseudo palette */
1079        oi->ivtvfb_info.pseudo_palette =
1080                kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
1081
1082        if (!oi->ivtvfb_info.pseudo_palette) {
1083                IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
1084                return -ENOMEM;
1085        }
1086
1087        return 0;
1088}
1089
1090/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1091
1092static int ivtvfb_init_io(struct ivtv *itv)
1093{
1094        struct osd_info *oi = itv->osd_info;
1095        /* Find the largest power of two that maps the whole buffer */
1096        int size_shift = 31;
1097
1098        mutex_lock(&itv->serialize_lock);
1099        if (ivtv_init_on_first_open(itv)) {
1100                mutex_unlock(&itv->serialize_lock);
1101                IVTVFB_ERR("Failed to initialize ivtv\n");
1102                return -ENXIO;
1103        }
1104        mutex_unlock(&itv->serialize_lock);
1105
1106        if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
1107                                        &oi->video_buffer_size) < 0) {
1108                IVTVFB_ERR("Firmware failed to respond\n");
1109                return -EIO;
1110        }
1111
1112        /* The osd buffer size depends on the number of video buffers allocated
1113           on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1114           size to prevent any overlap. */
1115        oi->video_buffer_size = 1704960;
1116
1117        oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1118        oi->video_vbase = itv->dec_mem + oi->video_rbase;
1119
1120        if (!oi->video_vbase) {
1121                IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1122                     oi->video_buffer_size, oi->video_pbase);
1123                return -EIO;
1124        }
1125
1126        IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1127                        oi->video_pbase, oi->video_vbase,
1128                        oi->video_buffer_size / 1024);
1129
1130        while (!(oi->video_buffer_size & (1 << size_shift)))
1131                size_shift--;
1132        size_shift++;
1133        oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1134        oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1135        oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1136        oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1137        oi->wc_cookie = arch_phys_wc_add(oi->fb_start_aligned_physaddr,
1138                                         oi->fb_end_aligned_physaddr -
1139                                         oi->fb_start_aligned_physaddr);
1140        /* Blank the entire osd. */
1141        memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1142
1143        return 0;
1144}
1145
1146/* Release any memory we've grabbed & remove mtrr entry */
1147static void ivtvfb_release_buffers (struct ivtv *itv)
1148{
1149        struct osd_info *oi = itv->osd_info;
1150
1151        /* Release cmap */
1152        if (oi->ivtvfb_info.cmap.len)
1153                fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1154
1155        /* Release pseudo palette */
1156        kfree(oi->ivtvfb_info.pseudo_palette);
1157        arch_phys_wc_del(oi->wc_cookie);
1158        kfree(oi);
1159        itv->osd_info = NULL;
1160}
1161
1162/* Initialize the specified card */
1163
1164static int ivtvfb_init_card(struct ivtv *itv)
1165{
1166        int rc;
1167
1168#ifdef CONFIG_X86_64
1169        if (pat_enabled()) {
1170                pr_warn("ivtvfb needs PAT disabled, boot with nopat kernel parameter\n");
1171                return -ENODEV;
1172        }
1173#endif
1174
1175        if (itv->osd_info) {
1176                IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1177                return -EBUSY;
1178        }
1179
1180        itv->osd_info = kzalloc(sizeof(struct osd_info),
1181                                        GFP_ATOMIC|__GFP_NOWARN);
1182        if (itv->osd_info == NULL) {
1183                IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1184                return -ENOMEM;
1185        }
1186
1187        /* Find & setup the OSD buffer */
1188        rc = ivtvfb_init_io(itv);
1189        if (rc) {
1190                ivtvfb_release_buffers(itv);
1191                return rc;
1192        }
1193
1194        /* Set the startup video mode information */
1195        if ((rc = ivtvfb_init_vidmode(itv))) {
1196                ivtvfb_release_buffers(itv);
1197                return rc;
1198        }
1199
1200        /* Register the framebuffer */
1201        if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1202                ivtvfb_release_buffers(itv);
1203                return -EINVAL;
1204        }
1205
1206        itv->osd_video_pbase = itv->osd_info->video_pbase;
1207
1208        /* Set the card to the requested mode */
1209        ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1210
1211        /* Set color 0 to black */
1212        write_reg(0, 0x02a30);
1213        write_reg(0, 0x02a34);
1214
1215        /* Enable the osd */
1216        ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1217
1218        /* Enable restart */
1219        itv->ivtvfb_restore = ivtvfb_restore;
1220
1221        /* Allocate DMA */
1222        ivtv_udma_alloc(itv);
1223        return 0;
1224
1225}
1226
1227static int __init ivtvfb_callback_init(struct device *dev, void *p)
1228{
1229        struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1230        struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1231
1232        if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1233                if (ivtvfb_init_card(itv) == 0) {
1234                        IVTVFB_INFO("Framebuffer registered on %s\n",
1235                                        itv->v4l2_dev.name);
1236                        (*(int *)p)++;
1237                }
1238        }
1239        return 0;
1240}
1241
1242static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1243{
1244        struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1245        struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1246        struct osd_info *oi = itv->osd_info;
1247
1248        if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1249                if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1250                        IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
1251                                       itv->instance);
1252                        return 0;
1253                }
1254                IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1255                itv->ivtvfb_restore = NULL;
1256                ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1257                ivtvfb_release_buffers(itv);
1258                itv->osd_video_pbase = 0;
1259        }
1260        return 0;
1261}
1262
1263static int __init ivtvfb_init(void)
1264{
1265        struct device_driver *drv;
1266        int registered = 0;
1267        int err;
1268
1269
1270        if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1271                pr_err("ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1272                     IVTV_MAX_CARDS - 1);
1273                return -EINVAL;
1274        }
1275
1276        drv = driver_find("ivtv", &pci_bus_type);
1277        err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
1278        (void)err;      /* suppress compiler warning */
1279        if (!registered) {
1280                pr_err("no cards found\n");
1281                return -ENODEV;
1282        }
1283        return 0;
1284}
1285
1286static void ivtvfb_cleanup(void)
1287{
1288        struct device_driver *drv;
1289        int err;
1290
1291        pr_info("Unloading framebuffer module\n");
1292
1293        drv = driver_find("ivtv", &pci_bus_type);
1294        err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
1295        (void)err;      /* suppress compiler warning */
1296}
1297
1298module_init(ivtvfb_init);
1299module_exit(ivtvfb_cleanup);
1300