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