Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / 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         /* Pass screen size back to yuv handler */
508         itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
509         itv->yuv_info.osd_full_h = ivtv_osd.lines;
510
511         /* Force update of yuv registers */
512         itv->yuv_info.yuv_forced_update = 1;
513
514         IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
515                       var->xres, var->yres,
516                       var->xres_virtual, var->yres_virtual,
517                       var->bits_per_pixel);
518
519         IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
520                       var->left_margin, var->upper_margin);
521
522         IVTVFB_DEBUG_INFO("Display filter: %s\n",
523                         (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
524         IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
525
526         return 0;
527 }
528
529 static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
530 {
531         struct osd_info *oi = itv->osd_info;
532
533         IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
534         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
535         strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
536         fix->smem_start = oi->video_pbase;
537         fix->smem_len = oi->video_buffer_size;
538         fix->type = FB_TYPE_PACKED_PIXELS;
539         fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
540         fix->xpanstep = 1;
541         fix->ypanstep = 1;
542         fix->ywrapstep = 0;
543         fix->line_length = oi->display_byte_stride;
544         fix->accel = FB_ACCEL_NONE;
545         return 0;
546 }
547
548 /* Check the requested display mode, returning -EINVAL if we can't
549    handle it. */
550
551 static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
552 {
553         struct osd_info *oi = itv->osd_info;
554         int osd_height_limit;
555         u32 pixclock, hlimit, vlimit;
556
557         IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
558
559         /* Set base references for mode calcs. */
560         if (itv->is_50hz) {
561                 pixclock = 84316;
562                 hlimit = 776;
563                 vlimit = 591;
564                 osd_height_limit = 576;
565         }
566         else {
567                 pixclock = 83926;
568                 hlimit = 776;
569                 vlimit = 495;
570                 osd_height_limit = 480;
571         }
572
573         if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
574                 var->transp.offset = 24;
575                 var->transp.length = 8;
576                 var->red.offset = 16;
577                 var->red.length = 8;
578                 var->green.offset = 8;
579                 var->green.length = 8;
580                 var->blue.offset = 0;
581                 var->blue.length = 8;
582         }
583         else if (var->bits_per_pixel == 16) {
584                 /* To find out the true mode, check green length */
585                 switch (var->green.length) {
586                         case 4:
587                                 var->red.offset = 8;
588                                 var->red.length = 4;
589                                 var->green.offset = 4;
590                                 var->green.length = 4;
591                                 var->blue.offset = 0;
592                                 var->blue.length = 4;
593                                 var->transp.offset = 12;
594                                 var->transp.length = 1;
595                                 break;
596                         case 5:
597                                 var->red.offset = 10;
598                                 var->red.length = 5;
599                                 var->green.offset = 5;
600                                 var->green.length = 5;
601                                 var->blue.offset = 0;
602                                 var->blue.length = 5;
603                                 var->transp.offset = 15;
604                                 var->transp.length = 1;
605                                 break;
606                         default:
607                                 var->red.offset = 11;
608                                 var->red.length = 5;
609                                 var->green.offset = 5;
610                                 var->green.length = 6;
611                                 var->blue.offset = 0;
612                                 var->blue.length = 5;
613                                 var->transp.offset = 0;
614                                 var->transp.length = 0;
615                                 break;
616                 }
617         }
618         else {
619                 IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
620                 return -EINVAL;
621         }
622
623         /* Check the resolution */
624         if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
625                 IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
626                                 var->xres, var->yres);
627                 return -EINVAL;
628         }
629
630         /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
631         if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
632             var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
633             var->xres_virtual < var->xres ||
634             var->yres_virtual < var->yres) {
635                 IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
636                         var->xres_virtual, var->yres_virtual);
637                 return -EINVAL;
638         }
639
640         /* Some extra checks if in 8 bit mode */
641         if (var->bits_per_pixel == 8) {
642                 /* Width must be a multiple of 4 */
643                 if (var->xres & 3) {
644                         IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
645                         return -EINVAL;
646                 }
647                 if (var->xres_virtual & 3) {
648                         IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
649                         return -EINVAL;
650                 }
651         }
652         else if (var->bits_per_pixel == 16) {
653                 /* Width must be a multiple of 2 */
654                 if (var->xres & 1) {
655                         IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
656                         return -EINVAL;
657                 }
658                 if (var->xres_virtual & 1) {
659                         IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
660                         return -EINVAL;
661                 }
662         }
663
664         /* Now check the offsets */
665         if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
666                 IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
667                         var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
668                 return -EINVAL;
669         }
670
671         /* Check pixel format */
672         if (var->nonstd > 1) {
673                 IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
674                 return -EINVAL;
675         }
676
677         /* Check video mode */
678         if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
679                 ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
680                 IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
681                 return -EINVAL;
682         }
683
684         /* Check the left & upper margins
685            If the margins are too large, just center the screen
686            (enforcing margins causes too many problems) */
687
688         if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) {
689                 var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
690         }
691         if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) {
692                 var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2);
693         }
694
695         /* Maintain overall 'size' for a constant refresh rate */
696         var->right_margin = hlimit - var->left_margin - var->xres;
697         var->lower_margin = vlimit - var->upper_margin - var->yres;
698
699         /* Fixed sync times */
700         var->hsync_len = 24;
701         var->vsync_len = 2;
702
703         /* Non-interlaced / interlaced mode is used to switch the OSD filter
704            on or off. Adjust the clock timings to maintain a constant
705            vertical refresh rate. */
706         if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
707                 var->pixclock = pixclock / 2;
708         else
709                 var->pixclock = pixclock;
710
711         IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
712                       var->xres, var->yres,
713                       var->xres_virtual, var->yres_virtual,
714                       var->bits_per_pixel);
715
716         IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
717                       var->left_margin, var->upper_margin);
718
719         IVTVFB_DEBUG_INFO("Display filter: %s\n",
720                         (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
721         IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
722         return 0;
723 }
724
725 static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
726 {
727         struct ivtv *itv = (struct ivtv *) info->par;
728         IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
729         return _ivtvfb_check_var(var, itv);
730 }
731
732 static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
733 {
734         u32 osd_pan_index;
735         struct ivtv *itv = (struct ivtv *) info->par;
736
737         osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8;
738         write_reg(osd_pan_index, 0x02A0C);
739
740         /* Pass this info back the yuv handler */
741         itv->yuv_info.osd_x_pan = var->xoffset;
742         itv->yuv_info.osd_y_pan = var->yoffset;
743         /* Force update of yuv registers */
744         itv->yuv_info.yuv_forced_update = 1;
745         return 0;
746 }
747
748 static int ivtvfb_set_par(struct fb_info *info)
749 {
750         int rc = 0;
751         struct ivtv *itv = (struct ivtv *) info->par;
752
753         IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
754
755         rc = ivtvfb_set_var(itv, &info->var);
756         ivtvfb_pan_display(&info->var, info);
757         ivtvfb_get_fix(itv, &info->fix);
758         return rc;
759 }
760
761 static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
762                                 unsigned blue, unsigned transp,
763                                 struct fb_info *info)
764 {
765         u32 color, *palette;
766         struct ivtv *itv = (struct ivtv *)info->par;
767
768         if (regno >= info->cmap.len)
769                 return -EINVAL;
770
771         color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
772         if (info->var.bits_per_pixel <= 8) {
773                 write_reg(regno, 0x02a30);
774                 write_reg(color, 0x02a34);
775                 return 0;
776         }
777         if (regno >= 16)
778                 return -EINVAL;
779
780         palette = info->pseudo_palette;
781         if (info->var.bits_per_pixel == 16) {
782                 switch (info->var.green.length) {
783                         case 4:
784                                 color = ((red & 0xf000) >> 4) |
785                                         ((green & 0xf000) >> 8) |
786                                         ((blue & 0xf000) >> 12);
787                                 break;
788                         case 5:
789                                 color = ((red & 0xf800) >> 1) |
790                                         ((green & 0xf800) >> 6) |
791                                         ((blue & 0xf800) >> 11);
792                                 break;
793                         case 6:
794                                 color = (red & 0xf800 ) |
795                                         ((green & 0xfc00) >> 5) |
796                                         ((blue & 0xf800) >> 11);
797                                 break;
798                 }
799         }
800         palette[regno] = color;
801         return 0;
802 }
803
804 /* We don't really support blanking. All this does is enable or
805    disable the OSD. */
806 static int ivtvfb_blank(int blank_mode, struct fb_info *info)
807 {
808         struct ivtv *itv = (struct ivtv *)info->par;
809
810         IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
811         switch (blank_mode) {
812         case FB_BLANK_UNBLANK:
813                 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
814                 break;
815         case FB_BLANK_NORMAL:
816         case FB_BLANK_HSYNC_SUSPEND:
817         case FB_BLANK_VSYNC_SUSPEND:
818         case FB_BLANK_POWERDOWN:
819                 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
820                 break;
821         }
822         return 0;
823 }
824
825 static struct fb_ops ivtvfb_ops = {
826         .owner = THIS_MODULE,
827         .fb_check_var   = ivtvfb_check_var,
828         .fb_set_par     = ivtvfb_set_par,
829         .fb_setcolreg   = ivtvfb_setcolreg,
830         .fb_fillrect    = cfb_fillrect,
831         .fb_copyarea    = cfb_copyarea,
832         .fb_imageblit   = cfb_imageblit,
833         .fb_cursor      = NULL,
834         .fb_ioctl       = ivtvfb_ioctl,
835         .fb_pan_display = ivtvfb_pan_display,
836         .fb_blank       = ivtvfb_blank,
837 };
838
839 /* Initialization */
840
841
842 /* Setup our initial video mode */
843 static int ivtvfb_init_vidmode(struct ivtv *itv)
844 {
845         struct osd_info *oi = itv->osd_info;
846         struct v4l2_rect start_window;
847         int max_height;
848
849         /* Color mode */
850
851         if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
852                 osd_depth = 8;
853         oi->bits_per_pixel = osd_depth;
854         oi->bytes_per_pixel = oi->bits_per_pixel / 8;
855
856         /* Horizontal size & position */
857
858         if (osd_xres > 720)
859                 osd_xres = 720;
860
861         /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
862         if (osd_depth == 8)
863                 osd_xres &= ~3;
864         else if (osd_depth == 16)
865                 osd_xres &= ~1;
866
867         start_window.width = osd_xres ? osd_xres : 640;
868
869         /* Check horizontal start (osd_left). */
870         if (osd_left && osd_left + start_window.width > 721) {
871                 IVTVFB_ERR("Invalid osd_left - assuming default\n");
872                 osd_left = 0;
873         }
874
875         /* Hardware coords start at 0, user coords start at 1. */
876         osd_left--;
877
878         start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
879
880         oi->display_byte_stride =
881                         start_window.width * oi->bytes_per_pixel;
882
883         /* Vertical size & position */
884
885         max_height = itv->is_50hz ? 576 : 480;
886
887         if (osd_yres > max_height)
888                 osd_yres = max_height;
889
890         start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;
891
892         /* Check vertical start (osd_upper). */
893         if (osd_upper + start_window.height > max_height + 1) {
894                 IVTVFB_ERR("Invalid osd_upper - assuming default\n");
895                 osd_upper = 0;
896         }
897
898         /* Hardware coords start at 0, user coords start at 1. */
899         osd_upper--;
900
901         start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
902
903         oi->display_width = start_window.width;
904         oi->display_height = start_window.height;
905
906         /* Generate a valid fb_var_screeninfo */
907
908         oi->ivtvfb_defined.xres = oi->display_width;
909         oi->ivtvfb_defined.yres = oi->display_height;
910         oi->ivtvfb_defined.xres_virtual = oi->display_width;
911         oi->ivtvfb_defined.yres_virtual = oi->display_height;
912         oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
913         oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
914         oi->ivtvfb_defined.left_margin = start_window.left + 1;
915         oi->ivtvfb_defined.upper_margin = start_window.top + 1;
916         oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
917         oi->ivtvfb_defined.nonstd = 0;
918
919         /* We've filled in the most data, let the usual mode check
920            routine fill in the rest. */
921         _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
922
923         /* Generate valid fb_fix_screeninfo */
924
925         ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
926
927         /* Generate valid fb_info */
928
929         oi->ivtvfb_info.node = -1;
930         oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
931         oi->ivtvfb_info.fbops = &ivtvfb_ops;
932         oi->ivtvfb_info.par = itv;
933         oi->ivtvfb_info.var = oi->ivtvfb_defined;
934         oi->ivtvfb_info.fix = oi->ivtvfb_fix;
935         oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
936         oi->ivtvfb_info.fbops = &ivtvfb_ops;
937
938         /* Supply some monitor specs. Bogus values will do for now */
939         oi->ivtvfb_info.monspecs.hfmin = 8000;
940         oi->ivtvfb_info.monspecs.hfmax = 70000;
941         oi->ivtvfb_info.monspecs.vfmin = 10;
942         oi->ivtvfb_info.monspecs.vfmax = 100;
943
944         /* Allocate color map */
945         if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
946                 IVTVFB_ERR("abort, unable to alloc cmap\n");
947                 return -ENOMEM;
948         }
949
950         /* Allocate the pseudo palette */
951         oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
952
953         if (!oi->ivtvfb_info.pseudo_palette) {
954                 IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
955                 return -ENOMEM;
956         }
957
958         return 0;
959 }
960
961 /* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
962
963 static int ivtvfb_init_io(struct ivtv *itv)
964 {
965         struct osd_info *oi = itv->osd_info;
966
967         mutex_lock(&itv->serialize_lock);
968         if (ivtv_init_on_first_open(itv)) {
969                 mutex_unlock(&itv->serialize_lock);
970                 IVTVFB_ERR("Failed to initialize ivtv\n");
971                 return -ENXIO;
972         }
973         mutex_unlock(&itv->serialize_lock);
974
975         ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);
976
977         /* The osd buffer size depends on the number of video buffers allocated
978            on the PVR350 itself. For now we'll hardcode the smallest osd buffer
979            size to prevent any overlap. */
980         oi->video_buffer_size = 1704960;
981
982         oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
983         oi->video_vbase = itv->dec_mem + oi->video_rbase;
984
985         if (!oi->video_vbase) {
986                 IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
987                      oi->video_buffer_size, oi->video_pbase);
988                 return -EIO;
989         }
990
991         IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
992                         oi->video_pbase, oi->video_vbase,
993                         oi->video_buffer_size / 1024);
994
995 #ifdef CONFIG_MTRR
996         {
997                 /* Find the largest power of two that maps the whole buffer */
998                 int size_shift = 31;
999
1000                 while (!(oi->video_buffer_size & (1 << size_shift))) {
1001                         size_shift--;
1002                 }
1003                 size_shift++;
1004                 oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
1005                 oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
1006                 oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
1007                 oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
1008                 if (mtrr_add(oi->fb_start_aligned_physaddr,
1009                         oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
1010                              MTRR_TYPE_WRCOMB, 1) < 0) {
1011                         IVTVFB_INFO("disabled mttr\n");
1012                         oi->fb_start_aligned_physaddr = 0;
1013                         oi->fb_end_aligned_physaddr = 0;
1014                 }
1015         }
1016 #endif
1017
1018         /* Blank the entire osd. */
1019         memset_io(oi->video_vbase, 0, oi->video_buffer_size);
1020
1021         return 0;
1022 }
1023
1024 /* Release any memory we've grabbed & remove mtrr entry */
1025 static void ivtvfb_release_buffers (struct ivtv *itv)
1026 {
1027         struct osd_info *oi = itv->osd_info;
1028
1029         /* Release cmap */
1030         if (oi->ivtvfb_info.cmap.len)
1031                 fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
1032
1033         /* Release pseudo palette */
1034         if (oi->ivtvfb_info.pseudo_palette)
1035                 kfree(oi->ivtvfb_info.pseudo_palette);
1036
1037 #ifdef CONFIG_MTRR
1038         if (oi->fb_end_aligned_physaddr) {
1039                 mtrr_del(-1, oi->fb_start_aligned_physaddr,
1040                         oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
1041         }
1042 #endif
1043
1044         kfree(oi);
1045         itv->osd_info = NULL;
1046 }
1047
1048 /* Initialize the specified card */
1049
1050 static int ivtvfb_init_card(struct ivtv *itv)
1051 {
1052         int rc;
1053
1054         if (itv->osd_info) {
1055                 IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
1056                 return -EBUSY;
1057         }
1058
1059         itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC);
1060         if (itv->osd_info == NULL) {
1061                 IVTVFB_ERR("Failed to allocate memory for osd_info\n");
1062                 return -ENOMEM;
1063         }
1064
1065         /* Find & setup the OSD buffer */
1066         if ((rc = ivtvfb_init_io(itv)))
1067                 return rc;
1068
1069         /* Set the startup video mode information */
1070         if ((rc = ivtvfb_init_vidmode(itv))) {
1071                 ivtvfb_release_buffers(itv);
1072                 return rc;
1073         }
1074
1075         /* Register the framebuffer */
1076         if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
1077                 ivtvfb_release_buffers(itv);
1078                 return -EINVAL;
1079         }
1080
1081         itv->osd_video_pbase = itv->osd_info->video_pbase;
1082
1083         /* Set the card to the requested mode */
1084         ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
1085
1086         /* Set color 0 to black */
1087         write_reg(0, 0x02a30);
1088         write_reg(0, 0x02a34);
1089
1090         /* Enable the osd */
1091         ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
1092
1093         /* Allocate DMA */
1094         ivtv_udma_alloc(itv);
1095         return 0;
1096
1097 }
1098
1099 static int __init ivtvfb_init(void)
1100 {
1101         struct ivtv *itv;
1102         int i, registered = 0;
1103
1104         if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
1105                 printk(KERN_ERR "ivtvfb:  ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
1106                      IVTV_MAX_CARDS - 1);
1107                 return -EINVAL;
1108         }
1109
1110         /* Locate & initialise all cards supporting an OSD. */
1111         for (i = 0; i < ivtv_cards_active; i++) {
1112                 if (ivtvfb_card_id != -1 && i != ivtvfb_card_id)
1113                         continue;
1114                 itv = ivtv_cards[i];
1115                 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
1116                         if (ivtvfb_init_card(itv) == 0) {
1117                                 IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i);
1118                                 registered++;
1119                         }
1120                 }
1121         }
1122         if (!registered) {
1123                 printk(KERN_ERR "ivtvfb:  no cards found");
1124                 return -ENODEV;
1125         }
1126         return 0;
1127 }
1128
1129 static void ivtvfb_cleanup(void)
1130 {
1131         struct ivtv *itv;
1132         int i;
1133
1134         printk(KERN_INFO "ivtvfb:  Unloading framebuffer module\n");
1135
1136         for (i = 0; i < ivtv_cards_active; i++) {
1137                 itv = ivtv_cards[i];
1138                 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) {
1139                         if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
1140                                 IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i);
1141                                 return;
1142                         }
1143                         IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);
1144                         ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
1145                         ivtvfb_release_buffers(itv);
1146                         itv->osd_video_pbase = 0;
1147                 }
1148         }
1149 }
1150
1151 module_init(ivtvfb_init);
1152 module_exit(ivtvfb_cleanup);