ivtvfb.c revision 7b3a0d49e3e929b810ade38926342faca53e867d
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 */ 5532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtv_fb_card_id = -1; 5632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtv_fb_debug = 0; 5732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_laced; 5832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_compat; 5932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_depth; 6032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_upper; 6132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_left; 6232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_yres; 6332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int osd_xres; 6432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 6532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(ivtv_fb_card_id, int, 0444); 6632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param_named(debug,ivtv_fb_debug, int, 0644); 6732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_laced, bool, 0444); 6832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_compat, bool, 0444); 6932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_depth, int, 0444); 7032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_upper, int, 0444); 7132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_left, int, 0444); 7232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_yres, int, 0444); 7332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_param(osd_xres, int, 0444); 7432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 7532db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(ivtv_fb_card_id, 7632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Only use framebuffer of the specified ivtv card (0-31)\n" 7732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault -1: initialize all available framebuffers"); 7832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 7932db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(debug, 8032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Debug level (bitmask). Default: errors only\n" 8132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t(debug = 3 gives full debugging)"); 8232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8332db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_compat, 8432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Compatibility mode - Display size is locked (use for old X drivers)\n" 8532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t0=off\n" 8632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t1=on\n" 8732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault off"); 8832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 8932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Why upper, left, xres, yres, depth, laced ? To match terminology used 9032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil by fbset. 9132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */ 9232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 9332db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_laced, 9432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Interlaced mode\n" 9532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t0=off\n" 9632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t1=on\n" 9732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault off"); 9832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 9932db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_depth, 100be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil "Bits per pixel - 8, 16, 32\n" 10132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 8"); 10232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 10332db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_upper, 10432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Vertical start position\n" 10532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 0 (Centered)"); 10632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 10732db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_left, 10832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Horizontal start position\n" 10932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 0 (Centered)"); 11032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 11132db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_yres, 11232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Display height\n" 11332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 480 (PAL)\n" 11432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\t 400 (NTSC)"); 11532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 11632db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_PARM_DESC(osd_xres, 11732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Display width\n" 11832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "\t\t\tdefault 640"); 11932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 12032db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong"); 12132db775452818656d5fd8fd8b0f54425f5cfc177Hans VerkuilMODULE_LICENSE("GPL"); 12232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 12332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* --------------------------------------------------------------------- */ 12432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 12532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_FB_DBGFLG_WARN (1 << 0) 12632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_FB_DBGFLG_INFO (1 << 1) 12732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 12832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_FB_DEBUG(x, type, fmt, args...) \ 12932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil do { \ 13032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if ((x) & ivtv_fb_debug) \ 1317b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->num , ## args); \ 13232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } while (0) 13332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_FB_DEBUG_WARN(fmt, args...) IVTV_FB_DEBUG(IVTV_FB_DBGFLG_WARN, "warning", fmt , ## args) 13432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_FB_DEBUG_INFO(fmt, args...) IVTV_FB_DEBUG(IVTV_FB_DBGFLG_INFO, "info", fmt , ## args) 13532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 13632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Standard kernel messages */ 1377b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil#define IVTV_FB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->num , ## args) 1387b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil#define IVTV_FB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->num , ## args) 1397b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil#define IVTV_FB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->num , ## args) 14032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 14132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* --------------------------------------------------------------------- */ 14232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 14332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_MAX_WIDTH 720 14432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_MAX_HEIGHT 576 14532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 14632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_8 0x00 14732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_16_444 0x03 14832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_16_555 0x02 14932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_16_565 0x01 15032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#define IVTV_OSD_BPP_32 0x04 15132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 15232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstruct osd_info { 15332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Physical base address */ 15432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long video_pbase; 15532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Relative base address (relative to start of decoder memory) */ 15632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 video_rbase; 15732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Mapped base address */ 15832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil volatile char __iomem *video_vbase; 15932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Buffer size */ 16032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 video_buffer_size; 16132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 16232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#ifdef CONFIG_MTRR 16332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* video_base rounded down as required by hardware MTRRs */ 16432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long fb_start_aligned_physaddr; 16532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* video_base rounded up as required by hardware MTRRs */ 16632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long fb_end_aligned_physaddr; 16732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#endif 16832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 169aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong /* Current osd mode */ 170aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong int osd_mode; 171aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong 17232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Store the buffer offset */ 17332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int set_osd_coords_x; 17432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int set_osd_coords_y; 17532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 17632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Current dimensions (NOT VISIBLE SIZE!) */ 17732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int display_width; 17832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int display_height; 17932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int display_byte_stride; 18032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 18132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Current bits per pixel */ 18232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int bits_per_pixel; 18332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int bytes_per_pixel; 18432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 18532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Frame buffer stuff */ 18632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_info ivtvfb_info; 18732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_var_screeninfo ivtvfb_defined; 18832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_fix_screeninfo ivtvfb_fix; 18932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil}; 19032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 19132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstruct ivtv_osd_coords { 19232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long offset; 19332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long max_offset; 19432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int pixel_stride; 19532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int lines; 19632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int x; 19732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int y; 19832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil}; 19932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 20032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* --------------------------------------------------------------------- */ 20132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 20232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* ivtv API calls for framebuffer related support */ 20332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 20432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtv_fb_get_framebuffer(struct ivtv *itv, u32 *fbbase, 20532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 *fblength) 20632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 20732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 data[CX2341X_MBOX_MAX_DATA]; 20832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int rc; 20932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 21032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0); 21132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil *fbbase = data[0]; 21232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil *fblength = data[1]; 21332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 21432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 21532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 21632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtv_fb_get_osd_coords(struct ivtv *itv, 21732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv_osd_coords *osd) 21832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 219be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 22032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 data[CX2341X_MBOX_MAX_DATA]; 22132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 22232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0); 22332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 224be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd->offset = data[0] - oi->video_rbase; 225be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd->max_offset = oi->display_width * oi->display_height * 4; 22632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->pixel_stride = data[1]; 22732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->lines = data[2]; 22832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->x = data[3]; 22932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->y = data[4]; 23032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 23132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 23232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 23332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtv_fb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd) 23432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 235be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 236be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 237be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_width = osd->pixel_stride; 238be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel; 239be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->set_osd_coords_x += osd->x; 240be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->set_osd_coords_y = osd->y; 24132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 24232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5, 243be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd->offset + oi->video_rbase, 24432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->pixel_stride, 24532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd->lines, osd->x, osd->y); 24632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 24732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 24832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtv_fb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window) 24932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 25032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int osd_height_limit = itv->is_50hz ? 576 : 480; 25132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 25232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Only fail if resolution too high, otherwise fudge the start coords. */ 25332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH)) 25432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 25532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 25632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Ensure we don't exceed display limits */ 25732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_window->top + ivtv_window->height > osd_height_limit) { 258be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n", 25932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->top, ivtv_window->height); 26032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->top = osd_height_limit - ivtv_window->height; 26132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 26232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 26332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) { 264be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n", 26532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->left, ivtv_window->width); 26632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width; 26732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 26832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 26932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the OSD origin */ 27032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04); 27132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 27232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* How much to display */ 27332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08); 27432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 27532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Pass this info back the yuv handler */ 27632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_vis_w = ivtv_window->width; 27732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_vis_h = ivtv_window->height; 27832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_x_offset = ivtv_window->left; 27932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_y_offset = ivtv_window->top; 28032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 28132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 28232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 28332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 28432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtv_fb_prep_dec_dma_to_device(struct ivtv *itv, 28532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned long ivtv_dest_addr, void __user *userbuf, 28632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int size_in_bytes) 28732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 28832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil DEFINE_WAIT(wait); 28932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int ret = 0; 29032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int got_sig = 0; 29132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 29232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil mutex_lock(&itv->udma.lock); 29332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Map User DMA */ 29432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) { 29532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil mutex_unlock(&itv->udma.lock); 29632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_WARN("ivtvfb_prep_dec_dma_to_device, " 29732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil "Error with get_user_pages: %d bytes, %d pages returned\n", 29832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_in_bytes, itv->udma.page_count); 29932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 30032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* get_user_pages must have failed completely */ 30132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EIO; 30232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 30332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 30432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n", 30532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_in_bytes, itv->udma.page_count); 30632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 30732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_udma_prepare(itv); 30832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); 30932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* if no UDMA is pending and no UDMA is in progress, then the DMA 31032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil is finished */ 31132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { 31232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* don't interrupt if the DMA is in progress but break off 31332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil a still pending DMA. */ 31432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil got_sig = signal_pending(current); 31532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) 31632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 31732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil got_sig = 0; 31832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil schedule(); 31932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 32032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil finish_wait(&itv->dma_waitq, &wait); 32132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 32232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Unmap Last DMA Xfer */ 32332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_udma_unmap(itv); 32432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil mutex_unlock(&itv->udma.lock); 32532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (got_sig) { 32632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_DEBUG_INFO("User stopped OSD\n"); 32732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINTR; 32832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 32932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 33032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return ret; 33132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 33232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 333be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuilstatic int ivtv_fb_prep_frame(struct ivtv *itv, int cmd, void __user *source, 334be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil unsigned long dest_offset, int count) 33532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 33632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil DEFINE_WAIT(wait); 337aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong struct osd_info *oi = itv->osd_info; 33832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 33932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Nothing to do */ 34032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (count == 0) { 34132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_DEBUG_WARN("ivtv_fb_prep_frame: Nothing to do. count = 0\n"); 34232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 34332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 34432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 34532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check Total FB Size */ 346aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong if ((dest_offset + count) > oi->video_buffer_size) { 347be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_WARN("ivtv_fb_prep_frame: Overflowing the framebuffer %ld, only %d available\n", 348aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong dest_offset + count, oi->video_buffer_size); 34932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -E2BIG; 35032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 35132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 35232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Not fatal, but will have undesirable results */ 35332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if ((unsigned long)source & 3) 354be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_WARN("ivtv_fb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n", 355be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil (unsigned long)source); 35632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 35732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (dest_offset & 3) 358be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_WARN("ivtv_fb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset); 35932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 36032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (count & 3) 361be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_WARN("ivtv_fb_prep_frame: Count not a multiple of 4 (%d)\n", count); 36232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 36332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check Source */ 36432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (!access_ok(VERIFY_READ, source + dest_offset, count)) { 365be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_WARN("Invalid userspace pointer 0x%08lx\n", 36632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil (unsigned long)source); 36732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 368be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n", 36932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil dest_offset, (unsigned long)source, 37032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil count); 37132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 37232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 37332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 37432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* OSD Address to send DMA to */ 37533c0fcad2160bc211272295e862c6f708118d006Hans Verkuil dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase; 37632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 37732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Fill Buffers */ 37832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return ivtv_fb_prep_dec_dma_to_device(itv, dest_offset, source, count); 37932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 38032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 38132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) 38232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 38332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil DEFINE_WAIT(wait); 38432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *)info->par; 385be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil int rc = 0; 38632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 38732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (cmd) { 38832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FBIOGET_VBLANK: { 38932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_vblank vblank; 39032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 trace; 39132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 39232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | 39332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil FB_VBLANK_HAVE_VSYNC; 394be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil trace = read_reg(0x028c0) >> 16; 39532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv->is_50hz && trace > 312) trace -= 312; 39632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (itv->is_60hz && trace > 262) trace -= 262; 39732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING; 398a158f3559334c6314c7876390caffe88c9fdb64dHans Verkuil vblank.count = itv->last_vsync_field; 39932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vblank.vcount = trace; 40032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vblank.hcount = 0; 40132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank))) 40232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EFAULT; 40332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 40432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 40532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 406be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case FBIO_WAITFORVSYNC: 40732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); 40884149a0f70a73385ee7fbb77024544cbed4fe16dHans Verkuil if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT; 409be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil finish_wait(&itv->vsync_waitq, &wait); 41032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 41132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 412d715e766ddf4786a06abe6a841e956ad8a875963Hans Verkuil case IVTVFB_IOC_DMA_FRAME: { 413d715e766ddf4786a06abe6a841e956ad8a875963Hans Verkuil struct ivtvfb_dma_frame args; 41432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 415d715e766ddf4786a06abe6a841e956ad8a875963Hans Verkuil IVTV_FB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n"); 41632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (copy_from_user(&args, (void __user *)arg, sizeof(args))) 41732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EFAULT; 41832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 41932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return ivtv_fb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count); 42032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 42132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 42232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 423c6f95d16e0da4d909afc787a3a3dfc504be12177Hans Verkuil IVTV_FB_DEBUG_INFO("Unknown ioctl %08x\n", cmd); 42432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 42532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 42632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 42732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 42832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 42932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Framebuffer device handling */ 43032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 43132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) 43232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 433aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong struct osd_info *oi = itv->osd_info; 43432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv_osd_coords ivtv_osd; 43532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct v4l2_rect ivtv_window; 436aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong int osd_mode = -1; 43732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 43832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_DEBUG_INFO("ivtvfb_set_var\n"); 43932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 44032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Select color space */ 44132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->nonstd) /* YUV */ 442be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00); 44332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else /* RGB */ 444be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00); 44532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 446aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong /* Set the color mode */ 44732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->bits_per_pixel) { 44832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 8: 449aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_8; 45032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 45132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 32: 452aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_32; 45332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 45432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 16: 45532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->green.length) { 45632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 4: 457aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_16_444; 45832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 45932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 5: 460aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_16_555; 46132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 46232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 6: 463aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong osd_mode = IVTV_OSD_BPP_16_565; 46432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 46532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 46632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); 46732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 46832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 46932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 47032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); 47132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 47232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 473aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong /* Change osd mode if needed. 474aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong Although rare, things can go wrong. The extra mode 475aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong change seems to help... */ 476aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong if (osd_mode != -1 && osd_mode != oi->osd_mode) { 477aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0); 478aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode); 479aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong oi->osd_mode = osd_mode; 480aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong } 481aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong 482aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong oi->bits_per_pixel = var->bits_per_pixel; 483aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong oi->bytes_per_pixel = var->bits_per_pixel / 8; 48432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 48532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the flicker filter */ 48632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->vmode & FB_VMODE_MASK) { 48732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_VMODE_NONINTERLACED: /* Filter on */ 48832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1); 48932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 49032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_VMODE_INTERLACED: /* Filter off */ 49132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0); 49232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 49332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 49432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n"); 49532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 49632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 49732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Read the current osd info */ 49832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_fb_get_osd_coords(itv, &ivtv_osd); 49932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 50032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Now set the OSD to the size we want */ 50132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.pixel_stride = var->xres_virtual; 50232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.lines = var->yres_virtual; 50332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.x = 0; 50432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_osd.y = 0; 50532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_fb_set_osd_coords(itv, &ivtv_osd); 50632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 50732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Can't seem to find the right API combo for this. 50832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil Use another function which does what we need through direct register access. */ 50932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.width = var->xres; 51032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.height = var->yres; 51132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 51232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Minimum margin cannot be 0, as X won't allow such a mode */ 513be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!var->upper_margin) var->upper_margin++; 514be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!var->left_margin) var->left_margin++; 51532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.top = var->upper_margin - 1; 51632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_window.left = var->left_margin - 1; 51732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 51832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_fb_set_display_window(itv, &ivtv_window); 51932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 52032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Force update of yuv registers */ 52132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.yuv_forced_update = 1; 52232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 523be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", 524be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres, var->yres, 525be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres_virtual, var->yres_virtual, 526be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->bits_per_pixel); 52732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 528be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Display position: %d, %d\n", 529be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->left_margin, var->upper_margin); 53032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 531be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Display filter: %s\n", 532be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); 533be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); 53432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 53532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 53632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 53732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 53832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix) 53932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 540be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 541be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 542be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("ivtvfb_get_fix\n"); 54332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 54432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil strcpy(fix->id, "cx23415 TV out"); 545be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->smem_start = oi->video_pbase; 546be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->smem_len = oi->video_buffer_size; 54732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->type = FB_TYPE_PACKED_PIXELS; 548be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 54932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->xpanstep = 1; 55032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->ypanstep = 1; 55132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->ywrapstep = 0; 552be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fix->line_length = oi->display_byte_stride; 55332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil fix->accel = FB_ACCEL_NONE; 55432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 55532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 55632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 55732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Check the requested display mode, returning -EINVAL if we can't 55832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil handle it. */ 55932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 56032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) 56132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 562be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 56368a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong int osd_height_limit; 56468a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong u32 pixclock, hlimit, vlimit; 56532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 566be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("ivtvfb_check_var\n"); 56732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 56868a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong /* Set base references for mode calcs. */ 56968a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong if (itv->is_50hz) { 57068a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong pixclock = 84316; 57168a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong hlimit = 776; 57268a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong vlimit = 591; 57368a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong osd_height_limit = 576; 57468a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong } 57568a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong else { 57668a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong pixclock = 83926; 57768a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong hlimit = 776; 57868a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong vlimit = 495; 57968a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong osd_height_limit = 480; 58068a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong } 58168a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong 58232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check the bits per pixel */ 58332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_compat) { 58432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->bits_per_pixel != 32) { 585be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel); 58632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 58732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 58832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 58932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 59032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) { 59132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->transp.offset = 24; 59232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->transp.length = 8; 59332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 16; 59432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 8; 59532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 8; 59632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 8; 59732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 59832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 8; 59932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 60032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (var->bits_per_pixel == 16) { 60132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* To find out the true mode, check green length */ 60232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (var->green.length) { 60332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 4: 60432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 8; 60532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 4; 60632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 4; 60732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 4; 60832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 60932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 4; 610459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.offset = 12; 611459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.length = 1; 61232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 61332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case 5: 61432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 10; 61532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 5; 61632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 5; 61732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 5; 61832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 61932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 5; 620459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.offset = 15; 621459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.length = 1; 62232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 62332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil default: 62432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.offset = 11; 62532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->red.length = 5; 62632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.offset = 5; 62732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->green.length = 6; 62832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.offset = 0; 62932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->blue.length = 5; 630459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.offset = 0; 631459a52fab2c42cd5fadfd51fdcfc6dea8107fabfHans Verkuil var->transp.length = 0; 63232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 63332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 63432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 63532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else { 636be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel); 63732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 63832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 63932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 64032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check the resolution */ 64132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_compat) { 642be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (var->xres != oi->ivtvfb_defined.xres || 643be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->yres != oi->ivtvfb_defined.yres || 644be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres_virtual != oi->ivtvfb_defined.xres_virtual || 645be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->yres_virtual != oi->ivtvfb_defined.yres_virtual) { 646be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid resolution: %dx%d (virtual %dx%d)\n", 647be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres, var->yres, var->xres_virtual, var->yres_virtual); 64832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 64932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 65032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 65132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else { 652be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) { 653be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid resolution: %dx%d\n", 654be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres, var->yres); 65532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 65632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 65732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 65832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */ 65932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) || 660be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size || 66132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->xres_virtual < var->xres || 66232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->yres_virtual < var->yres) { 663be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n", 66432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->xres_virtual, var->yres_virtual); 66532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 66632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 66732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 66832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 66932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Some extra checks if in 8 bit mode */ 67032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->bits_per_pixel == 8) { 67132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Width must be a multiple of 4 */ 67232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres & 3) { 673be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres); 67432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 67532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 67632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres_virtual & 3) { 677be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual); 67832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 67932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 68032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 68132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (var->bits_per_pixel == 16) { 68232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Width must be a multiple of 2 */ 68332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres & 1) { 684be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres); 68532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 68632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 68732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xres_virtual & 1) { 688be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual); 68932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 69032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 69132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 69232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 69332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Now check the offsets */ 69432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) { 695be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n", 696be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual); 69732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 69832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 69932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 70032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check pixel format */ 70132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->nonstd > 1) { 702be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd); 70332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 70432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 70532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 70632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check video mode */ 70732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) && 70832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) { 709be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK); 71032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 71132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 71232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 71332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check the left & upper margins 71432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil If the margins are too large, just center the screen 71532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil (enforcing margins causes too many problems) */ 71632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 71732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) { 71832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2); 71932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 72032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (var->upper_margin + var->yres > (itv->is_50hz ? 577 : 481)) { 72132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->upper_margin = 1 + (((itv->is_50hz ? 576 : 480) - var->yres) / 2); 72232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 72332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 72432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Maintain overall 'size' for a constant refresh rate */ 72568a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->right_margin = hlimit - var->left_margin - var->xres; 72668a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->lower_margin = vlimit - var->upper_margin - var->yres; 72732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 72832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Fixed sync times */ 72932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->hsync_len = 24; 73032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->vsync_len = 2; 73132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 73232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Non-interlaced / interlaced mode is used to switch the OSD filter 73332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil on or off. Adjust the clock timings to maintain a constant 73432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil vertical refresh rate. */ 73532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) 73668a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->pixclock = pixclock / 2; 73768a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong else 73868a341a53ab5a3c5b7dad4b226124414c62c124dIan Armstrong var->pixclock = pixclock; 73932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 740be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", 741be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres, var->yres, 742be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->xres_virtual, var->yres_virtual, 74332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil var->bits_per_pixel); 74432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 745be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Display position: %d, %d\n", 746be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil var->left_margin, var->upper_margin); 74732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 748be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Display filter: %s\n", 749be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); 750be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); 75132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 75232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 75332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 75432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 75532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 75632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *) info->par; 757be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("ivtvfb_check_var\n"); 758be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil return _ivtvfb_check_var(var, itv); 75932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 76032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 76132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 76232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 76332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 osd_pan_index; 76432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *) info->par; 76532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 76632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_pan_index = (var->xoffset + (var->yoffset * var->xres_virtual))*var->bits_per_pixel/8; 767be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil write_reg(osd_pan_index, 0x02A0C); 76832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 76932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Pass this info back the yuv handler */ 77032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_x_pan = var->xoffset; 77132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.osd_y_pan = var->yoffset; 77232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Force update of yuv registers */ 77332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->yuv_info.yuv_forced_update = 1; 77432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 77532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 77632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 77732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_set_par(struct fb_info *info) 77832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 77932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int rc = 0; 78032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *) info->par; 78132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 782be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("ivtvfb_set_par\n"); 78332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 78432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil rc = ivtvfb_set_var(itv, &info->var); 78532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_pan_display(&info->var, info); 786be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ivtvfb_get_fix(itv, &info->fix); 78732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 78832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 78932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 79032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green, 79132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unsigned blue, unsigned transp, 79232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct fb_info *info) 79332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 79432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil u32 color, *palette; 795be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct ivtv *itv = (struct ivtv *)info->par; 79632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 79732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (regno >= info->cmap.len) 79832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 79932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 80032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); 80132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (info->var.bits_per_pixel <= 8) { 80232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(regno, 0x02a30); 80332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(color, 0x02a34); 804be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil return 0; 80532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 806be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (regno >= 16) 807be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil return -EINVAL; 80832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 809be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil palette = info->pseudo_palette; 810be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (info->var.bits_per_pixel == 16) { 811be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil switch (info->var.green.length) { 812be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case 4: 813be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil color = ((red & 0xf000) >> 4) | 814be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((green & 0xf000) >> 8) | 815be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((blue & 0xf000) >> 12); 816be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil break; 817be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case 5: 818be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil color = ((red & 0xf800) >> 1) | 819be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((green & 0xf800) >> 6) | 820be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((blue & 0xf800) >> 11); 821be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil break; 822be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil case 6: 823be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil color = (red & 0xf800 ) | 824be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((green & 0xfc00) >> 5) | 825be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ((blue & 0xf800) >> 11); 826be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil break; 82732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 82832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 829be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil palette[regno] = color; 83032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 83132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 83232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 83332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* We don't really support blanking. All this does is enable or 83432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil disable the OSD. */ 83532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_blank(int blank_mode, struct fb_info *info) 83632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 83732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv = (struct ivtv *)info->par; 83832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 839be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode); 84032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil switch (blank_mode) { 84132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_UNBLANK: 84232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1); 84332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 84432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_NORMAL: 84532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_HSYNC_SUSPEND: 84632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_VSYNC_SUSPEND: 84732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil case FB_BLANK_POWERDOWN: 84832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); 84932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil break; 85032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 85132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 85232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 85332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 85432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic struct fb_ops ivtvfb_ops = { 85532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .owner = THIS_MODULE, 85632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_check_var = ivtvfb_check_var, 85732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_set_par = ivtvfb_set_par, 85832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_setcolreg = ivtvfb_setcolreg, 85932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_fillrect = cfb_fillrect, 86032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_copyarea = cfb_copyarea, 86132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_imageblit = cfb_imageblit, 86232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_cursor = NULL, 86332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_ioctl = ivtvfb_ioctl, 86432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_pan_display = ivtvfb_pan_display, 86532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil .fb_blank = ivtvfb_blank, 86632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil}; 86732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 86832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Initialization */ 86932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 87032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 87132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Setup our initial video mode */ 87232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_init_vidmode(struct ivtv *itv) 87332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 874be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 87532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct v4l2_rect start_window; 876be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil int max_height; 87732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 87832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Color mode */ 87932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 88032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_compat) osd_depth = 32; 88132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32) osd_depth = 8; 882be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->bits_per_pixel = osd_depth; 883be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->bytes_per_pixel = oi->bits_per_pixel / 8; 88432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 885aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong /* Invalidate current osd mode to force a mode switch later */ 886aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong oi->osd_mode = -1; 887aaf9fa21b684509973dd593e30423fc0a6a5e7a3Ian Armstrong 88832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Horizontal size & position */ 88932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 89032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_xres > 720) osd_xres = 720; 89132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 89232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */ 89332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_depth == 8) 89432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_xres &= ~3; 89532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else if (osd_depth == 16) 89632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_xres &= ~1; 89732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 89832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_xres) 89932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil start_window.width = osd_xres; 90032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil else 90132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil start_window.width = osd_compat ? 720: 640; 90232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 90332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check horizontal start (osd_left). */ 90432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_left && osd_left + start_window.width > 721) { 905be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_ERR("Invalid osd_left - assuming default\n"); 90632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_left = 0; 90732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 90832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 90932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Hardware coords start at 0, user coords start at 1. */ 910be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd_left--; 91132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 912be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); 91332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 914be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_byte_stride = 915be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil start_window.width * oi->bytes_per_pixel; 91632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 91732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Vertical size & position */ 91832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 91932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil max_height = itv->is_50hz ? 576 : 480; 92032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 921be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (osd_yres > max_height) 922be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd_yres = max_height; 92332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 92432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_yres) 92532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil start_window.height = osd_yres; 926be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil else 927be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil start_window.height = osd_compat ? max_height : (itv->is_50hz ? 480 : 400); 92832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 92932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Check vertical start (osd_upper). */ 93032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_upper + start_window.height > max_height + 1) { 931be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_ERR("Invalid osd_upper - assuming default\n"); 93232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil osd_upper = 0; 93332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 93432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 93532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Hardware coords start at 0, user coords start at 1. */ 936be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil osd_upper--; 93732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 93832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2); 93932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 940be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_width = start_window.width; 941be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->display_height = start_window.height; 94232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 94332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Generate a valid fb_var_screeninfo */ 94432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 945be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.xres = oi->display_width; 946be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.yres = oi->display_height; 947be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.xres_virtual = oi->display_width; 948be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.yres_virtual = oi->display_height; 949be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel; 950be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED); 951be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.left_margin = start_window.left + 1; 952be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.upper_margin = start_window.top + 1; 953be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE; 954be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_defined.nonstd = 0; 95532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 95632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* We've filled in the most data, let the usual mode check 95732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil routine fill in the rest. */ 958be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil _ivtvfb_check_var(&oi->ivtvfb_defined, itv); 95932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 96032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Generate valid fb_fix_screeninfo */ 96132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 962be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ivtvfb_get_fix(itv, &oi->ivtvfb_fix); 96332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 96432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Generate valid fb_info */ 96532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 966be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.node = -1; 967be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT; 968be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.fbops = &ivtvfb_ops; 969be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.par = itv; 970be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.var = oi->ivtvfb_defined; 971be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.fix = oi->ivtvfb_fix; 972be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase; 973be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.fbops = &ivtvfb_ops; 97432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 97532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Supply some monitor specs. Bogus values will do for now */ 976be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.hfmin = 8000; 977be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.hfmax = 70000; 978be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.vfmin = 10; 979be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.monspecs.vfmax = 100; 98032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 98132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Allocate color map */ 982be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) { 983be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_ERR("abort, unable to alloc cmap\n"); 98432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENOMEM; 98532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 98632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 98732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Allocate the pseudo palette */ 988be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); 98932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 990be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!oi->ivtvfb_info.pseudo_palette) { 991be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_ERR("abort, unable to alloc pseudo pallete\n"); 99232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENOMEM; 99332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 99432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 99532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 99632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 99732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 99832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */ 99932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 100032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int ivtvfb_init_io(struct ivtv *itv) 100132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 1002be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 1003be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 100426e9d599561e9a964bd4d7c2be0029db8aaff852Hans Verkuil mutex_lock(&itv->serialize_lock); 10056e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil if (ivtv_init_on_first_open(itv)) { 100626e9d599561e9a964bd4d7c2be0029db8aaff852Hans Verkuil mutex_unlock(&itv->serialize_lock); 10076e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil IVTV_FB_ERR("Failed to initialize ivtv\n"); 10086e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil return -ENXIO; 10096e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil } 101026e9d599561e9a964bd4d7c2be0029db8aaff852Hans Verkuil mutex_unlock(&itv->serialize_lock); 10116e5eb59102aa6007d3ea2b382a1d3ca4112c272aHans Verkuil 1012be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil ivtv_fb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size); 101332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 101432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* The osd buffer size depends on the number of video buffers allocated 101532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil on the PVR350 itself. For now we'll hardcode the smallest osd buffer 101632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size to prevent any overlap. */ 1017be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_buffer_size = 1704960; 101832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1019be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase; 1020be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_vbase = itv->dec_mem + oi->video_rbase; 102132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1022be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (!oi->video_vbase) { 102332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n", 1024be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_buffer_size, oi->video_pbase); 102532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EIO; 102632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 102732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 102832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", 1029be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_pbase, oi->video_vbase, 1030be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->video_buffer_size / 1024); 103132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 103232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#ifdef CONFIG_MTRR 103332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil { 103432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Find the largest power of two that maps the whole buffer */ 103532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int size_shift = 31; 103632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1037be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil while (!(oi->video_buffer_size & (1 << size_shift))) { 103832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_shift--; 103932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 104032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil size_shift++; 1041be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1); 1042be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size; 1043be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr += (1 << size_shift) - 1; 1044be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1); 1045be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (mtrr_add(oi->fb_start_aligned_physaddr, 1046be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr, 104732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil MTRR_TYPE_WRCOMB, 1) < 0) { 1048be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil IVTV_FB_WARN("cannot use mttr\n"); 1049be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_start_aligned_physaddr = 0; 1050be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr = 0; 105132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 105232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 1053be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil#endif 105432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 105532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Blank the entire osd. */ 1056be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil memset_io(oi->video_vbase, 0, oi->video_buffer_size); 105732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 105832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 105932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 106032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 106132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Release any memory we've grabbed & remove mtrr entry */ 106232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic void ivtvfb_release_buffers (struct ivtv *itv) 106332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 1064be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil struct osd_info *oi = itv->osd_info; 1065be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil 106632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Release cmap */ 1067be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (oi->ivtvfb_info.cmap.len); 1068be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil fb_dealloc_cmap(&oi->ivtvfb_info.cmap); 106932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 107032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Release pseudo palette */ 1071be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (oi->ivtvfb_info.pseudo_palette) 1072be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil kfree(oi->ivtvfb_info.pseudo_palette); 107332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 107432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil#ifdef CONFIG_MTRR 1075be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if (oi->fb_end_aligned_physaddr) { 1076be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil mtrr_del(-1, oi->fb_start_aligned_physaddr, 1077be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr); 1078be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil } 1079be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil#endif 108032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1081be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil kfree(oi); 108232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_info = NULL; 108332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 108432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 108532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil/* Initialize the specified card */ 108632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 1087be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuilstatic int ivtvfb_init_card(struct ivtv *itv) 108832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 108932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int rc; 109032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 109132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv->osd_info) { 109232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_ERR("Card %d already initialised\n", ivtv_fb_card_id); 109332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EBUSY; 109432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 109532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 109632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC); 109732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv->osd_info == 0) { 109832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_ERR("Failed to allocate memory for osd_info\n"); 109932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENOMEM; 110032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 110132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 110232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Find & setup the OSD buffer */ 1103be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if ((rc = ivtvfb_init_io(itv))) 110432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 110532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 110632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the startup video mode information */ 1107be383bd312c4defab8bd4bde8c06fea5bfe0996bHans Verkuil if ((rc = ivtvfb_init_vidmode(itv))) { 110832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_release_buffers(itv); 110932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return rc; 111032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 111132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 111232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Register the framebuffer */ 111332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) { 111432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_release_buffers(itv); 111532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 111632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 111732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 111832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_video_pbase = itv->osd_info->video_pbase; 111932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 112032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set the card to the requested mode */ 112132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_set_par(&itv->osd_info->ivtvfb_info); 112232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 112332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Set color 0 to black */ 112432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(0, 0x02a30); 112532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil write_reg(0, 0x02a34); 112632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 112732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Enable the osd */ 112832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); 112932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 113032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Note if we're running in compatibility mode */ 113132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (osd_compat) 113232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_INFO("Running in compatibility mode. Display resize & mode change disabled\n"); 113332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 113432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Allocate DMA */ 113532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtv_udma_alloc(itv); 113632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 113732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 113832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 113932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 114032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic int __init ivtvfb_init(void) 114132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 114232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv; 114332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int i, registered = 0; 114432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 114532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_fb_card_id < -1 || ivtv_fb_card_id >= IVTV_MAX_CARDS) { 11467b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil printk(KERN_ERR "ivtvfb: ivtv_fb_card_id parameter is out of range (valid range: -1 - %d)\n", 114732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_MAX_CARDS - 1); 114832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -EINVAL; 114932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 115032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 115132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil /* Locate & initialise all cards supporting an OSD. */ 115232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil for (i = 0; i < ivtv_cards_active; i++) { 115332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtv_fb_card_id != -1 && i != ivtv_fb_card_id) 115432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil continue; 115532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv = ivtv_cards[i]; 115632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { 115732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (ivtvfb_init_card(itv) == 0) { 115832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_INFO("Framebuffer registered on ivtv card id %d\n", i); 115932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil registered++; 116032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 116132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 116232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 116332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (!registered) { 11647b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil printk(KERN_ERR "ivtvfb: no cards found"); 116532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return -ENODEV; 116632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 116732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil return 0; 116832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 116932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 117032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilstatic void ivtvfb_cleanup(void) 117132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil{ 117232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil struct ivtv *itv; 117332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil int i; 117432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 11757b3a0d49e3e929b810ade38926342faca53e867dHans Verkuil printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n"); 117632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 117732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil for (i = 0; i < ivtv_cards_active; i++) { 117832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv = ivtv_cards[i]; 117932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) { 118032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil IVTV_FB_DEBUG_INFO("Unregister framebuffer %d\n", i); 118132db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); 118232db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil unregister_framebuffer(&itv->osd_info->ivtvfb_info); 118332db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil ivtvfb_release_buffers(itv); 118432db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil itv->osd_video_pbase = 0; 118532db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 118632db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil } 118732db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil} 118832db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuil 118932db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_init(ivtvfb_init); 119032db775452818656d5fd8fd8b0f54425f5cfc177Hans Verkuilmodule_exit(ivtvfb_cleanup); 1191