Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     On Screen Display cx23415 Framebuffer driver
0004 
0005     This module presents the cx23415 OSD (onscreen display) framebuffer memory
0006     as a standard Linux /dev/fb style framebuffer device. The framebuffer has
0007     support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
0008     mode, there is a choice of a three color depths (12, 15 or 16 bits), but no
0009     local alpha. The colorspace is selectable between rgb & yuv.
0010     Depending on the TV standard configured in the ivtv module at load time,
0011     the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp.
0012     Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL)
0013     or 59.94 (NTSC)
0014 
0015     Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com>
0016 
0017     Derived from drivers/video/vesafb.c
0018     Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
0019 
0020     2.6 kernel port:
0021     Copyright (C) 2004 Matthias Badaire
0022 
0023     Copyright (C) 2004  Chris Kennedy <c@groovy.org>
0024 
0025     Copyright (C) 2006  Ian Armstrong <ian@iarmst.demon.co.uk>
0026 
0027  */
0028 
0029 #include "ivtv-driver.h"
0030 #include "ivtv-cards.h"
0031 #include "ivtv-i2c.h"
0032 #include "ivtv-udma.h"
0033 #include "ivtv-mailbox.h"
0034 #include "ivtv-firmware.h"
0035 
0036 #include <linux/fb.h>
0037 #include <linux/ivtvfb.h>
0038 
0039 #if defined(CONFIG_X86_64) && !defined(CONFIG_UML)
0040 #include <asm/memtype.h>
0041 #endif
0042 
0043 /* card parameters */
0044 static int ivtvfb_card_id = -1;
0045 static int ivtvfb_debug;
0046 static bool ivtvfb_force_pat = IS_ENABLED(CONFIG_VIDEO_FB_IVTV_FORCE_PAT);
0047 static bool osd_laced;
0048 static int osd_depth;
0049 static int osd_upper;
0050 static int osd_left;
0051 static unsigned int osd_yres;
0052 static unsigned int osd_xres;
0053 
0054 module_param(ivtvfb_card_id, int, 0444);
0055 module_param_named(debug,ivtvfb_debug, int, 0644);
0056 module_param_named(force_pat, ivtvfb_force_pat, bool, 0644);
0057 module_param(osd_laced, bool, 0444);
0058 module_param(osd_depth, int, 0444);
0059 module_param(osd_upper, int, 0444);
0060 module_param(osd_left, int, 0444);
0061 module_param(osd_yres, uint, 0444);
0062 module_param(osd_xres, uint, 0444);
0063 
0064 MODULE_PARM_DESC(ivtvfb_card_id,
0065          "Only use framebuffer of the specified ivtv card (0-31)\n"
0066          "\t\t\tdefault -1: initialize all available framebuffers");
0067 
0068 MODULE_PARM_DESC(debug,
0069          "Debug level (bitmask). Default: errors only\n"
0070          "\t\t\t(debug = 3 gives full debugging)");
0071 
0072 MODULE_PARM_DESC(force_pat,
0073          "Force initialization on x86 PAT-enabled systems (bool).\n");
0074 
0075 /* Why upper, left, xres, yres, depth, laced ? To match terminology used
0076    by fbset.
0077    Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
0078 
0079 MODULE_PARM_DESC(osd_laced,
0080          "Interlaced mode\n"
0081          "\t\t\t0=off\n"
0082          "\t\t\t1=on\n"
0083          "\t\t\tdefault off");
0084 
0085 MODULE_PARM_DESC(osd_depth,
0086          "Bits per pixel - 8, 16, 32\n"
0087          "\t\t\tdefault 8");
0088 
0089 MODULE_PARM_DESC(osd_upper,
0090          "Vertical start position\n"
0091          "\t\t\tdefault 0 (Centered)");
0092 
0093 MODULE_PARM_DESC(osd_left,
0094          "Horizontal start position\n"
0095          "\t\t\tdefault 0 (Centered)");
0096 
0097 MODULE_PARM_DESC(osd_yres,
0098          "Display height\n"
0099          "\t\t\tdefault 480 (PAL)\n"
0100          "\t\t\t        400 (NTSC)");
0101 
0102 MODULE_PARM_DESC(osd_xres,
0103          "Display width\n"
0104          "\t\t\tdefault 640");
0105 
0106 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
0107 MODULE_LICENSE("GPL");
0108 
0109 /* --------------------------------------------------------------------- */
0110 
0111 #define IVTVFB_DBGFLG_WARN  (1 << 0)
0112 #define IVTVFB_DBGFLG_INFO  (1 << 1)
0113 
0114 #define IVTVFB_DEBUG(x, type, fmt, args...) \
0115     do { \
0116         if ((x) & ivtvfb_debug) \
0117             printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
0118     } while (0)
0119 #define IVTVFB_DEBUG_WARN(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
0120 #define IVTVFB_DEBUG_INFO(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
0121 
0122 /* Standard kernel messages */
0123 #define IVTVFB_ERR(fmt, args...)   printk(KERN_ERR  "ivtvfb%d: " fmt, itv->instance , ## args)
0124 #define IVTVFB_WARN(fmt, args...)  printk(KERN_WARNING  "ivtvfb%d: " fmt, itv->instance , ## args)
0125 #define IVTVFB_INFO(fmt, args...)  printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
0126 
0127 /* --------------------------------------------------------------------- */
0128 
0129 #define IVTV_OSD_MAX_WIDTH  720
0130 #define IVTV_OSD_MAX_HEIGHT 576
0131 
0132 #define IVTV_OSD_BPP_8      0x00
0133 #define IVTV_OSD_BPP_16_444 0x03
0134 #define IVTV_OSD_BPP_16_555 0x02
0135 #define IVTV_OSD_BPP_16_565 0x01
0136 #define IVTV_OSD_BPP_32     0x04
0137 
0138 struct osd_info {
0139     /* Physical base address */
0140     unsigned long video_pbase;
0141     /* Relative base address (relative to start of decoder memory) */
0142     u32 video_rbase;
0143     /* Mapped base address */
0144     volatile char __iomem *video_vbase;
0145     /* Buffer size */
0146     u32 video_buffer_size;
0147 
0148     /* video_base rounded down as required by hardware MTRRs */
0149     unsigned long fb_start_aligned_physaddr;
0150     /* video_base rounded up as required by hardware MTRRs */
0151     unsigned long fb_end_aligned_physaddr;
0152     int wc_cookie;
0153 
0154     /* Store the buffer offset */
0155     int set_osd_coords_x;
0156     int set_osd_coords_y;
0157 
0158     /* Current dimensions (NOT VISIBLE SIZE!) */
0159     int display_width;
0160     int display_height;
0161     int display_byte_stride;
0162 
0163     /* Current bits per pixel */
0164     int bits_per_pixel;
0165     int bytes_per_pixel;
0166 
0167     /* Frame buffer stuff */
0168     struct fb_info ivtvfb_info;
0169     struct fb_var_screeninfo ivtvfb_defined;
0170     struct fb_fix_screeninfo ivtvfb_fix;
0171 
0172     /* Used for a warm start */
0173     struct fb_var_screeninfo fbvar_cur;
0174     int blank_cur;
0175     u32 palette_cur[256];
0176     u32 pan_cur;
0177 };
0178 
0179 struct ivtv_osd_coords {
0180     unsigned long offset;
0181     unsigned long max_offset;
0182     int pixel_stride;
0183     int lines;
0184     int x;
0185     int y;
0186 };
0187 
0188 /* --------------------------------------------------------------------- */
0189 
0190 /* ivtv API calls for framebuffer related support */
0191 
0192 static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
0193                        u32 *fblength)
0194 {
0195     u32 data[CX2341X_MBOX_MAX_DATA];
0196     int rc;
0197 
0198     ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
0199     rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
0200     *fbbase = data[0];
0201     *fblength = data[1];
0202     return rc;
0203 }
0204 
0205 static int ivtvfb_get_osd_coords(struct ivtv *itv,
0206                       struct ivtv_osd_coords *osd)
0207 {
0208     struct osd_info *oi = itv->osd_info;
0209     u32 data[CX2341X_MBOX_MAX_DATA];
0210 
0211     ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
0212 
0213     osd->offset = data[0] - oi->video_rbase;
0214     osd->max_offset = oi->display_width * oi->display_height * 4;
0215     osd->pixel_stride = data[1];
0216     osd->lines = data[2];
0217     osd->x = data[3];
0218     osd->y = data[4];
0219     return 0;
0220 }
0221 
0222 static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
0223 {
0224     struct osd_info *oi = itv->osd_info;
0225 
0226     oi->display_width = osd->pixel_stride;
0227     oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel;
0228     oi->set_osd_coords_x += osd->x;
0229     oi->set_osd_coords_y = osd->y;
0230 
0231     return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
0232             osd->offset + oi->video_rbase,
0233             osd->pixel_stride,
0234             osd->lines, osd->x, osd->y);
0235 }
0236 
0237 static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
0238 {
0239     int osd_height_limit = itv->is_out_50hz ? 576 : 480;
0240 
0241     /* Only fail if resolution too high, otherwise fudge the start coords. */
0242     if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
0243         return -EINVAL;
0244 
0245     /* Ensure we don't exceed display limits */
0246     if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
0247         IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
0248             ivtv_window->top, ivtv_window->height);
0249         ivtv_window->top = osd_height_limit - ivtv_window->height;
0250     }
0251 
0252     if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) {
0253         IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
0254             ivtv_window->left, ivtv_window->width);
0255         ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
0256     }
0257 
0258     /* Set the OSD origin */
0259     write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
0260 
0261     /* How much to display */
0262     write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
0263 
0264     /* Pass this info back the yuv handler */
0265     itv->yuv_info.osd_vis_w = ivtv_window->width;
0266     itv->yuv_info.osd_vis_h = ivtv_window->height;
0267     itv->yuv_info.osd_x_offset = ivtv_window->left;
0268     itv->yuv_info.osd_y_offset = ivtv_window->top;
0269 
0270     return 0;
0271 }
0272 
0273 static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
0274                   unsigned long ivtv_dest_addr, void __user *userbuf,
0275                   int size_in_bytes)
0276 {
0277     DEFINE_WAIT(wait);
0278     int got_sig = 0;
0279 
0280     mutex_lock(&itv->udma.lock);
0281     /* Map User DMA */
0282     if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
0283         mutex_unlock(&itv->udma.lock);
0284         IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with pin_user_pages: %d bytes, %d pages returned\n",
0285                    size_in_bytes, itv->udma.page_count);
0286 
0287         /* pin_user_pages must have failed completely */
0288         return -EIO;
0289     }
0290 
0291     IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
0292                size_in_bytes, itv->udma.page_count);
0293 
0294     ivtv_udma_prepare(itv);
0295     prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
0296     /* if no UDMA is pending and no UDMA is in progress, then the DMA
0297        is finished */
0298     while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
0299            test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
0300         /* don't interrupt if the DMA is in progress but break off
0301            a still pending DMA. */
0302         got_sig = signal_pending(current);
0303         if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
0304             break;
0305         got_sig = 0;
0306         schedule();
0307     }
0308     finish_wait(&itv->dma_waitq, &wait);
0309 
0310     /* Unmap Last DMA Xfer */
0311     ivtv_udma_unmap(itv);
0312     mutex_unlock(&itv->udma.lock);
0313     if (got_sig) {
0314         IVTV_DEBUG_INFO("User stopped OSD\n");
0315         return -EINTR;
0316     }
0317 
0318     return 0;
0319 }
0320 
0321 static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
0322                   unsigned long dest_offset, int count)
0323 {
0324     DEFINE_WAIT(wait);
0325     struct osd_info *oi = itv->osd_info;
0326 
0327     /* Nothing to do */
0328     if (count == 0) {
0329         IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
0330         return -EINVAL;
0331     }
0332 
0333     /* Check Total FB Size */
0334     if ((dest_offset + count) > oi->video_buffer_size) {
0335         IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
0336             dest_offset + count, oi->video_buffer_size);
0337         return -E2BIG;
0338     }
0339 
0340     /* Not fatal, but will have undesirable results */
0341     if ((unsigned long)source & 3)
0342         IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (%p)\n",
0343                 source);
0344 
0345     if (dest_offset & 3)
0346         IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
0347 
0348     if (count & 3)
0349         IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
0350 
0351     /* Check Source */
0352     if (!access_ok(source + dest_offset, count)) {
0353         IVTVFB_WARN("Invalid userspace pointer %p\n", source);
0354 
0355         IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source %p count %d\n",
0356                   dest_offset, source, count);
0357         return -EINVAL;
0358     }
0359 
0360     /* OSD Address to send DMA to */
0361     dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
0362 
0363     /* Fill Buffers */
0364     return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
0365 }
0366 
0367 static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
0368                         size_t count, loff_t *ppos)
0369 {
0370     unsigned long p = *ppos;
0371     void *dst;
0372     int err = 0;
0373     int dma_err;
0374     unsigned long total_size;
0375     struct ivtv *itv = (struct ivtv *) info->par;
0376     unsigned long dma_offset =
0377             IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
0378     unsigned long dma_size;
0379     u16 lead = 0, tail = 0;
0380 
0381     if (info->state != FBINFO_STATE_RUNNING)
0382         return -EPERM;
0383 
0384     total_size = info->screen_size;
0385 
0386     if (total_size == 0)
0387         total_size = info->fix.smem_len;
0388 
0389     if (p > total_size)
0390         return -EFBIG;
0391 
0392     if (count > total_size) {
0393         err = -EFBIG;
0394         count = total_size;
0395     }
0396 
0397     if (count + p > total_size) {
0398         if (!err)
0399             err = -ENOSPC;
0400         count = total_size - p;
0401     }
0402 
0403     dst = (void __force *) (info->screen_base + p);
0404 
0405     if (info->fbops->fb_sync)
0406         info->fbops->fb_sync(info);
0407 
0408     /* If transfer size > threshold and both src/dst
0409     addresses are aligned, use DMA */
0410     if (count >= 4096 &&
0411         ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
0412         /* Odd address = can't DMA. Align */
0413         if ((unsigned long)dst & 3) {
0414             lead = 4 - ((unsigned long)dst & 3);
0415             if (copy_from_user(dst, buf, lead))
0416                 return -EFAULT;
0417             buf += lead;
0418             dst += lead;
0419         }
0420         /* DMA resolution is 32 bits */
0421         if ((count - lead) & 3)
0422             tail = (count - lead) & 3;
0423         /* DMA the data */
0424         dma_size = count - lead - tail;
0425         dma_err = ivtvfb_prep_dec_dma_to_device(itv,
0426                p + lead + dma_offset, (void __user *)buf, dma_size);
0427         if (dma_err)
0428             return dma_err;
0429         dst += dma_size;
0430         buf += dma_size;
0431         /* Copy any leftover data */
0432         if (tail && copy_from_user(dst, buf, tail))
0433             return -EFAULT;
0434     } else if (copy_from_user(dst, buf, count)) {
0435         return -EFAULT;
0436     }
0437 
0438     if  (!err)
0439         *ppos += count;
0440 
0441     return (err) ? err : count;
0442 }
0443 
0444 static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
0445 {
0446     DEFINE_WAIT(wait);
0447     struct ivtv *itv = (struct ivtv *)info->par;
0448     int rc = 0;
0449 
0450     switch (cmd) {
0451         case FBIOGET_VBLANK: {
0452             struct fb_vblank vblank;
0453             u32 trace;
0454 
0455             memset(&vblank, 0, sizeof(struct fb_vblank));
0456 
0457             vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
0458                     FB_VBLANK_HAVE_VSYNC;
0459             trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
0460             if (itv->is_out_50hz && trace > 312)
0461                 trace -= 312;
0462             else if (itv->is_out_60hz && trace > 262)
0463                 trace -= 262;
0464             if (trace == 1)
0465                 vblank.flags |= FB_VBLANK_VSYNCING;
0466             vblank.count = itv->last_vsync_field;
0467             vblank.vcount = trace;
0468             vblank.hcount = 0;
0469             if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
0470                 return -EFAULT;
0471             return 0;
0472         }
0473 
0474         case FBIO_WAITFORVSYNC:
0475             prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
0476             if (!schedule_timeout(msecs_to_jiffies(50)))
0477                 rc = -ETIMEDOUT;
0478             finish_wait(&itv->vsync_waitq, &wait);
0479             return rc;
0480 
0481         case IVTVFB_IOC_DMA_FRAME: {
0482             struct ivtvfb_dma_frame args;
0483 
0484             IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
0485             if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
0486                 return -EFAULT;
0487 
0488             return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
0489         }
0490 
0491         default:
0492             IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
0493             return -EINVAL;
0494     }
0495     return 0;
0496 }
0497 
0498 /* Framebuffer device handling */
0499 
0500 static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
0501 {
0502     struct osd_info *oi = itv->osd_info;
0503     struct ivtv_osd_coords ivtv_osd;
0504     struct v4l2_rect ivtv_window;
0505     int osd_mode = -1;
0506 
0507     IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
0508 
0509     /* Select color space */
0510     if (var->nonstd) /* YUV */
0511         write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
0512     else /* RGB  */
0513         write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
0514 
0515     /* Set the color mode */
0516     switch (var->bits_per_pixel) {
0517         case 8:
0518             osd_mode = IVTV_OSD_BPP_8;
0519             break;
0520         case 32:
0521             osd_mode = IVTV_OSD_BPP_32;
0522             break;
0523         case 16:
0524             switch (var->green.length) {
0525             case 4:
0526                 osd_mode = IVTV_OSD_BPP_16_444;
0527                 break;
0528             case 5:
0529                 osd_mode = IVTV_OSD_BPP_16_555;
0530                 break;
0531             case 6:
0532                 osd_mode = IVTV_OSD_BPP_16_565;
0533                 break;
0534             default:
0535                 IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
0536             }
0537             break;
0538         default:
0539             IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
0540     }
0541 
0542     /* Set video mode. Although rare, the display can become scrambled even
0543        if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
0544     if (osd_mode != -1) {
0545         ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
0546         ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
0547     }
0548 
0549     oi->bits_per_pixel = var->bits_per_pixel;
0550     oi->bytes_per_pixel = var->bits_per_pixel / 8;
0551 
0552     /* Set the flicker filter */
0553     switch (var->vmode & FB_VMODE_MASK) {
0554         case FB_VMODE_NONINTERLACED: /* Filter on */
0555             ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
0556             break;
0557         case FB_VMODE_INTERLACED: /* Filter off */
0558             ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
0559             break;
0560         default:
0561             IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
0562     }
0563 
0564     /* Read the current osd info */
0565     ivtvfb_get_osd_coords(itv, &ivtv_osd);
0566 
0567     /* Now set the OSD to the size we want */
0568     ivtv_osd.pixel_stride = var->xres_virtual;
0569     ivtv_osd.lines = var->yres_virtual;
0570     ivtv_osd.x = 0;
0571     ivtv_osd.y = 0;
0572     ivtvfb_set_osd_coords(itv, &ivtv_osd);
0573 
0574     /* Can't seem to find the right API combo for this.
0575        Use another function which does what we need through direct register access. */
0576     ivtv_window.width = var->xres;
0577     ivtv_window.height = var->yres;
0578 
0579     /* Minimum margin cannot be 0, as X won't allow such a mode */
0580     if (!var->upper_margin)
0581         var->upper_margin++;
0582     if (!var->left_margin)
0583         var->left_margin++;
0584     ivtv_window.top = var->upper_margin - 1;
0585     ivtv_window.left = var->left_margin - 1;
0586 
0587     ivtvfb_set_display_window(itv, &ivtv_window);
0588 
0589     /* Pass screen size back to yuv handler */
0590     itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
0591     itv->yuv_info.osd_full_h = ivtv_osd.lines;
0592 
0593     /* Force update of yuv registers */
0594     itv->yuv_info.yuv_forced_update = 1;
0595 
0596     /* Keep a copy of these settings */
0597     memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
0598 
0599     IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
0600               var->xres, var->yres,
0601               var->xres_virtual, var->yres_virtual,
0602               var->bits_per_pixel);
0603 
0604     IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
0605               var->left_margin, var->upper_margin);
0606 
0607     IVTVFB_DEBUG_INFO("Display filter: %s\n",
0608             (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
0609     IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
0610 
0611     return 0;
0612 }
0613 
0614 static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
0615 {
0616     struct osd_info *oi = itv->osd_info;
0617 
0618     IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
0619     memset(fix, 0, sizeof(struct fb_fix_screeninfo));
0620     strscpy(fix->id, "cx23415 TV out", sizeof(fix->id));
0621     fix->smem_start = oi->video_pbase;
0622     fix->smem_len = oi->video_buffer_size;
0623     fix->type = FB_TYPE_PACKED_PIXELS;
0624     fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
0625     fix->xpanstep = 1;
0626     fix->ypanstep = 1;
0627     fix->ywrapstep = 0;
0628     fix->line_length = oi->display_byte_stride;
0629     fix->accel = FB_ACCEL_NONE;
0630     return 0;
0631 }
0632 
0633 /* Check the requested display mode, returning -EINVAL if we can't
0634    handle it. */
0635 
0636 static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
0637 {
0638     struct osd_info *oi = itv->osd_info;
0639     int osd_height_limit;
0640     u32 pixclock, hlimit, vlimit;
0641 
0642     IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
0643 
0644     /* Set base references for mode calcs. */
0645     if (itv->is_out_50hz) {
0646         pixclock = 84316;
0647         hlimit = 776;
0648         vlimit = 591;
0649         osd_height_limit = 576;
0650     }
0651     else {
0652         pixclock = 83926;
0653         hlimit = 776;
0654         vlimit = 495;
0655         osd_height_limit = 480;
0656     }
0657 
0658     if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
0659         var->transp.offset = 24;
0660         var->transp.length = 8;
0661         var->red.offset = 16;
0662         var->red.length = 8;
0663         var->green.offset = 8;
0664         var->green.length = 8;
0665         var->blue.offset = 0;
0666         var->blue.length = 8;
0667     }
0668     else if (var->bits_per_pixel == 16) {
0669         /* To find out the true mode, check green length */
0670         switch (var->green.length) {
0671             case 4:
0672                 var->red.offset = 8;
0673                 var->red.length = 4;
0674                 var->green.offset = 4;
0675                 var->green.length = 4;
0676                 var->blue.offset = 0;
0677                 var->blue.length = 4;
0678                 var->transp.offset = 12;
0679                 var->transp.length = 1;
0680                 break;
0681             case 5:
0682                 var->red.offset = 10;
0683                 var->red.length = 5;
0684                 var->green.offset = 5;
0685                 var->green.length = 5;
0686                 var->blue.offset = 0;
0687                 var->blue.length = 5;
0688                 var->transp.offset = 15;
0689                 var->transp.length = 1;
0690                 break;
0691             default:
0692                 var->red.offset = 11;
0693                 var->red.length = 5;
0694                 var->green.offset = 5;
0695                 var->green.length = 6;
0696                 var->blue.offset = 0;
0697                 var->blue.length = 5;
0698                 var->transp.offset = 0;
0699                 var->transp.length = 0;
0700                 break;
0701         }
0702     }
0703     else {
0704         IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
0705         return -EINVAL;
0706     }
0707 
0708     /* Check the resolution */
0709     if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
0710         IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
0711                 var->xres, var->yres);
0712         return -EINVAL;
0713     }
0714 
0715     /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
0716     if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
0717         var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
0718         var->xres_virtual < var->xres ||
0719         var->yres_virtual < var->yres) {
0720         IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
0721             var->xres_virtual, var->yres_virtual);
0722         return -EINVAL;
0723     }
0724 
0725     /* Some extra checks if in 8 bit mode */
0726     if (var->bits_per_pixel == 8) {
0727         /* Width must be a multiple of 4 */
0728         if (var->xres & 3) {
0729             IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
0730             return -EINVAL;
0731         }
0732         if (var->xres_virtual & 3) {
0733             IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
0734             return -EINVAL;
0735         }
0736     }
0737     else if (var->bits_per_pixel == 16) {
0738         /* Width must be a multiple of 2 */
0739         if (var->xres & 1) {
0740             IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
0741             return -EINVAL;
0742         }
0743         if (var->xres_virtual & 1) {
0744             IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
0745             return -EINVAL;
0746         }
0747     }
0748 
0749     /* Now check the offsets */
0750     if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
0751         IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
0752             var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
0753         return -EINVAL;
0754     }
0755 
0756     /* Check pixel format */
0757     if (var->nonstd > 1) {
0758         IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
0759         return -EINVAL;
0760     }
0761 
0762     /* Check video mode */
0763     if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
0764         ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
0765         IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
0766         return -EINVAL;
0767     }
0768 
0769     /* Check the left & upper margins
0770        If the margins are too large, just center the screen
0771        (enforcing margins causes too many problems) */
0772 
0773     if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
0774         var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
0775 
0776     if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
0777         var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
0778             var->yres) / 2);
0779 
0780     /* Maintain overall 'size' for a constant refresh rate */
0781     var->right_margin = hlimit - var->left_margin - var->xres;
0782     var->lower_margin = vlimit - var->upper_margin - var->yres;
0783 
0784     /* Fixed sync times */
0785     var->hsync_len = 24;
0786     var->vsync_len = 2;
0787 
0788     /* Non-interlaced / interlaced mode is used to switch the OSD filter
0789        on or off. Adjust the clock timings to maintain a constant
0790        vertical refresh rate. */
0791     if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
0792         var->pixclock = pixclock / 2;
0793     else
0794         var->pixclock = pixclock;
0795 
0796     itv->osd_rect.width = var->xres;
0797     itv->osd_rect.height = var->yres;
0798 
0799     IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
0800               var->xres, var->yres,
0801               var->xres_virtual, var->yres_virtual,
0802               var->bits_per_pixel);
0803 
0804     IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
0805               var->left_margin, var->upper_margin);
0806 
0807     IVTVFB_DEBUG_INFO("Display filter: %s\n",
0808             (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
0809     IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
0810     return 0;
0811 }
0812 
0813 static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
0814 {
0815     struct ivtv *itv = (struct ivtv *) info->par;
0816     IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
0817     return _ivtvfb_check_var(var, itv);
0818 }
0819 
0820 static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
0821 {
0822     u32 osd_pan_index;
0823     struct ivtv *itv = (struct ivtv *) info->par;
0824 
0825     if (var->yoffset + info->var.yres > info->var.yres_virtual ||
0826         var->xoffset + info->var.xres > info->var.xres_virtual)
0827         return -EINVAL;
0828 
0829     osd_pan_index = var->yoffset * info->fix.line_length
0830               + var->xoffset * info->var.bits_per_pixel / 8;
0831     write_reg(osd_pan_index, 0x02A0C);
0832 
0833     /* Pass this info back the yuv handler */
0834     itv->yuv_info.osd_x_pan = var->xoffset;
0835     itv->yuv_info.osd_y_pan = var->yoffset;
0836     /* Force update of yuv registers */
0837     itv->yuv_info.yuv_forced_update = 1;
0838     /* Remember this value */
0839     itv->osd_info->pan_cur = osd_pan_index;
0840     return 0;
0841 }
0842 
0843 static int ivtvfb_set_par(struct fb_info *info)
0844 {
0845     int rc = 0;
0846     struct ivtv *itv = (struct ivtv *) info->par;
0847 
0848     IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
0849 
0850     rc = ivtvfb_set_var(itv, &info->var);
0851     ivtvfb_pan_display(&info->var, info);
0852     ivtvfb_get_fix(itv, &info->fix);
0853     ivtv_firmware_check(itv, "ivtvfb_set_par");
0854     return rc;
0855 }
0856 
0857 static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
0858                 unsigned blue, unsigned transp,
0859                 struct fb_info *info)
0860 {
0861     u32 color, *palette;
0862     struct ivtv *itv = (struct ivtv *)info->par;
0863 
0864     if (regno >= info->cmap.len)
0865         return -EINVAL;
0866 
0867     color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
0868     if (info->var.bits_per_pixel <= 8) {
0869         write_reg(regno, 0x02a30);
0870         write_reg(color, 0x02a34);
0871         itv->osd_info->palette_cur[regno] = color;
0872         return 0;
0873     }
0874     if (regno >= 16)
0875         return -EINVAL;
0876 
0877     palette = info->pseudo_palette;
0878     if (info->var.bits_per_pixel == 16) {
0879         switch (info->var.green.length) {
0880             case 4:
0881                 color = ((red & 0xf000) >> 4) |
0882                     ((green & 0xf000) >> 8) |
0883                     ((blue & 0xf000) >> 12);
0884                 break;
0885             case 5:
0886                 color = ((red & 0xf800) >> 1) |
0887                     ((green & 0xf800) >> 6) |
0888                     ((blue & 0xf800) >> 11);
0889                 break;
0890             case 6:
0891                 color = (red & 0xf800 ) |
0892                     ((green & 0xfc00) >> 5) |
0893                     ((blue & 0xf800) >> 11);
0894                 break;
0895         }
0896     }
0897     palette[regno] = color;
0898     return 0;
0899 }
0900 
0901 /* We don't really support blanking. All this does is enable or
0902    disable the OSD. */
0903 static int ivtvfb_blank(int blank_mode, struct fb_info *info)
0904 {
0905     struct ivtv *itv = (struct ivtv *)info->par;
0906 
0907     IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
0908     switch (blank_mode) {
0909     case FB_BLANK_UNBLANK:
0910         ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
0911         ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
0912         break;
0913     case FB_BLANK_NORMAL:
0914     case FB_BLANK_HSYNC_SUSPEND:
0915     case FB_BLANK_VSYNC_SUSPEND:
0916         ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
0917         ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
0918         break;
0919     case FB_BLANK_POWERDOWN:
0920         ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
0921         ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
0922         break;
0923     }
0924     itv->osd_info->blank_cur = blank_mode;
0925     return 0;
0926 }
0927 
0928 static const struct fb_ops ivtvfb_ops = {
0929     .owner = THIS_MODULE,
0930     .fb_write       = ivtvfb_write,
0931     .fb_check_var   = ivtvfb_check_var,
0932     .fb_set_par     = ivtvfb_set_par,
0933     .fb_setcolreg   = ivtvfb_setcolreg,
0934     .fb_fillrect    = cfb_fillrect,
0935     .fb_copyarea    = cfb_copyarea,
0936     .fb_imageblit   = cfb_imageblit,
0937     .fb_cursor      = NULL,
0938     .fb_ioctl       = ivtvfb_ioctl,
0939     .fb_pan_display = ivtvfb_pan_display,
0940     .fb_blank       = ivtvfb_blank,
0941 };
0942 
0943 /* Restore hardware after firmware restart */
0944 static void ivtvfb_restore(struct ivtv *itv)
0945 {
0946     struct osd_info *oi = itv->osd_info;
0947     int i;
0948 
0949     ivtvfb_set_var(itv, &oi->fbvar_cur);
0950     ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
0951     for (i = 0; i < 256; i++) {
0952         write_reg(i, 0x02a30);
0953         write_reg(oi->palette_cur[i], 0x02a34);
0954     }
0955     write_reg(oi->pan_cur, 0x02a0c);
0956 }
0957 
0958 /* Initialization */
0959 
0960 
0961 /* Setup our initial video mode */
0962 static int ivtvfb_init_vidmode(struct ivtv *itv)
0963 {
0964     struct osd_info *oi = itv->osd_info;
0965     struct v4l2_rect start_window;
0966     int max_height;
0967 
0968     /* Color mode */
0969 
0970     if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
0971         osd_depth = 8;
0972     oi->bits_per_pixel = osd_depth;
0973     oi->bytes_per_pixel = oi->bits_per_pixel / 8;
0974 
0975     /* Horizontal size & position */
0976 
0977     if (osd_xres > 720)
0978         osd_xres = 720;
0979 
0980     /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
0981     if (osd_depth == 8)
0982         osd_xres &= ~3;
0983     else if (osd_depth == 16)
0984         osd_xres &= ~1;
0985 
0986     start_window.width = osd_xres ? osd_xres : 640;
0987 
0988     /* Check horizontal start (osd_left). */
0989     if (osd_left && osd_left + start_window.width > 721) {
0990         IVTVFB_ERR("Invalid osd_left - assuming default\n");
0991         osd_left = 0;
0992     }
0993 
0994     /* Hardware coords start at 0, user coords start at 1. */
0995     osd_left--;
0996 
0997     start_window.left = osd_left >= 0 ?
0998          osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
0999 
1000     oi->display_byte_stride =
1001             start_window.width * oi->bytes_per_pixel;
1002 
1003     /* Vertical size & position */
1004 
1005     max_height = itv->is_out_50hz ? 576 : 480;
1006 
1007     if (osd_yres > max_height)
1008         osd_yres = max_height;
1009 
1010     start_window.height = osd_yres ?
1011         osd_yres : itv->is_out_50hz ? 480 : 400;
1012 
1013     /* Check vertical start (osd_upper). */
1014     if (osd_upper + start_window.height > max_height + 1) {
1015         IVTVFB_ERR("Invalid osd_upper - assuming default\n");
1016         osd_upper = 0;
1017     }
1018 
1019     /* Hardware coords start at 0, user coords start at 1. */
1020     osd_upper--;
1021 
1022     start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
1023 
1024     oi->display_width = start_window.width;
1025     oi->display_height = start_window.height;
1026 
1027     /* Generate a valid fb_var_screeninfo */
1028 
1029     oi->ivtvfb_defined.xres = oi->display_width;
1030     oi->ivtvfb_defined.yres = oi->display_height;
1031     oi->ivtvfb_defined.xres_virtual = oi->display_width;
1032     oi->ivtvfb_defined.yres_virtual = oi->display_height;
1033     oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
1034     oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
1035     oi->ivtvfb_defined.left_margin = start_window.left + 1;
1036     oi->ivtvfb_defined.upper_margin = start_window.top + 1;
1037     oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
1038     oi->ivtvfb_defined.nonstd = 0;
1039 
1040     /* We've filled in the most data, let the usual mode check
1041        routine fill in the rest. */
1042     _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
1043 
1044     /* Generate valid fb_fix_screeninfo */
1045 
1046     ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
1047 
1048     /* Generate valid fb_info */
1049 
1050     oi->ivtvfb_info.node = -1;
1051     oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
1052     oi->ivtvfb_info.par = itv;
1053     oi->ivtvfb_info.var = oi->ivtvfb_defined;
1054     oi->ivtvfb_info.fix = oi->ivtvfb_fix;
1055     oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
1056     oi->ivtvfb_info.fbops = &ivtvfb_ops;
1057 
1058     /* Supply some monitor specs. Bogus values will do for now */
1059     oi->ivtvfb_info.monspecs.hfmin = 8000;
1060     oi->ivtvfb_info.monspecs.hfmax = 70000;
1061     oi->ivtvfb_info.monspecs.vfmin = 10;
1062     oi->ivtvfb_info.monspecs.vfmax = 100;
1063 
1064     /* Allocate color map */
1065     if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
1066         IVTVFB_ERR("abort, unable to alloc cmap\n");
1067         return -ENOMEM;
1068     }
1069 
1070     /* Allocate the pseudo palette */
1071     oi->ivtvfb_info.pseudo_palette =
1072         kmalloc_array(16, sizeof(u32), GFP_KERNEL|__GFP_NOWARN);
1073 
1074     if (!oi->ivtvfb_info.pseudo_palette) {
1075         IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
1076         return -ENOMEM;
1077     }
1078 
1079     return 0;
1080 }
1081 
1082 /* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
1083 
1084 static int ivtvfb_init_io(struct ivtv *itv)
1085 {
1086     struct osd_info *oi = itv->osd_info;
1087     /* Find the largest power of two that maps the whole buffer */
1088     int size_shift = 31;
1089 
1090     mutex_lock(&itv->serialize_lock);
1091     if (ivtv_init_on_first_open(itv)) {
1092         mutex_unlock(&itv->serialize_lock);
1093         IVTVFB_ERR("Failed to initialize ivtv\n");
1094         return -ENXIO;
1095     }
1096     mutex_unlock(&itv->serialize_lock);
1097 
1098     if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
1099                     &oi->video_buffer_size) < 0) {
1100         IVTVFB_ERR("Firmware failed to respond\n");
1101         return -EIO;
1102     }
1103 
1104     /* The osd buffer size depends on the number of video buffers allocated
1105        on the PVR350 itself. For now we'll hardcode the smallest osd buffer
1106        size to prevent any overlap. */
1107     oi->video_buffer_size = 1704960;
1108 
1109     oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
1110     oi->video_vbase = itv->dec_mem + oi->video_rbase;
1111 
1112     if (!oi->video_vbase) {
1113         IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
1114              oi->video_buffer_size, oi->video_pbase);
1115         return -EIO;
1116     }
1117 
1118     IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
1119             oi->video_pbase, oi->video_vbase,
1120             oi->video_buffer_size / 1024);
1121 
1122     while (!(oi->video_buffer_size & (1 << size_shift)))
1123         size_shift--;
1124     size_shift++;
1125     oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1126     oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1127     oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1128     oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1129     oi->wc_cookie = arch_phys_wc_add(oi->fb_start_aligned_physaddr,
1130                      oi->fb_end_aligned_physaddr -
1131                      oi->fb_start_aligned_physaddr);
1132     /* Blank the entire osd. */
1133     memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1134 
1135     return 0;
1136 }
1137 
1138 /* Release any memory we've grabbed & remove mtrr entry */
1139 static void ivtvfb_release_buffers (struct ivtv *itv)
1140 {
1141     struct osd_info *oi = itv->osd_info;
1142 
1143     /* Release cmap */
1144     if (oi->ivtvfb_info.cmap.len)
1145         fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1146 
1147     /* Release pseudo palette */
1148     kfree(oi->ivtvfb_info.pseudo_palette);
1149     arch_phys_wc_del(oi->wc_cookie);
1150     kfree(oi);
1151     itv->osd_info = NULL;
1152 }
1153 
1154 /* Initialize the specified card */
1155 
1156 static int ivtvfb_init_card(struct ivtv *itv)
1157 {
1158     int rc;
1159 
1160 #if defined(CONFIG_X86_64) && !defined(CONFIG_UML)
1161     if (pat_enabled()) {
1162         if (ivtvfb_force_pat) {
1163             pr_info("PAT is enabled. Write-combined framebuffer caching will be disabled.\n");
1164             pr_info("To enable caching, boot with nopat kernel parameter\n");
1165         } else {
1166             pr_warn("ivtvfb needs PAT disabled for write-combined framebuffer caching.\n");
1167             pr_warn("Boot with nopat kernel parameter to use caching, or use the\n");
1168             pr_warn("force_pat module parameter to run with caching disabled\n");
1169             return -ENODEV;
1170         }
1171     }
1172 #endif
1173 
1174     if (itv->osd_info) {
1175         IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1176         return -EBUSY;
1177     }
1178 
1179     itv->osd_info = kzalloc(sizeof(struct osd_info),
1180                     GFP_KERNEL|__GFP_NOWARN);
1181     if (itv->osd_info == NULL) {
1182         IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1183         return -ENOMEM;
1184     }
1185 
1186     /* Find & setup the OSD buffer */
1187     rc = ivtvfb_init_io(itv);
1188     if (rc) {
1189         ivtvfb_release_buffers(itv);
1190         return rc;
1191     }
1192 
1193     /* Set the startup video mode information */
1194     if ((rc = ivtvfb_init_vidmode(itv))) {
1195         ivtvfb_release_buffers(itv);
1196         return rc;
1197     }
1198 
1199     /* Register the framebuffer */
1200     if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1201         ivtvfb_release_buffers(itv);
1202         return -EINVAL;
1203     }
1204 
1205     itv->osd_video_pbase = itv->osd_info->video_pbase;
1206 
1207     /* Set the card to the requested mode */
1208     ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1209 
1210     /* Set color 0 to black */
1211     write_reg(0, 0x02a30);
1212     write_reg(0, 0x02a34);
1213 
1214     /* Enable the osd */
1215     ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1216 
1217     /* Enable restart */
1218     itv->ivtvfb_restore = ivtvfb_restore;
1219 
1220     /* Allocate DMA */
1221     ivtv_udma_alloc(itv);
1222     itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps |=
1223         V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1224     itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps |=
1225         V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1226     itv->v4l2_cap |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1227     return 0;
1228 
1229 }
1230 
1231 static int __init ivtvfb_callback_init(struct device *dev, void *p)
1232 {
1233     struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1234     struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1235 
1236     if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1237         if (ivtvfb_init_card(itv) == 0) {
1238             IVTVFB_INFO("Framebuffer registered on %s\n",
1239                     itv->v4l2_dev.name);
1240             (*(int *)p)++;
1241         }
1242     }
1243     return 0;
1244 }
1245 
1246 static int ivtvfb_callback_cleanup(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     struct osd_info *oi = itv->osd_info;
1251 
1252     if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1253         itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps &=
1254             ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1255         itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps &=
1256             ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1257         itv->v4l2_cap &= ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
1258         unregister_framebuffer(&itv->osd_info->ivtvfb_info);
1259         IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1260         itv->ivtvfb_restore = NULL;
1261         ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1262         ivtvfb_release_buffers(itv);
1263         itv->osd_video_pbase = 0;
1264     }
1265     return 0;
1266 }
1267 
1268 static int __init ivtvfb_init(void)
1269 {
1270     struct device_driver *drv;
1271     int registered = 0;
1272     int err;
1273 
1274 
1275     if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1276         pr_err("ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1277              IVTV_MAX_CARDS - 1);
1278         return -EINVAL;
1279     }
1280 
1281     drv = driver_find("ivtv", &pci_bus_type);
1282     err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
1283     (void)err;  /* suppress compiler warning */
1284     if (!registered) {
1285         pr_err("no cards found\n");
1286         return -ENODEV;
1287     }
1288     return 0;
1289 }
1290 
1291 static void ivtvfb_cleanup(void)
1292 {
1293     struct device_driver *drv;
1294     int err;
1295 
1296     pr_info("Unloading framebuffer module\n");
1297 
1298     drv = driver_find("ivtv", &pci_bus_type);
1299     err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
1300     (void)err;  /* suppress compiler warning */
1301 }
1302 
1303 module_init(ivtvfb_init);
1304 module_exit(ivtvfb_cleanup);