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