brintos

brintos / linux-shallow public Read only

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