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