1*0c0d06caSMauro Carvalho Chehab /* 2*0c0d06caSMauro Carvalho Chehab * 3*0c0d06caSMauro Carvalho Chehab * Support for a cx23417 mpeg encoder via cx231xx host port. 4*0c0d06caSMauro Carvalho Chehab * 5*0c0d06caSMauro Carvalho Chehab * (c) 2004 Jelle Foks <jelle@foks.us> 6*0c0d06caSMauro Carvalho Chehab * (c) 2004 Gerd Knorr <kraxel@bytesex.org> 7*0c0d06caSMauro Carvalho Chehab * (c) 2008 Steven Toth <stoth@linuxtv.org> 8*0c0d06caSMauro Carvalho Chehab * - CX23885/7/8 support 9*0c0d06caSMauro Carvalho Chehab * 10*0c0d06caSMauro Carvalho Chehab * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), 11*0c0d06caSMauro Carvalho Chehab * 12*0c0d06caSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 13*0c0d06caSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 14*0c0d06caSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 15*0c0d06caSMauro Carvalho Chehab * (at your option) any later version. 16*0c0d06caSMauro Carvalho Chehab * 17*0c0d06caSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 18*0c0d06caSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 19*0c0d06caSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20*0c0d06caSMauro Carvalho Chehab * GNU General Public License for more details. 21*0c0d06caSMauro Carvalho Chehab * 22*0c0d06caSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 23*0c0d06caSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 24*0c0d06caSMauro Carvalho Chehab * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25*0c0d06caSMauro Carvalho Chehab */ 26*0c0d06caSMauro Carvalho Chehab 27*0c0d06caSMauro Carvalho Chehab #include <linux/module.h> 28*0c0d06caSMauro Carvalho Chehab #include <linux/moduleparam.h> 29*0c0d06caSMauro Carvalho Chehab #include <linux/init.h> 30*0c0d06caSMauro Carvalho Chehab #include <linux/fs.h> 31*0c0d06caSMauro Carvalho Chehab #include <linux/delay.h> 32*0c0d06caSMauro Carvalho Chehab #include <linux/device.h> 33*0c0d06caSMauro Carvalho Chehab #include <linux/firmware.h> 34*0c0d06caSMauro Carvalho Chehab #include <linux/vmalloc.h> 35*0c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h> 36*0c0d06caSMauro Carvalho Chehab #include <media/v4l2-ioctl.h> 37*0c0d06caSMauro Carvalho Chehab #include <media/cx2341x.h> 38*0c0d06caSMauro Carvalho Chehab #include <linux/usb.h> 39*0c0d06caSMauro Carvalho Chehab 40*0c0d06caSMauro Carvalho Chehab #include "cx231xx.h" 41*0c0d06caSMauro Carvalho Chehab /*#include "cx23885-ioctl.h"*/ 42*0c0d06caSMauro Carvalho Chehab 43*0c0d06caSMauro Carvalho Chehab #define CX231xx_FIRM_IMAGE_SIZE 376836 44*0c0d06caSMauro Carvalho Chehab #define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" 45*0c0d06caSMauro Carvalho Chehab 46*0c0d06caSMauro Carvalho Chehab /* for polaris ITVC */ 47*0c0d06caSMauro Carvalho Chehab #define ITVC_WRITE_DIR 0x03FDFC00 48*0c0d06caSMauro Carvalho Chehab #define ITVC_READ_DIR 0x0001FC00 49*0c0d06caSMauro Carvalho Chehab 50*0c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE0 0x00 51*0c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE1 0x08 52*0c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE2 0x10 53*0c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_DATA_BYTE3 0x18 54*0c0d06caSMauro Carvalho Chehab 55*0c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_ADDRESS_BYTE2 0x20 56*0c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_ADDRESS_BYTE1 0x28 57*0c0d06caSMauro Carvalho Chehab #define MCI_MEMORY_ADDRESS_BYTE0 0x30 58*0c0d06caSMauro Carvalho Chehab 59*0c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE0 0x40 60*0c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE1 0x48 61*0c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE2 0x50 62*0c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_DATA_BYTE3 0x58 63*0c0d06caSMauro Carvalho Chehab 64*0c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_ADDRESS_BYTE0 0x60 65*0c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_ADDRESS_BYTE1 0x68 66*0c0d06caSMauro Carvalho Chehab 67*0c0d06caSMauro Carvalho Chehab #define MCI_REGISTER_MODE 0x70 68*0c0d06caSMauro Carvalho Chehab 69*0c0d06caSMauro Carvalho Chehab /* Read and write modes for polaris ITVC */ 70*0c0d06caSMauro Carvalho Chehab #define MCI_MODE_REGISTER_READ 0x000 71*0c0d06caSMauro Carvalho Chehab #define MCI_MODE_REGISTER_WRITE 0x100 72*0c0d06caSMauro Carvalho Chehab #define MCI_MODE_MEMORY_READ 0x000 73*0c0d06caSMauro Carvalho Chehab #define MCI_MODE_MEMORY_WRITE 0x4000 74*0c0d06caSMauro Carvalho Chehab 75*0c0d06caSMauro Carvalho Chehab static unsigned int mpegbufs = 8; 76*0c0d06caSMauro Carvalho Chehab module_param(mpegbufs, int, 0644); 77*0c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32"); 78*0c0d06caSMauro Carvalho Chehab static unsigned int mpeglines = 128; 79*0c0d06caSMauro Carvalho Chehab module_param(mpeglines, int, 0644); 80*0c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32"); 81*0c0d06caSMauro Carvalho Chehab static unsigned int mpeglinesize = 512; 82*0c0d06caSMauro Carvalho Chehab module_param(mpeglinesize, int, 0644); 83*0c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(mpeglinesize, 84*0c0d06caSMauro Carvalho Chehab "number of bytes in each line of an MPEG buffer, range 512-1024"); 85*0c0d06caSMauro Carvalho Chehab 86*0c0d06caSMauro Carvalho Chehab static unsigned int v4l_debug = 1; 87*0c0d06caSMauro Carvalho Chehab module_param(v4l_debug, int, 0644); 88*0c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages"); 89*0c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_qq; 90*0c0d06caSMauro Carvalho Chehab #define dprintk(level, fmt, arg...)\ 91*0c0d06caSMauro Carvalho Chehab do { if (v4l_debug >= level) \ 92*0c0d06caSMauro Carvalho Chehab printk(KERN_INFO "%s: " fmt, \ 93*0c0d06caSMauro Carvalho Chehab (dev) ? dev->name : "cx231xx[?]", ## arg); \ 94*0c0d06caSMauro Carvalho Chehab } while (0) 95*0c0d06caSMauro Carvalho Chehab 96*0c0d06caSMauro Carvalho Chehab static struct cx231xx_tvnorm cx231xx_tvnorms[] = { 97*0c0d06caSMauro Carvalho Chehab { 98*0c0d06caSMauro Carvalho Chehab .name = "NTSC-M", 99*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_NTSC_M, 100*0c0d06caSMauro Carvalho Chehab }, { 101*0c0d06caSMauro Carvalho Chehab .name = "NTSC-JP", 102*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_NTSC_M_JP, 103*0c0d06caSMauro Carvalho Chehab }, { 104*0c0d06caSMauro Carvalho Chehab .name = "PAL-BG", 105*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_BG, 106*0c0d06caSMauro Carvalho Chehab }, { 107*0c0d06caSMauro Carvalho Chehab .name = "PAL-DK", 108*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_DK, 109*0c0d06caSMauro Carvalho Chehab }, { 110*0c0d06caSMauro Carvalho Chehab .name = "PAL-I", 111*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_I, 112*0c0d06caSMauro Carvalho Chehab }, { 113*0c0d06caSMauro Carvalho Chehab .name = "PAL-M", 114*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_M, 115*0c0d06caSMauro Carvalho Chehab }, { 116*0c0d06caSMauro Carvalho Chehab .name = "PAL-N", 117*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_N, 118*0c0d06caSMauro Carvalho Chehab }, { 119*0c0d06caSMauro Carvalho Chehab .name = "PAL-Nc", 120*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_Nc, 121*0c0d06caSMauro Carvalho Chehab }, { 122*0c0d06caSMauro Carvalho Chehab .name = "PAL-60", 123*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_PAL_60, 124*0c0d06caSMauro Carvalho Chehab }, { 125*0c0d06caSMauro Carvalho Chehab .name = "SECAM-L", 126*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_SECAM_L, 127*0c0d06caSMauro Carvalho Chehab }, { 128*0c0d06caSMauro Carvalho Chehab .name = "SECAM-DK", 129*0c0d06caSMauro Carvalho Chehab .id = V4L2_STD_SECAM_DK, 130*0c0d06caSMauro Carvalho Chehab } 131*0c0d06caSMauro Carvalho Chehab }; 132*0c0d06caSMauro Carvalho Chehab 133*0c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 134*0c0d06caSMauro Carvalho Chehab enum cx231xx_capture_type { 135*0c0d06caSMauro Carvalho Chehab CX231xx_MPEG_CAPTURE, 136*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_CAPTURE, 137*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_PASSTHRU_CAPTURE 138*0c0d06caSMauro Carvalho Chehab }; 139*0c0d06caSMauro Carvalho Chehab enum cx231xx_capture_bits { 140*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_NONE = 0x00, 141*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_YUV_CAPTURE = 0x01, 142*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_PCM_CAPTURE = 0x02, 143*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_VBI_CAPTURE = 0x04, 144*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08, 145*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_TO_HOST_CAPTURE = 0x10 146*0c0d06caSMauro Carvalho Chehab }; 147*0c0d06caSMauro Carvalho Chehab enum cx231xx_capture_end { 148*0c0d06caSMauro Carvalho Chehab CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */ 149*0c0d06caSMauro Carvalho Chehab CX231xx_END_NOW, /* stop immediately, no irq */ 150*0c0d06caSMauro Carvalho Chehab }; 151*0c0d06caSMauro Carvalho Chehab enum cx231xx_framerate { 152*0c0d06caSMauro Carvalho Chehab CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */ 153*0c0d06caSMauro Carvalho Chehab CX231xx_FRAMERATE_PAL_25 /* PAL: 25fps */ 154*0c0d06caSMauro Carvalho Chehab }; 155*0c0d06caSMauro Carvalho Chehab enum cx231xx_stream_port { 156*0c0d06caSMauro Carvalho Chehab CX231xx_OUTPUT_PORT_MEMORY, 157*0c0d06caSMauro Carvalho Chehab CX231xx_OUTPUT_PORT_STREAMING, 158*0c0d06caSMauro Carvalho Chehab CX231xx_OUTPUT_PORT_SERIAL 159*0c0d06caSMauro Carvalho Chehab }; 160*0c0d06caSMauro Carvalho Chehab enum cx231xx_data_xfer_status { 161*0c0d06caSMauro Carvalho Chehab CX231xx_MORE_BUFFERS_FOLLOW, 162*0c0d06caSMauro Carvalho Chehab CX231xx_LAST_BUFFER, 163*0c0d06caSMauro Carvalho Chehab }; 164*0c0d06caSMauro Carvalho Chehab enum cx231xx_picture_mask { 165*0c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_NONE, 166*0c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_I_FRAMES, 167*0c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3, 168*0c0d06caSMauro Carvalho Chehab CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7, 169*0c0d06caSMauro Carvalho Chehab }; 170*0c0d06caSMauro Carvalho Chehab enum cx231xx_vbi_mode_bits { 171*0c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SLICED, 172*0c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_RAW, 173*0c0d06caSMauro Carvalho Chehab }; 174*0c0d06caSMauro Carvalho Chehab enum cx231xx_vbi_insertion_bits { 175*0c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA, 176*0c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1, 177*0c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1, 178*0c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, 179*0c0d06caSMauro Carvalho Chehab CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, 180*0c0d06caSMauro Carvalho Chehab }; 181*0c0d06caSMauro Carvalho Chehab enum cx231xx_dma_unit { 182*0c0d06caSMauro Carvalho Chehab CX231xx_DMA_BYTES, 183*0c0d06caSMauro Carvalho Chehab CX231xx_DMA_FRAMES, 184*0c0d06caSMauro Carvalho Chehab }; 185*0c0d06caSMauro Carvalho Chehab enum cx231xx_dma_transfer_status_bits { 186*0c0d06caSMauro Carvalho Chehab CX231xx_DMA_TRANSFER_BITS_DONE = 0x01, 187*0c0d06caSMauro Carvalho Chehab CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04, 188*0c0d06caSMauro Carvalho Chehab CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10, 189*0c0d06caSMauro Carvalho Chehab }; 190*0c0d06caSMauro Carvalho Chehab enum cx231xx_pause { 191*0c0d06caSMauro Carvalho Chehab CX231xx_PAUSE_ENCODING, 192*0c0d06caSMauro Carvalho Chehab CX231xx_RESUME_ENCODING, 193*0c0d06caSMauro Carvalho Chehab }; 194*0c0d06caSMauro Carvalho Chehab enum cx231xx_copyright { 195*0c0d06caSMauro Carvalho Chehab CX231xx_COPYRIGHT_OFF, 196*0c0d06caSMauro Carvalho Chehab CX231xx_COPYRIGHT_ON, 197*0c0d06caSMauro Carvalho Chehab }; 198*0c0d06caSMauro Carvalho Chehab enum cx231xx_notification_type { 199*0c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_REFRESH, 200*0c0d06caSMauro Carvalho Chehab }; 201*0c0d06caSMauro Carvalho Chehab enum cx231xx_notification_status { 202*0c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_OFF, 203*0c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_ON, 204*0c0d06caSMauro Carvalho Chehab }; 205*0c0d06caSMauro Carvalho Chehab enum cx231xx_notification_mailbox { 206*0c0d06caSMauro Carvalho Chehab CX231xx_NOTIFICATION_NO_MAILBOX = -1, 207*0c0d06caSMauro Carvalho Chehab }; 208*0c0d06caSMauro Carvalho Chehab enum cx231xx_field1_lines { 209*0c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */ 210*0c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */ 211*0c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */ 212*0c0d06caSMauro Carvalho Chehab }; 213*0c0d06caSMauro Carvalho Chehab enum cx231xx_field2_lines { 214*0c0d06caSMauro Carvalho Chehab CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */ 215*0c0d06caSMauro Carvalho Chehab CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */ 216*0c0d06caSMauro Carvalho Chehab CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */ 217*0c0d06caSMauro Carvalho Chehab }; 218*0c0d06caSMauro Carvalho Chehab enum cx231xx_custom_data_type { 219*0c0d06caSMauro Carvalho Chehab CX231xx_CUSTOM_EXTENSION_USR_DATA, 220*0c0d06caSMauro Carvalho Chehab CX231xx_CUSTOM_PRIVATE_PACKET, 221*0c0d06caSMauro Carvalho Chehab }; 222*0c0d06caSMauro Carvalho Chehab enum cx231xx_mute { 223*0c0d06caSMauro Carvalho Chehab CX231xx_UNMUTE, 224*0c0d06caSMauro Carvalho Chehab CX231xx_MUTE, 225*0c0d06caSMauro Carvalho Chehab }; 226*0c0d06caSMauro Carvalho Chehab enum cx231xx_mute_video_mask { 227*0c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00, 228*0c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000, 229*0c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000, 230*0c0d06caSMauro Carvalho Chehab }; 231*0c0d06caSMauro Carvalho Chehab enum cx231xx_mute_video_shift { 232*0c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_V_SHIFT = 8, 233*0c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_U_SHIFT = 16, 234*0c0d06caSMauro Carvalho Chehab CX231xx_MUTE_VIDEO_Y_SHIFT = 24, 235*0c0d06caSMauro Carvalho Chehab }; 236*0c0d06caSMauro Carvalho Chehab 237*0c0d06caSMauro Carvalho Chehab /* defines below are from ivtv-driver.h */ 238*0c0d06caSMauro Carvalho Chehab #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF 239*0c0d06caSMauro Carvalho Chehab 240*0c0d06caSMauro Carvalho Chehab /* Firmware API commands */ 241*0c0d06caSMauro Carvalho Chehab #define IVTV_API_STD_TIMEOUT 500 242*0c0d06caSMauro Carvalho Chehab 243*0c0d06caSMauro Carvalho Chehab /* Registers */ 244*0c0d06caSMauro Carvalho Chehab /* IVTV_REG_OFFSET */ 245*0c0d06caSMauro Carvalho Chehab #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8) 246*0c0d06caSMauro Carvalho Chehab #define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC) 247*0c0d06caSMauro Carvalho Chehab #define IVTV_REG_SPU (0x9050) 248*0c0d06caSMauro Carvalho Chehab #define IVTV_REG_HW_BLOCKS (0x9054) 249*0c0d06caSMauro Carvalho Chehab #define IVTV_REG_VPU (0x9058) 250*0c0d06caSMauro Carvalho Chehab #define IVTV_REG_APU (0xA064) 251*0c0d06caSMauro Carvalho Chehab 252*0c0d06caSMauro Carvalho Chehab /* 253*0c0d06caSMauro Carvalho Chehab * Bit definitions for MC417_RWD and MC417_OEN registers 254*0c0d06caSMauro Carvalho Chehab * 255*0c0d06caSMauro Carvalho Chehab * bits 31-16 256*0c0d06caSMauro Carvalho Chehab *+-----------+ 257*0c0d06caSMauro Carvalho Chehab *| Reserved | 258*0c0d06caSMauro Carvalho Chehab *|+-----------+ 259*0c0d06caSMauro Carvalho Chehab *| bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8 260*0c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 261*0c0d06caSMauro Carvalho Chehab *|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0| 262*0c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 263*0c0d06caSMauro Carvalho Chehab *| bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 264*0c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 265*0c0d06caSMauro Carvalho Chehab *||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0| 266*0c0d06caSMauro Carvalho Chehab *|+-------+-------+-------+-------+-------+-------+-------+-------+ 267*0c0d06caSMauro Carvalho Chehab */ 268*0c0d06caSMauro Carvalho Chehab #define MC417_MIWR 0x8000 269*0c0d06caSMauro Carvalho Chehab #define MC417_MIRD 0x4000 270*0c0d06caSMauro Carvalho Chehab #define MC417_MICS 0x2000 271*0c0d06caSMauro Carvalho Chehab #define MC417_MIRDY 0x1000 272*0c0d06caSMauro Carvalho Chehab #define MC417_MIADDR 0x0F00 273*0c0d06caSMauro Carvalho Chehab #define MC417_MIDATA 0x00FF 274*0c0d06caSMauro Carvalho Chehab 275*0c0d06caSMauro Carvalho Chehab 276*0c0d06caSMauro Carvalho Chehab /* Bit definitions for MC417_CTL register **** 277*0c0d06caSMauro Carvalho Chehab *bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0 278*0c0d06caSMauro Carvalho Chehab *+--------+-------------+--------+--------------+------------+ 279*0c0d06caSMauro Carvalho Chehab *|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN| 280*0c0d06caSMauro Carvalho Chehab *+--------+-------------+--------+--------------+------------+ 281*0c0d06caSMauro Carvalho Chehab */ 282*0c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030) 283*0c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006) 284*0c0d06caSMauro Carvalho Chehab #define MC417_UART_GPIO_EN 0x00000001 285*0c0d06caSMauro Carvalho Chehab 286*0c0d06caSMauro Carvalho Chehab /* Values for speed control */ 287*0c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL_SLOW 0x1 288*0c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL_MEDIUM 0x0 289*0c0d06caSMauro Carvalho Chehab #define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */ 290*0c0d06caSMauro Carvalho Chehab 291*0c0d06caSMauro Carvalho Chehab /* Values for GPIO select */ 292*0c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO3 0x3 293*0c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO2 0x2 294*0c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO1 0x1 295*0c0d06caSMauro Carvalho Chehab #define MC417_GPIO_SEL_GPIO0 0x0 296*0c0d06caSMauro Carvalho Chehab 297*0c0d06caSMauro Carvalho Chehab 298*0c0d06caSMauro Carvalho Chehab #define CX23417_GPIO_MASK 0xFC0003FF 299*0c0d06caSMauro Carvalho Chehab static int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value) 300*0c0d06caSMauro Carvalho Chehab { 301*0c0d06caSMauro Carvalho Chehab int status = 0; 302*0c0d06caSMauro Carvalho Chehab u32 _gpio_direction = 0; 303*0c0d06caSMauro Carvalho Chehab 304*0c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; 305*0c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction|gpio_direction; 306*0c0d06caSMauro Carvalho Chehab status = cx231xx_send_gpio_cmd(dev, _gpio_direction, 307*0c0d06caSMauro Carvalho Chehab (u8 *)&value, 4, 0, 0); 308*0c0d06caSMauro Carvalho Chehab return status; 309*0c0d06caSMauro Carvalho Chehab } 310*0c0d06caSMauro Carvalho Chehab static int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue) 311*0c0d06caSMauro Carvalho Chehab { 312*0c0d06caSMauro Carvalho Chehab int status = 0; 313*0c0d06caSMauro Carvalho Chehab u32 _gpio_direction = 0; 314*0c0d06caSMauro Carvalho Chehab 315*0c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; 316*0c0d06caSMauro Carvalho Chehab _gpio_direction = _gpio_direction|gpio_direction; 317*0c0d06caSMauro Carvalho Chehab 318*0c0d06caSMauro Carvalho Chehab status = cx231xx_send_gpio_cmd(dev, _gpio_direction, 319*0c0d06caSMauro Carvalho Chehab (u8 *)pValue, 4, 0, 1); 320*0c0d06caSMauro Carvalho Chehab return status; 321*0c0d06caSMauro Carvalho Chehab } 322*0c0d06caSMauro Carvalho Chehab 323*0c0d06caSMauro Carvalho Chehab static int waitForMciComplete(struct cx231xx *dev) 324*0c0d06caSMauro Carvalho Chehab { 325*0c0d06caSMauro Carvalho Chehab u32 gpio; 326*0c0d06caSMauro Carvalho Chehab u32 gpio_driection = 0; 327*0c0d06caSMauro Carvalho Chehab u8 count = 0; 328*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, gpio_driection, &gpio); 329*0c0d06caSMauro Carvalho Chehab 330*0c0d06caSMauro Carvalho Chehab while (!(gpio&0x020000)) { 331*0c0d06caSMauro Carvalho Chehab msleep(10); 332*0c0d06caSMauro Carvalho Chehab 333*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, gpio_driection, &gpio); 334*0c0d06caSMauro Carvalho Chehab 335*0c0d06caSMauro Carvalho Chehab if (count++ > 100) { 336*0c0d06caSMauro Carvalho Chehab dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio); 337*0c0d06caSMauro Carvalho Chehab return -1; 338*0c0d06caSMauro Carvalho Chehab } 339*0c0d06caSMauro Carvalho Chehab } 340*0c0d06caSMauro Carvalho Chehab return 0; 341*0c0d06caSMauro Carvalho Chehab } 342*0c0d06caSMauro Carvalho Chehab 343*0c0d06caSMauro Carvalho Chehab static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value) 344*0c0d06caSMauro Carvalho Chehab { 345*0c0d06caSMauro Carvalho Chehab u32 temp; 346*0c0d06caSMauro Carvalho Chehab int status = 0; 347*0c0d06caSMauro Carvalho Chehab 348*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8); 349*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 350*0c0d06caSMauro Carvalho Chehab status = setITVCReg(dev, ITVC_WRITE_DIR, temp); 351*0c0d06caSMauro Carvalho Chehab if (status < 0) 352*0c0d06caSMauro Carvalho Chehab return status; 353*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 354*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 355*0c0d06caSMauro Carvalho Chehab 356*0c0d06caSMauro Carvalho Chehab /*write data byte 1;*/ 357*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00); 358*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 359*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 360*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 361*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 362*0c0d06caSMauro Carvalho Chehab 363*0c0d06caSMauro Carvalho Chehab /*write data byte 2;*/ 364*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8); 365*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 366*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 367*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 368*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 369*0c0d06caSMauro Carvalho Chehab 370*0c0d06caSMauro Carvalho Chehab /*write data byte 3;*/ 371*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16); 372*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 373*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 374*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 375*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 376*0c0d06caSMauro Carvalho Chehab 377*0c0d06caSMauro Carvalho Chehab /*write address byte 0;*/ 378*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8); 379*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 380*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 381*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 382*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 383*0c0d06caSMauro Carvalho Chehab 384*0c0d06caSMauro Carvalho Chehab /*write address byte 1;*/ 385*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00); 386*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 387*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 388*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 389*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 390*0c0d06caSMauro Carvalho Chehab 391*0c0d06caSMauro Carvalho Chehab /*Write that the mode is write.*/ 392*0c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE; 393*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 394*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 395*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 396*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 397*0c0d06caSMauro Carvalho Chehab 398*0c0d06caSMauro Carvalho Chehab return waitForMciComplete(dev); 399*0c0d06caSMauro Carvalho Chehab } 400*0c0d06caSMauro Carvalho Chehab 401*0c0d06caSMauro Carvalho Chehab static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value) 402*0c0d06caSMauro Carvalho Chehab { 403*0c0d06caSMauro Carvalho Chehab /*write address byte 0;*/ 404*0c0d06caSMauro Carvalho Chehab u32 temp; 405*0c0d06caSMauro Carvalho Chehab u32 return_value = 0; 406*0c0d06caSMauro Carvalho Chehab int ret = 0; 407*0c0d06caSMauro Carvalho Chehab 408*0c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8); 409*0c0d06caSMauro Carvalho Chehab temp = temp << 10; 410*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 411*0c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 412*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 413*0c0d06caSMauro Carvalho Chehab 414*0c0d06caSMauro Carvalho Chehab /*write address byte 1;*/ 415*0c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00); 416*0c0d06caSMauro Carvalho Chehab temp = temp << 10; 417*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 418*0c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 419*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 420*0c0d06caSMauro Carvalho Chehab 421*0c0d06caSMauro Carvalho Chehab /*write that the mode is read;*/ 422*0c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ; 423*0c0d06caSMauro Carvalho Chehab temp = temp << 10; 424*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 425*0c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 426*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 427*0c0d06caSMauro Carvalho Chehab 428*0c0d06caSMauro Carvalho Chehab /*wait for the MIRDY line to be asserted , 429*0c0d06caSMauro Carvalho Chehab signalling that the read is done;*/ 430*0c0d06caSMauro Carvalho Chehab ret = waitForMciComplete(dev); 431*0c0d06caSMauro Carvalho Chehab 432*0c0d06caSMauro Carvalho Chehab /*switch the DATA- GPIO to input mode;*/ 433*0c0d06caSMauro Carvalho Chehab 434*0c0d06caSMauro Carvalho Chehab /*Read data byte 0;*/ 435*0c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10; 436*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 437*0c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10); 438*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 439*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 440*0c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) >> 18); 441*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 442*0c0d06caSMauro Carvalho Chehab 443*0c0d06caSMauro Carvalho Chehab /* Read data byte 1;*/ 444*0c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10; 445*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 446*0c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10); 447*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 448*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 449*0c0d06caSMauro Carvalho Chehab 450*0c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) >> 10); 451*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 452*0c0d06caSMauro Carvalho Chehab 453*0c0d06caSMauro Carvalho Chehab /*Read data byte 2;*/ 454*0c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10; 455*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 456*0c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10); 457*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 458*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 459*0c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) >> 2); 460*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 461*0c0d06caSMauro Carvalho Chehab 462*0c0d06caSMauro Carvalho Chehab /*Read data byte 3;*/ 463*0c0d06caSMauro Carvalho Chehab temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10; 464*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 465*0c0d06caSMauro Carvalho Chehab temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10); 466*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 467*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 468*0c0d06caSMauro Carvalho Chehab return_value |= ((temp & 0x03FC0000) << 6); 469*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); 470*0c0d06caSMauro Carvalho Chehab 471*0c0d06caSMauro Carvalho Chehab *value = return_value; 472*0c0d06caSMauro Carvalho Chehab 473*0c0d06caSMauro Carvalho Chehab 474*0c0d06caSMauro Carvalho Chehab return ret; 475*0c0d06caSMauro Carvalho Chehab } 476*0c0d06caSMauro Carvalho Chehab 477*0c0d06caSMauro Carvalho Chehab static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value) 478*0c0d06caSMauro Carvalho Chehab { 479*0c0d06caSMauro Carvalho Chehab /*write data byte 0;*/ 480*0c0d06caSMauro Carvalho Chehab 481*0c0d06caSMauro Carvalho Chehab u32 temp; 482*0c0d06caSMauro Carvalho Chehab int ret = 0; 483*0c0d06caSMauro Carvalho Chehab 484*0c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_MEMORY_DATA_BYTE0|((value & 0x000000FF) << 8); 485*0c0d06caSMauro Carvalho Chehab temp = temp << 10; 486*0c0d06caSMauro Carvalho Chehab ret = setITVCReg(dev, ITVC_WRITE_DIR, temp); 487*0c0d06caSMauro Carvalho Chehab if (ret < 0) 488*0c0d06caSMauro Carvalho Chehab return ret; 489*0c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 490*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 491*0c0d06caSMauro Carvalho Chehab 492*0c0d06caSMauro Carvalho Chehab /*write data byte 1;*/ 493*0c0d06caSMauro Carvalho Chehab temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00); 494*0c0d06caSMauro Carvalho Chehab temp = temp << 10; 495*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 496*0c0d06caSMauro Carvalho Chehab temp = temp | ((0x05) << 10); 497*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 498*0c0d06caSMauro Carvalho Chehab 499*0c0d06caSMauro Carvalho Chehab /*write data byte 2;*/ 500*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8); 501*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 502*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 503*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 504*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 505*0c0d06caSMauro Carvalho Chehab 506*0c0d06caSMauro Carvalho Chehab /*write data byte 3;*/ 507*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16); 508*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 509*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 510*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 511*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 512*0c0d06caSMauro Carvalho Chehab 513*0c0d06caSMauro Carvalho Chehab /* write address byte 2;*/ 514*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | 515*0c0d06caSMauro Carvalho Chehab ((address & 0x003F0000)>>8); 516*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 517*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 518*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 519*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 520*0c0d06caSMauro Carvalho Chehab 521*0c0d06caSMauro Carvalho Chehab /* write address byte 1;*/ 522*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 523*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 524*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 525*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 526*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 527*0c0d06caSMauro Carvalho Chehab 528*0c0d06caSMauro Carvalho Chehab /* write address byte 0;*/ 529*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8); 530*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 531*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 532*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 533*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 534*0c0d06caSMauro Carvalho Chehab 535*0c0d06caSMauro Carvalho Chehab /*wait for MIRDY line;*/ 536*0c0d06caSMauro Carvalho Chehab waitForMciComplete(dev); 537*0c0d06caSMauro Carvalho Chehab 538*0c0d06caSMauro Carvalho Chehab return 0; 539*0c0d06caSMauro Carvalho Chehab } 540*0c0d06caSMauro Carvalho Chehab 541*0c0d06caSMauro Carvalho Chehab static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value) 542*0c0d06caSMauro Carvalho Chehab { 543*0c0d06caSMauro Carvalho Chehab u32 temp = 0; 544*0c0d06caSMauro Carvalho Chehab u32 return_value = 0; 545*0c0d06caSMauro Carvalho Chehab int ret = 0; 546*0c0d06caSMauro Carvalho Chehab 547*0c0d06caSMauro Carvalho Chehab /*write address byte 2;*/ 548*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ | 549*0c0d06caSMauro Carvalho Chehab ((address & 0x003F0000)>>8); 550*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 551*0c0d06caSMauro Carvalho Chehab ret = setITVCReg(dev, ITVC_WRITE_DIR, temp); 552*0c0d06caSMauro Carvalho Chehab if (ret < 0) 553*0c0d06caSMauro Carvalho Chehab return ret; 554*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 555*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 556*0c0d06caSMauro Carvalho Chehab 557*0c0d06caSMauro Carvalho Chehab /*write address byte 1*/ 558*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 559*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 560*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 561*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 562*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 563*0c0d06caSMauro Carvalho Chehab 564*0c0d06caSMauro Carvalho Chehab /*write address byte 0*/ 565*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8); 566*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 567*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 568*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 569*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_WRITE_DIR, temp); 570*0c0d06caSMauro Carvalho Chehab 571*0c0d06caSMauro Carvalho Chehab /*Wait for MIRDY line*/ 572*0c0d06caSMauro Carvalho Chehab ret = waitForMciComplete(dev); 573*0c0d06caSMauro Carvalho Chehab 574*0c0d06caSMauro Carvalho Chehab 575*0c0d06caSMauro Carvalho Chehab /*Read data byte 3;*/ 576*0c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10; 577*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 578*0c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10); 579*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 580*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 581*0c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)<<6); 582*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 583*0c0d06caSMauro Carvalho Chehab 584*0c0d06caSMauro Carvalho Chehab /*Read data byte 2;*/ 585*0c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10; 586*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 587*0c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10); 588*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 589*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 590*0c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)>>2); 591*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 592*0c0d06caSMauro Carvalho Chehab 593*0c0d06caSMauro Carvalho Chehab /* Read data byte 1;*/ 594*0c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10; 595*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 596*0c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10); 597*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 598*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 599*0c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)>>10); 600*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 601*0c0d06caSMauro Carvalho Chehab 602*0c0d06caSMauro Carvalho Chehab /*Read data byte 0;*/ 603*0c0d06caSMauro Carvalho Chehab temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10; 604*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 605*0c0d06caSMauro Carvalho Chehab temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10); 606*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, temp); 607*0c0d06caSMauro Carvalho Chehab getITVCReg(dev, ITVC_READ_DIR, &temp); 608*0c0d06caSMauro Carvalho Chehab return_value |= ((temp&0x03FC0000)>>18); 609*0c0d06caSMauro Carvalho Chehab setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); 610*0c0d06caSMauro Carvalho Chehab 611*0c0d06caSMauro Carvalho Chehab *value = return_value; 612*0c0d06caSMauro Carvalho Chehab return ret; 613*0c0d06caSMauro Carvalho Chehab } 614*0c0d06caSMauro Carvalho Chehab 615*0c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 616*0c0d06caSMauro Carvalho Chehab 617*0c0d06caSMauro Carvalho Chehab /* MPEG encoder API */ 618*0c0d06caSMauro Carvalho Chehab static char *cmd_to_str(int cmd) 619*0c0d06caSMauro Carvalho Chehab { 620*0c0d06caSMauro Carvalho Chehab switch (cmd) { 621*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_PING_FW: 622*0c0d06caSMauro Carvalho Chehab return "PING_FW"; 623*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_START_CAPTURE: 624*0c0d06caSMauro Carvalho Chehab return "START_CAPTURE"; 625*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_STOP_CAPTURE: 626*0c0d06caSMauro Carvalho Chehab return "STOP_CAPTURE"; 627*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_AUDIO_ID: 628*0c0d06caSMauro Carvalho Chehab return "SET_AUDIO_ID"; 629*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_VIDEO_ID: 630*0c0d06caSMauro Carvalho Chehab return "SET_VIDEO_ID"; 631*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_PCR_ID: 632*0c0d06caSMauro Carvalho Chehab return "SET_PCR_PID"; 633*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_FRAME_RATE: 634*0c0d06caSMauro Carvalho Chehab return "SET_FRAME_RATE"; 635*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_FRAME_SIZE: 636*0c0d06caSMauro Carvalho Chehab return "SET_FRAME_SIZE"; 637*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_BIT_RATE: 638*0c0d06caSMauro Carvalho Chehab return "SET_BIT_RATE"; 639*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_GOP_PROPERTIES: 640*0c0d06caSMauro Carvalho Chehab return "SET_GOP_PROPERTIES"; 641*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_ASPECT_RATIO: 642*0c0d06caSMauro Carvalho Chehab return "SET_ASPECT_RATIO"; 643*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_DNR_FILTER_MODE: 644*0c0d06caSMauro Carvalho Chehab return "SET_DNR_FILTER_PROPS"; 645*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_DNR_FILTER_PROPS: 646*0c0d06caSMauro Carvalho Chehab return "SET_DNR_FILTER_PROPS"; 647*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_CORING_LEVELS: 648*0c0d06caSMauro Carvalho Chehab return "SET_CORING_LEVELS"; 649*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE: 650*0c0d06caSMauro Carvalho Chehab return "SET_SPATIAL_FILTER_TYPE"; 651*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_VBI_LINE: 652*0c0d06caSMauro Carvalho Chehab return "SET_VBI_LINE"; 653*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_STREAM_TYPE: 654*0c0d06caSMauro Carvalho Chehab return "SET_STREAM_TYPE"; 655*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_OUTPUT_PORT: 656*0c0d06caSMauro Carvalho Chehab return "SET_OUTPUT_PORT"; 657*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_AUDIO_PROPERTIES: 658*0c0d06caSMauro Carvalho Chehab return "SET_AUDIO_PROPERTIES"; 659*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_HALT_FW: 660*0c0d06caSMauro Carvalho Chehab return "HALT_FW"; 661*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_VERSION: 662*0c0d06caSMauro Carvalho Chehab return "GET_VERSION"; 663*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_GOP_CLOSURE: 664*0c0d06caSMauro Carvalho Chehab return "SET_GOP_CLOSURE"; 665*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_SEQ_END: 666*0c0d06caSMauro Carvalho Chehab return "GET_SEQ_END"; 667*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_PGM_INDEX_INFO: 668*0c0d06caSMauro Carvalho Chehab return "SET_PGM_INDEX_INFO"; 669*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_VBI_CONFIG: 670*0c0d06caSMauro Carvalho Chehab return "SET_VBI_CONFIG"; 671*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_DMA_BLOCK_SIZE: 672*0c0d06caSMauro Carvalho Chehab return "SET_DMA_BLOCK_SIZE"; 673*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10: 674*0c0d06caSMauro Carvalho Chehab return "GET_PREV_DMA_INFO_MB_10"; 675*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9: 676*0c0d06caSMauro Carvalho Chehab return "GET_PREV_DMA_INFO_MB_9"; 677*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SCHED_DMA_TO_HOST: 678*0c0d06caSMauro Carvalho Chehab return "SCHED_DMA_TO_HOST"; 679*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_INITIALIZE_INPUT: 680*0c0d06caSMauro Carvalho Chehab return "INITIALIZE_INPUT"; 681*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_FRAME_DROP_RATE: 682*0c0d06caSMauro Carvalho Chehab return "SET_FRAME_DROP_RATE"; 683*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_PAUSE_ENCODER: 684*0c0d06caSMauro Carvalho Chehab return "PAUSE_ENCODER"; 685*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_REFRESH_INPUT: 686*0c0d06caSMauro Carvalho Chehab return "REFRESH_INPUT"; 687*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_COPYRIGHT: 688*0c0d06caSMauro Carvalho Chehab return "SET_COPYRIGHT"; 689*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_EVENT_NOTIFICATION: 690*0c0d06caSMauro Carvalho Chehab return "SET_EVENT_NOTIFICATION"; 691*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_NUM_VSYNC_LINES: 692*0c0d06caSMauro Carvalho Chehab return "SET_NUM_VSYNC_LINES"; 693*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_SET_PLACEHOLDER: 694*0c0d06caSMauro Carvalho Chehab return "SET_PLACEHOLDER"; 695*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_MUTE_VIDEO: 696*0c0d06caSMauro Carvalho Chehab return "MUTE_VIDEO"; 697*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_MUTE_AUDIO: 698*0c0d06caSMauro Carvalho Chehab return "MUTE_AUDIO"; 699*0c0d06caSMauro Carvalho Chehab case CX2341X_ENC_MISC: 700*0c0d06caSMauro Carvalho Chehab return "MISC"; 701*0c0d06caSMauro Carvalho Chehab default: 702*0c0d06caSMauro Carvalho Chehab return "UNKNOWN"; 703*0c0d06caSMauro Carvalho Chehab } 704*0c0d06caSMauro Carvalho Chehab } 705*0c0d06caSMauro Carvalho Chehab 706*0c0d06caSMauro Carvalho Chehab static int cx231xx_mbox_func(void *priv, 707*0c0d06caSMauro Carvalho Chehab u32 command, 708*0c0d06caSMauro Carvalho Chehab int in, 709*0c0d06caSMauro Carvalho Chehab int out, 710*0c0d06caSMauro Carvalho Chehab u32 data[CX2341X_MBOX_MAX_DATA]) 711*0c0d06caSMauro Carvalho Chehab { 712*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = priv; 713*0c0d06caSMauro Carvalho Chehab unsigned long timeout; 714*0c0d06caSMauro Carvalho Chehab u32 value, flag, retval = 0; 715*0c0d06caSMauro Carvalho Chehab int i; 716*0c0d06caSMauro Carvalho Chehab 717*0c0d06caSMauro Carvalho Chehab dprintk(3, "%s: command(0x%X) = %s\n", __func__, command, 718*0c0d06caSMauro Carvalho Chehab cmd_to_str(command)); 719*0c0d06caSMauro Carvalho Chehab 720*0c0d06caSMauro Carvalho Chehab /* this may not be 100% safe if we can't read any memory location 721*0c0d06caSMauro Carvalho Chehab without side effects */ 722*0c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value); 723*0c0d06caSMauro Carvalho Chehab if (value != 0x12345678) { 724*0c0d06caSMauro Carvalho Chehab dprintk(3, 725*0c0d06caSMauro Carvalho Chehab "Firmware and/or mailbox pointer not initialized " 726*0c0d06caSMauro Carvalho Chehab "or corrupted, signature = 0x%x, cmd = %s\n", value, 727*0c0d06caSMauro Carvalho Chehab cmd_to_str(command)); 728*0c0d06caSMauro Carvalho Chehab return -1; 729*0c0d06caSMauro Carvalho Chehab } 730*0c0d06caSMauro Carvalho Chehab 731*0c0d06caSMauro Carvalho Chehab /* This read looks at 32 bits, but flag is only 8 bits. 732*0c0d06caSMauro Carvalho Chehab * Seems we also bail if CMD or TIMEOUT bytes are set??? 733*0c0d06caSMauro Carvalho Chehab */ 734*0c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox, &flag); 735*0c0d06caSMauro Carvalho Chehab if (flag) { 736*0c0d06caSMauro Carvalho Chehab dprintk(3, "ERROR: Mailbox appears to be in use " 737*0c0d06caSMauro Carvalho Chehab "(%x), cmd = %s\n", flag, cmd_to_str(command)); 738*0c0d06caSMauro Carvalho Chehab return -1; 739*0c0d06caSMauro Carvalho Chehab } 740*0c0d06caSMauro Carvalho Chehab 741*0c0d06caSMauro Carvalho Chehab flag |= 1; /* tell 'em we're working on it */ 742*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox, flag); 743*0c0d06caSMauro Carvalho Chehab 744*0c0d06caSMauro Carvalho Chehab /* write command + args + fill remaining with zeros */ 745*0c0d06caSMauro Carvalho Chehab /* command code */ 746*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 1, command); 747*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 3, 748*0c0d06caSMauro Carvalho Chehab IVTV_API_STD_TIMEOUT); /* timeout */ 749*0c0d06caSMauro Carvalho Chehab for (i = 0; i < in; i++) { 750*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]); 751*0c0d06caSMauro Carvalho Chehab dprintk(3, "API Input %d = %d\n", i, data[i]); 752*0c0d06caSMauro Carvalho Chehab } 753*0c0d06caSMauro Carvalho Chehab for (; i < CX2341X_MBOX_MAX_DATA; i++) 754*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0); 755*0c0d06caSMauro Carvalho Chehab 756*0c0d06caSMauro Carvalho Chehab flag |= 3; /* tell 'em we're done writing */ 757*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox, flag); 758*0c0d06caSMauro Carvalho Chehab 759*0c0d06caSMauro Carvalho Chehab /* wait for firmware to handle the API command */ 760*0c0d06caSMauro Carvalho Chehab timeout = jiffies + msecs_to_jiffies(10); 761*0c0d06caSMauro Carvalho Chehab for (;;) { 762*0c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox, &flag); 763*0c0d06caSMauro Carvalho Chehab if (0 != (flag & 4)) 764*0c0d06caSMauro Carvalho Chehab break; 765*0c0d06caSMauro Carvalho Chehab if (time_after(jiffies, timeout)) { 766*0c0d06caSMauro Carvalho Chehab dprintk(3, "ERROR: API Mailbox timeout\n"); 767*0c0d06caSMauro Carvalho Chehab return -1; 768*0c0d06caSMauro Carvalho Chehab } 769*0c0d06caSMauro Carvalho Chehab udelay(10); 770*0c0d06caSMauro Carvalho Chehab } 771*0c0d06caSMauro Carvalho Chehab 772*0c0d06caSMauro Carvalho Chehab /* read output values */ 773*0c0d06caSMauro Carvalho Chehab for (i = 0; i < out; i++) { 774*0c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i); 775*0c0d06caSMauro Carvalho Chehab dprintk(3, "API Output %d = %d\n", i, data[i]); 776*0c0d06caSMauro Carvalho Chehab } 777*0c0d06caSMauro Carvalho Chehab 778*0c0d06caSMauro Carvalho Chehab mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval); 779*0c0d06caSMauro Carvalho Chehab dprintk(3, "API result = %d\n", retval); 780*0c0d06caSMauro Carvalho Chehab 781*0c0d06caSMauro Carvalho Chehab flag = 0; 782*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, dev->cx23417_mailbox, flag); 783*0c0d06caSMauro Carvalho Chehab 784*0c0d06caSMauro Carvalho Chehab return retval; 785*0c0d06caSMauro Carvalho Chehab } 786*0c0d06caSMauro Carvalho Chehab 787*0c0d06caSMauro Carvalho Chehab /* We don't need to call the API often, so using just one 788*0c0d06caSMauro Carvalho Chehab * mailbox will probably suffice 789*0c0d06caSMauro Carvalho Chehab */ 790*0c0d06caSMauro Carvalho Chehab static int cx231xx_api_cmd(struct cx231xx *dev, 791*0c0d06caSMauro Carvalho Chehab u32 command, 792*0c0d06caSMauro Carvalho Chehab u32 inputcnt, 793*0c0d06caSMauro Carvalho Chehab u32 outputcnt, 794*0c0d06caSMauro Carvalho Chehab ...) 795*0c0d06caSMauro Carvalho Chehab { 796*0c0d06caSMauro Carvalho Chehab u32 data[CX2341X_MBOX_MAX_DATA]; 797*0c0d06caSMauro Carvalho Chehab va_list vargs; 798*0c0d06caSMauro Carvalho Chehab int i, err; 799*0c0d06caSMauro Carvalho Chehab 800*0c0d06caSMauro Carvalho Chehab dprintk(3, "%s() cmds = 0x%08x\n", __func__, command); 801*0c0d06caSMauro Carvalho Chehab 802*0c0d06caSMauro Carvalho Chehab va_start(vargs, outputcnt); 803*0c0d06caSMauro Carvalho Chehab for (i = 0; i < inputcnt; i++) 804*0c0d06caSMauro Carvalho Chehab data[i] = va_arg(vargs, int); 805*0c0d06caSMauro Carvalho Chehab 806*0c0d06caSMauro Carvalho Chehab err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data); 807*0c0d06caSMauro Carvalho Chehab for (i = 0; i < outputcnt; i++) { 808*0c0d06caSMauro Carvalho Chehab int *vptr = va_arg(vargs, int *); 809*0c0d06caSMauro Carvalho Chehab *vptr = data[i]; 810*0c0d06caSMauro Carvalho Chehab } 811*0c0d06caSMauro Carvalho Chehab va_end(vargs); 812*0c0d06caSMauro Carvalho Chehab 813*0c0d06caSMauro Carvalho Chehab return err; 814*0c0d06caSMauro Carvalho Chehab } 815*0c0d06caSMauro Carvalho Chehab 816*0c0d06caSMauro Carvalho Chehab static int cx231xx_find_mailbox(struct cx231xx *dev) 817*0c0d06caSMauro Carvalho Chehab { 818*0c0d06caSMauro Carvalho Chehab u32 signature[4] = { 819*0c0d06caSMauro Carvalho Chehab 0x12345678, 0x34567812, 0x56781234, 0x78123456 820*0c0d06caSMauro Carvalho Chehab }; 821*0c0d06caSMauro Carvalho Chehab int signaturecnt = 0; 822*0c0d06caSMauro Carvalho Chehab u32 value; 823*0c0d06caSMauro Carvalho Chehab int i; 824*0c0d06caSMauro Carvalho Chehab int ret = 0; 825*0c0d06caSMauro Carvalho Chehab 826*0c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 827*0c0d06caSMauro Carvalho Chehab 828*0c0d06caSMauro Carvalho Chehab for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/ 829*0c0d06caSMauro Carvalho Chehab ret = mc417_memory_read(dev, i, &value); 830*0c0d06caSMauro Carvalho Chehab if (ret < 0) 831*0c0d06caSMauro Carvalho Chehab return ret; 832*0c0d06caSMauro Carvalho Chehab if (value == signature[signaturecnt]) 833*0c0d06caSMauro Carvalho Chehab signaturecnt++; 834*0c0d06caSMauro Carvalho Chehab else 835*0c0d06caSMauro Carvalho Chehab signaturecnt = 0; 836*0c0d06caSMauro Carvalho Chehab if (4 == signaturecnt) { 837*0c0d06caSMauro Carvalho Chehab dprintk(1, "Mailbox signature found at 0x%x\n", i+1); 838*0c0d06caSMauro Carvalho Chehab return i+1; 839*0c0d06caSMauro Carvalho Chehab } 840*0c0d06caSMauro Carvalho Chehab } 841*0c0d06caSMauro Carvalho Chehab dprintk(3, "Mailbox signature values not found!\n"); 842*0c0d06caSMauro Carvalho Chehab return -1; 843*0c0d06caSMauro Carvalho Chehab } 844*0c0d06caSMauro Carvalho Chehab 845*0c0d06caSMauro Carvalho Chehab static void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value, 846*0c0d06caSMauro Carvalho Chehab u32 *p_fw_image) 847*0c0d06caSMauro Carvalho Chehab { 848*0c0d06caSMauro Carvalho Chehab 849*0c0d06caSMauro Carvalho Chehab u32 temp = 0; 850*0c0d06caSMauro Carvalho Chehab int i = 0; 851*0c0d06caSMauro Carvalho Chehab 852*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8); 853*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 854*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 855*0c0d06caSMauro Carvalho Chehab p_fw_image++; 856*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 857*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 858*0c0d06caSMauro Carvalho Chehab p_fw_image++; 859*0c0d06caSMauro Carvalho Chehab 860*0c0d06caSMauro Carvalho Chehab /*write data byte 1;*/ 861*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00); 862*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 863*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 864*0c0d06caSMauro Carvalho Chehab p_fw_image++; 865*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 866*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 867*0c0d06caSMauro Carvalho Chehab p_fw_image++; 868*0c0d06caSMauro Carvalho Chehab 869*0c0d06caSMauro Carvalho Chehab /*write data byte 2;*/ 870*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8); 871*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 872*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 873*0c0d06caSMauro Carvalho Chehab p_fw_image++; 874*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 875*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 876*0c0d06caSMauro Carvalho Chehab p_fw_image++; 877*0c0d06caSMauro Carvalho Chehab 878*0c0d06caSMauro Carvalho Chehab /*write data byte 3;*/ 879*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16); 880*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 881*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 882*0c0d06caSMauro Carvalho Chehab p_fw_image++; 883*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 884*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 885*0c0d06caSMauro Carvalho Chehab p_fw_image++; 886*0c0d06caSMauro Carvalho Chehab 887*0c0d06caSMauro Carvalho Chehab /* write address byte 2;*/ 888*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | 889*0c0d06caSMauro Carvalho Chehab ((address & 0x003F0000)>>8); 890*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 891*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 892*0c0d06caSMauro Carvalho Chehab p_fw_image++; 893*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 894*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 895*0c0d06caSMauro Carvalho Chehab p_fw_image++; 896*0c0d06caSMauro Carvalho Chehab 897*0c0d06caSMauro Carvalho Chehab /* write address byte 1;*/ 898*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); 899*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 900*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 901*0c0d06caSMauro Carvalho Chehab p_fw_image++; 902*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 903*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 904*0c0d06caSMauro Carvalho Chehab p_fw_image++; 905*0c0d06caSMauro Carvalho Chehab 906*0c0d06caSMauro Carvalho Chehab /* write address byte 0;*/ 907*0c0d06caSMauro Carvalho Chehab temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8); 908*0c0d06caSMauro Carvalho Chehab temp = temp<<10; 909*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 910*0c0d06caSMauro Carvalho Chehab p_fw_image++; 911*0c0d06caSMauro Carvalho Chehab temp = temp|((0x05)<<10); 912*0c0d06caSMauro Carvalho Chehab *p_fw_image = temp; 913*0c0d06caSMauro Carvalho Chehab p_fw_image++; 914*0c0d06caSMauro Carvalho Chehab 915*0c0d06caSMauro Carvalho Chehab for (i = 0; i < 6; i++) { 916*0c0d06caSMauro Carvalho Chehab *p_fw_image = 0xFFFFFFFF; 917*0c0d06caSMauro Carvalho Chehab p_fw_image++; 918*0c0d06caSMauro Carvalho Chehab } 919*0c0d06caSMauro Carvalho Chehab } 920*0c0d06caSMauro Carvalho Chehab 921*0c0d06caSMauro Carvalho Chehab 922*0c0d06caSMauro Carvalho Chehab static int cx231xx_load_firmware(struct cx231xx *dev) 923*0c0d06caSMauro Carvalho Chehab { 924*0c0d06caSMauro Carvalho Chehab static const unsigned char magic[8] = { 925*0c0d06caSMauro Carvalho Chehab 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa 926*0c0d06caSMauro Carvalho Chehab }; 927*0c0d06caSMauro Carvalho Chehab const struct firmware *firmware; 928*0c0d06caSMauro Carvalho Chehab int i, retval = 0; 929*0c0d06caSMauro Carvalho Chehab u32 value = 0; 930*0c0d06caSMauro Carvalho Chehab u32 gpio_output = 0; 931*0c0d06caSMauro Carvalho Chehab /*u32 checksum = 0;*/ 932*0c0d06caSMauro Carvalho Chehab /*u32 *dataptr;*/ 933*0c0d06caSMauro Carvalho Chehab u32 transfer_size = 0; 934*0c0d06caSMauro Carvalho Chehab u32 fw_data = 0; 935*0c0d06caSMauro Carvalho Chehab u32 address = 0; 936*0c0d06caSMauro Carvalho Chehab /*u32 current_fw[800];*/ 937*0c0d06caSMauro Carvalho Chehab u32 *p_current_fw, *p_fw; 938*0c0d06caSMauro Carvalho Chehab u32 *p_fw_data; 939*0c0d06caSMauro Carvalho Chehab int frame = 0; 940*0c0d06caSMauro Carvalho Chehab u16 _buffer_size = 4096; 941*0c0d06caSMauro Carvalho Chehab u8 *p_buffer; 942*0c0d06caSMauro Carvalho Chehab 943*0c0d06caSMauro Carvalho Chehab p_current_fw = vmalloc(1884180 * 4); 944*0c0d06caSMauro Carvalho Chehab p_fw = p_current_fw; 945*0c0d06caSMauro Carvalho Chehab if (p_current_fw == NULL) { 946*0c0d06caSMauro Carvalho Chehab dprintk(2, "FAIL!!!\n"); 947*0c0d06caSMauro Carvalho Chehab return -1; 948*0c0d06caSMauro Carvalho Chehab } 949*0c0d06caSMauro Carvalho Chehab 950*0c0d06caSMauro Carvalho Chehab p_buffer = vmalloc(4096); 951*0c0d06caSMauro Carvalho Chehab if (p_buffer == NULL) { 952*0c0d06caSMauro Carvalho Chehab dprintk(2, "FAIL!!!\n"); 953*0c0d06caSMauro Carvalho Chehab return -1; 954*0c0d06caSMauro Carvalho Chehab } 955*0c0d06caSMauro Carvalho Chehab 956*0c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 957*0c0d06caSMauro Carvalho Chehab 958*0c0d06caSMauro Carvalho Chehab /* Save GPIO settings before reset of APU */ 959*0c0d06caSMauro Carvalho Chehab retval |= mc417_memory_read(dev, 0x9020, &gpio_output); 960*0c0d06caSMauro Carvalho Chehab retval |= mc417_memory_read(dev, 0x900C, &value); 961*0c0d06caSMauro Carvalho Chehab 962*0c0d06caSMauro Carvalho Chehab retval = mc417_register_write(dev, 963*0c0d06caSMauro Carvalho Chehab IVTV_REG_VPU, 0xFFFFFFED); 964*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 965*0c0d06caSMauro Carvalho Chehab IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); 966*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 967*0c0d06caSMauro Carvalho Chehab IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800); 968*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 969*0c0d06caSMauro Carvalho Chehab IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); 970*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 971*0c0d06caSMauro Carvalho Chehab IVTV_REG_APU, 0); 972*0c0d06caSMauro Carvalho Chehab 973*0c0d06caSMauro Carvalho Chehab if (retval != 0) { 974*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s: Error with mc417_register_write\n", 975*0c0d06caSMauro Carvalho Chehab __func__); 976*0c0d06caSMauro Carvalho Chehab return -1; 977*0c0d06caSMauro Carvalho Chehab } 978*0c0d06caSMauro Carvalho Chehab 979*0c0d06caSMauro Carvalho Chehab retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME, 980*0c0d06caSMauro Carvalho Chehab &dev->udev->dev); 981*0c0d06caSMauro Carvalho Chehab 982*0c0d06caSMauro Carvalho Chehab if (retval != 0) { 983*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR 984*0c0d06caSMauro Carvalho Chehab "ERROR: Hotplug firmware request failed (%s).\n", 985*0c0d06caSMauro Carvalho Chehab CX231xx_FIRM_IMAGE_NAME); 986*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "Please fix your hotplug setup, the board will " 987*0c0d06caSMauro Carvalho Chehab "not work without firmware loaded!\n"); 988*0c0d06caSMauro Carvalho Chehab return -1; 989*0c0d06caSMauro Carvalho Chehab } 990*0c0d06caSMauro Carvalho Chehab 991*0c0d06caSMauro Carvalho Chehab if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) { 992*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "ERROR: Firmware size mismatch " 993*0c0d06caSMauro Carvalho Chehab "(have %zd, expected %d)\n", 994*0c0d06caSMauro Carvalho Chehab firmware->size, CX231xx_FIRM_IMAGE_SIZE); 995*0c0d06caSMauro Carvalho Chehab release_firmware(firmware); 996*0c0d06caSMauro Carvalho Chehab return -1; 997*0c0d06caSMauro Carvalho Chehab } 998*0c0d06caSMauro Carvalho Chehab 999*0c0d06caSMauro Carvalho Chehab if (0 != memcmp(firmware->data, magic, 8)) { 1000*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR 1001*0c0d06caSMauro Carvalho Chehab "ERROR: Firmware magic mismatch, wrong file?\n"); 1002*0c0d06caSMauro Carvalho Chehab release_firmware(firmware); 1003*0c0d06caSMauro Carvalho Chehab return -1; 1004*0c0d06caSMauro Carvalho Chehab } 1005*0c0d06caSMauro Carvalho Chehab 1006*0c0d06caSMauro Carvalho Chehab initGPIO(dev); 1007*0c0d06caSMauro Carvalho Chehab 1008*0c0d06caSMauro Carvalho Chehab /* transfer to the chip */ 1009*0c0d06caSMauro Carvalho Chehab dprintk(2, "Loading firmware to GPIO...\n"); 1010*0c0d06caSMauro Carvalho Chehab p_fw_data = (u32 *)firmware->data; 1011*0c0d06caSMauro Carvalho Chehab dprintk(2, "firmware->size=%zd\n", firmware->size); 1012*0c0d06caSMauro Carvalho Chehab for (transfer_size = 0; transfer_size < firmware->size; 1013*0c0d06caSMauro Carvalho Chehab transfer_size += 4) { 1014*0c0d06caSMauro Carvalho Chehab fw_data = *p_fw_data; 1015*0c0d06caSMauro Carvalho Chehab 1016*0c0d06caSMauro Carvalho Chehab mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw); 1017*0c0d06caSMauro Carvalho Chehab address = address + 1; 1018*0c0d06caSMauro Carvalho Chehab p_current_fw += 20; 1019*0c0d06caSMauro Carvalho Chehab p_fw_data += 1; 1020*0c0d06caSMauro Carvalho Chehab } 1021*0c0d06caSMauro Carvalho Chehab 1022*0c0d06caSMauro Carvalho Chehab /*download the firmware by ep5-out*/ 1023*0c0d06caSMauro Carvalho Chehab 1024*0c0d06caSMauro Carvalho Chehab for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size); 1025*0c0d06caSMauro Carvalho Chehab frame++) { 1026*0c0d06caSMauro Carvalho Chehab for (i = 0; i < _buffer_size; i++) { 1027*0c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF); 1028*0c0d06caSMauro Carvalho Chehab i++; 1029*0c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8); 1030*0c0d06caSMauro Carvalho Chehab i++; 1031*0c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16); 1032*0c0d06caSMauro Carvalho Chehab i++; 1033*0c0d06caSMauro Carvalho Chehab *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24); 1034*0c0d06caSMauro Carvalho Chehab } 1035*0c0d06caSMauro Carvalho Chehab cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size); 1036*0c0d06caSMauro Carvalho Chehab } 1037*0c0d06caSMauro Carvalho Chehab 1038*0c0d06caSMauro Carvalho Chehab p_current_fw = p_fw; 1039*0c0d06caSMauro Carvalho Chehab vfree(p_current_fw); 1040*0c0d06caSMauro Carvalho Chehab p_current_fw = NULL; 1041*0c0d06caSMauro Carvalho Chehab uninitGPIO(dev); 1042*0c0d06caSMauro Carvalho Chehab release_firmware(firmware); 1043*0c0d06caSMauro Carvalho Chehab dprintk(1, "Firmware upload successful.\n"); 1044*0c0d06caSMauro Carvalho Chehab 1045*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, 1046*0c0d06caSMauro Carvalho Chehab IVTV_CMD_HW_BLOCKS_RST); 1047*0c0d06caSMauro Carvalho Chehab if (retval < 0) { 1048*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s: Error with mc417_register_write\n", 1049*0c0d06caSMauro Carvalho Chehab __func__); 1050*0c0d06caSMauro Carvalho Chehab return retval; 1051*0c0d06caSMauro Carvalho Chehab } 1052*0c0d06caSMauro Carvalho Chehab /* F/W power up disturbs the GPIOs, restore state */ 1053*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 0x9020, gpio_output); 1054*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, 0x900C, value); 1055*0c0d06caSMauro Carvalho Chehab 1056*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); 1057*0c0d06caSMauro Carvalho Chehab retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); 1058*0c0d06caSMauro Carvalho Chehab 1059*0c0d06caSMauro Carvalho Chehab if (retval < 0) { 1060*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s: Error with mc417_register_write\n", 1061*0c0d06caSMauro Carvalho Chehab __func__); 1062*0c0d06caSMauro Carvalho Chehab return retval; 1063*0c0d06caSMauro Carvalho Chehab } 1064*0c0d06caSMauro Carvalho Chehab return 0; 1065*0c0d06caSMauro Carvalho Chehab } 1066*0c0d06caSMauro Carvalho Chehab 1067*0c0d06caSMauro Carvalho Chehab static void cx231xx_417_check_encoder(struct cx231xx *dev) 1068*0c0d06caSMauro Carvalho Chehab { 1069*0c0d06caSMauro Carvalho Chehab u32 status, seq; 1070*0c0d06caSMauro Carvalho Chehab 1071*0c0d06caSMauro Carvalho Chehab status = 0; 1072*0c0d06caSMauro Carvalho Chehab seq = 0; 1073*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq); 1074*0c0d06caSMauro Carvalho Chehab dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq); 1075*0c0d06caSMauro Carvalho Chehab } 1076*0c0d06caSMauro Carvalho Chehab 1077*0c0d06caSMauro Carvalho Chehab static void cx231xx_codec_settings(struct cx231xx *dev) 1078*0c0d06caSMauro Carvalho Chehab { 1079*0c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 1080*0c0d06caSMauro Carvalho Chehab 1081*0c0d06caSMauro Carvalho Chehab /* assign frame size */ 1082*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, 1083*0c0d06caSMauro Carvalho Chehab dev->ts1.height, dev->ts1.width); 1084*0c0d06caSMauro Carvalho Chehab 1085*0c0d06caSMauro Carvalho Chehab dev->mpeg_params.width = dev->ts1.width; 1086*0c0d06caSMauro Carvalho Chehab dev->mpeg_params.height = dev->ts1.height; 1087*0c0d06caSMauro Carvalho Chehab 1088*0c0d06caSMauro Carvalho Chehab cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params); 1089*0c0d06caSMauro Carvalho Chehab 1090*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); 1091*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); 1092*0c0d06caSMauro Carvalho Chehab } 1093*0c0d06caSMauro Carvalho Chehab 1094*0c0d06caSMauro Carvalho Chehab static int cx231xx_initialize_codec(struct cx231xx *dev) 1095*0c0d06caSMauro Carvalho Chehab { 1096*0c0d06caSMauro Carvalho Chehab int version; 1097*0c0d06caSMauro Carvalho Chehab int retval; 1098*0c0d06caSMauro Carvalho Chehab u32 i; 1099*0c0d06caSMauro Carvalho Chehab u32 val = 0; 1100*0c0d06caSMauro Carvalho Chehab 1101*0c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 1102*0c0d06caSMauro Carvalho Chehab cx231xx_disable656(dev); 1103*0c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ 1104*0c0d06caSMauro Carvalho Chehab if (retval < 0) { 1105*0c0d06caSMauro Carvalho Chehab dprintk(2, "%s() PING OK\n", __func__); 1106*0c0d06caSMauro Carvalho Chehab retval = cx231xx_load_firmware(dev); 1107*0c0d06caSMauro Carvalho Chehab if (retval < 0) { 1108*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s() f/w load failed\n", __func__); 1109*0c0d06caSMauro Carvalho Chehab return retval; 1110*0c0d06caSMauro Carvalho Chehab } 1111*0c0d06caSMauro Carvalho Chehab retval = cx231xx_find_mailbox(dev); 1112*0c0d06caSMauro Carvalho Chehab if (retval < 0) { 1113*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "%s() mailbox < 0, error\n", 1114*0c0d06caSMauro Carvalho Chehab __func__); 1115*0c0d06caSMauro Carvalho Chehab return -1; 1116*0c0d06caSMauro Carvalho Chehab } 1117*0c0d06caSMauro Carvalho Chehab dev->cx23417_mailbox = retval; 1118*0c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); 1119*0c0d06caSMauro Carvalho Chehab if (retval < 0) { 1120*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR 1121*0c0d06caSMauro Carvalho Chehab "ERROR: cx23417 firmware ping failed!\n"); 1122*0c0d06caSMauro Carvalho Chehab return -1; 1123*0c0d06caSMauro Carvalho Chehab } 1124*0c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, 1125*0c0d06caSMauro Carvalho Chehab &version); 1126*0c0d06caSMauro Carvalho Chehab if (retval < 0) { 1127*0c0d06caSMauro Carvalho Chehab printk(KERN_ERR "ERROR: cx23417 firmware get encoder :" 1128*0c0d06caSMauro Carvalho Chehab "version failed!\n"); 1129*0c0d06caSMauro Carvalho Chehab return -1; 1130*0c0d06caSMauro Carvalho Chehab } 1131*0c0d06caSMauro Carvalho Chehab dprintk(1, "cx23417 firmware version is 0x%08x\n", version); 1132*0c0d06caSMauro Carvalho Chehab msleep(200); 1133*0c0d06caSMauro Carvalho Chehab } 1134*0c0d06caSMauro Carvalho Chehab 1135*0c0d06caSMauro Carvalho Chehab for (i = 0; i < 1; i++) { 1136*0c0d06caSMauro Carvalho Chehab retval = mc417_register_read(dev, 0x20f8, &val); 1137*0c0d06caSMauro Carvalho Chehab dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n", 1138*0c0d06caSMauro Carvalho Chehab val); 1139*0c0d06caSMauro Carvalho Chehab if (retval < 0) 1140*0c0d06caSMauro Carvalho Chehab return retval; 1141*0c0d06caSMauro Carvalho Chehab } 1142*0c0d06caSMauro Carvalho Chehab 1143*0c0d06caSMauro Carvalho Chehab cx231xx_enable656(dev); 1144*0c0d06caSMauro Carvalho Chehab /* stop mpeg capture */ 1145*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 1146*0c0d06caSMauro Carvalho Chehab 3, 0, 1, 3, 4); 1147*0c0d06caSMauro Carvalho Chehab 1148*0c0d06caSMauro Carvalho Chehab cx231xx_codec_settings(dev); 1149*0c0d06caSMauro Carvalho Chehab msleep(60); 1150*0c0d06caSMauro Carvalho Chehab 1151*0c0d06caSMauro Carvalho Chehab /* cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, 1152*0c0d06caSMauro Carvalho Chehab CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115); 1153*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, 1154*0c0d06caSMauro Carvalho Chehab CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1155*0c0d06caSMauro Carvalho Chehab 0, 0); 1156*0c0d06caSMauro Carvalho Chehab */ 1157*0c0d06caSMauro Carvalho Chehab 1158*0c0d06caSMauro Carvalho Chehab #if 0 1159*0c0d06caSMauro Carvalho Chehab /* TODO */ 1160*0c0d06caSMauro Carvalho Chehab u32 data[7]; 1161*0c0d06caSMauro Carvalho Chehab 1162*0c0d06caSMauro Carvalho Chehab /* Setup to capture VBI */ 1163*0c0d06caSMauro Carvalho Chehab data[0] = 0x0001BD00; 1164*0c0d06caSMauro Carvalho Chehab data[1] = 1; /* frames per interrupt */ 1165*0c0d06caSMauro Carvalho Chehab data[2] = 4; /* total bufs */ 1166*0c0d06caSMauro Carvalho Chehab data[3] = 0x91559155; /* start codes */ 1167*0c0d06caSMauro Carvalho Chehab data[4] = 0x206080C0; /* stop codes */ 1168*0c0d06caSMauro Carvalho Chehab data[5] = 6; /* lines */ 1169*0c0d06caSMauro Carvalho Chehab data[6] = 64; /* BPL */ 1170*0c0d06caSMauro Carvalho Chehab 1171*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1], 1172*0c0d06caSMauro Carvalho Chehab data[2], data[3], data[4], data[5], data[6]); 1173*0c0d06caSMauro Carvalho Chehab 1174*0c0d06caSMauro Carvalho Chehab for (i = 2; i <= 24; i++) { 1175*0c0d06caSMauro Carvalho Chehab int valid; 1176*0c0d06caSMauro Carvalho Chehab 1177*0c0d06caSMauro Carvalho Chehab valid = ((i >= 19) && (i <= 21)); 1178*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i, 1179*0c0d06caSMauro Carvalho Chehab valid, 0 , 0, 0); 1180*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, 1181*0c0d06caSMauro Carvalho Chehab i | 0x80000000, valid, 0, 0, 0); 1182*0c0d06caSMauro Carvalho Chehab } 1183*0c0d06caSMauro Carvalho Chehab #endif 1184*0c0d06caSMauro Carvalho Chehab /* cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE); 1185*0c0d06caSMauro Carvalho Chehab msleep(60); 1186*0c0d06caSMauro Carvalho Chehab */ 1187*0c0d06caSMauro Carvalho Chehab /* initialize the video input */ 1188*0c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); 1189*0c0d06caSMauro Carvalho Chehab if (retval < 0) 1190*0c0d06caSMauro Carvalho Chehab return retval; 1191*0c0d06caSMauro Carvalho Chehab msleep(60); 1192*0c0d06caSMauro Carvalho Chehab 1193*0c0d06caSMauro Carvalho Chehab /* Enable VIP style pixel invalidation so we work with scaled mode */ 1194*0c0d06caSMauro Carvalho Chehab mc417_memory_write(dev, 2120, 0x00000080); 1195*0c0d06caSMauro Carvalho Chehab 1196*0c0d06caSMauro Carvalho Chehab /* start capturing to the host interface */ 1197*0c0d06caSMauro Carvalho Chehab retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 1198*0c0d06caSMauro Carvalho Chehab CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE); 1199*0c0d06caSMauro Carvalho Chehab if (retval < 0) 1200*0c0d06caSMauro Carvalho Chehab return retval; 1201*0c0d06caSMauro Carvalho Chehab msleep(10); 1202*0c0d06caSMauro Carvalho Chehab 1203*0c0d06caSMauro Carvalho Chehab for (i = 0; i < 1; i++) { 1204*0c0d06caSMauro Carvalho Chehab mc417_register_read(dev, 0x20f8, &val); 1205*0c0d06caSMauro Carvalho Chehab dprintk(3, "***VIM Capture Lines =%d ***\n", val); 1206*0c0d06caSMauro Carvalho Chehab } 1207*0c0d06caSMauro Carvalho Chehab 1208*0c0d06caSMauro Carvalho Chehab return 0; 1209*0c0d06caSMauro Carvalho Chehab } 1210*0c0d06caSMauro Carvalho Chehab 1211*0c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 1212*0c0d06caSMauro Carvalho Chehab 1213*0c0d06caSMauro Carvalho Chehab static int bb_buf_setup(struct videobuf_queue *q, 1214*0c0d06caSMauro Carvalho Chehab unsigned int *count, unsigned int *size) 1215*0c0d06caSMauro Carvalho Chehab { 1216*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = q->priv_data; 1217*0c0d06caSMauro Carvalho Chehab 1218*0c0d06caSMauro Carvalho Chehab fh->dev->ts1.ts_packet_size = mpeglinesize; 1219*0c0d06caSMauro Carvalho Chehab fh->dev->ts1.ts_packet_count = mpeglines; 1220*0c0d06caSMauro Carvalho Chehab 1221*0c0d06caSMauro Carvalho Chehab *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; 1222*0c0d06caSMauro Carvalho Chehab *count = mpegbufs; 1223*0c0d06caSMauro Carvalho Chehab 1224*0c0d06caSMauro Carvalho Chehab return 0; 1225*0c0d06caSMauro Carvalho Chehab } 1226*0c0d06caSMauro Carvalho Chehab static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) 1227*0c0d06caSMauro Carvalho Chehab { 1228*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = vq->priv_data; 1229*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1230*0c0d06caSMauro Carvalho Chehab unsigned long flags = 0; 1231*0c0d06caSMauro Carvalho Chehab 1232*0c0d06caSMauro Carvalho Chehab if (in_interrupt()) 1233*0c0d06caSMauro Carvalho Chehab BUG(); 1234*0c0d06caSMauro Carvalho Chehab 1235*0c0d06caSMauro Carvalho Chehab spin_lock_irqsave(&dev->video_mode.slock, flags); 1236*0c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) { 1237*0c0d06caSMauro Carvalho Chehab if (dev->video_mode.isoc_ctl.buf == buf) 1238*0c0d06caSMauro Carvalho Chehab dev->video_mode.isoc_ctl.buf = NULL; 1239*0c0d06caSMauro Carvalho Chehab } else { 1240*0c0d06caSMauro Carvalho Chehab if (dev->video_mode.bulk_ctl.buf == buf) 1241*0c0d06caSMauro Carvalho Chehab dev->video_mode.bulk_ctl.buf = NULL; 1242*0c0d06caSMauro Carvalho Chehab } 1243*0c0d06caSMauro Carvalho Chehab spin_unlock_irqrestore(&dev->video_mode.slock, flags); 1244*0c0d06caSMauro Carvalho Chehab videobuf_waiton(vq, &buf->vb, 0, 0); 1245*0c0d06caSMauro Carvalho Chehab videobuf_vmalloc_free(&buf->vb); 1246*0c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_NEEDS_INIT; 1247*0c0d06caSMauro Carvalho Chehab } 1248*0c0d06caSMauro Carvalho Chehab 1249*0c0d06caSMauro Carvalho Chehab static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb, 1250*0c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q) 1251*0c0d06caSMauro Carvalho Chehab { 1252*0c0d06caSMauro Carvalho Chehab void *vbuf; 1253*0c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf; 1254*0c0d06caSMauro Carvalho Chehab u32 tail_data = 0; 1255*0c0d06caSMauro Carvalho Chehab char *p_data; 1256*0c0d06caSMauro Carvalho Chehab 1257*0c0d06caSMauro Carvalho Chehab if (dma_q->mpeg_buffer_done == 0) { 1258*0c0d06caSMauro Carvalho Chehab if (list_empty(&dma_q->active)) 1259*0c0d06caSMauro Carvalho Chehab return; 1260*0c0d06caSMauro Carvalho Chehab 1261*0c0d06caSMauro Carvalho Chehab buf = list_entry(dma_q->active.next, 1262*0c0d06caSMauro Carvalho Chehab struct cx231xx_buffer, vb.queue); 1263*0c0d06caSMauro Carvalho Chehab dev->video_mode.isoc_ctl.buf = buf; 1264*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_done = 1; 1265*0c0d06caSMauro Carvalho Chehab } 1266*0c0d06caSMauro Carvalho Chehab /* Fill buffer */ 1267*0c0d06caSMauro Carvalho Chehab buf = dev->video_mode.isoc_ctl.buf; 1268*0c0d06caSMauro Carvalho Chehab vbuf = videobuf_to_vmalloc(&buf->vb); 1269*0c0d06caSMauro Carvalho Chehab 1270*0c0d06caSMauro Carvalho Chehab if ((dma_q->mpeg_buffer_completed+len) < 1271*0c0d06caSMauro Carvalho Chehab mpeglines*mpeglinesize) { 1272*0c0d06caSMauro Carvalho Chehab if (dma_q->add_ps_package_head == 1273*0c0d06caSMauro Carvalho Chehab CX231XX_NEED_ADD_PS_PACKAGE_HEAD) { 1274*0c0d06caSMauro Carvalho Chehab memcpy(vbuf+dma_q->mpeg_buffer_completed, 1275*0c0d06caSMauro Carvalho Chehab dma_q->ps_head, 3); 1276*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = 1277*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed + 3; 1278*0c0d06caSMauro Carvalho Chehab dma_q->add_ps_package_head = 1279*0c0d06caSMauro Carvalho Chehab CX231XX_NONEED_PS_PACKAGE_HEAD; 1280*0c0d06caSMauro Carvalho Chehab } 1281*0c0d06caSMauro Carvalho Chehab memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len); 1282*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = 1283*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed + len; 1284*0c0d06caSMauro Carvalho Chehab } else { 1285*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_done = 0; 1286*0c0d06caSMauro Carvalho Chehab 1287*0c0d06caSMauro Carvalho Chehab tail_data = 1288*0c0d06caSMauro Carvalho Chehab mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed; 1289*0c0d06caSMauro Carvalho Chehab memcpy(vbuf+dma_q->mpeg_buffer_completed, 1290*0c0d06caSMauro Carvalho Chehab data, tail_data); 1291*0c0d06caSMauro Carvalho Chehab 1292*0c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_DONE; 1293*0c0d06caSMauro Carvalho Chehab buf->vb.field_count++; 1294*0c0d06caSMauro Carvalho Chehab do_gettimeofday(&buf->vb.ts); 1295*0c0d06caSMauro Carvalho Chehab list_del(&buf->vb.queue); 1296*0c0d06caSMauro Carvalho Chehab wake_up(&buf->vb.done); 1297*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = 0; 1298*0c0d06caSMauro Carvalho Chehab 1299*0c0d06caSMauro Carvalho Chehab if (len - tail_data > 0) { 1300*0c0d06caSMauro Carvalho Chehab p_data = data + tail_data; 1301*0c0d06caSMauro Carvalho Chehab dma_q->left_data_count = len - tail_data; 1302*0c0d06caSMauro Carvalho Chehab memcpy(dma_q->p_left_data, 1303*0c0d06caSMauro Carvalho Chehab p_data, len - tail_data); 1304*0c0d06caSMauro Carvalho Chehab } 1305*0c0d06caSMauro Carvalho Chehab 1306*0c0d06caSMauro Carvalho Chehab } 1307*0c0d06caSMauro Carvalho Chehab 1308*0c0d06caSMauro Carvalho Chehab return; 1309*0c0d06caSMauro Carvalho Chehab } 1310*0c0d06caSMauro Carvalho Chehab 1311*0c0d06caSMauro Carvalho Chehab static void buffer_filled(char *data, int len, struct urb *urb, 1312*0c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q) 1313*0c0d06caSMauro Carvalho Chehab { 1314*0c0d06caSMauro Carvalho Chehab void *vbuf; 1315*0c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf; 1316*0c0d06caSMauro Carvalho Chehab 1317*0c0d06caSMauro Carvalho Chehab if (list_empty(&dma_q->active)) 1318*0c0d06caSMauro Carvalho Chehab return; 1319*0c0d06caSMauro Carvalho Chehab 1320*0c0d06caSMauro Carvalho Chehab 1321*0c0d06caSMauro Carvalho Chehab buf = list_entry(dma_q->active.next, 1322*0c0d06caSMauro Carvalho Chehab struct cx231xx_buffer, vb.queue); 1323*0c0d06caSMauro Carvalho Chehab 1324*0c0d06caSMauro Carvalho Chehab 1325*0c0d06caSMauro Carvalho Chehab /* Fill buffer */ 1326*0c0d06caSMauro Carvalho Chehab vbuf = videobuf_to_vmalloc(&buf->vb); 1327*0c0d06caSMauro Carvalho Chehab memcpy(vbuf, data, len); 1328*0c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_DONE; 1329*0c0d06caSMauro Carvalho Chehab buf->vb.field_count++; 1330*0c0d06caSMauro Carvalho Chehab do_gettimeofday(&buf->vb.ts); 1331*0c0d06caSMauro Carvalho Chehab list_del(&buf->vb.queue); 1332*0c0d06caSMauro Carvalho Chehab wake_up(&buf->vb.done); 1333*0c0d06caSMauro Carvalho Chehab 1334*0c0d06caSMauro Carvalho Chehab return; 1335*0c0d06caSMauro Carvalho Chehab } 1336*0c0d06caSMauro Carvalho Chehab static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) 1337*0c0d06caSMauro Carvalho Chehab { 1338*0c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q = urb->context; 1339*0c0d06caSMauro Carvalho Chehab unsigned char *p_buffer; 1340*0c0d06caSMauro Carvalho Chehab u32 buffer_size = 0; 1341*0c0d06caSMauro Carvalho Chehab u32 i = 0; 1342*0c0d06caSMauro Carvalho Chehab 1343*0c0d06caSMauro Carvalho Chehab for (i = 0; i < urb->number_of_packets; i++) { 1344*0c0d06caSMauro Carvalho Chehab if (dma_q->left_data_count > 0) { 1345*0c0d06caSMauro Carvalho Chehab buffer_copy(dev, dma_q->p_left_data, 1346*0c0d06caSMauro Carvalho Chehab dma_q->left_data_count, urb, dma_q); 1347*0c0d06caSMauro Carvalho Chehab dma_q->mpeg_buffer_completed = dma_q->left_data_count; 1348*0c0d06caSMauro Carvalho Chehab dma_q->left_data_count = 0; 1349*0c0d06caSMauro Carvalho Chehab } 1350*0c0d06caSMauro Carvalho Chehab 1351*0c0d06caSMauro Carvalho Chehab p_buffer = urb->transfer_buffer + 1352*0c0d06caSMauro Carvalho Chehab urb->iso_frame_desc[i].offset; 1353*0c0d06caSMauro Carvalho Chehab buffer_size = urb->iso_frame_desc[i].actual_length; 1354*0c0d06caSMauro Carvalho Chehab 1355*0c0d06caSMauro Carvalho Chehab if (buffer_size > 0) 1356*0c0d06caSMauro Carvalho Chehab buffer_copy(dev, p_buffer, buffer_size, urb, dma_q); 1357*0c0d06caSMauro Carvalho Chehab } 1358*0c0d06caSMauro Carvalho Chehab 1359*0c0d06caSMauro Carvalho Chehab return 0; 1360*0c0d06caSMauro Carvalho Chehab } 1361*0c0d06caSMauro Carvalho Chehab static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) 1362*0c0d06caSMauro Carvalho Chehab { 1363*0c0d06caSMauro Carvalho Chehab 1364*0c0d06caSMauro Carvalho Chehab /*char *outp;*/ 1365*0c0d06caSMauro Carvalho Chehab /*struct cx231xx_buffer *buf;*/ 1366*0c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *dma_q = urb->context; 1367*0c0d06caSMauro Carvalho Chehab unsigned char *p_buffer, *buffer; 1368*0c0d06caSMauro Carvalho Chehab u32 buffer_size = 0; 1369*0c0d06caSMauro Carvalho Chehab 1370*0c0d06caSMauro Carvalho Chehab p_buffer = urb->transfer_buffer; 1371*0c0d06caSMauro Carvalho Chehab buffer_size = urb->actual_length; 1372*0c0d06caSMauro Carvalho Chehab 1373*0c0d06caSMauro Carvalho Chehab buffer = kmalloc(buffer_size, GFP_ATOMIC); 1374*0c0d06caSMauro Carvalho Chehab 1375*0c0d06caSMauro Carvalho Chehab memcpy(buffer, dma_q->ps_head, 3); 1376*0c0d06caSMauro Carvalho Chehab memcpy(buffer+3, p_buffer, buffer_size-3); 1377*0c0d06caSMauro Carvalho Chehab memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3); 1378*0c0d06caSMauro Carvalho Chehab 1379*0c0d06caSMauro Carvalho Chehab p_buffer = buffer; 1380*0c0d06caSMauro Carvalho Chehab buffer_filled(p_buffer, buffer_size, urb, dma_q); 1381*0c0d06caSMauro Carvalho Chehab 1382*0c0d06caSMauro Carvalho Chehab kfree(buffer); 1383*0c0d06caSMauro Carvalho Chehab return 0; 1384*0c0d06caSMauro Carvalho Chehab } 1385*0c0d06caSMauro Carvalho Chehab 1386*0c0d06caSMauro Carvalho Chehab static int bb_buf_prepare(struct videobuf_queue *q, 1387*0c0d06caSMauro Carvalho Chehab struct videobuf_buffer *vb, enum v4l2_field field) 1388*0c0d06caSMauro Carvalho Chehab { 1389*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = q->priv_data; 1390*0c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf = 1391*0c0d06caSMauro Carvalho Chehab container_of(vb, struct cx231xx_buffer, vb); 1392*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1393*0c0d06caSMauro Carvalho Chehab int rc = 0, urb_init = 0; 1394*0c0d06caSMauro Carvalho Chehab int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; 1395*0c0d06caSMauro Carvalho Chehab 1396*0c0d06caSMauro Carvalho Chehab dma_qq = &dev->video_mode.vidq; 1397*0c0d06caSMauro Carvalho Chehab 1398*0c0d06caSMauro Carvalho Chehab if (0 != buf->vb.baddr && buf->vb.bsize < size) 1399*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1400*0c0d06caSMauro Carvalho Chehab buf->vb.width = fh->dev->ts1.ts_packet_size; 1401*0c0d06caSMauro Carvalho Chehab buf->vb.height = fh->dev->ts1.ts_packet_count; 1402*0c0d06caSMauro Carvalho Chehab buf->vb.size = size; 1403*0c0d06caSMauro Carvalho Chehab buf->vb.field = field; 1404*0c0d06caSMauro Carvalho Chehab 1405*0c0d06caSMauro Carvalho Chehab if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { 1406*0c0d06caSMauro Carvalho Chehab rc = videobuf_iolock(q, &buf->vb, NULL); 1407*0c0d06caSMauro Carvalho Chehab if (rc < 0) 1408*0c0d06caSMauro Carvalho Chehab goto fail; 1409*0c0d06caSMauro Carvalho Chehab } 1410*0c0d06caSMauro Carvalho Chehab 1411*0c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) { 1412*0c0d06caSMauro Carvalho Chehab if (!dev->video_mode.isoc_ctl.num_bufs) 1413*0c0d06caSMauro Carvalho Chehab urb_init = 1; 1414*0c0d06caSMauro Carvalho Chehab } else { 1415*0c0d06caSMauro Carvalho Chehab if (!dev->video_mode.bulk_ctl.num_bufs) 1416*0c0d06caSMauro Carvalho Chehab urb_init = 1; 1417*0c0d06caSMauro Carvalho Chehab } 1418*0c0d06caSMauro Carvalho Chehab /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n", 1419*0c0d06caSMauro Carvalho Chehab urb_init, dev->video_mode.max_pkt_size);*/ 1420*0c0d06caSMauro Carvalho Chehab dev->mode_tv = 1; 1421*0c0d06caSMauro Carvalho Chehab 1422*0c0d06caSMauro Carvalho Chehab if (urb_init) { 1423*0c0d06caSMauro Carvalho Chehab rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); 1424*0c0d06caSMauro Carvalho Chehab rc = cx231xx_unmute_audio(dev); 1425*0c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) { 1426*0c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_TS1, 4); 1427*0c0d06caSMauro Carvalho Chehab rc = cx231xx_init_isoc(dev, mpeglines, 1428*0c0d06caSMauro Carvalho Chehab mpegbufs, 1429*0c0d06caSMauro Carvalho Chehab dev->ts1_mode.max_pkt_size, 1430*0c0d06caSMauro Carvalho Chehab cx231xx_isoc_copy); 1431*0c0d06caSMauro Carvalho Chehab } else { 1432*0c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_TS1, 0); 1433*0c0d06caSMauro Carvalho Chehab rc = cx231xx_init_bulk(dev, mpeglines, 1434*0c0d06caSMauro Carvalho Chehab mpegbufs, 1435*0c0d06caSMauro Carvalho Chehab dev->ts1_mode.max_pkt_size, 1436*0c0d06caSMauro Carvalho Chehab cx231xx_bulk_copy); 1437*0c0d06caSMauro Carvalho Chehab } 1438*0c0d06caSMauro Carvalho Chehab if (rc < 0) 1439*0c0d06caSMauro Carvalho Chehab goto fail; 1440*0c0d06caSMauro Carvalho Chehab } 1441*0c0d06caSMauro Carvalho Chehab 1442*0c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_PREPARED; 1443*0c0d06caSMauro Carvalho Chehab return 0; 1444*0c0d06caSMauro Carvalho Chehab 1445*0c0d06caSMauro Carvalho Chehab fail: 1446*0c0d06caSMauro Carvalho Chehab free_buffer(q, buf); 1447*0c0d06caSMauro Carvalho Chehab return rc; 1448*0c0d06caSMauro Carvalho Chehab } 1449*0c0d06caSMauro Carvalho Chehab 1450*0c0d06caSMauro Carvalho Chehab static void bb_buf_queue(struct videobuf_queue *q, 1451*0c0d06caSMauro Carvalho Chehab struct videobuf_buffer *vb) 1452*0c0d06caSMauro Carvalho Chehab { 1453*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = q->priv_data; 1454*0c0d06caSMauro Carvalho Chehab 1455*0c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf = 1456*0c0d06caSMauro Carvalho Chehab container_of(vb, struct cx231xx_buffer, vb); 1457*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1458*0c0d06caSMauro Carvalho Chehab struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; 1459*0c0d06caSMauro Carvalho Chehab 1460*0c0d06caSMauro Carvalho Chehab buf->vb.state = VIDEOBUF_QUEUED; 1461*0c0d06caSMauro Carvalho Chehab list_add_tail(&buf->vb.queue, &vidq->active); 1462*0c0d06caSMauro Carvalho Chehab 1463*0c0d06caSMauro Carvalho Chehab } 1464*0c0d06caSMauro Carvalho Chehab 1465*0c0d06caSMauro Carvalho Chehab static void bb_buf_release(struct videobuf_queue *q, 1466*0c0d06caSMauro Carvalho Chehab struct videobuf_buffer *vb) 1467*0c0d06caSMauro Carvalho Chehab { 1468*0c0d06caSMauro Carvalho Chehab struct cx231xx_buffer *buf = 1469*0c0d06caSMauro Carvalho Chehab container_of(vb, struct cx231xx_buffer, vb); 1470*0c0d06caSMauro Carvalho Chehab /*struct cx231xx_fh *fh = q->priv_data;*/ 1471*0c0d06caSMauro Carvalho Chehab /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/ 1472*0c0d06caSMauro Carvalho Chehab 1473*0c0d06caSMauro Carvalho Chehab free_buffer(q, buf); 1474*0c0d06caSMauro Carvalho Chehab } 1475*0c0d06caSMauro Carvalho Chehab 1476*0c0d06caSMauro Carvalho Chehab static struct videobuf_queue_ops cx231xx_qops = { 1477*0c0d06caSMauro Carvalho Chehab .buf_setup = bb_buf_setup, 1478*0c0d06caSMauro Carvalho Chehab .buf_prepare = bb_buf_prepare, 1479*0c0d06caSMauro Carvalho Chehab .buf_queue = bb_buf_queue, 1480*0c0d06caSMauro Carvalho Chehab .buf_release = bb_buf_release, 1481*0c0d06caSMauro Carvalho Chehab }; 1482*0c0d06caSMauro Carvalho Chehab 1483*0c0d06caSMauro Carvalho Chehab /* ------------------------------------------------------------------ */ 1484*0c0d06caSMauro Carvalho Chehab 1485*0c0d06caSMauro Carvalho Chehab static const u32 *ctrl_classes[] = { 1486*0c0d06caSMauro Carvalho Chehab cx2341x_mpeg_ctrls, 1487*0c0d06caSMauro Carvalho Chehab NULL 1488*0c0d06caSMauro Carvalho Chehab }; 1489*0c0d06caSMauro Carvalho Chehab 1490*0c0d06caSMauro Carvalho Chehab static int cx231xx_queryctrl(struct cx231xx *dev, 1491*0c0d06caSMauro Carvalho Chehab struct v4l2_queryctrl *qctrl) 1492*0c0d06caSMauro Carvalho Chehab { 1493*0c0d06caSMauro Carvalho Chehab qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); 1494*0c0d06caSMauro Carvalho Chehab if (qctrl->id == 0) 1495*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1496*0c0d06caSMauro Carvalho Chehab 1497*0c0d06caSMauro Carvalho Chehab /* MPEG V4L2 controls */ 1498*0c0d06caSMauro Carvalho Chehab if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl)) 1499*0c0d06caSMauro Carvalho Chehab qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; 1500*0c0d06caSMauro Carvalho Chehab 1501*0c0d06caSMauro Carvalho Chehab return 0; 1502*0c0d06caSMauro Carvalho Chehab } 1503*0c0d06caSMauro Carvalho Chehab 1504*0c0d06caSMauro Carvalho Chehab static int cx231xx_querymenu(struct cx231xx *dev, 1505*0c0d06caSMauro Carvalho Chehab struct v4l2_querymenu *qmenu) 1506*0c0d06caSMauro Carvalho Chehab { 1507*0c0d06caSMauro Carvalho Chehab struct v4l2_queryctrl qctrl; 1508*0c0d06caSMauro Carvalho Chehab 1509*0c0d06caSMauro Carvalho Chehab qctrl.id = qmenu->id; 1510*0c0d06caSMauro Carvalho Chehab cx231xx_queryctrl(dev, &qctrl); 1511*0c0d06caSMauro Carvalho Chehab return v4l2_ctrl_query_menu(qmenu, &qctrl, 1512*0c0d06caSMauro Carvalho Chehab cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); 1513*0c0d06caSMauro Carvalho Chehab } 1514*0c0d06caSMauro Carvalho Chehab 1515*0c0d06caSMauro Carvalho Chehab static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) 1516*0c0d06caSMauro Carvalho Chehab { 1517*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1518*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1519*0c0d06caSMauro Carvalho Chehab 1520*0c0d06caSMauro Carvalho Chehab *norm = dev->encodernorm.id; 1521*0c0d06caSMauro Carvalho Chehab return 0; 1522*0c0d06caSMauro Carvalho Chehab } 1523*0c0d06caSMauro Carvalho Chehab static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) 1524*0c0d06caSMauro Carvalho Chehab { 1525*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1526*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1527*0c0d06caSMauro Carvalho Chehab unsigned int i; 1528*0c0d06caSMauro Carvalho Chehab 1529*0c0d06caSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++) 1530*0c0d06caSMauro Carvalho Chehab if (*id & cx231xx_tvnorms[i].id) 1531*0c0d06caSMauro Carvalho Chehab break; 1532*0c0d06caSMauro Carvalho Chehab if (i == ARRAY_SIZE(cx231xx_tvnorms)) 1533*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1534*0c0d06caSMauro Carvalho Chehab dev->encodernorm = cx231xx_tvnorms[i]; 1535*0c0d06caSMauro Carvalho Chehab 1536*0c0d06caSMauro Carvalho Chehab if (dev->encodernorm.id & 0xb000) { 1537*0c0d06caSMauro Carvalho Chehab dprintk(3, "encodernorm set to NTSC\n"); 1538*0c0d06caSMauro Carvalho Chehab dev->norm = V4L2_STD_NTSC; 1539*0c0d06caSMauro Carvalho Chehab dev->ts1.height = 480; 1540*0c0d06caSMauro Carvalho Chehab dev->mpeg_params.is_50hz = 0; 1541*0c0d06caSMauro Carvalho Chehab } else { 1542*0c0d06caSMauro Carvalho Chehab dprintk(3, "encodernorm set to PAL\n"); 1543*0c0d06caSMauro Carvalho Chehab dev->norm = V4L2_STD_PAL_B; 1544*0c0d06caSMauro Carvalho Chehab dev->ts1.height = 576; 1545*0c0d06caSMauro Carvalho Chehab dev->mpeg_params.is_50hz = 1; 1546*0c0d06caSMauro Carvalho Chehab } 1547*0c0d06caSMauro Carvalho Chehab call_all(dev, core, s_std, dev->norm); 1548*0c0d06caSMauro Carvalho Chehab /* do mode control overrides */ 1549*0c0d06caSMauro Carvalho Chehab cx231xx_do_mode_ctrl_overrides(dev); 1550*0c0d06caSMauro Carvalho Chehab 1551*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_s_std() i=0x%x\n", i); 1552*0c0d06caSMauro Carvalho Chehab return 0; 1553*0c0d06caSMauro Carvalho Chehab } 1554*0c0d06caSMauro Carvalho Chehab static int vidioc_g_audio(struct file *file, void *fh, 1555*0c0d06caSMauro Carvalho Chehab struct v4l2_audio *a) 1556*0c0d06caSMauro Carvalho Chehab { 1557*0c0d06caSMauro Carvalho Chehab struct v4l2_audio *vin = a; 1558*0c0d06caSMauro Carvalho Chehab 1559*0c0d06caSMauro Carvalho Chehab int ret = -EINVAL; 1560*0c0d06caSMauro Carvalho Chehab if (vin->index > 0) 1561*0c0d06caSMauro Carvalho Chehab return ret; 1562*0c0d06caSMauro Carvalho Chehab strncpy(vin->name, "VideoGrabber Audio", 14); 1563*0c0d06caSMauro Carvalho Chehab vin->capability = V4L2_AUDCAP_STEREO; 1564*0c0d06caSMauro Carvalho Chehab return 0; 1565*0c0d06caSMauro Carvalho Chehab } 1566*0c0d06caSMauro Carvalho Chehab static int vidioc_enumaudio(struct file *file, void *fh, 1567*0c0d06caSMauro Carvalho Chehab struct v4l2_audio *a) 1568*0c0d06caSMauro Carvalho Chehab { 1569*0c0d06caSMauro Carvalho Chehab struct v4l2_audio *vin = a; 1570*0c0d06caSMauro Carvalho Chehab 1571*0c0d06caSMauro Carvalho Chehab int ret = -EINVAL; 1572*0c0d06caSMauro Carvalho Chehab 1573*0c0d06caSMauro Carvalho Chehab if (vin->index > 0) 1574*0c0d06caSMauro Carvalho Chehab return ret; 1575*0c0d06caSMauro Carvalho Chehab strncpy(vin->name, "VideoGrabber Audio", 14); 1576*0c0d06caSMauro Carvalho Chehab vin->capability = V4L2_AUDCAP_STEREO; 1577*0c0d06caSMauro Carvalho Chehab 1578*0c0d06caSMauro Carvalho Chehab 1579*0c0d06caSMauro Carvalho Chehab return 0; 1580*0c0d06caSMauro Carvalho Chehab } 1581*0c0d06caSMauro Carvalho Chehab static const char *iname[] = { 1582*0c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_COMPOSITE1] = "Composite1", 1583*0c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_SVIDEO] = "S-Video", 1584*0c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_TELEVISION] = "Television", 1585*0c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_CABLE] = "Cable TV", 1586*0c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_DVB] = "DVB", 1587*0c0d06caSMauro Carvalho Chehab [CX231XX_VMUX_DEBUG] = "for debug only", 1588*0c0d06caSMauro Carvalho Chehab }; 1589*0c0d06caSMauro Carvalho Chehab static int vidioc_enum_input(struct file *file, void *priv, 1590*0c0d06caSMauro Carvalho Chehab struct v4l2_input *i) 1591*0c0d06caSMauro Carvalho Chehab { 1592*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1593*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1594*0c0d06caSMauro Carvalho Chehab struct cx231xx_input *input; 1595*0c0d06caSMauro Carvalho Chehab int n; 1596*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index); 1597*0c0d06caSMauro Carvalho Chehab 1598*0c0d06caSMauro Carvalho Chehab if (i->index >= 4) 1599*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1600*0c0d06caSMauro Carvalho Chehab 1601*0c0d06caSMauro Carvalho Chehab 1602*0c0d06caSMauro Carvalho Chehab input = &cx231xx_boards[dev->model].input[i->index]; 1603*0c0d06caSMauro Carvalho Chehab 1604*0c0d06caSMauro Carvalho Chehab if (input->type == 0) 1605*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1606*0c0d06caSMauro Carvalho Chehab 1607*0c0d06caSMauro Carvalho Chehab /* FIXME 1608*0c0d06caSMauro Carvalho Chehab * strcpy(i->name, input->name); */ 1609*0c0d06caSMauro Carvalho Chehab 1610*0c0d06caSMauro Carvalho Chehab n = i->index; 1611*0c0d06caSMauro Carvalho Chehab strcpy(i->name, iname[INPUT(n)->type]); 1612*0c0d06caSMauro Carvalho Chehab 1613*0c0d06caSMauro Carvalho Chehab if (input->type == CX231XX_VMUX_TELEVISION || 1614*0c0d06caSMauro Carvalho Chehab input->type == CX231XX_VMUX_CABLE) 1615*0c0d06caSMauro Carvalho Chehab i->type = V4L2_INPUT_TYPE_TUNER; 1616*0c0d06caSMauro Carvalho Chehab else 1617*0c0d06caSMauro Carvalho Chehab i->type = V4L2_INPUT_TYPE_CAMERA; 1618*0c0d06caSMauro Carvalho Chehab 1619*0c0d06caSMauro Carvalho Chehab 1620*0c0d06caSMauro Carvalho Chehab return 0; 1621*0c0d06caSMauro Carvalho Chehab } 1622*0c0d06caSMauro Carvalho Chehab 1623*0c0d06caSMauro Carvalho Chehab static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) 1624*0c0d06caSMauro Carvalho Chehab { 1625*0c0d06caSMauro Carvalho Chehab *i = 0; 1626*0c0d06caSMauro Carvalho Chehab return 0; 1627*0c0d06caSMauro Carvalho Chehab } 1628*0c0d06caSMauro Carvalho Chehab 1629*0c0d06caSMauro Carvalho Chehab static int vidioc_s_input(struct file *file, void *priv, unsigned int i) 1630*0c0d06caSMauro Carvalho Chehab { 1631*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1632*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1633*0c0d06caSMauro Carvalho Chehab 1634*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_s_input() i=%d\n", i); 1635*0c0d06caSMauro Carvalho Chehab 1636*0c0d06caSMauro Carvalho Chehab mutex_lock(&dev->lock); 1637*0c0d06caSMauro Carvalho Chehab 1638*0c0d06caSMauro Carvalho Chehab video_mux(dev, i); 1639*0c0d06caSMauro Carvalho Chehab 1640*0c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 1641*0c0d06caSMauro Carvalho Chehab 1642*0c0d06caSMauro Carvalho Chehab if (i >= 4) 1643*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1644*0c0d06caSMauro Carvalho Chehab dev->input = i; 1645*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_s_input()\n"); 1646*0c0d06caSMauro Carvalho Chehab return 0; 1647*0c0d06caSMauro Carvalho Chehab } 1648*0c0d06caSMauro Carvalho Chehab 1649*0c0d06caSMauro Carvalho Chehab static int vidioc_g_tuner(struct file *file, void *priv, 1650*0c0d06caSMauro Carvalho Chehab struct v4l2_tuner *t) 1651*0c0d06caSMauro Carvalho Chehab { 1652*0c0d06caSMauro Carvalho Chehab return 0; 1653*0c0d06caSMauro Carvalho Chehab } 1654*0c0d06caSMauro Carvalho Chehab 1655*0c0d06caSMauro Carvalho Chehab static int vidioc_s_tuner(struct file *file, void *priv, 1656*0c0d06caSMauro Carvalho Chehab struct v4l2_tuner *t) 1657*0c0d06caSMauro Carvalho Chehab { 1658*0c0d06caSMauro Carvalho Chehab return 0; 1659*0c0d06caSMauro Carvalho Chehab } 1660*0c0d06caSMauro Carvalho Chehab 1661*0c0d06caSMauro Carvalho Chehab static int vidioc_g_frequency(struct file *file, void *priv, 1662*0c0d06caSMauro Carvalho Chehab struct v4l2_frequency *f) 1663*0c0d06caSMauro Carvalho Chehab { 1664*0c0d06caSMauro Carvalho Chehab return 0; 1665*0c0d06caSMauro Carvalho Chehab } 1666*0c0d06caSMauro Carvalho Chehab 1667*0c0d06caSMauro Carvalho Chehab static int vidioc_s_frequency(struct file *file, void *priv, 1668*0c0d06caSMauro Carvalho Chehab struct v4l2_frequency *f) 1669*0c0d06caSMauro Carvalho Chehab { 1670*0c0d06caSMauro Carvalho Chehab 1671*0c0d06caSMauro Carvalho Chehab 1672*0c0d06caSMauro Carvalho Chehab return 0; 1673*0c0d06caSMauro Carvalho Chehab } 1674*0c0d06caSMauro Carvalho Chehab 1675*0c0d06caSMauro Carvalho Chehab static int vidioc_s_ctrl(struct file *file, void *priv, 1676*0c0d06caSMauro Carvalho Chehab struct v4l2_control *ctl) 1677*0c0d06caSMauro Carvalho Chehab { 1678*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1679*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1680*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_s_ctrl()\n"); 1681*0c0d06caSMauro Carvalho Chehab /* Update the A/V core */ 1682*0c0d06caSMauro Carvalho Chehab call_all(dev, core, s_ctrl, ctl); 1683*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_s_ctrl()\n"); 1684*0c0d06caSMauro Carvalho Chehab return 0; 1685*0c0d06caSMauro Carvalho Chehab } 1686*0c0d06caSMauro Carvalho Chehab static struct v4l2_capability pvr_capability = { 1687*0c0d06caSMauro Carvalho Chehab .driver = "cx231xx", 1688*0c0d06caSMauro Carvalho Chehab .card = "VideoGrabber", 1689*0c0d06caSMauro Carvalho Chehab .bus_info = "usb", 1690*0c0d06caSMauro Carvalho Chehab .version = 1, 1691*0c0d06caSMauro Carvalho Chehab .capabilities = (V4L2_CAP_VIDEO_CAPTURE | 1692*0c0d06caSMauro Carvalho Chehab V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | 1693*0c0d06caSMauro Carvalho Chehab V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), 1694*0c0d06caSMauro Carvalho Chehab }; 1695*0c0d06caSMauro Carvalho Chehab static int vidioc_querycap(struct file *file, void *priv, 1696*0c0d06caSMauro Carvalho Chehab struct v4l2_capability *cap) 1697*0c0d06caSMauro Carvalho Chehab { 1698*0c0d06caSMauro Carvalho Chehab 1699*0c0d06caSMauro Carvalho Chehab 1700*0c0d06caSMauro Carvalho Chehab 1701*0c0d06caSMauro Carvalho Chehab memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); 1702*0c0d06caSMauro Carvalho Chehab return 0; 1703*0c0d06caSMauro Carvalho Chehab } 1704*0c0d06caSMauro Carvalho Chehab 1705*0c0d06caSMauro Carvalho Chehab static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 1706*0c0d06caSMauro Carvalho Chehab struct v4l2_fmtdesc *f) 1707*0c0d06caSMauro Carvalho Chehab { 1708*0c0d06caSMauro Carvalho Chehab 1709*0c0d06caSMauro Carvalho Chehab if (f->index != 0) 1710*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1711*0c0d06caSMauro Carvalho Chehab 1712*0c0d06caSMauro Carvalho Chehab strlcpy(f->description, "MPEG", sizeof(f->description)); 1713*0c0d06caSMauro Carvalho Chehab f->pixelformat = V4L2_PIX_FMT_MPEG; 1714*0c0d06caSMauro Carvalho Chehab 1715*0c0d06caSMauro Carvalho Chehab return 0; 1716*0c0d06caSMauro Carvalho Chehab } 1717*0c0d06caSMauro Carvalho Chehab 1718*0c0d06caSMauro Carvalho Chehab static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, 1719*0c0d06caSMauro Carvalho Chehab struct v4l2_format *f) 1720*0c0d06caSMauro Carvalho Chehab { 1721*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1722*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1723*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_g_fmt_vid_cap()\n"); 1724*0c0d06caSMauro Carvalho Chehab f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 1725*0c0d06caSMauro Carvalho Chehab f->fmt.pix.bytesperline = 0; 1726*0c0d06caSMauro Carvalho Chehab f->fmt.pix.sizeimage = 1727*0c0d06caSMauro Carvalho Chehab dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; 1728*0c0d06caSMauro Carvalho Chehab f->fmt.pix.colorspace = 0; 1729*0c0d06caSMauro Carvalho Chehab f->fmt.pix.width = dev->ts1.width; 1730*0c0d06caSMauro Carvalho Chehab f->fmt.pix.height = dev->ts1.height; 1731*0c0d06caSMauro Carvalho Chehab f->fmt.pix.field = fh->vidq.field; 1732*0c0d06caSMauro Carvalho Chehab dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", 1733*0c0d06caSMauro Carvalho Chehab dev->ts1.width, dev->ts1.height, fh->vidq.field); 1734*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_g_fmt_vid_cap()\n"); 1735*0c0d06caSMauro Carvalho Chehab return 0; 1736*0c0d06caSMauro Carvalho Chehab } 1737*0c0d06caSMauro Carvalho Chehab 1738*0c0d06caSMauro Carvalho Chehab static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, 1739*0c0d06caSMauro Carvalho Chehab struct v4l2_format *f) 1740*0c0d06caSMauro Carvalho Chehab { 1741*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1742*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1743*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_try_fmt_vid_cap()\n"); 1744*0c0d06caSMauro Carvalho Chehab f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 1745*0c0d06caSMauro Carvalho Chehab f->fmt.pix.bytesperline = 0; 1746*0c0d06caSMauro Carvalho Chehab f->fmt.pix.sizeimage = 1747*0c0d06caSMauro Carvalho Chehab dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; 1748*0c0d06caSMauro Carvalho Chehab f->fmt.pix.colorspace = 0; 1749*0c0d06caSMauro Carvalho Chehab dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", 1750*0c0d06caSMauro Carvalho Chehab dev->ts1.width, dev->ts1.height, fh->vidq.field); 1751*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_try_fmt_vid_cap()\n"); 1752*0c0d06caSMauro Carvalho Chehab return 0; 1753*0c0d06caSMauro Carvalho Chehab } 1754*0c0d06caSMauro Carvalho Chehab 1755*0c0d06caSMauro Carvalho Chehab static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, 1756*0c0d06caSMauro Carvalho Chehab struct v4l2_format *f) 1757*0c0d06caSMauro Carvalho Chehab { 1758*0c0d06caSMauro Carvalho Chehab 1759*0c0d06caSMauro Carvalho Chehab return 0; 1760*0c0d06caSMauro Carvalho Chehab } 1761*0c0d06caSMauro Carvalho Chehab 1762*0c0d06caSMauro Carvalho Chehab static int vidioc_reqbufs(struct file *file, void *priv, 1763*0c0d06caSMauro Carvalho Chehab struct v4l2_requestbuffers *p) 1764*0c0d06caSMauro Carvalho Chehab { 1765*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1766*0c0d06caSMauro Carvalho Chehab 1767*0c0d06caSMauro Carvalho Chehab return videobuf_reqbufs(&fh->vidq, p); 1768*0c0d06caSMauro Carvalho Chehab } 1769*0c0d06caSMauro Carvalho Chehab 1770*0c0d06caSMauro Carvalho Chehab static int vidioc_querybuf(struct file *file, void *priv, 1771*0c0d06caSMauro Carvalho Chehab struct v4l2_buffer *p) 1772*0c0d06caSMauro Carvalho Chehab { 1773*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1774*0c0d06caSMauro Carvalho Chehab 1775*0c0d06caSMauro Carvalho Chehab return videobuf_querybuf(&fh->vidq, p); 1776*0c0d06caSMauro Carvalho Chehab } 1777*0c0d06caSMauro Carvalho Chehab 1778*0c0d06caSMauro Carvalho Chehab static int vidioc_qbuf(struct file *file, void *priv, 1779*0c0d06caSMauro Carvalho Chehab struct v4l2_buffer *p) 1780*0c0d06caSMauro Carvalho Chehab { 1781*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1782*0c0d06caSMauro Carvalho Chehab 1783*0c0d06caSMauro Carvalho Chehab return videobuf_qbuf(&fh->vidq, p); 1784*0c0d06caSMauro Carvalho Chehab } 1785*0c0d06caSMauro Carvalho Chehab 1786*0c0d06caSMauro Carvalho Chehab static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) 1787*0c0d06caSMauro Carvalho Chehab { 1788*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 1789*0c0d06caSMauro Carvalho Chehab 1790*0c0d06caSMauro Carvalho Chehab return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK); 1791*0c0d06caSMauro Carvalho Chehab } 1792*0c0d06caSMauro Carvalho Chehab 1793*0c0d06caSMauro Carvalho Chehab 1794*0c0d06caSMauro Carvalho Chehab static int vidioc_streamon(struct file *file, void *priv, 1795*0c0d06caSMauro Carvalho Chehab enum v4l2_buf_type i) 1796*0c0d06caSMauro Carvalho Chehab { 1797*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1798*0c0d06caSMauro Carvalho Chehab 1799*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1800*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_streamon()\n"); 1801*0c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_TS1, 0); 1802*0c0d06caSMauro Carvalho Chehab cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); 1803*0c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) 1804*0c0d06caSMauro Carvalho Chehab cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, 1805*0c0d06caSMauro Carvalho Chehab CX231XX_NUM_BUFS, 1806*0c0d06caSMauro Carvalho Chehab dev->video_mode.max_pkt_size, 1807*0c0d06caSMauro Carvalho Chehab cx231xx_isoc_copy); 1808*0c0d06caSMauro Carvalho Chehab else { 1809*0c0d06caSMauro Carvalho Chehab cx231xx_init_bulk(dev, 320, 1810*0c0d06caSMauro Carvalho Chehab 5, 1811*0c0d06caSMauro Carvalho Chehab dev->ts1_mode.max_pkt_size, 1812*0c0d06caSMauro Carvalho Chehab cx231xx_bulk_copy); 1813*0c0d06caSMauro Carvalho Chehab } 1814*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_streamon()\n"); 1815*0c0d06caSMauro Carvalho Chehab return videobuf_streamon(&fh->vidq); 1816*0c0d06caSMauro Carvalho Chehab } 1817*0c0d06caSMauro Carvalho Chehab 1818*0c0d06caSMauro Carvalho Chehab static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) 1819*0c0d06caSMauro Carvalho Chehab { 1820*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1821*0c0d06caSMauro Carvalho Chehab 1822*0c0d06caSMauro Carvalho Chehab return videobuf_streamoff(&fh->vidq); 1823*0c0d06caSMauro Carvalho Chehab } 1824*0c0d06caSMauro Carvalho Chehab 1825*0c0d06caSMauro Carvalho Chehab static int vidioc_g_ext_ctrls(struct file *file, void *priv, 1826*0c0d06caSMauro Carvalho Chehab struct v4l2_ext_controls *f) 1827*0c0d06caSMauro Carvalho Chehab { 1828*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 1829*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1830*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_g_ext_ctrls()\n"); 1831*0c0d06caSMauro Carvalho Chehab if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 1832*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1833*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_g_ext_ctrls()\n"); 1834*0c0d06caSMauro Carvalho Chehab return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS); 1835*0c0d06caSMauro Carvalho Chehab } 1836*0c0d06caSMauro Carvalho Chehab 1837*0c0d06caSMauro Carvalho Chehab static int vidioc_s_ext_ctrls(struct file *file, void *priv, 1838*0c0d06caSMauro Carvalho Chehab struct v4l2_ext_controls *f) 1839*0c0d06caSMauro Carvalho Chehab { 1840*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 1841*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1842*0c0d06caSMauro Carvalho Chehab struct cx2341x_mpeg_params p; 1843*0c0d06caSMauro Carvalho Chehab int err; 1844*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_s_ext_ctrls()\n"); 1845*0c0d06caSMauro Carvalho Chehab if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 1846*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1847*0c0d06caSMauro Carvalho Chehab 1848*0c0d06caSMauro Carvalho Chehab p = dev->mpeg_params; 1849*0c0d06caSMauro Carvalho Chehab err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); 1850*0c0d06caSMauro Carvalho Chehab if (err == 0) { 1851*0c0d06caSMauro Carvalho Chehab err = cx2341x_update(dev, cx231xx_mbox_func, 1852*0c0d06caSMauro Carvalho Chehab &dev->mpeg_params, &p); 1853*0c0d06caSMauro Carvalho Chehab dev->mpeg_params = p; 1854*0c0d06caSMauro Carvalho Chehab } 1855*0c0d06caSMauro Carvalho Chehab 1856*0c0d06caSMauro Carvalho Chehab return err; 1857*0c0d06caSMauro Carvalho Chehab 1858*0c0d06caSMauro Carvalho Chehab 1859*0c0d06caSMauro Carvalho Chehab return 0; 1860*0c0d06caSMauro Carvalho Chehab } 1861*0c0d06caSMauro Carvalho Chehab 1862*0c0d06caSMauro Carvalho Chehab static int vidioc_try_ext_ctrls(struct file *file, void *priv, 1863*0c0d06caSMauro Carvalho Chehab struct v4l2_ext_controls *f) 1864*0c0d06caSMauro Carvalho Chehab { 1865*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 1866*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1867*0c0d06caSMauro Carvalho Chehab struct cx2341x_mpeg_params p; 1868*0c0d06caSMauro Carvalho Chehab int err; 1869*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_try_ext_ctrls()\n"); 1870*0c0d06caSMauro Carvalho Chehab if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 1871*0c0d06caSMauro Carvalho Chehab return -EINVAL; 1872*0c0d06caSMauro Carvalho Chehab 1873*0c0d06caSMauro Carvalho Chehab p = dev->mpeg_params; 1874*0c0d06caSMauro Carvalho Chehab err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); 1875*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err); 1876*0c0d06caSMauro Carvalho Chehab return err; 1877*0c0d06caSMauro Carvalho Chehab } 1878*0c0d06caSMauro Carvalho Chehab 1879*0c0d06caSMauro Carvalho Chehab static int vidioc_log_status(struct file *file, void *priv) 1880*0c0d06caSMauro Carvalho Chehab { 1881*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 1882*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1883*0c0d06caSMauro Carvalho Chehab char name[32 + 2]; 1884*0c0d06caSMauro Carvalho Chehab 1885*0c0d06caSMauro Carvalho Chehab snprintf(name, sizeof(name), "%s/2", dev->name); 1886*0c0d06caSMauro Carvalho Chehab dprintk(3, 1887*0c0d06caSMauro Carvalho Chehab "%s/2: ============ START LOG STATUS ============\n", 1888*0c0d06caSMauro Carvalho Chehab dev->name); 1889*0c0d06caSMauro Carvalho Chehab call_all(dev, core, log_status); 1890*0c0d06caSMauro Carvalho Chehab cx2341x_log_status(&dev->mpeg_params, name); 1891*0c0d06caSMauro Carvalho Chehab dprintk(3, 1892*0c0d06caSMauro Carvalho Chehab "%s/2: ============= END LOG STATUS =============\n", 1893*0c0d06caSMauro Carvalho Chehab dev->name); 1894*0c0d06caSMauro Carvalho Chehab return 0; 1895*0c0d06caSMauro Carvalho Chehab } 1896*0c0d06caSMauro Carvalho Chehab 1897*0c0d06caSMauro Carvalho Chehab static int vidioc_querymenu(struct file *file, void *priv, 1898*0c0d06caSMauro Carvalho Chehab struct v4l2_querymenu *a) 1899*0c0d06caSMauro Carvalho Chehab { 1900*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 1901*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1902*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_querymenu()\n"); 1903*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_querymenu()\n"); 1904*0c0d06caSMauro Carvalho Chehab return cx231xx_querymenu(dev, a); 1905*0c0d06caSMauro Carvalho Chehab } 1906*0c0d06caSMauro Carvalho Chehab 1907*0c0d06caSMauro Carvalho Chehab static int vidioc_queryctrl(struct file *file, void *priv, 1908*0c0d06caSMauro Carvalho Chehab struct v4l2_queryctrl *c) 1909*0c0d06caSMauro Carvalho Chehab { 1910*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = priv; 1911*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1912*0c0d06caSMauro Carvalho Chehab dprintk(3, "enter vidioc_queryctrl()\n"); 1913*0c0d06caSMauro Carvalho Chehab dprintk(3, "exit vidioc_queryctrl()\n"); 1914*0c0d06caSMauro Carvalho Chehab return cx231xx_queryctrl(dev, c); 1915*0c0d06caSMauro Carvalho Chehab } 1916*0c0d06caSMauro Carvalho Chehab 1917*0c0d06caSMauro Carvalho Chehab static int mpeg_open(struct file *file) 1918*0c0d06caSMauro Carvalho Chehab { 1919*0c0d06caSMauro Carvalho Chehab int minor = video_devdata(file)->minor; 1920*0c0d06caSMauro Carvalho Chehab struct cx231xx *h, *dev = NULL; 1921*0c0d06caSMauro Carvalho Chehab /*struct list_head *list;*/ 1922*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh; 1923*0c0d06caSMauro Carvalho Chehab /*u32 value = 0;*/ 1924*0c0d06caSMauro Carvalho Chehab 1925*0c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 1926*0c0d06caSMauro Carvalho Chehab 1927*0c0d06caSMauro Carvalho Chehab list_for_each_entry(h, &cx231xx_devlist, devlist) { 1928*0c0d06caSMauro Carvalho Chehab if (h->v4l_device->minor == minor) 1929*0c0d06caSMauro Carvalho Chehab dev = h; 1930*0c0d06caSMauro Carvalho Chehab } 1931*0c0d06caSMauro Carvalho Chehab 1932*0c0d06caSMauro Carvalho Chehab if (dev == NULL) 1933*0c0d06caSMauro Carvalho Chehab return -ENODEV; 1934*0c0d06caSMauro Carvalho Chehab 1935*0c0d06caSMauro Carvalho Chehab mutex_lock(&dev->lock); 1936*0c0d06caSMauro Carvalho Chehab 1937*0c0d06caSMauro Carvalho Chehab /* allocate + initialize per filehandle data */ 1938*0c0d06caSMauro Carvalho Chehab fh = kzalloc(sizeof(*fh), GFP_KERNEL); 1939*0c0d06caSMauro Carvalho Chehab if (NULL == fh) { 1940*0c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 1941*0c0d06caSMauro Carvalho Chehab return -ENOMEM; 1942*0c0d06caSMauro Carvalho Chehab } 1943*0c0d06caSMauro Carvalho Chehab 1944*0c0d06caSMauro Carvalho Chehab file->private_data = fh; 1945*0c0d06caSMauro Carvalho Chehab fh->dev = dev; 1946*0c0d06caSMauro Carvalho Chehab 1947*0c0d06caSMauro Carvalho Chehab 1948*0c0d06caSMauro Carvalho Chehab videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops, 1949*0c0d06caSMauro Carvalho Chehab NULL, &dev->video_mode.slock, 1950*0c0d06caSMauro Carvalho Chehab V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, 1951*0c0d06caSMauro Carvalho Chehab sizeof(struct cx231xx_buffer), fh, NULL); 1952*0c0d06caSMauro Carvalho Chehab /* 1953*0c0d06caSMauro Carvalho Chehab videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops, 1954*0c0d06caSMauro Carvalho Chehab &dev->udev->dev, &dev->ts1.slock, 1955*0c0d06caSMauro Carvalho Chehab V4L2_BUF_TYPE_VIDEO_CAPTURE, 1956*0c0d06caSMauro Carvalho Chehab V4L2_FIELD_INTERLACED, 1957*0c0d06caSMauro Carvalho Chehab sizeof(struct cx231xx_buffer), 1958*0c0d06caSMauro Carvalho Chehab fh, NULL); 1959*0c0d06caSMauro Carvalho Chehab */ 1960*0c0d06caSMauro Carvalho Chehab 1961*0c0d06caSMauro Carvalho Chehab 1962*0c0d06caSMauro Carvalho Chehab cx231xx_set_alt_setting(dev, INDEX_VANC, 1); 1963*0c0d06caSMauro Carvalho Chehab cx231xx_set_gpio_value(dev, 2, 0); 1964*0c0d06caSMauro Carvalho Chehab 1965*0c0d06caSMauro Carvalho Chehab cx231xx_initialize_codec(dev); 1966*0c0d06caSMauro Carvalho Chehab 1967*0c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 1968*0c0d06caSMauro Carvalho Chehab cx231xx_start_TS1(dev); 1969*0c0d06caSMauro Carvalho Chehab 1970*0c0d06caSMauro Carvalho Chehab return 0; 1971*0c0d06caSMauro Carvalho Chehab } 1972*0c0d06caSMauro Carvalho Chehab 1973*0c0d06caSMauro Carvalho Chehab static int mpeg_release(struct file *file) 1974*0c0d06caSMauro Carvalho Chehab { 1975*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 1976*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 1977*0c0d06caSMauro Carvalho Chehab 1978*0c0d06caSMauro Carvalho Chehab dprintk(3, "mpeg_release()! dev=0x%p\n", dev); 1979*0c0d06caSMauro Carvalho Chehab 1980*0c0d06caSMauro Carvalho Chehab if (!dev) { 1981*0c0d06caSMauro Carvalho Chehab dprintk(3, "abort!!!\n"); 1982*0c0d06caSMauro Carvalho Chehab return 0; 1983*0c0d06caSMauro Carvalho Chehab } 1984*0c0d06caSMauro Carvalho Chehab 1985*0c0d06caSMauro Carvalho Chehab mutex_lock(&dev->lock); 1986*0c0d06caSMauro Carvalho Chehab 1987*0c0d06caSMauro Carvalho Chehab cx231xx_stop_TS1(dev); 1988*0c0d06caSMauro Carvalho Chehab 1989*0c0d06caSMauro Carvalho Chehab /* do this before setting alternate! */ 1990*0c0d06caSMauro Carvalho Chehab if (dev->USE_ISO) 1991*0c0d06caSMauro Carvalho Chehab cx231xx_uninit_isoc(dev); 1992*0c0d06caSMauro Carvalho Chehab else 1993*0c0d06caSMauro Carvalho Chehab cx231xx_uninit_bulk(dev); 1994*0c0d06caSMauro Carvalho Chehab cx231xx_set_mode(dev, CX231XX_SUSPEND); 1995*0c0d06caSMauro Carvalho Chehab 1996*0c0d06caSMauro Carvalho Chehab cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, 1997*0c0d06caSMauro Carvalho Chehab CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, 1998*0c0d06caSMauro Carvalho Chehab CX231xx_RAW_BITS_NONE); 1999*0c0d06caSMauro Carvalho Chehab 2000*0c0d06caSMauro Carvalho Chehab /* FIXME: Review this crap */ 2001*0c0d06caSMauro Carvalho Chehab /* Shut device down on last close */ 2002*0c0d06caSMauro Carvalho Chehab if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { 2003*0c0d06caSMauro Carvalho Chehab if (atomic_dec_return(&dev->v4l_reader_count) == 0) { 2004*0c0d06caSMauro Carvalho Chehab /* stop mpeg capture */ 2005*0c0d06caSMauro Carvalho Chehab 2006*0c0d06caSMauro Carvalho Chehab msleep(500); 2007*0c0d06caSMauro Carvalho Chehab cx231xx_417_check_encoder(dev); 2008*0c0d06caSMauro Carvalho Chehab 2009*0c0d06caSMauro Carvalho Chehab } 2010*0c0d06caSMauro Carvalho Chehab } 2011*0c0d06caSMauro Carvalho Chehab 2012*0c0d06caSMauro Carvalho Chehab if (fh->vidq.streaming) 2013*0c0d06caSMauro Carvalho Chehab videobuf_streamoff(&fh->vidq); 2014*0c0d06caSMauro Carvalho Chehab if (fh->vidq.reading) 2015*0c0d06caSMauro Carvalho Chehab videobuf_read_stop(&fh->vidq); 2016*0c0d06caSMauro Carvalho Chehab 2017*0c0d06caSMauro Carvalho Chehab videobuf_mmap_free(&fh->vidq); 2018*0c0d06caSMauro Carvalho Chehab file->private_data = NULL; 2019*0c0d06caSMauro Carvalho Chehab kfree(fh); 2020*0c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 2021*0c0d06caSMauro Carvalho Chehab return 0; 2022*0c0d06caSMauro Carvalho Chehab } 2023*0c0d06caSMauro Carvalho Chehab 2024*0c0d06caSMauro Carvalho Chehab static ssize_t mpeg_read(struct file *file, char __user *data, 2025*0c0d06caSMauro Carvalho Chehab size_t count, loff_t *ppos) 2026*0c0d06caSMauro Carvalho Chehab { 2027*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 2028*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 2029*0c0d06caSMauro Carvalho Chehab 2030*0c0d06caSMauro Carvalho Chehab 2031*0c0d06caSMauro Carvalho Chehab /* Deal w/ A/V decoder * and mpeg encoder sync issues. */ 2032*0c0d06caSMauro Carvalho Chehab /* Start mpeg encoder on first read. */ 2033*0c0d06caSMauro Carvalho Chehab if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { 2034*0c0d06caSMauro Carvalho Chehab if (atomic_inc_return(&dev->v4l_reader_count) == 1) { 2035*0c0d06caSMauro Carvalho Chehab if (cx231xx_initialize_codec(dev) < 0) 2036*0c0d06caSMauro Carvalho Chehab return -EINVAL; 2037*0c0d06caSMauro Carvalho Chehab } 2038*0c0d06caSMauro Carvalho Chehab } 2039*0c0d06caSMauro Carvalho Chehab 2040*0c0d06caSMauro Carvalho Chehab return videobuf_read_stream(&fh->vidq, data, count, ppos, 0, 2041*0c0d06caSMauro Carvalho Chehab file->f_flags & O_NONBLOCK); 2042*0c0d06caSMauro Carvalho Chehab } 2043*0c0d06caSMauro Carvalho Chehab 2044*0c0d06caSMauro Carvalho Chehab static unsigned int mpeg_poll(struct file *file, 2045*0c0d06caSMauro Carvalho Chehab struct poll_table_struct *wait) 2046*0c0d06caSMauro Carvalho Chehab { 2047*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 2048*0c0d06caSMauro Carvalho Chehab /*struct cx231xx *dev = fh->dev;*/ 2049*0c0d06caSMauro Carvalho Chehab 2050*0c0d06caSMauro Carvalho Chehab /*dprintk(2, "%s\n", __func__);*/ 2051*0c0d06caSMauro Carvalho Chehab 2052*0c0d06caSMauro Carvalho Chehab return videobuf_poll_stream(file, &fh->vidq, wait); 2053*0c0d06caSMauro Carvalho Chehab } 2054*0c0d06caSMauro Carvalho Chehab 2055*0c0d06caSMauro Carvalho Chehab static int mpeg_mmap(struct file *file, struct vm_area_struct *vma) 2056*0c0d06caSMauro Carvalho Chehab { 2057*0c0d06caSMauro Carvalho Chehab struct cx231xx_fh *fh = file->private_data; 2058*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev = fh->dev; 2059*0c0d06caSMauro Carvalho Chehab 2060*0c0d06caSMauro Carvalho Chehab dprintk(2, "%s()\n", __func__); 2061*0c0d06caSMauro Carvalho Chehab 2062*0c0d06caSMauro Carvalho Chehab return videobuf_mmap_mapper(&fh->vidq, vma); 2063*0c0d06caSMauro Carvalho Chehab } 2064*0c0d06caSMauro Carvalho Chehab 2065*0c0d06caSMauro Carvalho Chehab static struct v4l2_file_operations mpeg_fops = { 2066*0c0d06caSMauro Carvalho Chehab .owner = THIS_MODULE, 2067*0c0d06caSMauro Carvalho Chehab .open = mpeg_open, 2068*0c0d06caSMauro Carvalho Chehab .release = mpeg_release, 2069*0c0d06caSMauro Carvalho Chehab .read = mpeg_read, 2070*0c0d06caSMauro Carvalho Chehab .poll = mpeg_poll, 2071*0c0d06caSMauro Carvalho Chehab .mmap = mpeg_mmap, 2072*0c0d06caSMauro Carvalho Chehab .ioctl = video_ioctl2, 2073*0c0d06caSMauro Carvalho Chehab }; 2074*0c0d06caSMauro Carvalho Chehab 2075*0c0d06caSMauro Carvalho Chehab static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { 2076*0c0d06caSMauro Carvalho Chehab .vidioc_s_std = vidioc_s_std, 2077*0c0d06caSMauro Carvalho Chehab .vidioc_g_std = vidioc_g_std, 2078*0c0d06caSMauro Carvalho Chehab .vidioc_enum_input = vidioc_enum_input, 2079*0c0d06caSMauro Carvalho Chehab .vidioc_enumaudio = vidioc_enumaudio, 2080*0c0d06caSMauro Carvalho Chehab .vidioc_g_audio = vidioc_g_audio, 2081*0c0d06caSMauro Carvalho Chehab .vidioc_g_input = vidioc_g_input, 2082*0c0d06caSMauro Carvalho Chehab .vidioc_s_input = vidioc_s_input, 2083*0c0d06caSMauro Carvalho Chehab .vidioc_g_tuner = vidioc_g_tuner, 2084*0c0d06caSMauro Carvalho Chehab .vidioc_s_tuner = vidioc_s_tuner, 2085*0c0d06caSMauro Carvalho Chehab .vidioc_g_frequency = vidioc_g_frequency, 2086*0c0d06caSMauro Carvalho Chehab .vidioc_s_frequency = vidioc_s_frequency, 2087*0c0d06caSMauro Carvalho Chehab .vidioc_s_ctrl = vidioc_s_ctrl, 2088*0c0d06caSMauro Carvalho Chehab .vidioc_querycap = vidioc_querycap, 2089*0c0d06caSMauro Carvalho Chehab .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 2090*0c0d06caSMauro Carvalho Chehab .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, 2091*0c0d06caSMauro Carvalho Chehab .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, 2092*0c0d06caSMauro Carvalho Chehab .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, 2093*0c0d06caSMauro Carvalho Chehab .vidioc_reqbufs = vidioc_reqbufs, 2094*0c0d06caSMauro Carvalho Chehab .vidioc_querybuf = vidioc_querybuf, 2095*0c0d06caSMauro Carvalho Chehab .vidioc_qbuf = vidioc_qbuf, 2096*0c0d06caSMauro Carvalho Chehab .vidioc_dqbuf = vidioc_dqbuf, 2097*0c0d06caSMauro Carvalho Chehab .vidioc_streamon = vidioc_streamon, 2098*0c0d06caSMauro Carvalho Chehab .vidioc_streamoff = vidioc_streamoff, 2099*0c0d06caSMauro Carvalho Chehab .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, 2100*0c0d06caSMauro Carvalho Chehab .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, 2101*0c0d06caSMauro Carvalho Chehab .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, 2102*0c0d06caSMauro Carvalho Chehab .vidioc_log_status = vidioc_log_status, 2103*0c0d06caSMauro Carvalho Chehab .vidioc_querymenu = vidioc_querymenu, 2104*0c0d06caSMauro Carvalho Chehab .vidioc_queryctrl = vidioc_queryctrl, 2105*0c0d06caSMauro Carvalho Chehab /* .vidioc_g_chip_ident = cx231xx_g_chip_ident,*/ 2106*0c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 2107*0c0d06caSMauro Carvalho Chehab /* .vidioc_g_register = cx231xx_g_register,*/ 2108*0c0d06caSMauro Carvalho Chehab /* .vidioc_s_register = cx231xx_s_register,*/ 2109*0c0d06caSMauro Carvalho Chehab #endif 2110*0c0d06caSMauro Carvalho Chehab }; 2111*0c0d06caSMauro Carvalho Chehab 2112*0c0d06caSMauro Carvalho Chehab static struct video_device cx231xx_mpeg_template = { 2113*0c0d06caSMauro Carvalho Chehab .name = "cx231xx", 2114*0c0d06caSMauro Carvalho Chehab .fops = &mpeg_fops, 2115*0c0d06caSMauro Carvalho Chehab .ioctl_ops = &mpeg_ioctl_ops, 2116*0c0d06caSMauro Carvalho Chehab .minor = -1, 2117*0c0d06caSMauro Carvalho Chehab .tvnorms = CX231xx_NORMS, 2118*0c0d06caSMauro Carvalho Chehab .current_norm = V4L2_STD_NTSC_M, 2119*0c0d06caSMauro Carvalho Chehab }; 2120*0c0d06caSMauro Carvalho Chehab 2121*0c0d06caSMauro Carvalho Chehab void cx231xx_417_unregister(struct cx231xx *dev) 2122*0c0d06caSMauro Carvalho Chehab { 2123*0c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 2124*0c0d06caSMauro Carvalho Chehab dprintk(3, "%s()\n", __func__); 2125*0c0d06caSMauro Carvalho Chehab 2126*0c0d06caSMauro Carvalho Chehab if (dev->v4l_device) { 2127*0c0d06caSMauro Carvalho Chehab if (-1 != dev->v4l_device->minor) 2128*0c0d06caSMauro Carvalho Chehab video_unregister_device(dev->v4l_device); 2129*0c0d06caSMauro Carvalho Chehab else 2130*0c0d06caSMauro Carvalho Chehab video_device_release(dev->v4l_device); 2131*0c0d06caSMauro Carvalho Chehab dev->v4l_device = NULL; 2132*0c0d06caSMauro Carvalho Chehab } 2133*0c0d06caSMauro Carvalho Chehab } 2134*0c0d06caSMauro Carvalho Chehab 2135*0c0d06caSMauro Carvalho Chehab static struct video_device *cx231xx_video_dev_alloc( 2136*0c0d06caSMauro Carvalho Chehab struct cx231xx *dev, 2137*0c0d06caSMauro Carvalho Chehab struct usb_device *usbdev, 2138*0c0d06caSMauro Carvalho Chehab struct video_device *template, 2139*0c0d06caSMauro Carvalho Chehab char *type) 2140*0c0d06caSMauro Carvalho Chehab { 2141*0c0d06caSMauro Carvalho Chehab struct video_device *vfd; 2142*0c0d06caSMauro Carvalho Chehab 2143*0c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 2144*0c0d06caSMauro Carvalho Chehab vfd = video_device_alloc(); 2145*0c0d06caSMauro Carvalho Chehab if (NULL == vfd) 2146*0c0d06caSMauro Carvalho Chehab return NULL; 2147*0c0d06caSMauro Carvalho Chehab *vfd = *template; 2148*0c0d06caSMauro Carvalho Chehab vfd->minor = -1; 2149*0c0d06caSMauro Carvalho Chehab snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, 2150*0c0d06caSMauro Carvalho Chehab type, cx231xx_boards[dev->model].name); 2151*0c0d06caSMauro Carvalho Chehab 2152*0c0d06caSMauro Carvalho Chehab vfd->v4l2_dev = &dev->v4l2_dev; 2153*0c0d06caSMauro Carvalho Chehab vfd->release = video_device_release; 2154*0c0d06caSMauro Carvalho Chehab 2155*0c0d06caSMauro Carvalho Chehab return vfd; 2156*0c0d06caSMauro Carvalho Chehab 2157*0c0d06caSMauro Carvalho Chehab } 2158*0c0d06caSMauro Carvalho Chehab 2159*0c0d06caSMauro Carvalho Chehab int cx231xx_417_register(struct cx231xx *dev) 2160*0c0d06caSMauro Carvalho Chehab { 2161*0c0d06caSMauro Carvalho Chehab /* FIXME: Port1 hardcoded here */ 2162*0c0d06caSMauro Carvalho Chehab int err = -ENODEV; 2163*0c0d06caSMauro Carvalho Chehab struct cx231xx_tsport *tsport = &dev->ts1; 2164*0c0d06caSMauro Carvalho Chehab 2165*0c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 2166*0c0d06caSMauro Carvalho Chehab 2167*0c0d06caSMauro Carvalho Chehab /* Set default TV standard */ 2168*0c0d06caSMauro Carvalho Chehab dev->encodernorm = cx231xx_tvnorms[0]; 2169*0c0d06caSMauro Carvalho Chehab 2170*0c0d06caSMauro Carvalho Chehab if (dev->encodernorm.id & V4L2_STD_525_60) 2171*0c0d06caSMauro Carvalho Chehab tsport->height = 480; 2172*0c0d06caSMauro Carvalho Chehab else 2173*0c0d06caSMauro Carvalho Chehab tsport->height = 576; 2174*0c0d06caSMauro Carvalho Chehab 2175*0c0d06caSMauro Carvalho Chehab tsport->width = 720; 2176*0c0d06caSMauro Carvalho Chehab cx2341x_fill_defaults(&dev->mpeg_params); 2177*0c0d06caSMauro Carvalho Chehab dev->norm = V4L2_STD_NTSC; 2178*0c0d06caSMauro Carvalho Chehab 2179*0c0d06caSMauro Carvalho Chehab dev->mpeg_params.port = CX2341X_PORT_SERIAL; 2180*0c0d06caSMauro Carvalho Chehab 2181*0c0d06caSMauro Carvalho Chehab /* Allocate and initialize V4L video device */ 2182*0c0d06caSMauro Carvalho Chehab dev->v4l_device = cx231xx_video_dev_alloc(dev, 2183*0c0d06caSMauro Carvalho Chehab dev->udev, &cx231xx_mpeg_template, "mpeg"); 2184*0c0d06caSMauro Carvalho Chehab err = video_register_device(dev->v4l_device, 2185*0c0d06caSMauro Carvalho Chehab VFL_TYPE_GRABBER, -1); 2186*0c0d06caSMauro Carvalho Chehab if (err < 0) { 2187*0c0d06caSMauro Carvalho Chehab dprintk(3, "%s: can't register mpeg device\n", dev->name); 2188*0c0d06caSMauro Carvalho Chehab return err; 2189*0c0d06caSMauro Carvalho Chehab } 2190*0c0d06caSMauro Carvalho Chehab 2191*0c0d06caSMauro Carvalho Chehab dprintk(3, "%s: registered device video%d [mpeg]\n", 2192*0c0d06caSMauro Carvalho Chehab dev->name, dev->v4l_device->num); 2193*0c0d06caSMauro Carvalho Chehab 2194*0c0d06caSMauro Carvalho Chehab return 0; 2195*0c0d06caSMauro Carvalho Chehab } 2196*0c0d06caSMauro Carvalho Chehab 2197*0c0d06caSMauro Carvalho Chehab MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME); 2198