ivtvfb.c revision 77aded6ba51f01335840ce8e18b413067810b68e
132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* 232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil On Screen Display cx23415 Framebuffer driver 332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil This module presents the cx23415 OSD (onscreen display) framebuffer memory 532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil as a standard Linux /dev/fb style framebuffer device. The framebuffer has 6be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp 732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil mode, there is a choice of a three color depths (12, 15 or 16 bits), but no 832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil local alpha. The colorspace is selectable between rgb & yuv. 932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Depending on the TV standard configured in the ivtv module at load time, 1032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp. 1132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL) 1232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil or 59.94 (NTSC) 1332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com> 1532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Derived from drivers/video/vesafb.c 1732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> 1832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 2.6 kernel port: 2032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Copyright (C) 2004 Matthias Badaire 2132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 2232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Copyright (C) 2004 Chris Kennedy <c@groovy.org> 2332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 2432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Copyright (C) 2006 Ian Armstrong <ian@iarmst.demon.co.uk> 2532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 2632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil This program is free software; you can redistribute it and/or modify 2732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil it under the terms of the GNU General Public License as published by 2832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil the Free Software Foundation; either version 2 of the License, or 2932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil (at your option) any later version. 3032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 3132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil This program is distributed in the hope that it will be useful, 3232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil but WITHOUT ANY WARRANTY; without even the implied warranty of 3332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil GNU General Public License for more details. 3532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 3632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil You should have received a copy of the GNU General Public License 3732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil along with this program; if not, write to the Free Software 3832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 3932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil */ 4032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 4132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#include <linux/module.h> 4232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#include <linux/kernel.h> 4332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#include <linux/fb.h> 440f45b8c57e40cca1778b0b75daab65ca139e5bb9Hans Verkuil#include <linux/ivtvfb.h> 4532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 4632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#ifdef CONFIG_MTRR 4732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#include <asm/mtrr.h> 4832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#endif 4932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 5032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#include "ivtv-driver.h" 5132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#include "ivtv-udma.h" 5232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#include "ivtv-mailbox.h" 5332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 5432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* card parameters */ 55641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_card_id = -1; 56641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_debug = 0; 5732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_laced; 5832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_depth; 5932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_upper; 6032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_left; 6132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_yres; 6232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_xres; 6332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 64641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilmodule_param(ivtvfb_card_id, int, 0444); 65641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilmodule_param_named(debug,ivtvfb_debug, int, 0644); 6632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_laced, bool, 0444); 6732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_depth, int, 0444); 6832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_upper, int, 0444); 6932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_left, int, 0444); 7032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_yres, int, 0444); 7132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_xres, int, 0444); 7232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 73641ed49db6ecf6c539a5eab50a7540542377add1Hans VerkuilMODULE_PARM_DESC(ivtvfb_card_id, 7432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Only use framebuffer of the specified ivtv card (0-31)\n" 7532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault -1: initialize all available framebuffers"); 7632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 7732db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(debug, 7832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Debug level (bitmask). Default: errors only\n" 7932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t(debug = 3 gives full debugging)"); 8032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Why upper, left, xres, yres, depth, laced ? To match terminology used 8232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil by fbset. 8332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */ 8432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8532db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_laced, 8632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Interlaced mode\n" 8732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t0=off\n" 8832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t1=on\n" 8932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault off"); 9032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 9132db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_depth, 92be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil "Bits per pixel - 8, 16, 32\n" 9332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 8"); 9432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 9532db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_upper, 9632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Vertical start position\n" 9732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 0 (Centered)"); 9832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 9932db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_left, 10032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Horizontal start position\n" 10132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 0 (Centered)"); 10232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 10332db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_yres, 10432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Display height\n" 10532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 480 (PAL)\n" 10632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t 400 (NTSC)"); 10732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 10832db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_xres, 10932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Display width\n" 11032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 640"); 11132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 11232db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong"); 11332db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_LICENSE("GPL"); 11432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 11532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* --------------------------------------------------------------------- */ 11632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 117641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_DBGFLG_WARN (1 << 0) 118641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_DBGFLG_INFO (1 << 1) 11932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 120641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_DEBUG(x, type, fmt, args...) \ 12132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil do { \ 122641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil if ((x) & ivtvfb_debug) \ 1237b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->num , ## args); \ 12432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } while (0) 125641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args) 126641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args) 12732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 12832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Standard kernel messages */ 129641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->num , ## args) 130641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->num , ## args) 131641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil#define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->num , ## args) 13232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 13332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* --------------------------------------------------------------------- */ 13432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 13532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_MAX_WIDTH 720 13632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_MAX_HEIGHT 576 13732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 13832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_8 0x00 13932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_16_444 0x03 14032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_16_555 0x02 14132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_16_565 0x01 14232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_32 0x04 14332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 14432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstruct osd_info { 14532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Physical base address */ 14632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long video_pbase; 14732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Relative base address (relative to start of decoder memory) */ 14832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 video_rbase; 14932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Mapped base address */ 15032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil volatile char __iomem *video_vbase; 15132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Buffer size */ 15232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 video_buffer_size; 15332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 15432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#ifdef CONFIG_MTRR 15532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* video_base rounded down as required by hardware MTRRs */ 15632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long fb_start_aligned_physaddr; 15732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* video_base rounded up as required by hardware MTRRs */ 15832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long fb_end_aligned_physaddr; 15932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#endif 16032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 16132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Store the buffer offset */ 16232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int set_osd_coords_x; 16332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int set_osd_coords_y; 16432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 16532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Current dimensions (NOT VISIBLE SIZE!) */ 16632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int display_width; 16732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int display_height; 16832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int display_byte_stride; 16932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 17032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Current bits per pixel */ 17132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int bits_per_pixel; 17232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int bytes_per_pixel; 17332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 17432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Frame buffer stuff */ 17532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_info ivtvfb_info; 17632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_var_screeninfo ivtvfb_defined; 17732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_fix_screeninfo ivtvfb_fix; 17832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil}; 17932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 18032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstruct ivtv_osd_coords { 18132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long offset; 18232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long max_offset; 18332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int pixel_stride; 18432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int lines; 18532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int x; 18632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int y; 18732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil}; 18832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 18932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* --------------------------------------------------------------------- */ 19032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 19132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* ivtv API calls for framebuffer related support */ 19232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 193641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase, 19432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 *fblength) 19532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 19632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 data[CX2341X_MBOX_MAX_DATA]; 19732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int rc; 19832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 19932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0); 20032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil *fbbase = data[0]; 20132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil *fblength = data[1]; 20232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 20332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 20432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 205641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_get_osd_coords(struct ivtv *itv, 20632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv_osd_coords *osd) 20732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 208be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 20932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 data[CX2341X_MBOX_MAX_DATA]; 21032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 21132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0); 21232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 213be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd->offset = data[0] - oi->video_rbase; 214be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd->max_offset = oi->display_width * oi->display_height * 4; 21532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->pixel_stride = data[1]; 21632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->lines = data[2]; 21732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->x = data[3]; 21832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->y = data[4]; 21932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 22032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 22132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 222641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd) 22332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 224be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 225be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 226be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_width = osd->pixel_stride; 227be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel; 228be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->set_osd_coords_x += osd->x; 229be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->set_osd_coords_y = osd->y; 23032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 23132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5, 232be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd->offset + oi->video_rbase, 23332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->pixel_stride, 23432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->lines, osd->x, osd->y); 23532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 23632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 237641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window) 23832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 23932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int osd_height_limit = itv->is_50hz ? 576 : 480; 24032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 24132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Only fail if resolution too high, otherwise fudge the start coords. */ 24232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH)) 24332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 24432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 24532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Ensure we don't exceed display limits */ 24632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_window->top + ivtv_window->height > osd_height_limit) { 247641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n", 24832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->top, ivtv_window->height); 24932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->top = osd_height_limit - ivtv_window->height; 25032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 25132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 25232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) { 253641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n", 25432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->left, ivtv_window->width); 25532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width; 25632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 25732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 25832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the OSD origin */ 25932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04); 26032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 26132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* How much to display */ 26232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08); 26332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 26432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Pass this info back the yuv handler */ 26532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_vis_w = ivtv_window->width; 26632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_vis_h = ivtv_window->height; 26732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_x_offset = ivtv_window->left; 26832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_y_offset = ivtv_window->top; 26932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 27032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 27132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 27232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 273641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, 27432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long ivtv_dest_addr, void __user *userbuf, 27532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int size_in_bytes) 27632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 27732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil DEFINE_WAIT(wait); 27832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int ret = 0; 27932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int got_sig = 0; 28032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 28132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil mutex_lock(&itv->udma.lock); 28232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Map User DMA */ 28332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) { 28432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil mutex_unlock(&itv->udma.lock); 285641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, " 28632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Error with get_user_pages: %d bytes, %d pages returned\n", 28732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_in_bytes, itv->udma.page_count); 28832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 28932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* get_user_pages must have failed completely */ 29032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EIO; 29132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 29232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 293641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n", 29432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_in_bytes, itv->udma.page_count); 29532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 29632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_udma_prepare(itv); 29732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); 29832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* if no UDMA is pending and no UDMA is in progress, then the DMA 29932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil is finished */ 30032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { 30132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* don't interrupt if the DMA is in progress but break off 30232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil a still pending DMA. */ 30332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil got_sig = signal_pending(current); 30432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) 30532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 30632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil got_sig = 0; 30732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil schedule(); 30832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 30932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil finish_wait(&itv->dma_waitq, &wait); 31032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 31132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Unmap Last DMA Xfer */ 31232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_udma_unmap(itv); 31332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil mutex_unlock(&itv->udma.lock); 31432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (got_sig) { 31532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_DEBUG_INFO("User stopped OSD\n"); 31632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINTR; 31732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 31832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 31932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return ret; 32032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 32132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 322641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuilstatic int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, 323be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil unsigned long dest_offset, int count) 32432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 32532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil DEFINE_WAIT(wait); 326aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong struct osd_info *oi = itv->osd_info; 32732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 32832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Nothing to do */ 32932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (count == 0) { 330641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n"); 33132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 33232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 33332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 33432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check Total FB Size */ 335aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong if ((dest_offset + count) > oi->video_buffer_size) { 336641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n", 337aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong dest_offset + count, oi->video_buffer_size); 33832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -E2BIG; 33932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 34032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 34132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Not fatal, but will have undesirable results */ 34232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if ((unsigned long)source & 3) 343641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n", 344be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil (unsigned long)source); 34532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 34632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (dest_offset & 3) 347641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset); 34832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 34932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (count & 3) 350641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count); 35132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 35232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check Source */ 35332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (!access_ok(VERIFY_READ, source + dest_offset, count)) { 354641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n", 35532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil (unsigned long)source); 35632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 357641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n", 35832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil dest_offset, (unsigned long)source, 35932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil count); 36032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 36132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 36232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 36332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* OSD Address to send DMA to */ 36433c0fcad2160bc211272295e862c6f708118d006Hans Verkuil dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase; 36532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 36632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Fill Buffers */ 367641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count); 36832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 36932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 37032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) 37132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 37232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil DEFINE_WAIT(wait); 37332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *)info->par; 374be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil int rc = 0; 37532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 37632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (cmd) { 37732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FBIOGET_VBLANK: { 37832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_vblank vblank; 37932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 trace; 38032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 38132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | 38232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil FB_VBLANK_HAVE_VSYNC; 383be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil trace = read_reg(0x028c0) >> 16; 38432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv->is_50hz && trace > 312) trace -= 312; 38532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (itv->is_60hz && trace > 262) trace -= 262; 38632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING; 387a158f3559334c6314c7876390caffe88c9fdb64dHans Verkuil vblank.count = itv->last_vsync_field; 38832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vblank.vcount = trace; 38932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vblank.hcount = 0; 39032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank))) 39132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EFAULT; 39232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 39332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 39432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 395be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case FBIO_WAITFORVSYNC: 39632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); 39784149a0f70a73385ee7fbb77024544cbed4fe16dHans Verkuil if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT; 398be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil finish_wait(&itv->vsync_waitq, &wait); 39932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 40032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 401d715e766ddf4786a06abe6a841e956ad8a875963Hans Verkuil case IVTVFB_IOC_DMA_FRAME: { 402d715e766ddf4786a06abe6a841e956ad8a875963Hans Verkuil struct ivtvfb_dma_frame args; 40332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 404641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n"); 40532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (copy_from_user(&args, (void __user *)arg, sizeof(args))) 40632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EFAULT; 40732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 408641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count); 40932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 41032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 41132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 412641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd); 41332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 41432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 41532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 41632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 41732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 41832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Framebuffer device handling */ 41932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 42032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) 42132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 422aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong struct osd_info *oi = itv->osd_info; 42332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv_osd_coords ivtv_osd; 42432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct v4l2_rect ivtv_window; 425aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong int osd_mode = -1; 42632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 427641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("ivtvfb_set_var\n"); 42832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 42932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Select color space */ 43032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->nonstd) /* YUV */ 431be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00); 43232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else /* RGB */ 433be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00); 43432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 435aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong /* Set the color mode */ 43632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->bits_per_pixel) { 43732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 8: 438aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_8; 43932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 44032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 32: 441aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_32; 44232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 44332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 16: 44432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->green.length) { 44532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 4: 446aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_16_444; 44732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 44832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 5: 449aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_16_555; 45032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 45132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 6: 452aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_16_565; 45332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 45432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 455641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); 45632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 45732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 45832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 459641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); 46032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 46132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 4626659e3ed559db2e730947268f9d57869b7a9016cIan Armstrong /* Set video mode. Although rare, the display can become scrambled even 4636659e3ed559db2e730947268f9d57869b7a9016cIan Armstrong if we don't change mode. Always 'bounce' to osd_mode via mode 0 */ 4646659e3ed559db2e730947268f9d57869b7a9016cIan Armstrong if (osd_mode != -1) { 465aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0); 466aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode); 467aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong } 468aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong 469aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong oi->bits_per_pixel = var->bits_per_pixel; 470aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong oi->bytes_per_pixel = var->bits_per_pixel / 8; 47132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 47232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the flicker filter */ 47332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->vmode & FB_VMODE_MASK) { 47432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_VMODE_NONINTERLACED: /* Filter on */ 47532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1); 47632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 47732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_VMODE_INTERLACED: /* Filter off */ 47832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0); 47932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 48032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 481641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n"); 48232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 48332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 48432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Read the current osd info */ 485641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil ivtvfb_get_osd_coords(itv, &ivtv_osd); 48632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 48732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Now set the OSD to the size we want */ 48832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.pixel_stride = var->xres_virtual; 48932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.lines = var->yres_virtual; 49032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.x = 0; 49132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.y = 0; 492641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil ivtvfb_set_osd_coords(itv, &ivtv_osd); 49332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 49432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Can't seem to find the right API combo for this. 49532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Use another function which does what we need through direct register access. */ 49632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.width = var->xres; 49732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.height = var->yres; 49832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 49932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Minimum margin cannot be 0, as X won't allow such a mode */ 500be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!var->upper_margin) var->upper_margin++; 501be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!var->left_margin) var->left_margin++; 50232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.top = var->upper_margin - 1; 50332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.left = var->left_margin - 1; 50432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 505641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil ivtvfb_set_display_window(itv, &ivtv_window); 50632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 50777aded6ba51f01335840ce8e18b413067810b68eIan Armstrong /* Pass screen size back to yuv handler */ 50877aded6ba51f01335840ce8e18b413067810b68eIan Armstrong itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride; 50977aded6ba51f01335840ce8e18b413067810b68eIan Armstrong itv->yuv_info.osd_full_h = ivtv_osd.lines; 51077aded6ba51f01335840ce8e18b413067810b68eIan Armstrong 51132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Force update of yuv registers */ 51232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.yuv_forced_update = 1; 51332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 514641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", 515be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres, var->yres, 516be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres_virtual, var->yres_virtual, 517be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->bits_per_pixel); 51832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 519641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Display position: %d, %d\n", 520be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->left_margin, var->upper_margin); 52132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 522641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Display filter: %s\n", 523be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); 524641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); 52532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 52632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 52732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 52832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 52932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix) 53032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 531be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 532be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 533641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n"); 53432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 53532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil strcpy(fix->id, "cx23415 TV out"); 536be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->smem_start = oi->video_pbase; 537be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->smem_len = oi->video_buffer_size; 53832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->type = FB_TYPE_PACKED_PIXELS; 539be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 54032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->xpanstep = 1; 54132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->ypanstep = 1; 54232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->ywrapstep = 0; 543be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->line_length = oi->display_byte_stride; 54432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->accel = FB_ACCEL_NONE; 54532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 54632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 54732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 54832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Check the requested display mode, returning -EINVAL if we can't 54932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil handle it. */ 55032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 55132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) 55232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 553be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 55468a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong int osd_height_limit; 55568a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong u32 pixclock, hlimit, vlimit; 55632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 557641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); 55832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 55968a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong /* Set base references for mode calcs. */ 56068a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong if (itv->is_50hz) { 56168a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong pixclock = 84316; 56268a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong hlimit = 776; 56368a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong vlimit = 591; 56468a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong osd_height_limit = 576; 56568a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong } 56668a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong else { 56768a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong pixclock = 83926; 56868a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong hlimit = 776; 56968a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong vlimit = 495; 57068a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong osd_height_limit = 480; 57168a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong } 57268a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong 57332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) { 57432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->transp.offset = 24; 57532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->transp.length = 8; 57632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 16; 57732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 8; 57832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 8; 57932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 8; 58032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 58132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 8; 58232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 58332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (var->bits_per_pixel == 16) { 58432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* To find out the true mode, check green length */ 58532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->green.length) { 58632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 4: 58732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 8; 58832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 4; 58932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 4; 59032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 4; 59132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 59232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 4; 593459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.offset = 12; 594459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.length = 1; 59532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 59632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 5: 59732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 10; 59832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 5; 59932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 5; 60032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 5; 60132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 60232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 5; 603459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.offset = 15; 604459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.length = 1; 60532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 60632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 60732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 11; 60832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 5; 60932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 5; 61032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 6; 61132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 61232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 5; 613459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.offset = 0; 614459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.length = 0; 61532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 61632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 61732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 61832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else { 619641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel); 62032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 62132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 62232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 62332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check the resolution */ 6246b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) { 6256b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n", 6266b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong var->xres, var->yres); 6276b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong return -EINVAL; 62832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 62932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 6306b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */ 6316b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) || 6326b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size || 6336b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong var->xres_virtual < var->xres || 6346b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong var->yres_virtual < var->yres) { 6356b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n", 6366b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong var->xres_virtual, var->yres_virtual); 6376b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong return -EINVAL; 63832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 63932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 64032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Some extra checks if in 8 bit mode */ 64132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->bits_per_pixel == 8) { 64232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Width must be a multiple of 4 */ 64332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres & 3) { 644641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres); 64532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 64632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 64732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres_virtual & 3) { 648641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual); 64932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 65032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 65132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 65232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (var->bits_per_pixel == 16) { 65332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Width must be a multiple of 2 */ 65432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres & 1) { 655641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres); 65632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 65732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 65832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres_virtual & 1) { 659641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual); 66032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 66132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 66232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 66332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 66432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Now check the offsets */ 66532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) { 666641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n", 667be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual); 66832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 66932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 67032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 67132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check pixel format */ 67232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->nonstd > 1) { 673641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd); 67432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 67532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 67632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 67732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check video mode */ 67832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) && 67932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) { 680641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK); 68132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 68232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 68332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 68432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check the left & upper margins 68532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil If the margins are too large, just center the screen 68632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil (enforcing margins causes too many problems) */ 68732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 68832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) { 68932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2); 69032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 69132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) { 69232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2); 69332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 69432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 69532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Maintain overall 'size' for a constant refresh rate */ 69668a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->right_margin = hlimit - var->left_margin - var->xres; 69768a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->lower_margin = vlimit - var->upper_margin - var->yres; 69832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 69932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Fixed sync times */ 70032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->hsync_len = 24; 70132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->vsync_len = 2; 70232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 70332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Non-interlaced / interlaced mode is used to switch the OSD filter 70432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil on or off. Adjust the clock timings to maintain a constant 70532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vertical refresh rate. */ 70632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) 70768a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->pixclock = pixclock / 2; 70868a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong else 70968a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->pixclock = pixclock; 71032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 711641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", 712be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres, var->yres, 713be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres_virtual, var->yres_virtual, 71432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->bits_per_pixel); 71532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 716641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Display position: %d, %d\n", 717be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->left_margin, var->upper_margin); 71832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 719641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Display filter: %s\n", 720be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); 721641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); 72232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 72332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 72432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 72532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 72632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 72732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *) info->par; 728641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); 729be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil return _ivtvfb_check_var(var, itv); 73032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 73132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 73232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 73332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 73432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 osd_pan_index; 73532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *) info->par; 73632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 73732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8; 738be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil write_reg(osd_pan_index, 0x02A0C); 73932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 74032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Pass this info back the yuv handler */ 74132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_x_pan = var->xoffset; 74232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_y_pan = var->yoffset; 74332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Force update of yuv registers */ 74432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.yuv_forced_update = 1; 74532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 74632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 74732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 74832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_set_par(struct fb_info *info) 74932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 75032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int rc = 0; 75132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *) info->par; 75232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 753641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("ivtvfb_set_par\n"); 75432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 75532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil rc = ivtvfb_set_var(itv, &info->var); 75632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_pan_display(&info->var, info); 757be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ivtvfb_get_fix(itv, &info->fix); 75832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 75932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 76032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 76132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green, 76232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned blue, unsigned transp, 76332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_info *info) 76432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 76532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 color, *palette; 766be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct ivtv *itv = (struct ivtv *)info->par; 76732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 76832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (regno >= info->cmap.len) 76932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 77032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 77132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); 77232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (info->var.bits_per_pixel <= 8) { 77332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(regno, 0x02a30); 77432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(color, 0x02a34); 775be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil return 0; 77632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 777be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (regno >= 16) 778be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil return -EINVAL; 77932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 780be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil palette = info->pseudo_palette; 781be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (info->var.bits_per_pixel == 16) { 782be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil switch (info->var.green.length) { 783be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case 4: 784be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil color = ((red & 0xf000) >> 4) | 785be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((green & 0xf000) >> 8) | 786be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((blue & 0xf000) >> 12); 787be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil break; 788be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case 5: 789be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil color = ((red & 0xf800) >> 1) | 790be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((green & 0xf800) >> 6) | 791be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((blue & 0xf800) >> 11); 792be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil break; 793be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case 6: 794be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil color = (red & 0xf800 ) | 795be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((green & 0xfc00) >> 5) | 796be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((blue & 0xf800) >> 11); 797be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil break; 79832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 79932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 800be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil palette[regno] = color; 80132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 80232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 80332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 80432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* We don't really support blanking. All this does is enable or 80532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil disable the OSD. */ 80632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_blank(int blank_mode, struct fb_info *info) 80732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 80832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *)info->par; 80932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 810641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode); 81132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (blank_mode) { 81232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_UNBLANK: 81332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1); 81432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 81532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_NORMAL: 81632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_HSYNC_SUSPEND: 81732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_VSYNC_SUSPEND: 81832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_POWERDOWN: 81932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); 82032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 82132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 82232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 82332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 82432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 82532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic struct fb_ops ivtvfb_ops = { 82632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .owner = THIS_MODULE, 82732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_check_var = ivtvfb_check_var, 82832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_set_par = ivtvfb_set_par, 82932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_setcolreg = ivtvfb_setcolreg, 83032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_fillrect = cfb_fillrect, 83132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_copyarea = cfb_copyarea, 83232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_imageblit = cfb_imageblit, 83332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_cursor = NULL, 83432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_ioctl = ivtvfb_ioctl, 83532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_pan_display = ivtvfb_pan_display, 83632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_blank = ivtvfb_blank, 83732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil}; 83832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 83932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Initialization */ 84032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 84132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 84232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Setup our initial video mode */ 84332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_init_vidmode(struct ivtv *itv) 84432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 845be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 84632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct v4l2_rect start_window; 847be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil int max_height; 84832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 84932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Color mode */ 85032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8516b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32) 8526b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong osd_depth = 8; 853be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->bits_per_pixel = osd_depth; 854be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->bytes_per_pixel = oi->bits_per_pixel / 8; 85532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 85632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Horizontal size & position */ 85732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8586b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong if (osd_xres > 720) 8596b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong osd_xres = 720; 86032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 86132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */ 86232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_depth == 8) 86332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_xres &= ~3; 86432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (osd_depth == 16) 86532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_xres &= ~1; 86632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8676b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong start_window.width = osd_xres ? osd_xres : 640; 86832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 86932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check horizontal start (osd_left). */ 87032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_left && osd_left + start_window.width > 721) { 871641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("Invalid osd_left - assuming default\n"); 87232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_left = 0; 87332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 87432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 87532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Hardware coords start at 0, user coords start at 1. */ 876be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd_left--; 87732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 878be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); 87932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 880be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_byte_stride = 881be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil start_window.width * oi->bytes_per_pixel; 88232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 88332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Vertical size & position */ 88432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 88532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil max_height = itv->is_50hz ? 576 : 480; 88632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 887be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (osd_yres > max_height) 888be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd_yres = max_height; 88932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8906b1ec9da152c03106aa92fa045f5cf9b7912597cIan Armstrong start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400; 89132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 89232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check vertical start (osd_upper). */ 89332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_upper + start_window.height > max_height + 1) { 894641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("Invalid osd_upper - assuming default\n"); 89532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_upper = 0; 89632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 89732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 89832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Hardware coords start at 0, user coords start at 1. */ 899be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd_upper--; 90032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 90132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2); 90232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 903be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_width = start_window.width; 904be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_height = start_window.height; 90532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 90632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Generate a valid fb_var_screeninfo */ 90732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 908be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.xres = oi->display_width; 909be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.yres = oi->display_height; 910be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.xres_virtual = oi->display_width; 911be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.yres_virtual = oi->display_height; 912be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel; 913be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED); 914be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.left_margin = start_window.left + 1; 915be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.upper_margin = start_window.top + 1; 916be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE; 917be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.nonstd = 0; 91832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 91932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* We've filled in the most data, let the usual mode check 92032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil routine fill in the rest. */ 921be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil _ivtvfb_check_var(&oi->ivtvfb_defined, itv); 92232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 92332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Generate valid fb_fix_screeninfo */ 92432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 925be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ivtvfb_get_fix(itv, &oi->ivtvfb_fix); 92632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 92732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Generate valid fb_info */ 92832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 929be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.node = -1; 930be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT; 931be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.fbops = &ivtvfb_ops; 932be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.par = itv; 933be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.var = oi->ivtvfb_defined; 934be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.fix = oi->ivtvfb_fix; 935be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase; 936be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.fbops = &ivtvfb_ops; 93732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 93832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Supply some monitor specs. Bogus values will do for now */ 939be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.hfmin = 8000; 940be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.hfmax = 70000; 941be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.vfmin = 10; 942be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.vfmax = 100; 94332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 94432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Allocate color map */ 945be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) { 946641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("abort, unable to alloc cmap\n"); 94732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENOMEM; 94832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 94932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 95032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Allocate the pseudo palette */ 951be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); 95232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 953be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!oi->ivtvfb_info.pseudo_palette) { 954641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("abort, unable to alloc pseudo pallete\n"); 95532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENOMEM; 95632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 95732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 95832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 95932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 96032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 96132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */ 96232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 96332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_init_io(struct ivtv *itv) 96432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 965be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 966be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 96726e9d599561e9a964bd4d7c2be0029db8aaff852Hans Verkuil mutex_lock(&itv->serialize_lock); 9686e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil if (ivtv_init_on_first_open(itv)) { 96926e9d599561e9a964bd4d7c2be0029db8aaff852Hans Verkuil mutex_unlock(&itv->serialize_lock); 970641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("Failed to initialize ivtv\n"); 9716e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil return -ENXIO; 9726e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil } 97326e9d599561e9a964bd4d7c2be0029db8aaff852Hans Verkuil mutex_unlock(&itv->serialize_lock); 9746e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil 975641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size); 97632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 97732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* The osd buffer size depends on the number of video buffers allocated 97832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil on the PVR350 itself. For now we'll hardcode the smallest osd buffer 97932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size to prevent any overlap. */ 980be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_buffer_size = 1704960; 98132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 982be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase; 983be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_vbase = itv->dec_mem + oi->video_rbase; 98432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 985be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!oi->video_vbase) { 986641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n", 987be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_buffer_size, oi->video_pbase); 98832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EIO; 98932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 99032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 991641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", 992be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_pbase, oi->video_vbase, 993be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_buffer_size / 1024); 99432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 99532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#ifdef CONFIG_MTRR 99632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil { 99732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Find the largest power of two that maps the whole buffer */ 99832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int size_shift = 31; 99932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1000be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil while (!(oi->video_buffer_size & (1 << size_shift))) { 100132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_shift--; 100232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 100332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_shift++; 1004be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1); 1005be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size; 1006be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr += (1 << size_shift) - 1; 1007be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1); 1008be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (mtrr_add(oi->fb_start_aligned_physaddr, 1009be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr, 101032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil MTRR_TYPE_WRCOMB, 1) < 0) { 1011641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_INFO("disabled mttr\n"); 1012be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_start_aligned_physaddr = 0; 1013be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr = 0; 101432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 101532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 1016be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil#endif 101732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 101832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Blank the entire osd. */ 1019be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil memset_io(oi->video_vbase, 0, oi->video_buffer_size); 102032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 102132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 102232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 102332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 102432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Release any memory we've grabbed & remove mtrr entry */ 102532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic void ivtvfb_release_buffers (struct ivtv *itv) 102632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 1027be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 1028be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 102932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Release cmap */ 1030136280322d894e6ec07187f2427b00c3d64ad066Adrian Bunk if (oi->ivtvfb_info.cmap.len) 1031136280322d894e6ec07187f2427b00c3d64ad066Adrian Bunk fb_dealloc_cmap(&oi->ivtvfb_info.cmap); 103232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 103332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Release pseudo palette */ 1034be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (oi->ivtvfb_info.pseudo_palette) 1035be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil kfree(oi->ivtvfb_info.pseudo_palette); 103632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 103732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#ifdef CONFIG_MTRR 1038be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (oi->fb_end_aligned_physaddr) { 1039be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil mtrr_del(-1, oi->fb_start_aligned_physaddr, 1040be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr); 1041be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil } 1042be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil#endif 104332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1044be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil kfree(oi); 104532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_info = NULL; 104632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 104732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 104832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Initialize the specified card */ 104932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1050be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuilstatic int ivtvfb_init_card(struct ivtv *itv) 105132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 105232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int rc; 105332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 105432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv->osd_info) { 1055641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id); 105632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EBUSY; 105732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 105832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 105932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC); 106032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv->osd_info == 0) { 1061641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_ERR("Failed to allocate memory for osd_info\n"); 106232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENOMEM; 106332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 106432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 106532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Find & setup the OSD buffer */ 1066be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if ((rc = ivtvfb_init_io(itv))) 106732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 106832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 106932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the startup video mode information */ 1070be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if ((rc = ivtvfb_init_vidmode(itv))) { 107132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_release_buffers(itv); 107232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 107332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 107432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 107532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Register the framebuffer */ 107632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) { 107732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_release_buffers(itv); 107832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 107932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 108032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 108132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_video_pbase = itv->osd_info->video_pbase; 108232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 108332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the card to the requested mode */ 108432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_set_par(&itv->osd_info->ivtvfb_info); 108532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 108632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set color 0 to black */ 108732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(0, 0x02a30); 108832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(0, 0x02a34); 108932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 109032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Enable the osd */ 109132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); 109232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 109332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Allocate DMA */ 109432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_udma_alloc(itv); 109532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 109632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 109732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 109832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 109932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int __init ivtvfb_init(void) 110032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 110132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv; 110232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int i, registered = 0; 110332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1104641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { 1105641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", 110632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_MAX_CARDS - 1); 110732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 110832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 110932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 111032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Locate & initialise all cards supporting an OSD. */ 111132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil for (i = 0; i < ivtv_cards_active; i++) { 1112641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil if (ivtvfb_card_id != -1 && i != ivtvfb_card_id) 111332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil continue; 111432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv = ivtv_cards[i]; 111532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { 111632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtvfb_init_card(itv) == 0) { 1117641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i); 111832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil registered++; 111932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 112032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 112132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 112232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (!registered) { 11237b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil printk(KERN_ERR "ivtvfb: no cards found"); 112432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENODEV; 112532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 112632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 112732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 112832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 112932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic void ivtvfb_cleanup(void) 113032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 113132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv; 113232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int i; 113332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 11347b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n"); 113532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 113632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil for (i = 0; i < ivtv_cards_active; i++) { 113732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv = ivtv_cards[i]; 113832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) { 1139d343d7f9792ac1790757cb35a419b8b0b5210917Hans Verkuil if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { 1140d343d7f9792ac1790757cb35a419b8b0b5210917Hans Verkuil IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i); 1141d343d7f9792ac1790757cb35a419b8b0b5210917Hans Verkuil return; 1142d343d7f9792ac1790757cb35a419b8b0b5210917Hans Verkuil } 1143641ed49db6ecf6c539a5eab50a7540542377add1Hans Verkuil IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i); 114432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); 114532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_release_buffers(itv); 114632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_video_pbase = 0; 114732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 114832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 114932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 115032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 115132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_init(ivtvfb_init); 115232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_exit(ivtvfb_cleanup); 1153