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