10c0d06caSMauro Carvalho Chehab /* 20c0d06caSMauro Carvalho Chehab * 30c0d06caSMauro Carvalho Chehab * Support for a cx23417 mpeg encoder via cx231xx host port. 40c0d06caSMauro Carvalho Chehab * 50c0d06caSMauro Carvalho Chehab * (c) 2004 Jelle Foks <jelle@foks.us> 60c0d06caSMauro Carvalho Chehab * (c) 2004 Gerd Knorr <kraxel@bytesex.org> 70c0d06caSMauro Carvalho Chehab * (c) 2008 Steven Toth <stoth@linuxtv.org> 80c0d06caSMauro Carvalho Chehab * - CX23885/7/8 support 90c0d06caSMauro Carvalho Chehab * 100c0d06caSMauro Carvalho Chehab * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), 110c0d06caSMauro Carvalho Chehab * 120c0d06caSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 130c0d06caSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 140c0d06caSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 150c0d06caSMauro Carvalho Chehab * (at your option) any later version. 160c0d06caSMauro Carvalho Chehab * 170c0d06caSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 180c0d06caSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 190c0d06caSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 200c0d06caSMauro Carvalho Chehab * GNU General Public License for more details. 210c0d06caSMauro Carvalho Chehab * 220c0d06caSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 230c0d06caSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 240c0d06caSMauro Carvalho Chehab * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 250c0d06caSMauro Carvalho Chehab */ 260c0d06caSMauro Carvalho Chehab 270c0d06caSMauro Carvalho Chehab #include <linux/module.h> 280c0d06caSMauro Carvalho Chehab #include <linux/moduleparam.h> 290c0d06caSMauro Carvalho Chehab #include <linux/init.h> 300c0d06caSMauro Carvalho Chehab #include <linux/fs.h> 310c0d06caSMauro Carvalho Chehab #include <linux/delay.h> 320c0d06caSMauro Carvalho Chehab #include <linux/device.h> 330c0d06caSMauro Carvalho Chehab #include <linux/firmware.h> 340c0d06caSMauro Carvalho Chehab #include <linux/vmalloc.h> 350c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h> 360c0d06caSMauro Carvalho Chehab #include <media/v4l2-ioctl.h> 370c0d06caSMauro Carvalho Chehab #include <media/cx2341x.h> 380c0d06caSMauro Carvalho Chehab #include <linux/usb.h> 390c0d06caSMauro Carvalho Chehab 400c0d06caSMauro Carvalho Chehab #include "cx231xx.h" 410c0d06caSMauro Carvalho Chehab /*#include "cx23885-ioctl.h"*/ 420c0d06caSMauro Carvalho Chehab 430c0d06caSMauro Carvalho Chehab #define CX231xx_FIRM_IMAGE_SIZE 376836 440c0d06caSMauro Carvalho Chehab #define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" 450c0d06caSMauro Carvalho Chehab 460c0d06caSMauro Carvalho Chehab /* for polaris ITVC */ 470c0d06caSMauro Carvalho Chehab #define ITVC_WRITE_DIR 0x03FDFC00 480c0d06caSMauro Carvalho Chehab #define ITVC_READ_DIR 0x0001FC00 490c0d06caSMauro Carvalho Chehab 500c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE0 0x00 510c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE1 0x08 520c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE2 0x10 530c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE3 0x18 540c0d06caSMauro Carvalho Chehab 550c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_ADDRESS_BYTE2 0x20 560c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_ADDRESS_BYTE1 0x28 570c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_ADDRESS_BYTE0 0x30 580c0d06caSMauro Carvalho Chehab 590c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE0 0x40 600c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE1 0x48 610c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE2 0x50 620c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE3 0x58 630c0d06caSMauro Carvalho Chehab 640c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_ADDRESS_BYTE0 0x60 650c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_ADDRESS_BYTE1 0x68 660c0d06caSMauro Carvalho Chehab 670c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_MODE 0x70 680c0d06caSMauro Carvalho Chehab 690c0d06caSMauro Carvalho Chehab /* Read and write modes for polaris ITVC */ 700c0d06caSMauro Carvalho Chehab #define MCI_MODE_REGISTER_READ 0x000 710c0d06caSMauro Carvalho Chehab #define MCI_MODE_REGISTER_WRITE 0x100 720c0d06caSMauro Carvalho Chehab #define MCI_MODE_MEMORY_READ 0x000 730c0d06caSMauro Carvalho Chehab #define MCI_MODE_MEMORY_WRITE 0x4000 740c0d06caSMauro Carvalho Chehab 750c0d06caSMauro Carvalho Chehab static unsigned int mpegbufs = 8; 760c0d06caSMauro Carvalho Chehab module_param(mpegbufs, int, 0644); 770c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32"); 780c0d06caSMauro Carvalho Chehab static unsigned int mpeglines = 128; 790c0d06caSMauro Carvalho Chehab module_param(mpeglines, int, 0644); 800c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32"); 810c0d06caSMauro Carvalho Chehab static unsigned int mpeglinesize = 512; 820c0d06caSMauro Carvalho Chehab module_param(mpeglinesize, int, 0644); 830c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(mpeglinesize, 840c0d06caSMauro Carvalho Chehab "number of bytes in each line of an MPEG buffer, range 512-1024"); 850c0d06caSMauro Carvalho Chehab 860c0d06caSMauro Carvalho Chehab static unsigned int v4l_debug = 1; 870c0d06caSMauro Carvalho Chehab module_param(v4l_debug, int, 0644); 880c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages"); 890c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_qq; 900c0d06caSMauro Carvalho Chehab #define dprintk(level, fmt, arg...)\ 910c0d06caSMauro Carvalho Chehab do { if (v4l_debug >= level) \ 920c0d06caSMauro Carvalho Chehab printk(KERN_INFO "%s: " fmt, \ 930c0d06caSMauro Carvalho Chehab (dev) ? dev->name : "cx231xx[?]", ## arg); \ 940c0d06caSMauro Carvalho Chehab } while (0) 950c0d06caSMauro Carvalho Chehab 960c0d06caSMauro Carvalho Chehab static struct cx231xx_tvnorm cx231xx_tvnorms[] = { 970c0d06caSMauro Carvalho Chehab { 980c0d06caSMauro Carvalho Chehab .name = "NTSC-M", 990c0d06caSMauro Carvalho Chehab .id = V4L2_STD_NTSC_M, 1000c0d06caSMauro Carvalho Chehab }, { 1010c0d06caSMauro Carvalho Chehab .name = "NTSC-JP", 1020c0d06caSMauro Carvalho Chehab .id = V4L2_STD_NTSC_M_JP, 1030c0d06caSMauro Carvalho Chehab }, { 1040c0d06caSMauro Carvalho Chehab .name = "PAL-BG", 1050c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_BG, 1060c0d06caSMauro Carvalho Chehab }, { 1070c0d06caSMauro Carvalho Chehab .name = "PAL-DK", 1080c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_DK, 1090c0d06caSMauro Carvalho Chehab }, { 1100c0d06caSMauro Carvalho Chehab .name = "PAL-I", 1110c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_I, 1120c0d06caSMauro Carvalho Chehab }, { 1130c0d06caSMauro Carvalho Chehab .name = "PAL-M", 1140c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_M, 1150c0d06caSMauro Carvalho Chehab }, { 1160c0d06caSMauro Carvalho Chehab .name = "PAL-N", 1170c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_N, 1180c0d06caSMauro Carvalho Chehab }, { 1190c0d06caSMauro Carvalho Chehab .name = "PAL-Nc", 1200c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_Nc, 1210c0d06caSMauro Carvalho Chehab }, { 1220c0d06caSMauro Carvalho Chehab .name = "PAL-60", 1230c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_60, 1240c0d06caSMauro Carvalho Chehab }, { 1250c0d06caSMauro Carvalho Chehab .name = "SECAM-L", 1260c0d06caSMauro Carvalho Chehab .id = V4L2_STD_SECAM_L, 1270c0d06caSMauro Carvalho Chehab }, { 1280c0d06caSMauro Carvalho Chehab .name = "SECAM-DK", 1290c0d06caSMauro Carvalho Chehab .id = V4L2_STD_SECAM_DK, 1300c0d06caSMauro Carvalho Chehab } 1310c0d06caSMauro Carvalho Chehab }; 1320c0d06caSMauro Carvalho Chehab 1330c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 1340c0d06caSMauro Carvalho Chehab enum cx231xx_capture_type { 1350c0d06caSMauro Carvalho Chehab CX231xx_MPEG_CAPTURE, 1360c0d06caSMauro Carvalho Chehab CX231xx_RAW_CAPTURE, 1370c0d06caSMauro Carvalho Chehab CX231xx_RAW_PASSTHRU_CAPTURE 1380c0d06caSMauro Carvalho Chehab }; 1390c0d06caSMauro Carvalho Chehab enum cx231xx_capture_bits { 1400c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_NONE = 0x00, 1410c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_YUV_CAPTURE = 0x01, 1420c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_PCM_CAPTURE = 0x02, 1430c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_VBI_CAPTURE = 0x04, 1440c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08, 1450c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_TO_HOST_CAPTURE = 0x10 1460c0d06caSMauro Carvalho Chehab }; 1470c0d06caSMauro Carvalho Chehab enum cx231xx_capture_end { 1480c0d06caSMauro Carvalho Chehab CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */ 1490c0d06caSMauro Carvalho Chehab CX231xx_END_NOW, /* stop immediately, no irq */ 1500c0d06caSMauro Carvalho Chehab }; 1510c0d06caSMauro Carvalho Chehab enum cx231xx_framerate { 1520c0d06caSMauro Carvalho Chehab CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */ 1530c0d06caSMauro Carvalho Chehab CX231xx_FRAMERATE_PAL_25 /* PAL: 25fps */ 1540c0d06caSMauro Carvalho Chehab }; 1550c0d06caSMauro Carvalho Chehab enum cx231xx_stream_port { 1560c0d06caSMauro Carvalho Chehab CX231xx_OUTPUT_PORT_MEMORY, 1570c0d06caSMauro Carvalho Chehab CX231xx_OUTPUT_PORT_STREAMING, 1580c0d06caSMauro Carvalho Chehab CX231xx_OUTPUT_PORT_SERIAL 1590c0d06caSMauro Carvalho Chehab }; 1600c0d06caSMauro Carvalho Chehab enum cx231xx_data_xfer_status { 1610c0d06caSMauro Carvalho Chehab CX231xx_MORE_BUFFERS_FOLLOW, 1620c0d06caSMauro Carvalho Chehab CX231xx_LAST_BUFFER, 1630c0d06caSMauro Carvalho Chehab }; 1640c0d06caSMauro Carvalho Chehab enum cx231xx_picture_mask { 1650c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_NONE, 1660c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_I_FRAMES, 1670c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3, 1680c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7, 1690c0d06caSMauro Carvalho Chehab }; 1700c0d06caSMauro Carvalho Chehab enum cx231xx_vbi_mode_bits { 1710c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SLICED, 1720c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_RAW, 1730c0d06caSMauro Carvalho Chehab }; 1740c0d06caSMauro Carvalho Chehab enum cx231xx_vbi_insertion_bits { 1750c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA, 1760c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1, 1770c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1, 1780c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, 1790c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, 1800c0d06caSMauro Carvalho Chehab }; 1810c0d06caSMauro Carvalho Chehab enum cx231xx_dma_unit { 1820c0d06caSMauro Carvalho Chehab CX231xx_DMA_BYTES, 1830c0d06caSMauro Carvalho Chehab CX231xx_DMA_FRAMES, 1840c0d06caSMauro Carvalho Chehab }; 1850c0d06caSMauro Carvalho Chehab enum cx231xx_dma_transfer_status_bits { 1860c0d06caSMauro Carvalho Chehab CX231xx_DMA_TRANSFER_BITS_DONE = 0x01, 1870c0d06caSMauro Carvalho Chehab CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04, 1880c0d06caSMauro Carvalho Chehab CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10, 1890c0d06caSMauro Carvalho Chehab }; 1900c0d06caSMauro Carvalho Chehab enum cx231xx_pause { 1910c0d06caSMauro Carvalho Chehab CX231xx_PAUSE_ENCODING, 1920c0d06caSMauro Carvalho Chehab CX231xx_RESUME_ENCODING, 1930c0d06caSMauro Carvalho Chehab }; 1940c0d06caSMauro Carvalho Chehab enum cx231xx_copyright { 1950c0d06caSMauro Carvalho Chehab CX231xx_COPYRIGHT_OFF, 1960c0d06caSMauro Carvalho Chehab CX231xx_COPYRIGHT_ON, 1970c0d06caSMauro Carvalho Chehab }; 1980c0d06caSMauro Carvalho Chehab enum cx231xx_notification_type { 1990c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_REFRESH, 2000c0d06caSMauro Carvalho Chehab }; 2010c0d06caSMauro Carvalho Chehab enum cx231xx_notification_status { 2020c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_OFF, 2030c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_ON, 2040c0d06caSMauro Carvalho Chehab }; 2050c0d06caSMauro Carvalho Chehab enum cx231xx_notification_mailbox { 2060c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_NO_MAILBOX = -1, 2070c0d06caSMauro Carvalho Chehab }; 2080c0d06caSMauro Carvalho Chehab enum cx231xx_field1_lines { 2090c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */ 2100c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */ 2110c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */ 2120c0d06caSMauro Carvalho Chehab }; 2130c0d06caSMauro Carvalho Chehab enum cx231xx_field2_lines { 2140c0d06caSMauro Carvalho Chehab CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */ 2150c0d06caSMauro Carvalho Chehab CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */ 2160c0d06caSMauro Carvalho Chehab CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */ 2170c0d06caSMauro Carvalho Chehab }; 2180c0d06caSMauro Carvalho Chehab enum cx231xx_custom_data_type { 2190c0d06caSMauro Carvalho Chehab CX231xx_CUSTOM_EXTENSION_USR_DATA, 2200c0d06caSMauro Carvalho Chehab CX231xx_CUSTOM_PRIVATE_PACKET, 2210c0d06caSMauro Carvalho Chehab }; 2220c0d06caSMauro Carvalho Chehab enum cx231xx_mute { 2230c0d06caSMauro Carvalho Chehab CX231xx_UNMUTE, 2240c0d06caSMauro Carvalho Chehab CX231xx_MUTE, 2250c0d06caSMauro Carvalho Chehab }; 2260c0d06caSMauro Carvalho Chehab enum cx231xx_mute_video_mask { 2270c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00, 2280c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000, 2290c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000, 2300c0d06caSMauro Carvalho Chehab }; 2310c0d06caSMauro Carvalho Chehab enum cx231xx_mute_video_shift { 2320c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_V_SHIFT = 8, 2330c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_U_SHIFT = 16, 2340c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_Y_SHIFT = 24, 2350c0d06caSMauro Carvalho Chehab }; 2360c0d06caSMauro Carvalho Chehab 2370c0d06caSMauro Carvalho Chehab /* defines below are from ivtv-driver.h */ 2380c0d06caSMauro Carvalho Chehab #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF 2390c0d06caSMauro Carvalho Chehab 2400c0d06caSMauro Carvalho Chehab /* Firmware API commands */ 2410c0d06caSMauro Carvalho Chehab #define IVTV_API_STD_TIMEOUT 500 2420c0d06caSMauro Carvalho Chehab 2430c0d06caSMauro Carvalho Chehab /* Registers */ 2440c0d06caSMauro Carvalho Chehab /* IVTV_REG_OFFSET */ 2450c0d06caSMauro Carvalho Chehab #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8) 2460c0d06caSMauro Carvalho Chehab #define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC) 2470c0d06caSMauro Carvalho Chehab #define IVTV_REG_SPU (0x9050) 2480c0d06caSMauro Carvalho Chehab #define IVTV_REG_HW_BLOCKS (0x9054) 2490c0d06caSMauro Carvalho Chehab #define IVTV_REG_VPU (0x9058) 2500c0d06caSMauro Carvalho Chehab #define IVTV_REG_APU (0xA064) 2510c0d06caSMauro Carvalho Chehab 2520c0d06caSMauro Carvalho Chehab /* 2530c0d06caSMauro Carvalho Chehab * Bit definitions for MC417_RWD and MC417_OEN registers 2540c0d06caSMauro Carvalho Chehab * 2550c0d06caSMauro Carvalho Chehab * bits 31-16 2560c0d06caSMauro Carvalho Chehab *+-----------+ 2570c0d06caSMauro Carvalho Chehab *| Reserved | 2580c0d06caSMauro Carvalho Chehab *|+-----------+ 2590c0d06caSMauro Carvalho Chehab *| bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8 2600c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2610c0d06caSMauro Carvalho Chehab *|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0| 2620c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2630c0d06caSMauro Carvalho Chehab *| bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 2640c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2650c0d06caSMauro Carvalho Chehab *||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0| 2660c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 2670c0d06caSMauro Carvalho Chehab */ 2680c0d06caSMauro Carvalho Chehab #define MC417_MIWR 0x8000 2690c0d06caSMauro Carvalho Chehab #define MC417_MIRD 0x4000 2700c0d06caSMauro Carvalho Chehab #define MC417_MICS 0x2000 2710c0d06caSMauro Carvalho Chehab #define MC417_MIRDY 0x1000 2720c0d06caSMauro Carvalho Chehab #define MC417_MIADDR 0x0F00 2730c0d06caSMauro Carvalho Chehab #define MC417_MIDATA 0x00FF 2740c0d06caSMauro Carvalho Chehab 2750c0d06caSMauro Carvalho Chehab 2760c0d06caSMauro Carvalho Chehab /* Bit definitions for MC417_CTL register **** 2770c0d06caSMauro Carvalho Chehab *bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0 2780c0d06caSMauro Carvalho Chehab *+--------+-------------+--------+--------------+------------+ 2790c0d06caSMauro Carvalho Chehab *|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN| 2800c0d06caSMauro Carvalho Chehab *+--------+-------------+--------+--------------+------------+ 2810c0d06caSMauro Carvalho Chehab */ 2820c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030) 2830c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006) 2840c0d06caSMauro Carvalho Chehab #define MC417_UART_GPIO_EN 0x00000001 2850c0d06caSMauro Carvalho Chehab 2860c0d06caSMauro Carvalho Chehab /* Values for speed control */ 2870c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL_SLOW 0x1 2880c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL_MEDIUM 0x0 2890c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */ 2900c0d06caSMauro Carvalho Chehab 2910c0d06caSMauro Carvalho Chehab /* Values for GPIO select */ 2920c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO3 0x3 2930c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO2 0x2 2940c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO1 0x1 2950c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO0 0x0 2960c0d06caSMauro Carvalho Chehab 2970c0d06caSMauro Carvalho Chehab 2980c0d06caSMauro Carvalho Chehab #define CX23417_GPIO_MASK 0xFC0003FF 2990c0d06caSMauro Carvalho Chehab static int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value) 3000c0d06caSMauro Carvalho Chehab { 3010c0d06caSMauro Carvalho Chehab int status = 0; 3020c0d06caSMauro Carvalho Chehab u32 _gpio_direction = 0; 3030c0d06caSMauro Carvalho Chehab 3040c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; 3050c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction|gpio_direction; 3060c0d06caSMauro Carvalho Chehab status = cx231xx_send_gpio_cmd(dev, _gpio_direction, 3070c0d06caSMauro Carvalho Chehab (u8 *)&value, 4, 0, 0); 3080c0d06caSMauro Carvalho Chehab return status; 3090c0d06caSMauro Carvalho Chehab } 3100c0d06caSMauro Carvalho Chehab static int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue) 3110c0d06caSMauro Carvalho Chehab { 3120c0d06caSMauro Carvalho Chehab int status = 0; 3130c0d06caSMauro Carvalho Chehab u32 _gpio_direction = 0; 3140c0d06caSMauro Carvalho Chehab 3150c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; 3160c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction|gpio_direction; 3170c0d06caSMauro Carvalho Chehab 3180c0d06caSMauro Carvalho Chehab status = cx231xx_send_gpio_cmd(dev, _gpio_direction, 3190c0d06caSMauro Carvalho Chehab (u8 *)pValue, 4, 0, 1); 3200c0d06caSMauro Carvalho Chehab return status; 3210c0d06caSMauro Carvalho Chehab } 3220c0d06caSMauro Carvalho Chehab 3230c0d06caSMauro Carvalho Chehab static int waitForMciComplete(struct cx231xx *dev) 3240c0d06caSMauro Carvalho Chehab { 3250c0d06caSMauro Carvalho Chehab u32 gpio; 3260c0d06caSMauro Carvalho Chehab u32 gpio_driection = 0; 3270c0d06caSMauro Carvalho Chehab u8 count = 0; 3280c0d06caSMauro Carvalho Chehab getITVCReg(dev, gpio_driection, &gpio); 3290c0d06caSMauro Carvalho Chehab 3300c0d06caSMauro Carvalho Chehab while (!(gpio&0x020000)) { 3310c0d06caSMauro Carvalho Chehab msleep(10); 3320c0d06caSMauro Carvalho Chehab 3330c0d06caSMauro Carvalho Chehab getITVCReg(dev, gpio_driection, &gpio); 3340c0d06caSMauro Carvalho Chehab 3350c0d06caSMauro Carvalho Chehab if (count++ > 100) { 3360c0d06caSMauro Carvalho Chehab dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio); 3370c0d06caSMauro Carvalho Chehab return -1; 3380c0d06caSMauro Carvalho Chehab } 3390c0d06caSMauro Carvalho Chehab } 3400c0d06caSMauro Carvalho Chehab return 0; 3410c0d06caSMauro Carvalho Chehab } 3420c0d06caSMauro Carvalho Chehab 3430c0d06caSMauro Carvalho Chehab static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value) 3440c0d06caSMauro Carvalho Chehab { 3450c0d06caSMauro Carvalho Chehab u32 temp; 3460c0d06caSMauro Carvalho Chehab int status = 0; 3470c0d06caSMauro Carvalho Chehab 3480c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8); 3490c0d06caSMauro Carvalho Chehab temp = temp<<10; 3500c0d06caSMauro Carvalho Chehab status = setITVCReg(dev, ITVC_WRITE_DIR, temp); 3510c0d06caSMauro Carvalho Chehab if (status < 0) 3520c0d06caSMauro Carvalho Chehab return status; 3530c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 3540c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3550c0d06caSMauro Carvalho Chehab 3560c0d06caSMauro Carvalho Chehab /*write data byte 1;*/ 3570c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00); 3580c0d06caSMauro Carvalho Chehab temp = temp<<10; 3590c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3600c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 3610c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3620c0d06caSMauro Carvalho Chehab 3630c0d06caSMauro Carvalho Chehab /*write data byte 2;*/ 3640c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8); 3650c0d06caSMauro Carvalho Chehab temp = temp<<10; 3660c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3670c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 3680c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3690c0d06caSMauro Carvalho Chehab 3700c0d06caSMauro Carvalho Chehab /*write data byte 3;*/ 3710c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16); 3720c0d06caSMauro Carvalho Chehab temp = temp<<10; 3730c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3740c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 3750c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3760c0d06caSMauro Carvalho Chehab 3770c0d06caSMauro Carvalho Chehab /*write address byte 0;*/ 3780c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8); 3790c0d06caSMauro Carvalho Chehab temp = temp<<10; 3800c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3810c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 3820c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3830c0d06caSMauro Carvalho Chehab 3840c0d06caSMauro Carvalho Chehab /*write address byte 1;*/ 3850c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00); 3860c0d06caSMauro Carvalho Chehab temp = temp<<10; 3870c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3880c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 3890c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3900c0d06caSMauro Carvalho Chehab 3910c0d06caSMauro Carvalho Chehab /*Write that the mode is write.*/ 3920c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE; 3930c0d06caSMauro Carvalho Chehab temp = temp<<10; 3940c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3950c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 3960c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 3970c0d06caSMauro Carvalho Chehab 3980c0d06caSMauro Carvalho Chehab return waitForMciComplete(dev); 3990c0d06caSMauro Carvalho Chehab } 4000c0d06caSMauro Carvalho Chehab 4010c0d06caSMauro Carvalho Chehab static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value) 4020c0d06caSMauro Carvalho Chehab { 4030c0d06caSMauro Carvalho Chehab /*write address byte 0;*/ 4040c0d06caSMauro Carvalho Chehab u32 temp; 4050c0d06caSMauro Carvalho Chehab u32 return_value = 0; 4060c0d06caSMauro Carvalho Chehab int ret = 0; 4070c0d06caSMauro Carvalho Chehab 4080c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8); 4090c0d06caSMauro Carvalho Chehab temp = temp << 10; 4100c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4110c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 4120c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4130c0d06caSMauro Carvalho Chehab 4140c0d06caSMauro Carvalho Chehab /*write address byte 1;*/ 4150c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00); 4160c0d06caSMauro Carvalho Chehab temp = temp << 10; 4170c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4180c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 4190c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4200c0d06caSMauro Carvalho Chehab 4210c0d06caSMauro Carvalho Chehab /*write that the mode is read;*/ 4220c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ; 4230c0d06caSMauro Carvalho Chehab temp = temp << 10; 4240c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4250c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 4260c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4270c0d06caSMauro Carvalho Chehab 4280c0d06caSMauro Carvalho Chehab /*wait for the MIRDY line to be asserted , 4290c0d06caSMauro Carvalho Chehab signalling that the read is done;*/ 4300c0d06caSMauro Carvalho Chehab ret = waitForMciComplete(dev); 4310c0d06caSMauro Carvalho Chehab 4320c0d06caSMauro Carvalho Chehab /*switch the DATA- GPIO to input mode;*/ 4330c0d06caSMauro Carvalho Chehab 4340c0d06caSMauro Carvalho Chehab /*Read data byte 0;*/ 4350c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10; 4360c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4370c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10); 4380c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4390c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 4400c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) >> 18); 4410c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 4420c0d06caSMauro Carvalho Chehab 4430c0d06caSMauro Carvalho Chehab /* Read data byte 1;*/ 4440c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10; 4450c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4460c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10); 4470c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4480c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 4490c0d06caSMauro Carvalho Chehab 4500c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) >> 10); 4510c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 4520c0d06caSMauro Carvalho Chehab 4530c0d06caSMauro Carvalho Chehab /*Read data byte 2;*/ 4540c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10; 4550c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4560c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10); 4570c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4580c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 4590c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) >> 2); 4600c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 4610c0d06caSMauro Carvalho Chehab 4620c0d06caSMauro Carvalho Chehab /*Read data byte 3;*/ 4630c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10; 4640c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4650c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10); 4660c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 4670c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 4680c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) << 6); 4690c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 4700c0d06caSMauro Carvalho Chehab 4710c0d06caSMauro Carvalho Chehab *value = return_value; 4720c0d06caSMauro Carvalho Chehab 4730c0d06caSMauro Carvalho Chehab 4740c0d06caSMauro Carvalho Chehab return ret; 4750c0d06caSMauro Carvalho Chehab } 4760c0d06caSMauro Carvalho Chehab 4770c0d06caSMauro Carvalho Chehab static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value) 4780c0d06caSMauro Carvalho Chehab { 4790c0d06caSMauro Carvalho Chehab /*write data byte 0;*/ 4800c0d06caSMauro Carvalho Chehab 4810c0d06caSMauro Carvalho Chehab u32 temp; 4820c0d06caSMauro Carvalho Chehab int ret = 0; 4830c0d06caSMauro Carvalho Chehab 4840c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_MEMORY_DATA_BYTE0|((value & 0x000000FF) << 8); 4850c0d06caSMauro Carvalho Chehab temp = temp << 10; 4860c0d06caSMauro Carvalho Chehab ret = setITVCReg(dev, ITVC_WRITE_DIR, temp); 4870c0d06caSMauro Carvalho Chehab if (ret < 0) 4880c0d06caSMauro Carvalho Chehab return ret; 4890c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 4900c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4910c0d06caSMauro Carvalho Chehab 4920c0d06caSMauro Carvalho Chehab /*write data byte 1;*/ 4930c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00); 4940c0d06caSMauro Carvalho Chehab temp = temp << 10; 4950c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4960c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 4970c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 4980c0d06caSMauro Carvalho Chehab 4990c0d06caSMauro Carvalho Chehab /*write data byte 2;*/ 5000c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8); 5010c0d06caSMauro Carvalho Chehab temp = temp<<10; 5020c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5030c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5040c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5050c0d06caSMauro Carvalho Chehab 5060c0d06caSMauro Carvalho Chehab /*write data byte 3;*/ 5070c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16); 5080c0d06caSMauro Carvalho Chehab temp = temp<<10; 5090c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5100c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5110c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5120c0d06caSMauro Carvalho Chehab 5130c0d06caSMauro Carvalho Chehab /* write address byte 2;*/ 5140c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | 5150c0d06caSMauro Carvalho Chehab ((address & 0x003F0000)>>8); 5160c0d06caSMauro Carvalho Chehab temp = temp<<10; 5170c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5180c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5190c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5200c0d06caSMauro Carvalho Chehab 5210c0d06caSMauro Carvalho Chehab /* write address byte 1;*/ 5220c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 5230c0d06caSMauro Carvalho Chehab temp = temp<<10; 5240c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5250c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5260c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5270c0d06caSMauro Carvalho Chehab 5280c0d06caSMauro Carvalho Chehab /* write address byte 0;*/ 5290c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8); 5300c0d06caSMauro Carvalho Chehab temp = temp<<10; 5310c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5320c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5330c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5340c0d06caSMauro Carvalho Chehab 5350c0d06caSMauro Carvalho Chehab /*wait for MIRDY line;*/ 5360c0d06caSMauro Carvalho Chehab waitForMciComplete(dev); 5370c0d06caSMauro Carvalho Chehab 5380c0d06caSMauro Carvalho Chehab return 0; 5390c0d06caSMauro Carvalho Chehab } 5400c0d06caSMauro Carvalho Chehab 5410c0d06caSMauro Carvalho Chehab static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value) 5420c0d06caSMauro Carvalho Chehab { 5430c0d06caSMauro Carvalho Chehab u32 temp = 0; 5440c0d06caSMauro Carvalho Chehab u32 return_value = 0; 5450c0d06caSMauro Carvalho Chehab int ret = 0; 5460c0d06caSMauro Carvalho Chehab 5470c0d06caSMauro Carvalho Chehab /*write address byte 2;*/ 5480c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ | 5490c0d06caSMauro Carvalho Chehab ((address & 0x003F0000)>>8); 5500c0d06caSMauro Carvalho Chehab temp = temp<<10; 5510c0d06caSMauro Carvalho Chehab ret = setITVCReg(dev, ITVC_WRITE_DIR, temp); 5520c0d06caSMauro Carvalho Chehab if (ret < 0) 5530c0d06caSMauro Carvalho Chehab return ret; 5540c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5550c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5560c0d06caSMauro Carvalho Chehab 5570c0d06caSMauro Carvalho Chehab /*write address byte 1*/ 5580c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 5590c0d06caSMauro Carvalho Chehab temp = temp<<10; 5600c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5610c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5620c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5630c0d06caSMauro Carvalho Chehab 5640c0d06caSMauro Carvalho Chehab /*write address byte 0*/ 5650c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8); 5660c0d06caSMauro Carvalho Chehab temp = temp<<10; 5670c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5680c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 5690c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 5700c0d06caSMauro Carvalho Chehab 5710c0d06caSMauro Carvalho Chehab /*Wait for MIRDY line*/ 5720c0d06caSMauro Carvalho Chehab ret = waitForMciComplete(dev); 5730c0d06caSMauro Carvalho Chehab 5740c0d06caSMauro Carvalho Chehab 5750c0d06caSMauro Carvalho Chehab /*Read data byte 3;*/ 5760c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10; 5770c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 5780c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10); 5790c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 5800c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 5810c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)<<6); 5820c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 5830c0d06caSMauro Carvalho Chehab 5840c0d06caSMauro Carvalho Chehab /*Read data byte 2;*/ 5850c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10; 5860c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 5870c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10); 5880c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 5890c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 5900c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)>>2); 5910c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 5920c0d06caSMauro Carvalho Chehab 5930c0d06caSMauro Carvalho Chehab /* Read data byte 1;*/ 5940c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10; 5950c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 5960c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10); 5970c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 5980c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 5990c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)>>10); 6000c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 6010c0d06caSMauro Carvalho Chehab 6020c0d06caSMauro Carvalho Chehab /*Read data byte 0;*/ 6030c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10; 6040c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 6050c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10); 6060c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 6070c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 6080c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)>>18); 6090c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 6100c0d06caSMauro Carvalho Chehab 6110c0d06caSMauro Carvalho Chehab *value = return_value; 6120c0d06caSMauro Carvalho Chehab return ret; 6130c0d06caSMauro Carvalho Chehab } 6140c0d06caSMauro Carvalho Chehab 6150c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 6160c0d06caSMauro Carvalho Chehab 6170c0d06caSMauro Carvalho Chehab /* MPEG encoder API */ 6180c0d06caSMauro Carvalho Chehab static char *cmd_to_str(int cmd) 6190c0d06caSMauro Carvalho Chehab { 6200c0d06caSMauro Carvalho Chehab switch (cmd) { 6210c0d06caSMauro Carvalho Chehab case CX2341X_ENC_PING_FW: 6220c0d06caSMauro Carvalho Chehab return "PING_FW"; 6230c0d06caSMauro Carvalho Chehab case CX2341X_ENC_START_CAPTURE: 6240c0d06caSMauro Carvalho Chehab return "START_CAPTURE"; 6250c0d06caSMauro Carvalho Chehab case CX2341X_ENC_STOP_CAPTURE: 6260c0d06caSMauro Carvalho Chehab return "STOP_CAPTURE"; 6270c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_AUDIO_ID: 6280c0d06caSMauro Carvalho Chehab return "SET_AUDIO_ID"; 6290c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_VIDEO_ID: 6300c0d06caSMauro Carvalho Chehab return "SET_VIDEO_ID"; 6310c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_PCR_ID: 6320c0d06caSMauro Carvalho Chehab return "SET_PCR_PID"; 6330c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_FRAME_RATE: 6340c0d06caSMauro Carvalho Chehab return "SET_FRAME_RATE"; 6350c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_FRAME_SIZE: 6360c0d06caSMauro Carvalho Chehab return "SET_FRAME_SIZE"; 6370c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_BIT_RATE: 6380c0d06caSMauro Carvalho Chehab return "SET_BIT_RATE"; 6390c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_GOP_PROPERTIES: 6400c0d06caSMauro Carvalho Chehab return "SET_GOP_PROPERTIES"; 6410c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_ASPECT_RATIO: 6420c0d06caSMauro Carvalho Chehab return "SET_ASPECT_RATIO"; 6430c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_DNR_FILTER_MODE: 6440c0d06caSMauro Carvalho Chehab return "SET_DNR_FILTER_PROPS"; 6450c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_DNR_FILTER_PROPS: 6460c0d06caSMauro Carvalho Chehab return "SET_DNR_FILTER_PROPS"; 6470c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_CORING_LEVELS: 6480c0d06caSMauro Carvalho Chehab return "SET_CORING_LEVELS"; 6490c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE: 6500c0d06caSMauro Carvalho Chehab return "SET_SPATIAL_FILTER_TYPE"; 6510c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_VBI_LINE: 6520c0d06caSMauro Carvalho Chehab return "SET_VBI_LINE"; 6530c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_STREAM_TYPE: 6540c0d06caSMauro Carvalho Chehab return "SET_STREAM_TYPE"; 6550c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_OUTPUT_PORT: 6560c0d06caSMauro Carvalho Chehab return "SET_OUTPUT_PORT"; 6570c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_AUDIO_PROPERTIES: 6580c0d06caSMauro Carvalho Chehab return "SET_AUDIO_PROPERTIES"; 6590c0d06caSMauro Carvalho Chehab case CX2341X_ENC_HALT_FW: 6600c0d06caSMauro Carvalho Chehab return "HALT_FW"; 6610c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_VERSION: 6620c0d06caSMauro Carvalho Chehab return "GET_VERSION"; 6630c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_GOP_CLOSURE: 6640c0d06caSMauro Carvalho Chehab return "SET_GOP_CLOSURE"; 6650c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_SEQ_END: 6660c0d06caSMauro Carvalho Chehab return "GET_SEQ_END"; 6670c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_PGM_INDEX_INFO: 6680c0d06caSMauro Carvalho Chehab return "SET_PGM_INDEX_INFO"; 6690c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_VBI_CONFIG: 6700c0d06caSMauro Carvalho Chehab return "SET_VBI_CONFIG"; 6710c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_DMA_BLOCK_SIZE: 6720c0d06caSMauro Carvalho Chehab return "SET_DMA_BLOCK_SIZE"; 6730c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10: 6740c0d06caSMauro Carvalho Chehab return "GET_PREV_DMA_INFO_MB_10"; 6750c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9: 6760c0d06caSMauro Carvalho Chehab return "GET_PREV_DMA_INFO_MB_9"; 6770c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SCHED_DMA_TO_HOST: 6780c0d06caSMauro Carvalho Chehab return "SCHED_DMA_TO_HOST"; 6790c0d06caSMauro Carvalho Chehab case CX2341X_ENC_INITIALIZE_INPUT: 6800c0d06caSMauro Carvalho Chehab return "INITIALIZE_INPUT"; 6810c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_FRAME_DROP_RATE: 6820c0d06caSMauro Carvalho Chehab return "SET_FRAME_DROP_RATE"; 6830c0d06caSMauro Carvalho Chehab case CX2341X_ENC_PAUSE_ENCODER: 6840c0d06caSMauro Carvalho Chehab return "PAUSE_ENCODER"; 6850c0d06caSMauro Carvalho Chehab case CX2341X_ENC_REFRESH_INPUT: 6860c0d06caSMauro Carvalho Chehab return "REFRESH_INPUT"; 6870c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_COPYRIGHT: 6880c0d06caSMauro Carvalho Chehab return "SET_COPYRIGHT"; 6890c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_EVENT_NOTIFICATION: 6900c0d06caSMauro Carvalho Chehab return "SET_EVENT_NOTIFICATION"; 6910c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_NUM_VSYNC_LINES: 6920c0d06caSMauro Carvalho Chehab return "SET_NUM_VSYNC_LINES"; 6930c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_PLACEHOLDER: 6940c0d06caSMauro Carvalho Chehab return "SET_PLACEHOLDER"; 6950c0d06caSMauro Carvalho Chehab case CX2341X_ENC_MUTE_VIDEO: 6960c0d06caSMauro Carvalho Chehab return "MUTE_VIDEO"; 6970c0d06caSMauro Carvalho Chehab case CX2341X_ENC_MUTE_AUDIO: 6980c0d06caSMauro Carvalho Chehab return "MUTE_AUDIO"; 6990c0d06caSMauro Carvalho Chehab case CX2341X_ENC_MISC: 7000c0d06caSMauro Carvalho Chehab return "MISC"; 7010c0d06caSMauro Carvalho Chehab default: 7020c0d06caSMauro Carvalho Chehab return "UNKNOWN"; 7030c0d06caSMauro Carvalho Chehab } 7040c0d06caSMauro Carvalho Chehab } 7050c0d06caSMauro Carvalho Chehab 7060c0d06caSMauro Carvalho Chehab static int cx231xx_mbox_func(void *priv, 7070c0d06caSMauro Carvalho Chehab u32 command, 7080c0d06caSMauro Carvalho Chehab int in, 7090c0d06caSMauro Carvalho Chehab int out, 7100c0d06caSMauro Carvalho Chehab u32 data[CX2341X_MBOX_MAX_DATA]) 7110c0d06caSMauro Carvalho Chehab { 7120c0d06caSMauro Carvalho Chehab struct cx231xx *dev = priv; 7130c0d06caSMauro Carvalho Chehab unsigned long timeout; 7140c0d06caSMauro Carvalho Chehab u32 value, flag, retval = 0; 7150c0d06caSMauro Carvalho Chehab int i; 7160c0d06caSMauro Carvalho Chehab 7170c0d06caSMauro Carvalho Chehab dprintk(3, "%s: command(0x%X) = %s\n", __func__, command, 7180c0d06caSMauro Carvalho Chehab cmd_to_str(command)); 7190c0d06caSMauro Carvalho Chehab 7200c0d06caSMauro Carvalho Chehab /* this may not be 100% safe if we can't read any memory location 7210c0d06caSMauro Carvalho Chehab without side effects */ 7220c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value); 7230c0d06caSMauro Carvalho Chehab if (value != 0x12345678) { 7240c0d06caSMauro Carvalho Chehab dprintk(3, 7250c0d06caSMauro Carvalho Chehab "Firmware and/or mailbox pointer not initialized " 7260c0d06caSMauro Carvalho Chehab "or corrupted, signature = 0x%x, cmd = %s\n", value, 7270c0d06caSMauro Carvalho Chehab cmd_to_str(command)); 7280c0d06caSMauro Carvalho Chehab return -1; 7290c0d06caSMauro Carvalho Chehab } 7300c0d06caSMauro Carvalho Chehab 7310c0d06caSMauro Carvalho Chehab /* This read looks at 32 bits, but flag is only 8 bits. 7320c0d06caSMauro Carvalho Chehab * Seems we also bail if CMD or TIMEOUT bytes are set??? 7330c0d06caSMauro Carvalho Chehab */ 7340c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox, &flag); 7350c0d06caSMauro Carvalho Chehab if (flag) { 7360c0d06caSMauro Carvalho Chehab dprintk(3, "ERROR: Mailbox appears to be in use " 7370c0d06caSMauro Carvalho Chehab "(%x), cmd = %s\n", flag, cmd_to_str(command)); 7380c0d06caSMauro Carvalho Chehab return -1; 7390c0d06caSMauro Carvalho Chehab } 7400c0d06caSMauro Carvalho Chehab 7410c0d06caSMauro Carvalho Chehab flag |= 1; /* tell 'em we're working on it */ 7420c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox, flag); 7430c0d06caSMauro Carvalho Chehab 7440c0d06caSMauro Carvalho Chehab /* write command + args + fill remaining with zeros */ 7450c0d06caSMauro Carvalho Chehab /* command code */ 7460c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 1, command); 7470c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 3, 7480c0d06caSMauro Carvalho Chehab IVTV_API_STD_TIMEOUT); /* timeout */ 7490c0d06caSMauro Carvalho Chehab for (i = 0; i < in; i++) { 7500c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]); 7510c0d06caSMauro Carvalho Chehab dprintk(3, "API Input %d = %d\n", i, data[i]); 7520c0d06caSMauro Carvalho Chehab } 7530c0d06caSMauro Carvalho Chehab for (; i < CX2341X_MBOX_MAX_DATA; i++) 7540c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0); 7550c0d06caSMauro Carvalho Chehab 7560c0d06caSMauro Carvalho Chehab flag |= 3; /* tell 'em we're done writing */ 7570c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox, flag); 7580c0d06caSMauro Carvalho Chehab 7590c0d06caSMauro Carvalho Chehab /* wait for firmware to handle the API command */ 7600c0d06caSMauro Carvalho Chehab timeout = jiffies + msecs_to_jiffies(10); 7610c0d06caSMauro Carvalho Chehab for (;;) { 7620c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox, &flag); 7630c0d06caSMauro Carvalho Chehab if (0 != (flag & 4)) 7640c0d06caSMauro Carvalho Chehab break; 7650c0d06caSMauro Carvalho Chehab if (time_after(jiffies, timeout)) { 7660c0d06caSMauro Carvalho Chehab dprintk(3, "ERROR: API Mailbox timeout\n"); 7670c0d06caSMauro Carvalho Chehab return -1; 7680c0d06caSMauro Carvalho Chehab } 7690c0d06caSMauro Carvalho Chehab udelay(10); 7700c0d06caSMauro Carvalho Chehab } 7710c0d06caSMauro Carvalho Chehab 7720c0d06caSMauro Carvalho Chehab /* read output values */ 7730c0d06caSMauro Carvalho Chehab for (i = 0; i < out; i++) { 7740c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i); 7750c0d06caSMauro Carvalho Chehab dprintk(3, "API Output %d = %d\n", i, data[i]); 7760c0d06caSMauro Carvalho Chehab } 7770c0d06caSMauro Carvalho Chehab 7780c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval); 7790c0d06caSMauro Carvalho Chehab dprintk(3, "API result = %d\n", retval); 7800c0d06caSMauro Carvalho Chehab 7810c0d06caSMauro Carvalho Chehab flag = 0; 7820c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox, flag); 7830c0d06caSMauro Carvalho Chehab 7840c0d06caSMauro Carvalho Chehab return retval; 7850c0d06caSMauro Carvalho Chehab } 7860c0d06caSMauro Carvalho Chehab 7870c0d06caSMauro Carvalho Chehab /* We don't need to call the API often, so using just one 7880c0d06caSMauro Carvalho Chehab * mailbox will probably suffice 7890c0d06caSMauro Carvalho Chehab */ 7900c0d06caSMauro Carvalho Chehab static int cx231xx_api_cmd(struct cx231xx *dev, 7910c0d06caSMauro Carvalho Chehab u32 command, 7920c0d06caSMauro Carvalho Chehab u32 inputcnt, 7930c0d06caSMauro Carvalho Chehab u32 outputcnt, 7940c0d06caSMauro Carvalho Chehab ...) 7950c0d06caSMauro Carvalho Chehab { 7960c0d06caSMauro Carvalho Chehab u32 data[CX2341X_MBOX_MAX_DATA]; 7970c0d06caSMauro Carvalho Chehab va_list vargs; 7980c0d06caSMauro Carvalho Chehab int i, err; 7990c0d06caSMauro Carvalho Chehab 8000c0d06caSMauro Carvalho Chehab dprintk(3, "%s() cmds = 0x%08x\n", __func__, command); 8010c0d06caSMauro Carvalho Chehab 8020c0d06caSMauro Carvalho Chehab va_start(vargs, outputcnt); 8030c0d06caSMauro Carvalho Chehab for (i = 0; i < inputcnt; i++) 8040c0d06caSMauro Carvalho Chehab data[i] = va_arg(vargs, int); 8050c0d06caSMauro Carvalho Chehab 8060c0d06caSMauro Carvalho Chehab err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data); 8070c0d06caSMauro Carvalho Chehab for (i = 0; i < outputcnt; i++) { 8080c0d06caSMauro Carvalho Chehab int *vptr = va_arg(vargs, int *); 8090c0d06caSMauro Carvalho Chehab *vptr = data[i]; 8100c0d06caSMauro Carvalho Chehab } 8110c0d06caSMauro Carvalho Chehab va_end(vargs); 8120c0d06caSMauro Carvalho Chehab 8130c0d06caSMauro Carvalho Chehab return err; 8140c0d06caSMauro Carvalho Chehab } 8150c0d06caSMauro Carvalho Chehab 8160c0d06caSMauro Carvalho Chehab static int cx231xx_find_mailbox(struct cx231xx *dev) 8170c0d06caSMauro Carvalho Chehab { 8180c0d06caSMauro Carvalho Chehab u32 signature[4] = { 8190c0d06caSMauro Carvalho Chehab 0x12345678, 0x34567812, 0x56781234, 0x78123456 8200c0d06caSMauro Carvalho Chehab }; 8210c0d06caSMauro Carvalho Chehab int signaturecnt = 0; 8220c0d06caSMauro Carvalho Chehab u32 value; 8230c0d06caSMauro Carvalho Chehab int i; 8240c0d06caSMauro Carvalho Chehab int ret = 0; 8250c0d06caSMauro Carvalho Chehab 8260c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 8270c0d06caSMauro Carvalho Chehab 8280c0d06caSMauro Carvalho Chehab for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/ 8290c0d06caSMauro Carvalho Chehab ret = mc417_memory_read(dev, i, &value); 8300c0d06caSMauro Carvalho Chehab if (ret < 0) 8310c0d06caSMauro Carvalho Chehab return ret; 8320c0d06caSMauro Carvalho Chehab if (value == signature[signaturecnt]) 8330c0d06caSMauro Carvalho Chehab signaturecnt++; 8340c0d06caSMauro Carvalho Chehab else 8350c0d06caSMauro Carvalho Chehab signaturecnt = 0; 8360c0d06caSMauro Carvalho Chehab if (4 == signaturecnt) { 8370c0d06caSMauro Carvalho Chehab dprintk(1, "Mailbox signature found at 0x%x\n", i+1); 8380c0d06caSMauro Carvalho Chehab return i+1; 8390c0d06caSMauro Carvalho Chehab } 8400c0d06caSMauro Carvalho Chehab } 8410c0d06caSMauro Carvalho Chehab dprintk(3, "Mailbox signature values not found!\n"); 8420c0d06caSMauro Carvalho Chehab return -1; 8430c0d06caSMauro Carvalho Chehab } 8440c0d06caSMauro Carvalho Chehab 8450c0d06caSMauro Carvalho Chehab static void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value, 8460c0d06caSMauro Carvalho Chehab u32 *p_fw_image) 8470c0d06caSMauro Carvalho Chehab { 8480c0d06caSMauro Carvalho Chehab 8490c0d06caSMauro Carvalho Chehab u32 temp = 0; 8500c0d06caSMauro Carvalho Chehab int i = 0; 8510c0d06caSMauro Carvalho Chehab 8520c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8); 8530c0d06caSMauro Carvalho Chehab temp = temp<<10; 8540c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8550c0d06caSMauro Carvalho Chehab p_fw_image++; 8560c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 8570c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8580c0d06caSMauro Carvalho Chehab p_fw_image++; 8590c0d06caSMauro Carvalho Chehab 8600c0d06caSMauro Carvalho Chehab /*write data byte 1;*/ 8610c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00); 8620c0d06caSMauro Carvalho Chehab temp = temp<<10; 8630c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8640c0d06caSMauro Carvalho Chehab p_fw_image++; 8650c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 8660c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8670c0d06caSMauro Carvalho Chehab p_fw_image++; 8680c0d06caSMauro Carvalho Chehab 8690c0d06caSMauro Carvalho Chehab /*write data byte 2;*/ 8700c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8); 8710c0d06caSMauro Carvalho Chehab temp = temp<<10; 8720c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8730c0d06caSMauro Carvalho Chehab p_fw_image++; 8740c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 8750c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8760c0d06caSMauro Carvalho Chehab p_fw_image++; 8770c0d06caSMauro Carvalho Chehab 8780c0d06caSMauro Carvalho Chehab /*write data byte 3;*/ 8790c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16); 8800c0d06caSMauro Carvalho Chehab temp = temp<<10; 8810c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8820c0d06caSMauro Carvalho Chehab p_fw_image++; 8830c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 8840c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8850c0d06caSMauro Carvalho Chehab p_fw_image++; 8860c0d06caSMauro Carvalho Chehab 8870c0d06caSMauro Carvalho Chehab /* write address byte 2;*/ 8880c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | 8890c0d06caSMauro Carvalho Chehab ((address & 0x003F0000)>>8); 8900c0d06caSMauro Carvalho Chehab temp = temp<<10; 8910c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8920c0d06caSMauro Carvalho Chehab p_fw_image++; 8930c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 8940c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 8950c0d06caSMauro Carvalho Chehab p_fw_image++; 8960c0d06caSMauro Carvalho Chehab 8970c0d06caSMauro Carvalho Chehab /* write address byte 1;*/ 8980c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 8990c0d06caSMauro Carvalho Chehab temp = temp<<10; 9000c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 9010c0d06caSMauro Carvalho Chehab p_fw_image++; 9020c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 9030c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 9040c0d06caSMauro Carvalho Chehab p_fw_image++; 9050c0d06caSMauro Carvalho Chehab 9060c0d06caSMauro Carvalho Chehab /* write address byte 0;*/ 9070c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8); 9080c0d06caSMauro Carvalho Chehab temp = temp<<10; 9090c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 9100c0d06caSMauro Carvalho Chehab p_fw_image++; 9110c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 9120c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 9130c0d06caSMauro Carvalho Chehab p_fw_image++; 9140c0d06caSMauro Carvalho Chehab 9150c0d06caSMauro Carvalho Chehab for (i = 0; i < 6; i++) { 9160c0d06caSMauro Carvalho Chehab *p_fw_image = 0xFFFFFFFF; 9170c0d06caSMauro Carvalho Chehab p_fw_image++; 9180c0d06caSMauro Carvalho Chehab } 9190c0d06caSMauro Carvalho Chehab } 9200c0d06caSMauro Carvalho Chehab 9210c0d06caSMauro Carvalho Chehab 9220c0d06caSMauro Carvalho Chehab static int cx231xx_load_firmware(struct cx231xx *dev) 9230c0d06caSMauro Carvalho Chehab { 9240c0d06caSMauro Carvalho Chehab static const unsigned char magic[8] = { 9250c0d06caSMauro Carvalho Chehab 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa 9260c0d06caSMauro Carvalho Chehab }; 9270c0d06caSMauro Carvalho Chehab const struct firmware *firmware; 9280c0d06caSMauro Carvalho Chehab int i, retval = 0; 9290c0d06caSMauro Carvalho Chehab u32 value = 0; 9300c0d06caSMauro Carvalho Chehab u32 gpio_output = 0; 9310c0d06caSMauro Carvalho Chehab /*u32 checksum = 0;*/ 9320c0d06caSMauro Carvalho Chehab /*u32 *dataptr;*/ 9330c0d06caSMauro Carvalho Chehab u32 transfer_size = 0; 9340c0d06caSMauro Carvalho Chehab u32 fw_data = 0; 9350c0d06caSMauro Carvalho Chehab u32 address = 0; 9360c0d06caSMauro Carvalho Chehab /*u32 current_fw[800];*/ 9370c0d06caSMauro Carvalho Chehab u32 *p_current_fw, *p_fw; 9380c0d06caSMauro Carvalho Chehab u32 *p_fw_data; 9390c0d06caSMauro Carvalho Chehab int frame = 0; 9400c0d06caSMauro Carvalho Chehab u16 _buffer_size = 4096; 9410c0d06caSMauro Carvalho Chehab u8 *p_buffer; 9420c0d06caSMauro Carvalho Chehab 9430c0d06caSMauro Carvalho Chehab p_current_fw = vmalloc(1884180 * 4); 9440c0d06caSMauro Carvalho Chehab p_fw = p_current_fw; 9450c0d06caSMauro Carvalho Chehab if (p_current_fw == NULL) { 9460c0d06caSMauro Carvalho Chehab dprintk(2, "FAIL!!!\n"); 9470c0d06caSMauro Carvalho Chehab return -1; 9480c0d06caSMauro Carvalho Chehab } 9490c0d06caSMauro Carvalho Chehab 9500c0d06caSMauro Carvalho Chehab p_buffer = vmalloc(4096); 9510c0d06caSMauro Carvalho Chehab if (p_buffer == NULL) { 9520c0d06caSMauro Carvalho Chehab dprintk(2, "FAIL!!!\n"); 9530c0d06caSMauro Carvalho Chehab return -1; 9540c0d06caSMauro Carvalho Chehab } 9550c0d06caSMauro Carvalho Chehab 9560c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 9570c0d06caSMauro Carvalho Chehab 9580c0d06caSMauro Carvalho Chehab /* Save GPIO settings before reset of APU */ 9590c0d06caSMauro Carvalho Chehab retval |= mc417_memory_read(dev, 0x9020, &gpio_output); 9600c0d06caSMauro Carvalho Chehab retval |= mc417_memory_read(dev, 0x900C, &value); 9610c0d06caSMauro Carvalho Chehab 9620c0d06caSMauro Carvalho Chehab retval = mc417_register_write(dev, 9630c0d06caSMauro Carvalho Chehab IVTV_REG_VPU, 0xFFFFFFED); 9640c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 9650c0d06caSMauro Carvalho Chehab IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); 9660c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 9670c0d06caSMauro Carvalho Chehab IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800); 9680c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 9690c0d06caSMauro Carvalho Chehab IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); 9700c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 9710c0d06caSMauro Carvalho Chehab IVTV_REG_APU, 0); 9720c0d06caSMauro Carvalho Chehab 9730c0d06caSMauro Carvalho Chehab if (retval != 0) { 9740c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s: Error with mc417_register_write\n", 9750c0d06caSMauro Carvalho Chehab __func__); 9760c0d06caSMauro Carvalho Chehab return -1; 9770c0d06caSMauro Carvalho Chehab } 9780c0d06caSMauro Carvalho Chehab 9790c0d06caSMauro Carvalho Chehab retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME, 9800c0d06caSMauro Carvalho Chehab &dev->udev->dev); 9810c0d06caSMauro Carvalho Chehab 9820c0d06caSMauro Carvalho Chehab if (retval != 0) { 9830c0d06caSMauro Carvalho Chehab printk(KERN_ERR 9840c0d06caSMauro Carvalho Chehab "ERROR: Hotplug firmware request failed (%s).\n", 9850c0d06caSMauro Carvalho Chehab CX231xx_FIRM_IMAGE_NAME); 9860c0d06caSMauro Carvalho Chehab printk(KERN_ERR "Please fix your hotplug setup, the board will " 9870c0d06caSMauro Carvalho Chehab "not work without firmware loaded!\n"); 9880c0d06caSMauro Carvalho Chehab return -1; 9890c0d06caSMauro Carvalho Chehab } 9900c0d06caSMauro Carvalho Chehab 9910c0d06caSMauro Carvalho Chehab if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) { 9920c0d06caSMauro Carvalho Chehab printk(KERN_ERR "ERROR: Firmware size mismatch " 9930c0d06caSMauro Carvalho Chehab "(have %zd, expected %d)\n", 9940c0d06caSMauro Carvalho Chehab firmware->size, CX231xx_FIRM_IMAGE_SIZE); 9950c0d06caSMauro Carvalho Chehab release_firmware(firmware); 9960c0d06caSMauro Carvalho Chehab return -1; 9970c0d06caSMauro Carvalho Chehab } 9980c0d06caSMauro Carvalho Chehab 9990c0d06caSMauro Carvalho Chehab if (0 != memcmp(firmware->data, magic, 8)) { 10000c0d06caSMauro Carvalho Chehab printk(KERN_ERR 10010c0d06caSMauro Carvalho Chehab "ERROR: Firmware magic mismatch, wrong file?\n"); 10020c0d06caSMauro Carvalho Chehab release_firmware(firmware); 10030c0d06caSMauro Carvalho Chehab return -1; 10040c0d06caSMauro Carvalho Chehab } 10050c0d06caSMauro Carvalho Chehab 10060c0d06caSMauro Carvalho Chehab initGPIO(dev); 10070c0d06caSMauro Carvalho Chehab 10080c0d06caSMauro Carvalho Chehab /* transfer to the chip */ 10090c0d06caSMauro Carvalho Chehab dprintk(2, "Loading firmware to GPIO...\n"); 10100c0d06caSMauro Carvalho Chehab p_fw_data = (u32 *)firmware->data; 10110c0d06caSMauro Carvalho Chehab dprintk(2, "firmware->size=%zd\n", firmware->size); 10120c0d06caSMauro Carvalho Chehab for (transfer_size = 0; transfer_size < firmware->size; 10130c0d06caSMauro Carvalho Chehab transfer_size += 4) { 10140c0d06caSMauro Carvalho Chehab fw_data = *p_fw_data; 10150c0d06caSMauro Carvalho Chehab 10160c0d06caSMauro Carvalho Chehab mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw); 10170c0d06caSMauro Carvalho Chehab address = address + 1; 10180c0d06caSMauro Carvalho Chehab p_current_fw += 20; 10190c0d06caSMauro Carvalho Chehab p_fw_data += 1; 10200c0d06caSMauro Carvalho Chehab } 10210c0d06caSMauro Carvalho Chehab 10220c0d06caSMauro Carvalho Chehab /*download the firmware by ep5-out*/ 10230c0d06caSMauro Carvalho Chehab 10240c0d06caSMauro Carvalho Chehab for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size); 10250c0d06caSMauro Carvalho Chehab frame++) { 10260c0d06caSMauro Carvalho Chehab for (i = 0; i < _buffer_size; i++) { 10270c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF); 10280c0d06caSMauro Carvalho Chehab i++; 10290c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8); 10300c0d06caSMauro Carvalho Chehab i++; 10310c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16); 10320c0d06caSMauro Carvalho Chehab i++; 10330c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24); 10340c0d06caSMauro Carvalho Chehab } 10350c0d06caSMauro Carvalho Chehab cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size); 10360c0d06caSMauro Carvalho Chehab } 10370c0d06caSMauro Carvalho Chehab 10380c0d06caSMauro Carvalho Chehab p_current_fw = p_fw; 10390c0d06caSMauro Carvalho Chehab vfree(p_current_fw); 10400c0d06caSMauro Carvalho Chehab p_current_fw = NULL; 10410c0d06caSMauro Carvalho Chehab uninitGPIO(dev); 10420c0d06caSMauro Carvalho Chehab release_firmware(firmware); 10430c0d06caSMauro Carvalho Chehab dprintk(1, "Firmware upload successful.\n"); 10440c0d06caSMauro Carvalho Chehab 10450c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, 10460c0d06caSMauro Carvalho Chehab IVTV_CMD_HW_BLOCKS_RST); 10470c0d06caSMauro Carvalho Chehab if (retval < 0) { 10480c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s: Error with mc417_register_write\n", 10490c0d06caSMauro Carvalho Chehab __func__); 10500c0d06caSMauro Carvalho Chehab return retval; 10510c0d06caSMauro Carvalho Chehab } 10520c0d06caSMauro Carvalho Chehab /* F/W power up disturbs the GPIOs, restore state */ 10530c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 0x9020, gpio_output); 10540c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 0x900C, value); 10550c0d06caSMauro Carvalho Chehab 10560c0d06caSMauro Carvalho Chehab retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); 10570c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); 10580c0d06caSMauro Carvalho Chehab 10590c0d06caSMauro Carvalho Chehab if (retval < 0) { 10600c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s: Error with mc417_register_write\n", 10610c0d06caSMauro Carvalho Chehab __func__); 10620c0d06caSMauro Carvalho Chehab return retval; 10630c0d06caSMauro Carvalho Chehab } 10640c0d06caSMauro Carvalho Chehab return 0; 10650c0d06caSMauro Carvalho Chehab } 10660c0d06caSMauro Carvalho Chehab 10670c0d06caSMauro Carvalho Chehab static void cx231xx_417_check_encoder(struct cx231xx *dev) 10680c0d06caSMauro Carvalho Chehab { 10690c0d06caSMauro Carvalho Chehab u32 status, seq; 10700c0d06caSMauro Carvalho Chehab 10710c0d06caSMauro Carvalho Chehab status = 0; 10720c0d06caSMauro Carvalho Chehab seq = 0; 10730c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq); 10740c0d06caSMauro Carvalho Chehab dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq); 10750c0d06caSMauro Carvalho Chehab } 10760c0d06caSMauro Carvalho Chehab 10770c0d06caSMauro Carvalho Chehab static void cx231xx_codec_settings(struct cx231xx *dev) 10780c0d06caSMauro Carvalho Chehab { 10790c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 10800c0d06caSMauro Carvalho Chehab 10810c0d06caSMauro Carvalho Chehab /* assign frame size */ 10820c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, 10830c0d06caSMauro Carvalho Chehab dev->ts1.height, dev->ts1.width); 10840c0d06caSMauro Carvalho Chehab 10850c0d06caSMauro Carvalho Chehab dev->mpeg_params.width = dev->ts1.width; 10860c0d06caSMauro Carvalho Chehab dev->mpeg_params.height = dev->ts1.height; 10870c0d06caSMauro Carvalho Chehab 10880c0d06caSMauro Carvalho Chehab cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params); 10890c0d06caSMauro Carvalho Chehab 10900c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); 10910c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); 10920c0d06caSMauro Carvalho Chehab } 10930c0d06caSMauro Carvalho Chehab 10940c0d06caSMauro Carvalho Chehab static int cx231xx_initialize_codec(struct cx231xx *dev) 10950c0d06caSMauro Carvalho Chehab { 10960c0d06caSMauro Carvalho Chehab int version; 10970c0d06caSMauro Carvalho Chehab int retval; 10980c0d06caSMauro Carvalho Chehab u32 i; 10990c0d06caSMauro Carvalho Chehab u32 val = 0; 11000c0d06caSMauro Carvalho Chehab 11010c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 11020c0d06caSMauro Carvalho Chehab cx231xx_disable656(dev); 11030c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ 11040c0d06caSMauro Carvalho Chehab if (retval < 0) { 11050c0d06caSMauro Carvalho Chehab dprintk(2, "%s() PING OK\n", __func__); 11060c0d06caSMauro Carvalho Chehab retval = cx231xx_load_firmware(dev); 11070c0d06caSMauro Carvalho Chehab if (retval < 0) { 11080c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s() f/w load failed\n", __func__); 11090c0d06caSMauro Carvalho Chehab return retval; 11100c0d06caSMauro Carvalho Chehab } 11110c0d06caSMauro Carvalho Chehab retval = cx231xx_find_mailbox(dev); 11120c0d06caSMauro Carvalho Chehab if (retval < 0) { 11130c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s() mailbox < 0, error\n", 11140c0d06caSMauro Carvalho Chehab __func__); 11150c0d06caSMauro Carvalho Chehab return -1; 11160c0d06caSMauro Carvalho Chehab } 11170c0d06caSMauro Carvalho Chehab dev->cx23417_mailbox = retval; 11180c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); 11190c0d06caSMauro Carvalho Chehab if (retval < 0) { 11200c0d06caSMauro Carvalho Chehab printk(KERN_ERR 11210c0d06caSMauro Carvalho Chehab "ERROR: cx23417 firmware ping failed!\n"); 11220c0d06caSMauro Carvalho Chehab return -1; 11230c0d06caSMauro Carvalho Chehab } 11240c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, 11250c0d06caSMauro Carvalho Chehab &version); 11260c0d06caSMauro Carvalho Chehab if (retval < 0) { 11270c0d06caSMauro Carvalho Chehab printk(KERN_ERR "ERROR: cx23417 firmware get encoder :" 11280c0d06caSMauro Carvalho Chehab "version failed!\n"); 11290c0d06caSMauro Carvalho Chehab return -1; 11300c0d06caSMauro Carvalho Chehab } 11310c0d06caSMauro Carvalho Chehab dprintk(1, "cx23417 firmware version is 0x%08x\n", version); 11320c0d06caSMauro Carvalho Chehab msleep(200); 11330c0d06caSMauro Carvalho Chehab } 11340c0d06caSMauro Carvalho Chehab 11350c0d06caSMauro Carvalho Chehab for (i = 0; i < 1; i++) { 11360c0d06caSMauro Carvalho Chehab retval = mc417_register_read(dev, 0x20f8, &val); 11370c0d06caSMauro Carvalho Chehab dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n", 11380c0d06caSMauro Carvalho Chehab val); 11390c0d06caSMauro Carvalho Chehab if (retval < 0) 11400c0d06caSMauro Carvalho Chehab return retval; 11410c0d06caSMauro Carvalho Chehab } 11420c0d06caSMauro Carvalho Chehab 11430c0d06caSMauro Carvalho Chehab cx231xx_enable656(dev); 11440c0d06caSMauro Carvalho Chehab /* stop mpeg capture */ 11450c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 11460c0d06caSMauro Carvalho Chehab 3, 0, 1, 3, 4); 11470c0d06caSMauro Carvalho Chehab 11480c0d06caSMauro Carvalho Chehab cx231xx_codec_settings(dev); 11490c0d06caSMauro Carvalho Chehab msleep(60); 11500c0d06caSMauro Carvalho Chehab 11510c0d06caSMauro Carvalho Chehab /* cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, 11520c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115); 11530c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, 11540c0d06caSMauro Carvalho Chehab CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11550c0d06caSMauro Carvalho Chehab 0, 0); 11560c0d06caSMauro Carvalho Chehab */ 11570c0d06caSMauro Carvalho Chehab 11580c0d06caSMauro Carvalho Chehab #if 0 11590c0d06caSMauro Carvalho Chehab /* TODO */ 11600c0d06caSMauro Carvalho Chehab u32 data[7]; 11610c0d06caSMauro Carvalho Chehab 11620c0d06caSMauro Carvalho Chehab /* Setup to capture VBI */ 11630c0d06caSMauro Carvalho Chehab data[0] = 0x0001BD00; 11640c0d06caSMauro Carvalho Chehab data[1] = 1; /* frames per interrupt */ 11650c0d06caSMauro Carvalho Chehab data[2] = 4; /* total bufs */ 11660c0d06caSMauro Carvalho Chehab data[3] = 0x91559155; /* start codes */ 11670c0d06caSMauro Carvalho Chehab data[4] = 0x206080C0; /* stop codes */ 11680c0d06caSMauro Carvalho Chehab data[5] = 6; /* lines */ 11690c0d06caSMauro Carvalho Chehab data[6] = 64; /* BPL */ 11700c0d06caSMauro Carvalho Chehab 11710c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1], 11720c0d06caSMauro Carvalho Chehab data[2], data[3], data[4], data[5], data[6]); 11730c0d06caSMauro Carvalho Chehab 11740c0d06caSMauro Carvalho Chehab for (i = 2; i <= 24; i++) { 11750c0d06caSMauro Carvalho Chehab int valid; 11760c0d06caSMauro Carvalho Chehab 11770c0d06caSMauro Carvalho Chehab valid = ((i >= 19) && (i <= 21)); 11780c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i, 11790c0d06caSMauro Carvalho Chehab valid, 0 , 0, 0); 11800c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, 11810c0d06caSMauro Carvalho Chehab i | 0x80000000, valid, 0, 0, 0); 11820c0d06caSMauro Carvalho Chehab } 11830c0d06caSMauro Carvalho Chehab #endif 11840c0d06caSMauro Carvalho Chehab /* cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE); 11850c0d06caSMauro Carvalho Chehab msleep(60); 11860c0d06caSMauro Carvalho Chehab */ 11870c0d06caSMauro Carvalho Chehab /* initialize the video input */ 11880c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); 11890c0d06caSMauro Carvalho Chehab if (retval < 0) 11900c0d06caSMauro Carvalho Chehab return retval; 11910c0d06caSMauro Carvalho Chehab msleep(60); 11920c0d06caSMauro Carvalho Chehab 11930c0d06caSMauro Carvalho Chehab /* Enable VIP style pixel invalidation so we work with scaled mode */ 11940c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, 2120, 0x00000080); 11950c0d06caSMauro Carvalho Chehab 11960c0d06caSMauro Carvalho Chehab /* start capturing to the host interface */ 11970c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 11980c0d06caSMauro Carvalho Chehab CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE); 11990c0d06caSMauro Carvalho Chehab if (retval < 0) 12000c0d06caSMauro Carvalho Chehab return retval; 12010c0d06caSMauro Carvalho Chehab msleep(10); 12020c0d06caSMauro Carvalho Chehab 12030c0d06caSMauro Carvalho Chehab for (i = 0; i < 1; i++) { 12040c0d06caSMauro Carvalho Chehab mc417_register_read(dev, 0x20f8, &val); 12050c0d06caSMauro Carvalho Chehab dprintk(3, "***VIM Capture Lines =%d ***\n", val); 12060c0d06caSMauro Carvalho Chehab } 12070c0d06caSMauro Carvalho Chehab 12080c0d06caSMauro Carvalho Chehab return 0; 12090c0d06caSMauro Carvalho Chehab } 12100c0d06caSMauro Carvalho Chehab 12110c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 12120c0d06caSMauro Carvalho Chehab 12130c0d06caSMauro Carvalho Chehab static int bb_buf_setup(struct videobuf_queue *q, 12140c0d06caSMauro Carvalho Chehab unsigned int *count, unsigned int *size) 12150c0d06caSMauro Carvalho Chehab { 12160c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = q->priv_data; 12170c0d06caSMauro Carvalho Chehab 12180c0d06caSMauro Carvalho Chehab fh->dev->ts1.ts_packet_size = mpeglinesize; 12190c0d06caSMauro Carvalho Chehab fh->dev->ts1.ts_packet_count = mpeglines; 12200c0d06caSMauro Carvalho Chehab 12210c0d06caSMauro Carvalho Chehab *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; 12220c0d06caSMauro Carvalho Chehab *count = mpegbufs; 12230c0d06caSMauro Carvalho Chehab 12240c0d06caSMauro Carvalho Chehab return 0; 12250c0d06caSMauro Carvalho Chehab } 12260c0d06caSMauro Carvalho Chehab static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) 12270c0d06caSMauro Carvalho Chehab { 12280c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = vq->priv_data; 12290c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 12300c0d06caSMauro Carvalho Chehab unsigned long flags = 0; 12310c0d06caSMauro Carvalho Chehab 12320c0d06caSMauro Carvalho Chehab if (in_interrupt()) 12330c0d06caSMauro Carvalho Chehab BUG(); 12340c0d06caSMauro Carvalho Chehab 12350c0d06caSMauro Carvalho Chehab spin_lock_irqsave(&dev->video_mode.slock, flags); 12360c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) { 12370c0d06caSMauro Carvalho Chehab if (dev->video_mode.isoc_ctl.buf == buf) 12380c0d06caSMauro Carvalho Chehab dev->video_mode.isoc_ctl.buf = NULL; 12390c0d06caSMauro Carvalho Chehab } else { 12400c0d06caSMauro Carvalho Chehab if (dev->video_mode.bulk_ctl.buf == buf) 12410c0d06caSMauro Carvalho Chehab dev->video_mode.bulk_ctl.buf = NULL; 12420c0d06caSMauro Carvalho Chehab } 12430c0d06caSMauro Carvalho Chehab spin_unlock_irqrestore(&dev->video_mode.slock, flags); 12440c0d06caSMauro Carvalho Chehab videobuf_waiton(vq, &buf->vb, 0, 0); 12450c0d06caSMauro Carvalho Chehab videobuf_vmalloc_free(&buf->vb); 12460c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_NEEDS_INIT; 12470c0d06caSMauro Carvalho Chehab } 12480c0d06caSMauro Carvalho Chehab 12490c0d06caSMauro Carvalho Chehab static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb, 12500c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q) 12510c0d06caSMauro Carvalho Chehab { 12520c0d06caSMauro Carvalho Chehab void *vbuf; 12530c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf; 12540c0d06caSMauro Carvalho Chehab u32 tail_data = 0; 12550c0d06caSMauro Carvalho Chehab char *p_data; 12560c0d06caSMauro Carvalho Chehab 12570c0d06caSMauro Carvalho Chehab if (dma_q->mpeg_buffer_done == 0) { 12580c0d06caSMauro Carvalho Chehab if (list_empty(&dma_q->active)) 12590c0d06caSMauro Carvalho Chehab return; 12600c0d06caSMauro Carvalho Chehab 12610c0d06caSMauro Carvalho Chehab buf = list_entry(dma_q->active.next, 12620c0d06caSMauro Carvalho Chehab struct cx231xx_buffer, vb.queue); 12630c0d06caSMauro Carvalho Chehab dev->video_mode.isoc_ctl.buf = buf; 12640c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_done = 1; 12650c0d06caSMauro Carvalho Chehab } 12660c0d06caSMauro Carvalho Chehab /* Fill buffer */ 12670c0d06caSMauro Carvalho Chehab buf = dev->video_mode.isoc_ctl.buf; 12680c0d06caSMauro Carvalho Chehab vbuf = videobuf_to_vmalloc(&buf->vb); 12690c0d06caSMauro Carvalho Chehab 12700c0d06caSMauro Carvalho Chehab if ((dma_q->mpeg_buffer_completed+len) < 12710c0d06caSMauro Carvalho Chehab mpeglines*mpeglinesize) { 12720c0d06caSMauro Carvalho Chehab if (dma_q->add_ps_package_head == 12730c0d06caSMauro Carvalho Chehab CX231XX_NEED_ADD_PS_PACKAGE_HEAD) { 12740c0d06caSMauro Carvalho Chehab memcpy(vbuf+dma_q->mpeg_buffer_completed, 12750c0d06caSMauro Carvalho Chehab dma_q->ps_head, 3); 12760c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = 12770c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed + 3; 12780c0d06caSMauro Carvalho Chehab dma_q->add_ps_package_head = 12790c0d06caSMauro Carvalho Chehab CX231XX_NONEED_PS_PACKAGE_HEAD; 12800c0d06caSMauro Carvalho Chehab } 12810c0d06caSMauro Carvalho Chehab memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len); 12820c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = 12830c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed + len; 12840c0d06caSMauro Carvalho Chehab } else { 12850c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_done = 0; 12860c0d06caSMauro Carvalho Chehab 12870c0d06caSMauro Carvalho Chehab tail_data = 12880c0d06caSMauro Carvalho Chehab mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed; 12890c0d06caSMauro Carvalho Chehab memcpy(vbuf+dma_q->mpeg_buffer_completed, 12900c0d06caSMauro Carvalho Chehab data, tail_data); 12910c0d06caSMauro Carvalho Chehab 12920c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_DONE; 12930c0d06caSMauro Carvalho Chehab buf->vb.field_count++; 12948e6057b5SSakari Ailus v4l2_get_timestamp(&buf->vb.ts); 12950c0d06caSMauro Carvalho Chehab list_del(&buf->vb.queue); 12960c0d06caSMauro Carvalho Chehab wake_up(&buf->vb.done); 12970c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = 0; 12980c0d06caSMauro Carvalho Chehab 12990c0d06caSMauro Carvalho Chehab if (len - tail_data > 0) { 13000c0d06caSMauro Carvalho Chehab p_data = data + tail_data; 13010c0d06caSMauro Carvalho Chehab dma_q->left_data_count = len - tail_data; 13020c0d06caSMauro Carvalho Chehab memcpy(dma_q->p_left_data, 13030c0d06caSMauro Carvalho Chehab p_data, len - tail_data); 13040c0d06caSMauro Carvalho Chehab } 13050c0d06caSMauro Carvalho Chehab 13060c0d06caSMauro Carvalho Chehab } 13070c0d06caSMauro Carvalho Chehab 13080c0d06caSMauro Carvalho Chehab return; 13090c0d06caSMauro Carvalho Chehab } 13100c0d06caSMauro Carvalho Chehab 13110c0d06caSMauro Carvalho Chehab static void buffer_filled(char *data, int len, struct urb *urb, 13120c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q) 13130c0d06caSMauro Carvalho Chehab { 13140c0d06caSMauro Carvalho Chehab void *vbuf; 13150c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf; 13160c0d06caSMauro Carvalho Chehab 13170c0d06caSMauro Carvalho Chehab if (list_empty(&dma_q->active)) 13180c0d06caSMauro Carvalho Chehab return; 13190c0d06caSMauro Carvalho Chehab 13200c0d06caSMauro Carvalho Chehab 13210c0d06caSMauro Carvalho Chehab buf = list_entry(dma_q->active.next, 13220c0d06caSMauro Carvalho Chehab struct cx231xx_buffer, vb.queue); 13230c0d06caSMauro Carvalho Chehab 13240c0d06caSMauro Carvalho Chehab 13250c0d06caSMauro Carvalho Chehab /* Fill buffer */ 13260c0d06caSMauro Carvalho Chehab vbuf = videobuf_to_vmalloc(&buf->vb); 13270c0d06caSMauro Carvalho Chehab memcpy(vbuf, data, len); 13280c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_DONE; 13290c0d06caSMauro Carvalho Chehab buf->vb.field_count++; 13308e6057b5SSakari Ailus v4l2_get_timestamp(&buf->vb.ts); 13310c0d06caSMauro Carvalho Chehab list_del(&buf->vb.queue); 13320c0d06caSMauro Carvalho Chehab wake_up(&buf->vb.done); 13330c0d06caSMauro Carvalho Chehab 13340c0d06caSMauro Carvalho Chehab return; 13350c0d06caSMauro Carvalho Chehab } 13360c0d06caSMauro Carvalho Chehab static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) 13370c0d06caSMauro Carvalho Chehab { 13380c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q = urb->context; 13390c0d06caSMauro Carvalho Chehab unsigned char *p_buffer; 13400c0d06caSMauro Carvalho Chehab u32 buffer_size = 0; 13410c0d06caSMauro Carvalho Chehab u32 i = 0; 13420c0d06caSMauro Carvalho Chehab 13430c0d06caSMauro Carvalho Chehab for (i = 0; i < urb->number_of_packets; i++) { 13440c0d06caSMauro Carvalho Chehab if (dma_q->left_data_count > 0) { 13450c0d06caSMauro Carvalho Chehab buffer_copy(dev, dma_q->p_left_data, 13460c0d06caSMauro Carvalho Chehab dma_q->left_data_count, urb, dma_q); 13470c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = dma_q->left_data_count; 13480c0d06caSMauro Carvalho Chehab dma_q->left_data_count = 0; 13490c0d06caSMauro Carvalho Chehab } 13500c0d06caSMauro Carvalho Chehab 13510c0d06caSMauro Carvalho Chehab p_buffer = urb->transfer_buffer + 13520c0d06caSMauro Carvalho Chehab urb->iso_frame_desc[i].offset; 13530c0d06caSMauro Carvalho Chehab buffer_size = urb->iso_frame_desc[i].actual_length; 13540c0d06caSMauro Carvalho Chehab 13550c0d06caSMauro Carvalho Chehab if (buffer_size > 0) 13560c0d06caSMauro Carvalho Chehab buffer_copy(dev, p_buffer, buffer_size, urb, dma_q); 13570c0d06caSMauro Carvalho Chehab } 13580c0d06caSMauro Carvalho Chehab 13590c0d06caSMauro Carvalho Chehab return 0; 13600c0d06caSMauro Carvalho Chehab } 13610c0d06caSMauro Carvalho Chehab static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) 13620c0d06caSMauro Carvalho Chehab { 13630c0d06caSMauro Carvalho Chehab 13640c0d06caSMauro Carvalho Chehab /*char *outp;*/ 13650c0d06caSMauro Carvalho Chehab /*struct cx231xx_buffer *buf;*/ 13660c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q = urb->context; 13670c0d06caSMauro Carvalho Chehab unsigned char *p_buffer, *buffer; 13680c0d06caSMauro Carvalho Chehab u32 buffer_size = 0; 13690c0d06caSMauro Carvalho Chehab 13700c0d06caSMauro Carvalho Chehab p_buffer = urb->transfer_buffer; 13710c0d06caSMauro Carvalho Chehab buffer_size = urb->actual_length; 13720c0d06caSMauro Carvalho Chehab 13730c0d06caSMauro Carvalho Chehab buffer = kmalloc(buffer_size, GFP_ATOMIC); 13740c0d06caSMauro Carvalho Chehab 13750c0d06caSMauro Carvalho Chehab memcpy(buffer, dma_q->ps_head, 3); 13760c0d06caSMauro Carvalho Chehab memcpy(buffer+3, p_buffer, buffer_size-3); 13770c0d06caSMauro Carvalho Chehab memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3); 13780c0d06caSMauro Carvalho Chehab 13790c0d06caSMauro Carvalho Chehab p_buffer = buffer; 13800c0d06caSMauro Carvalho Chehab buffer_filled(p_buffer, buffer_size, urb, dma_q); 13810c0d06caSMauro Carvalho Chehab 13820c0d06caSMauro Carvalho Chehab kfree(buffer); 13830c0d06caSMauro Carvalho Chehab return 0; 13840c0d06caSMauro Carvalho Chehab } 13850c0d06caSMauro Carvalho Chehab 13860c0d06caSMauro Carvalho Chehab static int bb_buf_prepare(struct videobuf_queue *q, 13870c0d06caSMauro Carvalho Chehab struct videobuf_buffer *vb, enum v4l2_field field) 13880c0d06caSMauro Carvalho Chehab { 13890c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = q->priv_data; 13900c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf = 13910c0d06caSMauro Carvalho Chehab container_of(vb, struct cx231xx_buffer, vb); 13920c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 13930c0d06caSMauro Carvalho Chehab int rc = 0, urb_init = 0; 13940c0d06caSMauro Carvalho Chehab int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; 13950c0d06caSMauro Carvalho Chehab 13960c0d06caSMauro Carvalho Chehab dma_qq = &dev->video_mode.vidq; 13970c0d06caSMauro Carvalho Chehab 13980c0d06caSMauro Carvalho Chehab if (0 != buf->vb.baddr && buf->vb.bsize < size) 13990c0d06caSMauro Carvalho Chehab return -EINVAL; 14000c0d06caSMauro Carvalho Chehab buf->vb.width = fh->dev->ts1.ts_packet_size; 14010c0d06caSMauro Carvalho Chehab buf->vb.height = fh->dev->ts1.ts_packet_count; 14020c0d06caSMauro Carvalho Chehab buf->vb.size = size; 14030c0d06caSMauro Carvalho Chehab buf->vb.field = field; 14040c0d06caSMauro Carvalho Chehab 14050c0d06caSMauro Carvalho Chehab if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { 14060c0d06caSMauro Carvalho Chehab rc = videobuf_iolock(q, &buf->vb, NULL); 14070c0d06caSMauro Carvalho Chehab if (rc < 0) 14080c0d06caSMauro Carvalho Chehab goto fail; 14090c0d06caSMauro Carvalho Chehab } 14100c0d06caSMauro Carvalho Chehab 14110c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) { 14120c0d06caSMauro Carvalho Chehab if (!dev->video_mode.isoc_ctl.num_bufs) 14130c0d06caSMauro Carvalho Chehab urb_init = 1; 14140c0d06caSMauro Carvalho Chehab } else { 14150c0d06caSMauro Carvalho Chehab if (!dev->video_mode.bulk_ctl.num_bufs) 14160c0d06caSMauro Carvalho Chehab urb_init = 1; 14170c0d06caSMauro Carvalho Chehab } 14180c0d06caSMauro Carvalho Chehab /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n", 14190c0d06caSMauro Carvalho Chehab urb_init, dev->video_mode.max_pkt_size);*/ 14200c0d06caSMauro Carvalho Chehab dev->mode_tv = 1; 14210c0d06caSMauro Carvalho Chehab 14220c0d06caSMauro Carvalho Chehab if (urb_init) { 14230c0d06caSMauro Carvalho Chehab rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); 14240c0d06caSMauro Carvalho Chehab rc = cx231xx_unmute_audio(dev); 14250c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) { 14260c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_TS1, 4); 14270c0d06caSMauro Carvalho Chehab rc = cx231xx_init_isoc(dev, mpeglines, 14280c0d06caSMauro Carvalho Chehab mpegbufs, 14290c0d06caSMauro Carvalho Chehab dev->ts1_mode.max_pkt_size, 14300c0d06caSMauro Carvalho Chehab cx231xx_isoc_copy); 14310c0d06caSMauro Carvalho Chehab } else { 14320c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_TS1, 0); 14330c0d06caSMauro Carvalho Chehab rc = cx231xx_init_bulk(dev, mpeglines, 14340c0d06caSMauro Carvalho Chehab mpegbufs, 14350c0d06caSMauro Carvalho Chehab dev->ts1_mode.max_pkt_size, 14360c0d06caSMauro Carvalho Chehab cx231xx_bulk_copy); 14370c0d06caSMauro Carvalho Chehab } 14380c0d06caSMauro Carvalho Chehab if (rc < 0) 14390c0d06caSMauro Carvalho Chehab goto fail; 14400c0d06caSMauro Carvalho Chehab } 14410c0d06caSMauro Carvalho Chehab 14420c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_PREPARED; 14430c0d06caSMauro Carvalho Chehab return 0; 14440c0d06caSMauro Carvalho Chehab 14450c0d06caSMauro Carvalho Chehab fail: 14460c0d06caSMauro Carvalho Chehab free_buffer(q, buf); 14470c0d06caSMauro Carvalho Chehab return rc; 14480c0d06caSMauro Carvalho Chehab } 14490c0d06caSMauro Carvalho Chehab 14500c0d06caSMauro Carvalho Chehab static void bb_buf_queue(struct videobuf_queue *q, 14510c0d06caSMauro Carvalho Chehab struct videobuf_buffer *vb) 14520c0d06caSMauro Carvalho Chehab { 14530c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = q->priv_data; 14540c0d06caSMauro Carvalho Chehab 14550c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf = 14560c0d06caSMauro Carvalho Chehab container_of(vb, struct cx231xx_buffer, vb); 14570c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 14580c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; 14590c0d06caSMauro Carvalho Chehab 14600c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_QUEUED; 14610c0d06caSMauro Carvalho Chehab list_add_tail(&buf->vb.queue, &vidq->active); 14620c0d06caSMauro Carvalho Chehab 14630c0d06caSMauro Carvalho Chehab } 14640c0d06caSMauro Carvalho Chehab 14650c0d06caSMauro Carvalho Chehab static void bb_buf_release(struct videobuf_queue *q, 14660c0d06caSMauro Carvalho Chehab struct videobuf_buffer *vb) 14670c0d06caSMauro Carvalho Chehab { 14680c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf = 14690c0d06caSMauro Carvalho Chehab container_of(vb, struct cx231xx_buffer, vb); 14700c0d06caSMauro Carvalho Chehab /*struct cx231xx_fh *fh = q->priv_data;*/ 14710c0d06caSMauro Carvalho Chehab /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/ 14720c0d06caSMauro Carvalho Chehab 14730c0d06caSMauro Carvalho Chehab free_buffer(q, buf); 14740c0d06caSMauro Carvalho Chehab } 14750c0d06caSMauro Carvalho Chehab 14760c0d06caSMauro Carvalho Chehab static struct videobuf_queue_ops cx231xx_qops = { 14770c0d06caSMauro Carvalho Chehab .buf_setup = bb_buf_setup, 14780c0d06caSMauro Carvalho Chehab .buf_prepare = bb_buf_prepare, 14790c0d06caSMauro Carvalho Chehab .buf_queue = bb_buf_queue, 14800c0d06caSMauro Carvalho Chehab .buf_release = bb_buf_release, 14810c0d06caSMauro Carvalho Chehab }; 14820c0d06caSMauro Carvalho Chehab 14830c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 14840c0d06caSMauro Carvalho Chehab 14850c0d06caSMauro Carvalho Chehab static const u32 *ctrl_classes[] = { 14860c0d06caSMauro Carvalho Chehab cx2341x_mpeg_ctrls, 14870c0d06caSMauro Carvalho Chehab NULL 14880c0d06caSMauro Carvalho Chehab }; 14890c0d06caSMauro Carvalho Chehab 14900c0d06caSMauro Carvalho Chehab static int cx231xx_queryctrl(struct cx231xx *dev, 14910c0d06caSMauro Carvalho Chehab struct v4l2_queryctrl *qctrl) 14920c0d06caSMauro Carvalho Chehab { 14930c0d06caSMauro Carvalho Chehab qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); 14940c0d06caSMauro Carvalho Chehab if (qctrl->id == 0) 14950c0d06caSMauro Carvalho Chehab return -EINVAL; 14960c0d06caSMauro Carvalho Chehab 14970c0d06caSMauro Carvalho Chehab /* MPEG V4L2 controls */ 14980c0d06caSMauro Carvalho Chehab if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl)) 14990c0d06caSMauro Carvalho Chehab qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; 15000c0d06caSMauro Carvalho Chehab 15010c0d06caSMauro Carvalho Chehab return 0; 15020c0d06caSMauro Carvalho Chehab } 15030c0d06caSMauro Carvalho Chehab 15040c0d06caSMauro Carvalho Chehab static int cx231xx_querymenu(struct cx231xx *dev, 15050c0d06caSMauro Carvalho Chehab struct v4l2_querymenu *qmenu) 15060c0d06caSMauro Carvalho Chehab { 15070c0d06caSMauro Carvalho Chehab struct v4l2_queryctrl qctrl; 15080c0d06caSMauro Carvalho Chehab 15090c0d06caSMauro Carvalho Chehab qctrl.id = qmenu->id; 15100c0d06caSMauro Carvalho Chehab cx231xx_queryctrl(dev, &qctrl); 15110c0d06caSMauro Carvalho Chehab return v4l2_ctrl_query_menu(qmenu, &qctrl, 15120c0d06caSMauro Carvalho Chehab cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); 15130c0d06caSMauro Carvalho Chehab } 15140c0d06caSMauro Carvalho Chehab 15150c0d06caSMauro Carvalho Chehab static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) 15160c0d06caSMauro Carvalho Chehab { 15170c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 15180c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 15190c0d06caSMauro Carvalho Chehab 15200c0d06caSMauro Carvalho Chehab *norm = dev->encodernorm.id; 15210c0d06caSMauro Carvalho Chehab return 0; 15220c0d06caSMauro Carvalho Chehab } 15230c0d06caSMauro Carvalho Chehab static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) 15240c0d06caSMauro Carvalho Chehab { 15250c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 15260c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 15270c0d06caSMauro Carvalho Chehab unsigned int i; 15280c0d06caSMauro Carvalho Chehab 15290c0d06caSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++) 15300c0d06caSMauro Carvalho Chehab if (*id & cx231xx_tvnorms[i].id) 15310c0d06caSMauro Carvalho Chehab break; 15320c0d06caSMauro Carvalho Chehab if (i == ARRAY_SIZE(cx231xx_tvnorms)) 15330c0d06caSMauro Carvalho Chehab return -EINVAL; 15340c0d06caSMauro Carvalho Chehab dev->encodernorm = cx231xx_tvnorms[i]; 15350c0d06caSMauro Carvalho Chehab 15360c0d06caSMauro Carvalho Chehab if (dev->encodernorm.id & 0xb000) { 15370c0d06caSMauro Carvalho Chehab dprintk(3, "encodernorm set to NTSC\n"); 15380c0d06caSMauro Carvalho Chehab dev->norm = V4L2_STD_NTSC; 15390c0d06caSMauro Carvalho Chehab dev->ts1.height = 480; 15400c0d06caSMauro Carvalho Chehab dev->mpeg_params.is_50hz = 0; 15410c0d06caSMauro Carvalho Chehab } else { 15420c0d06caSMauro Carvalho Chehab dprintk(3, "encodernorm set to PAL\n"); 15430c0d06caSMauro Carvalho Chehab dev->norm = V4L2_STD_PAL_B; 15440c0d06caSMauro Carvalho Chehab dev->ts1.height = 576; 15450c0d06caSMauro Carvalho Chehab dev->mpeg_params.is_50hz = 1; 15460c0d06caSMauro Carvalho Chehab } 15470c0d06caSMauro Carvalho Chehab call_all(dev, core, s_std, dev->norm); 15480c0d06caSMauro Carvalho Chehab /* do mode control overrides */ 15490c0d06caSMauro Carvalho Chehab cx231xx_do_mode_ctrl_overrides(dev); 15500c0d06caSMauro Carvalho Chehab 15510c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_s_std() i=0x%x\n", i); 15520c0d06caSMauro Carvalho Chehab return 0; 15530c0d06caSMauro Carvalho Chehab } 15540c0d06caSMauro Carvalho Chehab static const char *iname[] = { 15550c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_COMPOSITE1] = "Composite1", 15560c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_SVIDEO] = "S-Video", 15570c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_TELEVISION] = "Television", 15580c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_CABLE] = "Cable TV", 15590c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_DVB] = "DVB", 15600c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_DEBUG] = "for debug only", 15610c0d06caSMauro Carvalho Chehab }; 15620c0d06caSMauro Carvalho Chehab static int vidioc_enum_input(struct file *file, void *priv, 15630c0d06caSMauro Carvalho Chehab struct v4l2_input *i) 15640c0d06caSMauro Carvalho Chehab { 15650c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 15660c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 15670c0d06caSMauro Carvalho Chehab struct cx231xx_input *input; 15680c0d06caSMauro Carvalho Chehab int n; 15690c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index); 15700c0d06caSMauro Carvalho Chehab 15710c0d06caSMauro Carvalho Chehab if (i->index >= 4) 15720c0d06caSMauro Carvalho Chehab return -EINVAL; 15730c0d06caSMauro Carvalho Chehab 15740c0d06caSMauro Carvalho Chehab 15750c0d06caSMauro Carvalho Chehab input = &cx231xx_boards[dev->model].input[i->index]; 15760c0d06caSMauro Carvalho Chehab 15770c0d06caSMauro Carvalho Chehab if (input->type == 0) 15780c0d06caSMauro Carvalho Chehab return -EINVAL; 15790c0d06caSMauro Carvalho Chehab 15800c0d06caSMauro Carvalho Chehab /* FIXME 15810c0d06caSMauro Carvalho Chehab * strcpy(i->name, input->name); */ 15820c0d06caSMauro Carvalho Chehab 15830c0d06caSMauro Carvalho Chehab n = i->index; 15840c0d06caSMauro Carvalho Chehab strcpy(i->name, iname[INPUT(n)->type]); 15850c0d06caSMauro Carvalho Chehab 15860c0d06caSMauro Carvalho Chehab if (input->type == CX231XX_VMUX_TELEVISION || 15870c0d06caSMauro Carvalho Chehab input->type == CX231XX_VMUX_CABLE) 15880c0d06caSMauro Carvalho Chehab i->type = V4L2_INPUT_TYPE_TUNER; 15890c0d06caSMauro Carvalho Chehab else 15900c0d06caSMauro Carvalho Chehab i->type = V4L2_INPUT_TYPE_CAMERA; 15910c0d06caSMauro Carvalho Chehab 15920c0d06caSMauro Carvalho Chehab 15930c0d06caSMauro Carvalho Chehab return 0; 15940c0d06caSMauro Carvalho Chehab } 15950c0d06caSMauro Carvalho Chehab 15960c0d06caSMauro Carvalho Chehab static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) 15970c0d06caSMauro Carvalho Chehab { 15980c0d06caSMauro Carvalho Chehab *i = 0; 15990c0d06caSMauro Carvalho Chehab return 0; 16000c0d06caSMauro Carvalho Chehab } 16010c0d06caSMauro Carvalho Chehab 16020c0d06caSMauro Carvalho Chehab static int vidioc_s_input(struct file *file, void *priv, unsigned int i) 16030c0d06caSMauro Carvalho Chehab { 16040c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 16050c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 16060c0d06caSMauro Carvalho Chehab 16070c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_s_input() i=%d\n", i); 16080c0d06caSMauro Carvalho Chehab 16090c0d06caSMauro Carvalho Chehab video_mux(dev, i); 16100c0d06caSMauro Carvalho Chehab 16110c0d06caSMauro Carvalho Chehab if (i >= 4) 16120c0d06caSMauro Carvalho Chehab return -EINVAL; 16130c0d06caSMauro Carvalho Chehab dev->input = i; 16140c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_s_input()\n"); 16150c0d06caSMauro Carvalho Chehab return 0; 16160c0d06caSMauro Carvalho Chehab } 16170c0d06caSMauro Carvalho Chehab 16180c0d06caSMauro Carvalho Chehab static int vidioc_s_ctrl(struct file *file, void *priv, 16190c0d06caSMauro Carvalho Chehab struct v4l2_control *ctl) 16200c0d06caSMauro Carvalho Chehab { 16210c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 16220c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 16230c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_s_ctrl()\n"); 16240c0d06caSMauro Carvalho Chehab /* Update the A/V core */ 16250c0d06caSMauro Carvalho Chehab call_all(dev, core, s_ctrl, ctl); 16260c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_s_ctrl()\n"); 16270c0d06caSMauro Carvalho Chehab return 0; 16280c0d06caSMauro Carvalho Chehab } 16290c0d06caSMauro Carvalho Chehab static struct v4l2_capability pvr_capability = { 16300c0d06caSMauro Carvalho Chehab .driver = "cx231xx", 16310c0d06caSMauro Carvalho Chehab .card = "VideoGrabber", 16320c0d06caSMauro Carvalho Chehab .bus_info = "usb", 16330c0d06caSMauro Carvalho Chehab .version = 1, 16340c0d06caSMauro Carvalho Chehab .capabilities = (V4L2_CAP_VIDEO_CAPTURE | 16350c0d06caSMauro Carvalho Chehab V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | 16360c0d06caSMauro Carvalho Chehab V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), 16370c0d06caSMauro Carvalho Chehab }; 16380c0d06caSMauro Carvalho Chehab static int vidioc_querycap(struct file *file, void *priv, 16390c0d06caSMauro Carvalho Chehab struct v4l2_capability *cap) 16400c0d06caSMauro Carvalho Chehab { 16410c0d06caSMauro Carvalho Chehab 16420c0d06caSMauro Carvalho Chehab 16430c0d06caSMauro Carvalho Chehab 16440c0d06caSMauro Carvalho Chehab memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); 16450c0d06caSMauro Carvalho Chehab return 0; 16460c0d06caSMauro Carvalho Chehab } 16470c0d06caSMauro Carvalho Chehab 16480c0d06caSMauro Carvalho Chehab static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 16490c0d06caSMauro Carvalho Chehab struct v4l2_fmtdesc *f) 16500c0d06caSMauro Carvalho Chehab { 16510c0d06caSMauro Carvalho Chehab 16520c0d06caSMauro Carvalho Chehab if (f->index != 0) 16530c0d06caSMauro Carvalho Chehab return -EINVAL; 16540c0d06caSMauro Carvalho Chehab 16550c0d06caSMauro Carvalho Chehab strlcpy(f->description, "MPEG", sizeof(f->description)); 16560c0d06caSMauro Carvalho Chehab f->pixelformat = V4L2_PIX_FMT_MPEG; 16570c0d06caSMauro Carvalho Chehab 16580c0d06caSMauro Carvalho Chehab return 0; 16590c0d06caSMauro Carvalho Chehab } 16600c0d06caSMauro Carvalho Chehab 16610c0d06caSMauro Carvalho Chehab static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, 16620c0d06caSMauro Carvalho Chehab struct v4l2_format *f) 16630c0d06caSMauro Carvalho Chehab { 16640c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 16650c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 16660c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_g_fmt_vid_cap()\n"); 16670c0d06caSMauro Carvalho Chehab f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 16680c0d06caSMauro Carvalho Chehab f->fmt.pix.bytesperline = 0; 16690c0d06caSMauro Carvalho Chehab f->fmt.pix.sizeimage = 16700c0d06caSMauro Carvalho Chehab dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; 16710c0d06caSMauro Carvalho Chehab f->fmt.pix.colorspace = 0; 16720c0d06caSMauro Carvalho Chehab f->fmt.pix.width = dev->ts1.width; 16730c0d06caSMauro Carvalho Chehab f->fmt.pix.height = dev->ts1.height; 16740c0d06caSMauro Carvalho Chehab f->fmt.pix.field = fh->vidq.field; 16750c0d06caSMauro Carvalho Chehab dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", 16760c0d06caSMauro Carvalho Chehab dev->ts1.width, dev->ts1.height, fh->vidq.field); 16770c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_g_fmt_vid_cap()\n"); 16780c0d06caSMauro Carvalho Chehab return 0; 16790c0d06caSMauro Carvalho Chehab } 16800c0d06caSMauro Carvalho Chehab 16810c0d06caSMauro Carvalho Chehab static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, 16820c0d06caSMauro Carvalho Chehab struct v4l2_format *f) 16830c0d06caSMauro Carvalho Chehab { 16840c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 16850c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 16860c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_try_fmt_vid_cap()\n"); 16870c0d06caSMauro Carvalho Chehab f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 16880c0d06caSMauro Carvalho Chehab f->fmt.pix.bytesperline = 0; 16890c0d06caSMauro Carvalho Chehab f->fmt.pix.sizeimage = 16900c0d06caSMauro Carvalho Chehab dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; 16910c0d06caSMauro Carvalho Chehab f->fmt.pix.colorspace = 0; 16920c0d06caSMauro Carvalho Chehab dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", 16930c0d06caSMauro Carvalho Chehab dev->ts1.width, dev->ts1.height, fh->vidq.field); 16940c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_try_fmt_vid_cap()\n"); 16950c0d06caSMauro Carvalho Chehab return 0; 16960c0d06caSMauro Carvalho Chehab } 16970c0d06caSMauro Carvalho Chehab 16980c0d06caSMauro Carvalho Chehab static int vidioc_reqbufs(struct file *file, void *priv, 16990c0d06caSMauro Carvalho Chehab struct v4l2_requestbuffers *p) 17000c0d06caSMauro Carvalho Chehab { 17010c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 17020c0d06caSMauro Carvalho Chehab 17030c0d06caSMauro Carvalho Chehab return videobuf_reqbufs(&fh->vidq, p); 17040c0d06caSMauro Carvalho Chehab } 17050c0d06caSMauro Carvalho Chehab 17060c0d06caSMauro Carvalho Chehab static int vidioc_querybuf(struct file *file, void *priv, 17070c0d06caSMauro Carvalho Chehab struct v4l2_buffer *p) 17080c0d06caSMauro Carvalho Chehab { 17090c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 17100c0d06caSMauro Carvalho Chehab 17110c0d06caSMauro Carvalho Chehab return videobuf_querybuf(&fh->vidq, p); 17120c0d06caSMauro Carvalho Chehab } 17130c0d06caSMauro Carvalho Chehab 17140c0d06caSMauro Carvalho Chehab static int vidioc_qbuf(struct file *file, void *priv, 17150c0d06caSMauro Carvalho Chehab struct v4l2_buffer *p) 17160c0d06caSMauro Carvalho Chehab { 17170c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 17180c0d06caSMauro Carvalho Chehab 17190c0d06caSMauro Carvalho Chehab return videobuf_qbuf(&fh->vidq, p); 17200c0d06caSMauro Carvalho Chehab } 17210c0d06caSMauro Carvalho Chehab 17220c0d06caSMauro Carvalho Chehab static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) 17230c0d06caSMauro Carvalho Chehab { 17240c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 17250c0d06caSMauro Carvalho Chehab 17260c0d06caSMauro Carvalho Chehab return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK); 17270c0d06caSMauro Carvalho Chehab } 17280c0d06caSMauro Carvalho Chehab 17290c0d06caSMauro Carvalho Chehab 17300c0d06caSMauro Carvalho Chehab static int vidioc_streamon(struct file *file, void *priv, 17310c0d06caSMauro Carvalho Chehab enum v4l2_buf_type i) 17320c0d06caSMauro Carvalho Chehab { 17330c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 17340c0d06caSMauro Carvalho Chehab 17350c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 17360c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_streamon()\n"); 17370c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_TS1, 0); 17380c0d06caSMauro Carvalho Chehab cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); 17390c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) 17400c0d06caSMauro Carvalho Chehab cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, 17410c0d06caSMauro Carvalho Chehab CX231XX_NUM_BUFS, 17420c0d06caSMauro Carvalho Chehab dev->video_mode.max_pkt_size, 17430c0d06caSMauro Carvalho Chehab cx231xx_isoc_copy); 17440c0d06caSMauro Carvalho Chehab else { 17450c0d06caSMauro Carvalho Chehab cx231xx_init_bulk(dev, 320, 17460c0d06caSMauro Carvalho Chehab 5, 17470c0d06caSMauro Carvalho Chehab dev->ts1_mode.max_pkt_size, 17480c0d06caSMauro Carvalho Chehab cx231xx_bulk_copy); 17490c0d06caSMauro Carvalho Chehab } 17500c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_streamon()\n"); 17510c0d06caSMauro Carvalho Chehab return videobuf_streamon(&fh->vidq); 17520c0d06caSMauro Carvalho Chehab } 17530c0d06caSMauro Carvalho Chehab 17540c0d06caSMauro Carvalho Chehab static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) 17550c0d06caSMauro Carvalho Chehab { 17560c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 17570c0d06caSMauro Carvalho Chehab 17580c0d06caSMauro Carvalho Chehab return videobuf_streamoff(&fh->vidq); 17590c0d06caSMauro Carvalho Chehab } 17600c0d06caSMauro Carvalho Chehab 17610c0d06caSMauro Carvalho Chehab static int vidioc_g_ext_ctrls(struct file *file, void *priv, 17620c0d06caSMauro Carvalho Chehab struct v4l2_ext_controls *f) 17630c0d06caSMauro Carvalho Chehab { 17640c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 17650c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 17660c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_g_ext_ctrls()\n"); 17670c0d06caSMauro Carvalho Chehab if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 17680c0d06caSMauro Carvalho Chehab return -EINVAL; 17690c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_g_ext_ctrls()\n"); 17700c0d06caSMauro Carvalho Chehab return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS); 17710c0d06caSMauro Carvalho Chehab } 17720c0d06caSMauro Carvalho Chehab 17730c0d06caSMauro Carvalho Chehab static int vidioc_s_ext_ctrls(struct file *file, void *priv, 17740c0d06caSMauro Carvalho Chehab struct v4l2_ext_controls *f) 17750c0d06caSMauro Carvalho Chehab { 17760c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 17770c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 17780c0d06caSMauro Carvalho Chehab struct cx2341x_mpeg_params p; 17790c0d06caSMauro Carvalho Chehab int err; 17800c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_s_ext_ctrls()\n"); 17810c0d06caSMauro Carvalho Chehab if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 17820c0d06caSMauro Carvalho Chehab return -EINVAL; 17830c0d06caSMauro Carvalho Chehab 17840c0d06caSMauro Carvalho Chehab p = dev->mpeg_params; 17850c0d06caSMauro Carvalho Chehab err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); 17860c0d06caSMauro Carvalho Chehab if (err == 0) { 17870c0d06caSMauro Carvalho Chehab err = cx2341x_update(dev, cx231xx_mbox_func, 17880c0d06caSMauro Carvalho Chehab &dev->mpeg_params, &p); 17890c0d06caSMauro Carvalho Chehab dev->mpeg_params = p; 17900c0d06caSMauro Carvalho Chehab } 17910c0d06caSMauro Carvalho Chehab 17920c0d06caSMauro Carvalho Chehab return err; 17930c0d06caSMauro Carvalho Chehab 17940c0d06caSMauro Carvalho Chehab 17950c0d06caSMauro Carvalho Chehab return 0; 17960c0d06caSMauro Carvalho Chehab } 17970c0d06caSMauro Carvalho Chehab 17980c0d06caSMauro Carvalho Chehab static int vidioc_try_ext_ctrls(struct file *file, void *priv, 17990c0d06caSMauro Carvalho Chehab struct v4l2_ext_controls *f) 18000c0d06caSMauro Carvalho Chehab { 18010c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 18020c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 18030c0d06caSMauro Carvalho Chehab struct cx2341x_mpeg_params p; 18040c0d06caSMauro Carvalho Chehab int err; 18050c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_try_ext_ctrls()\n"); 18060c0d06caSMauro Carvalho Chehab if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 18070c0d06caSMauro Carvalho Chehab return -EINVAL; 18080c0d06caSMauro Carvalho Chehab 18090c0d06caSMauro Carvalho Chehab p = dev->mpeg_params; 18100c0d06caSMauro Carvalho Chehab err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); 18110c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err); 18120c0d06caSMauro Carvalho Chehab return err; 18130c0d06caSMauro Carvalho Chehab } 18140c0d06caSMauro Carvalho Chehab 18150c0d06caSMauro Carvalho Chehab static int vidioc_log_status(struct file *file, void *priv) 18160c0d06caSMauro Carvalho Chehab { 18170c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 18180c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 18190c0d06caSMauro Carvalho Chehab char name[32 + 2]; 18200c0d06caSMauro Carvalho Chehab 18210c0d06caSMauro Carvalho Chehab snprintf(name, sizeof(name), "%s/2", dev->name); 18220c0d06caSMauro Carvalho Chehab dprintk(3, 18230c0d06caSMauro Carvalho Chehab "%s/2: ============ START LOG STATUS ============\n", 18240c0d06caSMauro Carvalho Chehab dev->name); 18250c0d06caSMauro Carvalho Chehab call_all(dev, core, log_status); 18260c0d06caSMauro Carvalho Chehab cx2341x_log_status(&dev->mpeg_params, name); 18270c0d06caSMauro Carvalho Chehab dprintk(3, 18280c0d06caSMauro Carvalho Chehab "%s/2: ============= END LOG STATUS =============\n", 18290c0d06caSMauro Carvalho Chehab dev->name); 18300c0d06caSMauro Carvalho Chehab return 0; 18310c0d06caSMauro Carvalho Chehab } 18320c0d06caSMauro Carvalho Chehab 18330c0d06caSMauro Carvalho Chehab static int vidioc_querymenu(struct file *file, void *priv, 18340c0d06caSMauro Carvalho Chehab struct v4l2_querymenu *a) 18350c0d06caSMauro Carvalho Chehab { 18360c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 18370c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 18380c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_querymenu()\n"); 18390c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_querymenu()\n"); 18400c0d06caSMauro Carvalho Chehab return cx231xx_querymenu(dev, a); 18410c0d06caSMauro Carvalho Chehab } 18420c0d06caSMauro Carvalho Chehab 18430c0d06caSMauro Carvalho Chehab static int vidioc_queryctrl(struct file *file, void *priv, 18440c0d06caSMauro Carvalho Chehab struct v4l2_queryctrl *c) 18450c0d06caSMauro Carvalho Chehab { 18460c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 18470c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 18480c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_queryctrl()\n"); 18490c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_queryctrl()\n"); 18500c0d06caSMauro Carvalho Chehab return cx231xx_queryctrl(dev, c); 18510c0d06caSMauro Carvalho Chehab } 18520c0d06caSMauro Carvalho Chehab 18530c0d06caSMauro Carvalho Chehab static int mpeg_open(struct file *file) 18540c0d06caSMauro Carvalho Chehab { 18550c0d06caSMauro Carvalho Chehab int minor = video_devdata(file)->minor; 18560c0d06caSMauro Carvalho Chehab struct cx231xx *h, *dev = NULL; 18570c0d06caSMauro Carvalho Chehab /*struct list_head *list;*/ 18580c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh; 18590c0d06caSMauro Carvalho Chehab /*u32 value = 0;*/ 18600c0d06caSMauro Carvalho Chehab 18610c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 18620c0d06caSMauro Carvalho Chehab 18630c0d06caSMauro Carvalho Chehab list_for_each_entry(h, &cx231xx_devlist, devlist) { 18640c0d06caSMauro Carvalho Chehab if (h->v4l_device->minor == minor) 18650c0d06caSMauro Carvalho Chehab dev = h; 18660c0d06caSMauro Carvalho Chehab } 18670c0d06caSMauro Carvalho Chehab 18680c0d06caSMauro Carvalho Chehab if (dev == NULL) 18690c0d06caSMauro Carvalho Chehab return -ENODEV; 18700c0d06caSMauro Carvalho Chehab 18711265f080SHans Verkuil if (mutex_lock_interruptible(&dev->lock)) 18721265f080SHans Verkuil return -ERESTARTSYS; 18730c0d06caSMauro Carvalho Chehab 18740c0d06caSMauro Carvalho Chehab /* allocate + initialize per filehandle data */ 18750c0d06caSMauro Carvalho Chehab fh = kzalloc(sizeof(*fh), GFP_KERNEL); 18760c0d06caSMauro Carvalho Chehab if (NULL == fh) { 18770c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 18780c0d06caSMauro Carvalho Chehab return -ENOMEM; 18790c0d06caSMauro Carvalho Chehab } 18800c0d06caSMauro Carvalho Chehab 18810c0d06caSMauro Carvalho Chehab file->private_data = fh; 18820c0d06caSMauro Carvalho Chehab fh->dev = dev; 18830c0d06caSMauro Carvalho Chehab 18840c0d06caSMauro Carvalho Chehab 18850c0d06caSMauro Carvalho Chehab videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops, 18860c0d06caSMauro Carvalho Chehab NULL, &dev->video_mode.slock, 18870c0d06caSMauro Carvalho Chehab V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, 18881265f080SHans Verkuil sizeof(struct cx231xx_buffer), fh, &dev->lock); 18890c0d06caSMauro Carvalho Chehab /* 18900c0d06caSMauro Carvalho Chehab videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops, 18910c0d06caSMauro Carvalho Chehab &dev->udev->dev, &dev->ts1.slock, 18920c0d06caSMauro Carvalho Chehab V4L2_BUF_TYPE_VIDEO_CAPTURE, 18930c0d06caSMauro Carvalho Chehab V4L2_FIELD_INTERLACED, 18940c0d06caSMauro Carvalho Chehab sizeof(struct cx231xx_buffer), 18951265f080SHans Verkuil fh, &dev->lock); 18960c0d06caSMauro Carvalho Chehab */ 18970c0d06caSMauro Carvalho Chehab 18980c0d06caSMauro Carvalho Chehab 18990c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_VANC, 1); 19000c0d06caSMauro Carvalho Chehab cx231xx_set_gpio_value(dev, 2, 0); 19010c0d06caSMauro Carvalho Chehab 19020c0d06caSMauro Carvalho Chehab cx231xx_initialize_codec(dev); 19030c0d06caSMauro Carvalho Chehab 19040c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 19050c0d06caSMauro Carvalho Chehab cx231xx_start_TS1(dev); 19060c0d06caSMauro Carvalho Chehab 19070c0d06caSMauro Carvalho Chehab return 0; 19080c0d06caSMauro Carvalho Chehab } 19090c0d06caSMauro Carvalho Chehab 19100c0d06caSMauro Carvalho Chehab static int mpeg_release(struct file *file) 19110c0d06caSMauro Carvalho Chehab { 19120c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 19130c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 19140c0d06caSMauro Carvalho Chehab 19150c0d06caSMauro Carvalho Chehab dprintk(3, "mpeg_release()! dev=0x%p\n", dev); 19160c0d06caSMauro Carvalho Chehab 19170c0d06caSMauro Carvalho Chehab if (!dev) { 19180c0d06caSMauro Carvalho Chehab dprintk(3, "abort!!!\n"); 19190c0d06caSMauro Carvalho Chehab return 0; 19200c0d06caSMauro Carvalho Chehab } 19210c0d06caSMauro Carvalho Chehab 19220c0d06caSMauro Carvalho Chehab mutex_lock(&dev->lock); 19230c0d06caSMauro Carvalho Chehab 19240c0d06caSMauro Carvalho Chehab cx231xx_stop_TS1(dev); 19250c0d06caSMauro Carvalho Chehab 19260c0d06caSMauro Carvalho Chehab /* do this before setting alternate! */ 19270c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) 19280c0d06caSMauro Carvalho Chehab cx231xx_uninit_isoc(dev); 19290c0d06caSMauro Carvalho Chehab else 19300c0d06caSMauro Carvalho Chehab cx231xx_uninit_bulk(dev); 19310c0d06caSMauro Carvalho Chehab cx231xx_set_mode(dev, CX231XX_SUSPEND); 19320c0d06caSMauro Carvalho Chehab 19330c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, 19340c0d06caSMauro Carvalho Chehab CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, 19350c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_NONE); 19360c0d06caSMauro Carvalho Chehab 19370c0d06caSMauro Carvalho Chehab /* FIXME: Review this crap */ 19380c0d06caSMauro Carvalho Chehab /* Shut device down on last close */ 19390c0d06caSMauro Carvalho Chehab if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { 19400c0d06caSMauro Carvalho Chehab if (atomic_dec_return(&dev->v4l_reader_count) == 0) { 19410c0d06caSMauro Carvalho Chehab /* stop mpeg capture */ 19420c0d06caSMauro Carvalho Chehab 19430c0d06caSMauro Carvalho Chehab msleep(500); 19440c0d06caSMauro Carvalho Chehab cx231xx_417_check_encoder(dev); 19450c0d06caSMauro Carvalho Chehab 19460c0d06caSMauro Carvalho Chehab } 19470c0d06caSMauro Carvalho Chehab } 19480c0d06caSMauro Carvalho Chehab 19490c0d06caSMauro Carvalho Chehab if (fh->vidq.streaming) 19500c0d06caSMauro Carvalho Chehab videobuf_streamoff(&fh->vidq); 19510c0d06caSMauro Carvalho Chehab if (fh->vidq.reading) 19520c0d06caSMauro Carvalho Chehab videobuf_read_stop(&fh->vidq); 19530c0d06caSMauro Carvalho Chehab 19540c0d06caSMauro Carvalho Chehab videobuf_mmap_free(&fh->vidq); 19550c0d06caSMauro Carvalho Chehab file->private_data = NULL; 19560c0d06caSMauro Carvalho Chehab kfree(fh); 19570c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 19580c0d06caSMauro Carvalho Chehab return 0; 19590c0d06caSMauro Carvalho Chehab } 19600c0d06caSMauro Carvalho Chehab 19610c0d06caSMauro Carvalho Chehab static ssize_t mpeg_read(struct file *file, char __user *data, 19620c0d06caSMauro Carvalho Chehab size_t count, loff_t *ppos) 19630c0d06caSMauro Carvalho Chehab { 19640c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 19650c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 19660c0d06caSMauro Carvalho Chehab 19670c0d06caSMauro Carvalho Chehab 19680c0d06caSMauro Carvalho Chehab /* Deal w/ A/V decoder * and mpeg encoder sync issues. */ 19690c0d06caSMauro Carvalho Chehab /* Start mpeg encoder on first read. */ 19700c0d06caSMauro Carvalho Chehab if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { 19710c0d06caSMauro Carvalho Chehab if (atomic_inc_return(&dev->v4l_reader_count) == 1) { 19720c0d06caSMauro Carvalho Chehab if (cx231xx_initialize_codec(dev) < 0) 19730c0d06caSMauro Carvalho Chehab return -EINVAL; 19740c0d06caSMauro Carvalho Chehab } 19750c0d06caSMauro Carvalho Chehab } 19760c0d06caSMauro Carvalho Chehab 19770c0d06caSMauro Carvalho Chehab return videobuf_read_stream(&fh->vidq, data, count, ppos, 0, 19780c0d06caSMauro Carvalho Chehab file->f_flags & O_NONBLOCK); 19790c0d06caSMauro Carvalho Chehab } 19800c0d06caSMauro Carvalho Chehab 19810c0d06caSMauro Carvalho Chehab static unsigned int mpeg_poll(struct file *file, 19820c0d06caSMauro Carvalho Chehab struct poll_table_struct *wait) 19830c0d06caSMauro Carvalho Chehab { 19840c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 19850c0d06caSMauro Carvalho Chehab /*struct cx231xx *dev = fh->dev;*/ 19860c0d06caSMauro Carvalho Chehab 19870c0d06caSMauro Carvalho Chehab /*dprintk(2, "%s\n", __func__);*/ 19880c0d06caSMauro Carvalho Chehab 19890c0d06caSMauro Carvalho Chehab return videobuf_poll_stream(file, &fh->vidq, wait); 19900c0d06caSMauro Carvalho Chehab } 19910c0d06caSMauro Carvalho Chehab 19920c0d06caSMauro Carvalho Chehab static int mpeg_mmap(struct file *file, struct vm_area_struct *vma) 19930c0d06caSMauro Carvalho Chehab { 19940c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 19950c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 19960c0d06caSMauro Carvalho Chehab 19970c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 19980c0d06caSMauro Carvalho Chehab 19990c0d06caSMauro Carvalho Chehab return videobuf_mmap_mapper(&fh->vidq, vma); 20000c0d06caSMauro Carvalho Chehab } 20010c0d06caSMauro Carvalho Chehab 20020c0d06caSMauro Carvalho Chehab static struct v4l2_file_operations mpeg_fops = { 20030c0d06caSMauro Carvalho Chehab .owner = THIS_MODULE, 20040c0d06caSMauro Carvalho Chehab .open = mpeg_open, 20050c0d06caSMauro Carvalho Chehab .release = mpeg_release, 20060c0d06caSMauro Carvalho Chehab .read = mpeg_read, 20070c0d06caSMauro Carvalho Chehab .poll = mpeg_poll, 20080c0d06caSMauro Carvalho Chehab .mmap = mpeg_mmap, 20091265f080SHans Verkuil .unlocked_ioctl = video_ioctl2, 20100c0d06caSMauro Carvalho Chehab }; 20110c0d06caSMauro Carvalho Chehab 20120c0d06caSMauro Carvalho Chehab static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { 20130c0d06caSMauro Carvalho Chehab .vidioc_s_std = vidioc_s_std, 20140c0d06caSMauro Carvalho Chehab .vidioc_g_std = vidioc_g_std, 20150c0d06caSMauro Carvalho Chehab .vidioc_enum_input = vidioc_enum_input, 20160c0d06caSMauro Carvalho Chehab .vidioc_g_input = vidioc_g_input, 20170c0d06caSMauro Carvalho Chehab .vidioc_s_input = vidioc_s_input, 20180c0d06caSMauro Carvalho Chehab .vidioc_s_ctrl = vidioc_s_ctrl, 20190c0d06caSMauro Carvalho Chehab .vidioc_querycap = vidioc_querycap, 20200c0d06caSMauro Carvalho Chehab .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 20210c0d06caSMauro Carvalho Chehab .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 20220c0d06caSMauro Carvalho Chehab .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, 2023*3f926e32SHans Verkuil .vidioc_s_fmt_vid_cap = vidioc_try_fmt_vid_cap, 20240c0d06caSMauro Carvalho Chehab .vidioc_reqbufs = vidioc_reqbufs, 20250c0d06caSMauro Carvalho Chehab .vidioc_querybuf = vidioc_querybuf, 20260c0d06caSMauro Carvalho Chehab .vidioc_qbuf = vidioc_qbuf, 20270c0d06caSMauro Carvalho Chehab .vidioc_dqbuf = vidioc_dqbuf, 20280c0d06caSMauro Carvalho Chehab .vidioc_streamon = vidioc_streamon, 20290c0d06caSMauro Carvalho Chehab .vidioc_streamoff = vidioc_streamoff, 20300c0d06caSMauro Carvalho Chehab .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, 20310c0d06caSMauro Carvalho Chehab .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, 20320c0d06caSMauro Carvalho Chehab .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, 20330c0d06caSMauro Carvalho Chehab .vidioc_log_status = vidioc_log_status, 20340c0d06caSMauro Carvalho Chehab .vidioc_querymenu = vidioc_querymenu, 20350c0d06caSMauro Carvalho Chehab .vidioc_queryctrl = vidioc_queryctrl, 20360c0d06caSMauro Carvalho Chehab /* .vidioc_g_chip_ident = cx231xx_g_chip_ident,*/ 20370c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 20380c0d06caSMauro Carvalho Chehab /* .vidioc_g_register = cx231xx_g_register,*/ 20390c0d06caSMauro Carvalho Chehab /* .vidioc_s_register = cx231xx_s_register,*/ 20400c0d06caSMauro Carvalho Chehab #endif 20410c0d06caSMauro Carvalho Chehab }; 20420c0d06caSMauro Carvalho Chehab 20430c0d06caSMauro Carvalho Chehab static struct video_device cx231xx_mpeg_template = { 20440c0d06caSMauro Carvalho Chehab .name = "cx231xx", 20450c0d06caSMauro Carvalho Chehab .fops = &mpeg_fops, 20460c0d06caSMauro Carvalho Chehab .ioctl_ops = &mpeg_ioctl_ops, 20470c0d06caSMauro Carvalho Chehab .minor = -1, 20480c0d06caSMauro Carvalho Chehab .tvnorms = CX231xx_NORMS, 20490c0d06caSMauro Carvalho Chehab }; 20500c0d06caSMauro Carvalho Chehab 20510c0d06caSMauro Carvalho Chehab void cx231xx_417_unregister(struct cx231xx *dev) 20520c0d06caSMauro Carvalho Chehab { 20530c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 20540c0d06caSMauro Carvalho Chehab dprintk(3, "%s()\n", __func__); 20550c0d06caSMauro Carvalho Chehab 20560c0d06caSMauro Carvalho Chehab if (dev->v4l_device) { 20570c0d06caSMauro Carvalho Chehab if (-1 != dev->v4l_device->minor) 20580c0d06caSMauro Carvalho Chehab video_unregister_device(dev->v4l_device); 20590c0d06caSMauro Carvalho Chehab else 20600c0d06caSMauro Carvalho Chehab video_device_release(dev->v4l_device); 20610c0d06caSMauro Carvalho Chehab dev->v4l_device = NULL; 20620c0d06caSMauro Carvalho Chehab } 20630c0d06caSMauro Carvalho Chehab } 20640c0d06caSMauro Carvalho Chehab 20650c0d06caSMauro Carvalho Chehab static struct video_device *cx231xx_video_dev_alloc( 20660c0d06caSMauro Carvalho Chehab struct cx231xx *dev, 20670c0d06caSMauro Carvalho Chehab struct usb_device *usbdev, 20680c0d06caSMauro Carvalho Chehab struct video_device *template, 20690c0d06caSMauro Carvalho Chehab char *type) 20700c0d06caSMauro Carvalho Chehab { 20710c0d06caSMauro Carvalho Chehab struct video_device *vfd; 20720c0d06caSMauro Carvalho Chehab 20730c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 20740c0d06caSMauro Carvalho Chehab vfd = video_device_alloc(); 20750c0d06caSMauro Carvalho Chehab if (NULL == vfd) 20760c0d06caSMauro Carvalho Chehab return NULL; 20770c0d06caSMauro Carvalho Chehab *vfd = *template; 20780c0d06caSMauro Carvalho Chehab snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, 20790c0d06caSMauro Carvalho Chehab type, cx231xx_boards[dev->model].name); 20800c0d06caSMauro Carvalho Chehab 20810c0d06caSMauro Carvalho Chehab vfd->v4l2_dev = &dev->v4l2_dev; 20821265f080SHans Verkuil vfd->lock = &dev->lock; 20830c0d06caSMauro Carvalho Chehab vfd->release = video_device_release; 20840c0d06caSMauro Carvalho Chehab 20850c0d06caSMauro Carvalho Chehab return vfd; 20860c0d06caSMauro Carvalho Chehab 20870c0d06caSMauro Carvalho Chehab } 20880c0d06caSMauro Carvalho Chehab 20890c0d06caSMauro Carvalho Chehab int cx231xx_417_register(struct cx231xx *dev) 20900c0d06caSMauro Carvalho Chehab { 20910c0d06caSMauro Carvalho Chehab /* FIXME: Port1 hardcoded here */ 20920c0d06caSMauro Carvalho Chehab int err = -ENODEV; 20930c0d06caSMauro Carvalho Chehab struct cx231xx_tsport *tsport = &dev->ts1; 20940c0d06caSMauro Carvalho Chehab 20950c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 20960c0d06caSMauro Carvalho Chehab 20970c0d06caSMauro Carvalho Chehab /* Set default TV standard */ 20980c0d06caSMauro Carvalho Chehab dev->encodernorm = cx231xx_tvnorms[0]; 20990c0d06caSMauro Carvalho Chehab 21000c0d06caSMauro Carvalho Chehab if (dev->encodernorm.id & V4L2_STD_525_60) 21010c0d06caSMauro Carvalho Chehab tsport->height = 480; 21020c0d06caSMauro Carvalho Chehab else 21030c0d06caSMauro Carvalho Chehab tsport->height = 576; 21040c0d06caSMauro Carvalho Chehab 21050c0d06caSMauro Carvalho Chehab tsport->width = 720; 21060c0d06caSMauro Carvalho Chehab cx2341x_fill_defaults(&dev->mpeg_params); 21070c0d06caSMauro Carvalho Chehab dev->norm = V4L2_STD_NTSC; 21080c0d06caSMauro Carvalho Chehab 21090c0d06caSMauro Carvalho Chehab dev->mpeg_params.port = CX2341X_PORT_SERIAL; 21100c0d06caSMauro Carvalho Chehab 21110c0d06caSMauro Carvalho Chehab /* Allocate and initialize V4L video device */ 21120c0d06caSMauro Carvalho Chehab dev->v4l_device = cx231xx_video_dev_alloc(dev, 21130c0d06caSMauro Carvalho Chehab dev->udev, &cx231xx_mpeg_template, "mpeg"); 21140c0d06caSMauro Carvalho Chehab err = video_register_device(dev->v4l_device, 21150c0d06caSMauro Carvalho Chehab VFL_TYPE_GRABBER, -1); 21160c0d06caSMauro Carvalho Chehab if (err < 0) { 21170c0d06caSMauro Carvalho Chehab dprintk(3, "%s: can't register mpeg device\n", dev->name); 21180c0d06caSMauro Carvalho Chehab return err; 21190c0d06caSMauro Carvalho Chehab } 21200c0d06caSMauro Carvalho Chehab 21210c0d06caSMauro Carvalho Chehab dprintk(3, "%s: registered device video%d [mpeg]\n", 21220c0d06caSMauro Carvalho Chehab dev->name, dev->v4l_device->num); 21230c0d06caSMauro Carvalho Chehab 21240c0d06caSMauro Carvalho Chehab return 0; 21250c0d06caSMauro Carvalho Chehab } 21260c0d06caSMauro Carvalho Chehab 21270c0d06caSMauro Carvalho Chehab MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME); 2128