Path: blob/master/drivers/media/video/cx23885/cx23885-417.c
17892 views
/*1*2* Support for a cx23417 mpeg encoder via cx23885 host port.3*4* (c) 2004 Jelle Foks <[email protected]>5* (c) 2004 Gerd Knorr <[email protected]>6* (c) 2008 Steven Toth <[email protected]>7* - CX23885/7/8 support8*9* Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>10*11* This program is free software; you can redistribute it and/or modify12* it under the terms of the GNU General Public License as published by13* the Free Software Foundation; either version 2 of the License, or14* (at your option) any later version.15*16* This program is distributed in the hope that it will be useful,17* but WITHOUT ANY WARRANTY; without even the implied warranty of18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the19* GNU General Public License for more details.20*21* You should have received a copy of the GNU General Public License22* along with this program; if not, write to the Free Software23* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.24*/2526#include <linux/module.h>27#include <linux/moduleparam.h>28#include <linux/init.h>29#include <linux/fs.h>30#include <linux/delay.h>31#include <linux/device.h>32#include <linux/firmware.h>33#include <linux/slab.h>34#include <media/v4l2-common.h>35#include <media/v4l2-ioctl.h>36#include <media/cx2341x.h>3738#include "cx23885.h"39#include "cx23885-ioctl.h"4041#define CX23885_FIRM_IMAGE_SIZE 37683642#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"4344static unsigned int mpegbufs = 32;45module_param(mpegbufs, int, 0644);46MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");47static unsigned int mpeglines = 32;48module_param(mpeglines, int, 0644);49MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");50static unsigned int mpeglinesize = 512;51module_param(mpeglinesize, int, 0644);52MODULE_PARM_DESC(mpeglinesize,53"number of bytes in each line of an MPEG buffer, range 512-1024");5455static unsigned int v4l_debug;56module_param(v4l_debug, int, 0644);57MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");5859#define dprintk(level, fmt, arg...)\60do { if (v4l_debug >= level) \61printk(KERN_DEBUG "%s: " fmt, \62(dev) ? dev->name : "cx23885[?]", ## arg); \63} while (0)6465static struct cx23885_tvnorm cx23885_tvnorms[] = {66{67.name = "NTSC-M",68.id = V4L2_STD_NTSC_M,69}, {70.name = "NTSC-JP",71.id = V4L2_STD_NTSC_M_JP,72}, {73.name = "PAL-BG",74.id = V4L2_STD_PAL_BG,75}, {76.name = "PAL-DK",77.id = V4L2_STD_PAL_DK,78}, {79.name = "PAL-I",80.id = V4L2_STD_PAL_I,81}, {82.name = "PAL-M",83.id = V4L2_STD_PAL_M,84}, {85.name = "PAL-N",86.id = V4L2_STD_PAL_N,87}, {88.name = "PAL-Nc",89.id = V4L2_STD_PAL_Nc,90}, {91.name = "PAL-60",92.id = V4L2_STD_PAL_60,93}, {94.name = "SECAM-L",95.id = V4L2_STD_SECAM_L,96}, {97.name = "SECAM-DK",98.id = V4L2_STD_SECAM_DK,99}100};101102/* ------------------------------------------------------------------ */103enum cx23885_capture_type {104CX23885_MPEG_CAPTURE,105CX23885_RAW_CAPTURE,106CX23885_RAW_PASSTHRU_CAPTURE107};108enum cx23885_capture_bits {109CX23885_RAW_BITS_NONE = 0x00,110CX23885_RAW_BITS_YUV_CAPTURE = 0x01,111CX23885_RAW_BITS_PCM_CAPTURE = 0x02,112CX23885_RAW_BITS_VBI_CAPTURE = 0x04,113CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,114CX23885_RAW_BITS_TO_HOST_CAPTURE = 0x10115};116enum cx23885_capture_end {117CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */118CX23885_END_NOW, /* stop immediately, no irq */119};120enum cx23885_framerate {121CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */122CX23885_FRAMERATE_PAL_25 /* PAL: 25fps */123};124enum cx23885_stream_port {125CX23885_OUTPUT_PORT_MEMORY,126CX23885_OUTPUT_PORT_STREAMING,127CX23885_OUTPUT_PORT_SERIAL128};129enum cx23885_data_xfer_status {130CX23885_MORE_BUFFERS_FOLLOW,131CX23885_LAST_BUFFER,132};133enum cx23885_picture_mask {134CX23885_PICTURE_MASK_NONE,135CX23885_PICTURE_MASK_I_FRAMES,136CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,137CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,138};139enum cx23885_vbi_mode_bits {140CX23885_VBI_BITS_SLICED,141CX23885_VBI_BITS_RAW,142};143enum cx23885_vbi_insertion_bits {144CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,145CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,146CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,147CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,148CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,149};150enum cx23885_dma_unit {151CX23885_DMA_BYTES,152CX23885_DMA_FRAMES,153};154enum cx23885_dma_transfer_status_bits {155CX23885_DMA_TRANSFER_BITS_DONE = 0x01,156CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,157CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,158};159enum cx23885_pause {160CX23885_PAUSE_ENCODING,161CX23885_RESUME_ENCODING,162};163enum cx23885_copyright {164CX23885_COPYRIGHT_OFF,165CX23885_COPYRIGHT_ON,166};167enum cx23885_notification_type {168CX23885_NOTIFICATION_REFRESH,169};170enum cx23885_notification_status {171CX23885_NOTIFICATION_OFF,172CX23885_NOTIFICATION_ON,173};174enum cx23885_notification_mailbox {175CX23885_NOTIFICATION_NO_MAILBOX = -1,176};177enum cx23885_field1_lines {178CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */179CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */180CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */181};182enum cx23885_field2_lines {183CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */184CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */185CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */186};187enum cx23885_custom_data_type {188CX23885_CUSTOM_EXTENSION_USR_DATA,189CX23885_CUSTOM_PRIVATE_PACKET,190};191enum cx23885_mute {192CX23885_UNMUTE,193CX23885_MUTE,194};195enum cx23885_mute_video_mask {196CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,197CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,198CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,199};200enum cx23885_mute_video_shift {201CX23885_MUTE_VIDEO_V_SHIFT = 8,202CX23885_MUTE_VIDEO_U_SHIFT = 16,203CX23885_MUTE_VIDEO_Y_SHIFT = 24,204};205206/* defines below are from ivtv-driver.h */207#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF208209/* Firmware API commands */210#define IVTV_API_STD_TIMEOUT 500211212/* Registers */213/* IVTV_REG_OFFSET */214#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)215#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)216#define IVTV_REG_SPU (0x9050)217#define IVTV_REG_HW_BLOCKS (0x9054)218#define IVTV_REG_VPU (0x9058)219#define IVTV_REG_APU (0xA064)220221/**** Bit definitions for MC417_RWD and MC417_OEN registers ***222bits 31-16223+-----------+224| Reserved |225+-----------+226bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8227+-------+-------+-------+-------+-------+-------+-------+-------+228| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|229+-------+-------+-------+-------+-------+-------+-------+-------+230bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0231+-------+-------+-------+-------+-------+-------+-------+-------+232|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|233+-------+-------+-------+-------+-------+-------+-------+-------+234***/235#define MC417_MIWR 0x8000236#define MC417_MIRD 0x4000237#define MC417_MICS 0x2000238#define MC417_MIRDY 0x1000239#define MC417_MIADDR 0x0F00240#define MC417_MIDATA 0x00FF241242/* MIADDR* nibble definitions */243#define MCI_MEMORY_DATA_BYTE0 0x000244#define MCI_MEMORY_DATA_BYTE1 0x100245#define MCI_MEMORY_DATA_BYTE2 0x200246#define MCI_MEMORY_DATA_BYTE3 0x300247#define MCI_MEMORY_ADDRESS_BYTE2 0x400248#define MCI_MEMORY_ADDRESS_BYTE1 0x500249#define MCI_MEMORY_ADDRESS_BYTE0 0x600250#define MCI_REGISTER_DATA_BYTE0 0x800251#define MCI_REGISTER_DATA_BYTE1 0x900252#define MCI_REGISTER_DATA_BYTE2 0xA00253#define MCI_REGISTER_DATA_BYTE3 0xB00254#define MCI_REGISTER_ADDRESS_BYTE0 0xC00255#define MCI_REGISTER_ADDRESS_BYTE1 0xD00256#define MCI_REGISTER_MODE 0xE00257258/* Read and write modes */259#define MCI_MODE_REGISTER_READ 0260#define MCI_MODE_REGISTER_WRITE 1261#define MCI_MODE_MEMORY_READ 0262#define MCI_MODE_MEMORY_WRITE 0x40263264/*** Bit definitions for MC417_CTL register ****265bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0266+--------+-------------+--------+--------------+------------+267|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|268+--------+-------------+--------+--------------+------------+269***/270#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030)271#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006)272#define MC417_UART_GPIO_EN 0x00000001273274/* Values for speed control */275#define MC417_SPD_CTL_SLOW 0x1276#define MC417_SPD_CTL_MEDIUM 0x0277#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */278279/* Values for GPIO select */280#define MC417_GPIO_SEL_GPIO3 0x3281#define MC417_GPIO_SEL_GPIO2 0x2282#define MC417_GPIO_SEL_GPIO1 0x1283#define MC417_GPIO_SEL_GPIO0 0x0284285void cx23885_mc417_init(struct cx23885_dev *dev)286{287u32 regval;288289dprintk(2, "%s()\n", __func__);290291/* Configure MC417_CTL register to defaults. */292regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST) |293MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3) |294MC417_UART_GPIO_EN;295cx_write(MC417_CTL, regval);296297/* Configure MC417_OEN to defaults. */298regval = MC417_MIRDY;299cx_write(MC417_OEN, regval);300301/* Configure MC417_RWD to defaults. */302regval = MC417_MIWR | MC417_MIRD | MC417_MICS;303cx_write(MC417_RWD, regval);304}305306static int mc417_wait_ready(struct cx23885_dev *dev)307{308u32 mi_ready;309unsigned long timeout = jiffies + msecs_to_jiffies(1);310311for (;;) {312mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;313if (mi_ready != 0)314return 0;315if (time_after(jiffies, timeout))316return -1;317udelay(1);318}319}320321int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)322{323u32 regval;324325/* Enable MC417 GPIO outputs except for MC417_MIRDY,326* which is an input.327*/328cx_write(MC417_OEN, MC417_MIRDY);329330/* Write data byte 0 */331regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |332(value & 0x000000FF);333cx_write(MC417_RWD, regval);334335/* Transition CS/WR to effect write transaction across bus. */336regval |= MC417_MICS | MC417_MIWR;337cx_write(MC417_RWD, regval);338339/* Write data byte 1 */340regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |341((value >> 8) & 0x000000FF);342cx_write(MC417_RWD, regval);343regval |= MC417_MICS | MC417_MIWR;344cx_write(MC417_RWD, regval);345346/* Write data byte 2 */347regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |348((value >> 16) & 0x000000FF);349cx_write(MC417_RWD, regval);350regval |= MC417_MICS | MC417_MIWR;351cx_write(MC417_RWD, regval);352353/* Write data byte 3 */354regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |355((value >> 24) & 0x000000FF);356cx_write(MC417_RWD, regval);357regval |= MC417_MICS | MC417_MIWR;358cx_write(MC417_RWD, regval);359360/* Write address byte 0 */361regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |362(address & 0xFF);363cx_write(MC417_RWD, regval);364regval |= MC417_MICS | MC417_MIWR;365cx_write(MC417_RWD, regval);366367/* Write address byte 1 */368regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |369((address >> 8) & 0xFF);370cx_write(MC417_RWD, regval);371regval |= MC417_MICS | MC417_MIWR;372cx_write(MC417_RWD, regval);373374/* Indicate that this is a write. */375regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |376MCI_MODE_REGISTER_WRITE;377cx_write(MC417_RWD, regval);378regval |= MC417_MICS | MC417_MIWR;379cx_write(MC417_RWD, regval);380381/* Wait for the trans to complete (MC417_MIRDY asserted). */382return mc417_wait_ready(dev);383}384385int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)386{387int retval;388u32 regval;389u32 tempval;390u32 dataval;391392/* Enable MC417 GPIO outputs except for MC417_MIRDY,393* which is an input.394*/395cx_write(MC417_OEN, MC417_MIRDY);396397/* Write address byte 0 */398regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |399((address & 0x00FF));400cx_write(MC417_RWD, regval);401regval |= MC417_MICS | MC417_MIWR;402cx_write(MC417_RWD, regval);403404/* Write address byte 1 */405regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |406((address >> 8) & 0xFF);407cx_write(MC417_RWD, regval);408regval |= MC417_MICS | MC417_MIWR;409cx_write(MC417_RWD, regval);410411/* Indicate that this is a register read. */412regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |413MCI_MODE_REGISTER_READ;414cx_write(MC417_RWD, regval);415regval |= MC417_MICS | MC417_MIWR;416cx_write(MC417_RWD, regval);417418/* Wait for the trans to complete (MC417_MIRDY asserted). */419retval = mc417_wait_ready(dev);420421/* switch the DAT0-7 GPIO[10:3] to input mode */422cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);423424/* Read data byte 0 */425regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;426cx_write(MC417_RWD, regval);427428/* Transition RD to effect read transaction across bus.429* Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?430* Should it be 0x9000 -> 0xF000 (also why is RDY being set, its431* input only...)432*/433regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;434cx_write(MC417_RWD, regval);435436/* Collect byte */437tempval = cx_read(MC417_RWD);438dataval = tempval & 0x000000FF;439440/* Bring CS and RD high. */441regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;442cx_write(MC417_RWD, regval);443444/* Read data byte 1 */445regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;446cx_write(MC417_RWD, regval);447regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;448cx_write(MC417_RWD, regval);449tempval = cx_read(MC417_RWD);450dataval |= ((tempval & 0x000000FF) << 8);451regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;452cx_write(MC417_RWD, regval);453454/* Read data byte 2 */455regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;456cx_write(MC417_RWD, regval);457regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;458cx_write(MC417_RWD, regval);459tempval = cx_read(MC417_RWD);460dataval |= ((tempval & 0x000000FF) << 16);461regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;462cx_write(MC417_RWD, regval);463464/* Read data byte 3 */465regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;466cx_write(MC417_RWD, regval);467regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;468cx_write(MC417_RWD, regval);469tempval = cx_read(MC417_RWD);470dataval |= ((tempval & 0x000000FF) << 24);471regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;472cx_write(MC417_RWD, regval);473474*value = dataval;475476return retval;477}478479int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)480{481u32 regval;482483/* Enable MC417 GPIO outputs except for MC417_MIRDY,484* which is an input.485*/486cx_write(MC417_OEN, MC417_MIRDY);487488/* Write data byte 0 */489regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |490(value & 0x000000FF);491cx_write(MC417_RWD, regval);492493/* Transition CS/WR to effect write transaction across bus. */494regval |= MC417_MICS | MC417_MIWR;495cx_write(MC417_RWD, regval);496497/* Write data byte 1 */498regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |499((value >> 8) & 0x000000FF);500cx_write(MC417_RWD, regval);501regval |= MC417_MICS | MC417_MIWR;502cx_write(MC417_RWD, regval);503504/* Write data byte 2 */505regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |506((value >> 16) & 0x000000FF);507cx_write(MC417_RWD, regval);508regval |= MC417_MICS | MC417_MIWR;509cx_write(MC417_RWD, regval);510511/* Write data byte 3 */512regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |513((value >> 24) & 0x000000FF);514cx_write(MC417_RWD, regval);515regval |= MC417_MICS | MC417_MIWR;516cx_write(MC417_RWD, regval);517518/* Write address byte 2 */519regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |520MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);521cx_write(MC417_RWD, regval);522regval |= MC417_MICS | MC417_MIWR;523cx_write(MC417_RWD, regval);524525/* Write address byte 1 */526regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |527((address >> 8) & 0xFF);528cx_write(MC417_RWD, regval);529regval |= MC417_MICS | MC417_MIWR;530cx_write(MC417_RWD, regval);531532/* Write address byte 0 */533regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |534(address & 0xFF);535cx_write(MC417_RWD, regval);536regval |= MC417_MICS | MC417_MIWR;537cx_write(MC417_RWD, regval);538539/* Wait for the trans to complete (MC417_MIRDY asserted). */540return mc417_wait_ready(dev);541}542543int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)544{545int retval;546u32 regval;547u32 tempval;548u32 dataval;549550/* Enable MC417 GPIO outputs except for MC417_MIRDY,551* which is an input.552*/553cx_write(MC417_OEN, MC417_MIRDY);554555/* Write address byte 2 */556regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |557MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);558cx_write(MC417_RWD, regval);559regval |= MC417_MICS | MC417_MIWR;560cx_write(MC417_RWD, regval);561562/* Write address byte 1 */563regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |564((address >> 8) & 0xFF);565cx_write(MC417_RWD, regval);566regval |= MC417_MICS | MC417_MIWR;567cx_write(MC417_RWD, regval);568569/* Write address byte 0 */570regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |571(address & 0xFF);572cx_write(MC417_RWD, regval);573regval |= MC417_MICS | MC417_MIWR;574cx_write(MC417_RWD, regval);575576/* Wait for the trans to complete (MC417_MIRDY asserted). */577retval = mc417_wait_ready(dev);578579/* switch the DAT0-7 GPIO[10:3] to input mode */580cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);581582/* Read data byte 3 */583regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;584cx_write(MC417_RWD, regval);585586/* Transition RD to effect read transaction across bus. */587regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;588cx_write(MC417_RWD, regval);589590/* Collect byte */591tempval = cx_read(MC417_RWD);592dataval = ((tempval & 0x000000FF) << 24);593594/* Bring CS and RD high. */595regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;596cx_write(MC417_RWD, regval);597598/* Read data byte 2 */599regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;600cx_write(MC417_RWD, regval);601regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;602cx_write(MC417_RWD, regval);603tempval = cx_read(MC417_RWD);604dataval |= ((tempval & 0x000000FF) << 16);605regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;606cx_write(MC417_RWD, regval);607608/* Read data byte 1 */609regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;610cx_write(MC417_RWD, regval);611regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;612cx_write(MC417_RWD, regval);613tempval = cx_read(MC417_RWD);614dataval |= ((tempval & 0x000000FF) << 8);615regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;616cx_write(MC417_RWD, regval);617618/* Read data byte 0 */619regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;620cx_write(MC417_RWD, regval);621regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;622cx_write(MC417_RWD, regval);623tempval = cx_read(MC417_RWD);624dataval |= (tempval & 0x000000FF);625regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;626cx_write(MC417_RWD, regval);627628*value = dataval;629630return retval;631}632633void mc417_gpio_set(struct cx23885_dev *dev, u32 mask)634{635u32 val;636637/* Set the gpio value */638mc417_register_read(dev, 0x900C, &val);639val |= (mask & 0x000ffff);640mc417_register_write(dev, 0x900C, val);641}642643void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask)644{645u32 val;646647/* Clear the gpio value */648mc417_register_read(dev, 0x900C, &val);649val &= ~(mask & 0x0000ffff);650mc417_register_write(dev, 0x900C, val);651}652653void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)654{655u32 val;656657/* Enable GPIO direction bits */658mc417_register_read(dev, 0x9020, &val);659if (asoutput)660val |= (mask & 0x0000ffff);661else662val &= ~(mask & 0x0000ffff);663664mc417_register_write(dev, 0x9020, val);665}666/* ------------------------------------------------------------------ */667668/* MPEG encoder API */669static char *cmd_to_str(int cmd)670{671switch (cmd) {672case CX2341X_ENC_PING_FW:673return "PING_FW";674case CX2341X_ENC_START_CAPTURE:675return "START_CAPTURE";676case CX2341X_ENC_STOP_CAPTURE:677return "STOP_CAPTURE";678case CX2341X_ENC_SET_AUDIO_ID:679return "SET_AUDIO_ID";680case CX2341X_ENC_SET_VIDEO_ID:681return "SET_VIDEO_ID";682case CX2341X_ENC_SET_PCR_ID:683return "SET_PCR_ID";684case CX2341X_ENC_SET_FRAME_RATE:685return "SET_FRAME_RATE";686case CX2341X_ENC_SET_FRAME_SIZE:687return "SET_FRAME_SIZE";688case CX2341X_ENC_SET_BIT_RATE:689return "SET_BIT_RATE";690case CX2341X_ENC_SET_GOP_PROPERTIES:691return "SET_GOP_PROPERTIES";692case CX2341X_ENC_SET_ASPECT_RATIO:693return "SET_ASPECT_RATIO";694case CX2341X_ENC_SET_DNR_FILTER_MODE:695return "SET_DNR_FILTER_MODE";696case CX2341X_ENC_SET_DNR_FILTER_PROPS:697return "SET_DNR_FILTER_PROPS";698case CX2341X_ENC_SET_CORING_LEVELS:699return "SET_CORING_LEVELS";700case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:701return "SET_SPATIAL_FILTER_TYPE";702case CX2341X_ENC_SET_VBI_LINE:703return "SET_VBI_LINE";704case CX2341X_ENC_SET_STREAM_TYPE:705return "SET_STREAM_TYPE";706case CX2341X_ENC_SET_OUTPUT_PORT:707return "SET_OUTPUT_PORT";708case CX2341X_ENC_SET_AUDIO_PROPERTIES:709return "SET_AUDIO_PROPERTIES";710case CX2341X_ENC_HALT_FW:711return "HALT_FW";712case CX2341X_ENC_GET_VERSION:713return "GET_VERSION";714case CX2341X_ENC_SET_GOP_CLOSURE:715return "SET_GOP_CLOSURE";716case CX2341X_ENC_GET_SEQ_END:717return "GET_SEQ_END";718case CX2341X_ENC_SET_PGM_INDEX_INFO:719return "SET_PGM_INDEX_INFO";720case CX2341X_ENC_SET_VBI_CONFIG:721return "SET_VBI_CONFIG";722case CX2341X_ENC_SET_DMA_BLOCK_SIZE:723return "SET_DMA_BLOCK_SIZE";724case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:725return "GET_PREV_DMA_INFO_MB_10";726case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:727return "GET_PREV_DMA_INFO_MB_9";728case CX2341X_ENC_SCHED_DMA_TO_HOST:729return "SCHED_DMA_TO_HOST";730case CX2341X_ENC_INITIALIZE_INPUT:731return "INITIALIZE_INPUT";732case CX2341X_ENC_SET_FRAME_DROP_RATE:733return "SET_FRAME_DROP_RATE";734case CX2341X_ENC_PAUSE_ENCODER:735return "PAUSE_ENCODER";736case CX2341X_ENC_REFRESH_INPUT:737return "REFRESH_INPUT";738case CX2341X_ENC_SET_COPYRIGHT:739return "SET_COPYRIGHT";740case CX2341X_ENC_SET_EVENT_NOTIFICATION:741return "SET_EVENT_NOTIFICATION";742case CX2341X_ENC_SET_NUM_VSYNC_LINES:743return "SET_NUM_VSYNC_LINES";744case CX2341X_ENC_SET_PLACEHOLDER:745return "SET_PLACEHOLDER";746case CX2341X_ENC_MUTE_VIDEO:747return "MUTE_VIDEO";748case CX2341X_ENC_MUTE_AUDIO:749return "MUTE_AUDIO";750case CX2341X_ENC_MISC:751return "MISC";752default:753return "UNKNOWN";754}755}756757static int cx23885_mbox_func(void *priv,758u32 command,759int in,760int out,761u32 data[CX2341X_MBOX_MAX_DATA])762{763struct cx23885_dev *dev = priv;764unsigned long timeout;765u32 value, flag, retval = 0;766int i;767768dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,769cmd_to_str(command));770771/* this may not be 100% safe if we can't read any memory location772without side effects */773mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);774if (value != 0x12345678) {775printk(KERN_ERR776"Firmware and/or mailbox pointer not initialized "777"or corrupted, signature = 0x%x, cmd = %s\n", value,778cmd_to_str(command));779return -1;780}781782/* This read looks at 32 bits, but flag is only 8 bits.783* Seems we also bail if CMD or TIMEOUT bytes are set???784*/785mc417_memory_read(dev, dev->cx23417_mailbox, &flag);786if (flag) {787printk(KERN_ERR "ERROR: Mailbox appears to be in use "788"(%x), cmd = %s\n", flag, cmd_to_str(command));789return -1;790}791792flag |= 1; /* tell 'em we're working on it */793mc417_memory_write(dev, dev->cx23417_mailbox, flag);794795/* write command + args + fill remaining with zeros */796/* command code */797mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);798mc417_memory_write(dev, dev->cx23417_mailbox + 3,799IVTV_API_STD_TIMEOUT); /* timeout */800for (i = 0; i < in; i++) {801mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);802dprintk(3, "API Input %d = %d\n", i, data[i]);803}804for (; i < CX2341X_MBOX_MAX_DATA; i++)805mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);806807flag |= 3; /* tell 'em we're done writing */808mc417_memory_write(dev, dev->cx23417_mailbox, flag);809810/* wait for firmware to handle the API command */811timeout = jiffies + msecs_to_jiffies(10);812for (;;) {813mc417_memory_read(dev, dev->cx23417_mailbox, &flag);814if (0 != (flag & 4))815break;816if (time_after(jiffies, timeout)) {817printk(KERN_ERR "ERROR: API Mailbox timeout\n");818return -1;819}820udelay(10);821}822823/* read output values */824for (i = 0; i < out; i++) {825mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);826dprintk(3, "API Output %d = %d\n", i, data[i]);827}828829mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);830dprintk(3, "API result = %d\n", retval);831832flag = 0;833mc417_memory_write(dev, dev->cx23417_mailbox, flag);834835return retval;836}837838/* We don't need to call the API often, so using just one839* mailbox will probably suffice840*/841static int cx23885_api_cmd(struct cx23885_dev *dev,842u32 command,843u32 inputcnt,844u32 outputcnt,845...)846{847u32 data[CX2341X_MBOX_MAX_DATA];848va_list vargs;849int i, err;850851dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);852853va_start(vargs, outputcnt);854for (i = 0; i < inputcnt; i++)855data[i] = va_arg(vargs, int);856857err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);858for (i = 0; i < outputcnt; i++) {859int *vptr = va_arg(vargs, int *);860*vptr = data[i];861}862va_end(vargs);863864return err;865}866867static int cx23885_find_mailbox(struct cx23885_dev *dev)868{869u32 signature[4] = {8700x12345678, 0x34567812, 0x56781234, 0x78123456871};872int signaturecnt = 0;873u32 value;874int i;875876dprintk(2, "%s()\n", __func__);877878for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {879mc417_memory_read(dev, i, &value);880if (value == signature[signaturecnt])881signaturecnt++;882else883signaturecnt = 0;884if (4 == signaturecnt) {885dprintk(1, "Mailbox signature found at 0x%x\n", i+1);886return i+1;887}888}889printk(KERN_ERR "Mailbox signature values not found!\n");890return -1;891}892893static int cx23885_load_firmware(struct cx23885_dev *dev)894{895static const unsigned char magic[8] = {8960xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa897};898const struct firmware *firmware;899int i, retval = 0;900u32 value = 0;901u32 gpio_output = 0;902u32 checksum = 0;903u32 *dataptr;904905dprintk(2, "%s()\n", __func__);906907/* Save GPIO settings before reset of APU */908retval |= mc417_memory_read(dev, 0x9020, &gpio_output);909retval |= mc417_memory_read(dev, 0x900C, &value);910911retval = mc417_register_write(dev,912IVTV_REG_VPU, 0xFFFFFFED);913retval |= mc417_register_write(dev,914IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);915retval |= mc417_register_write(dev,916IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);917retval |= mc417_register_write(dev,918IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);919retval |= mc417_register_write(dev,920IVTV_REG_APU, 0);921922if (retval != 0) {923printk(KERN_ERR "%s: Error with mc417_register_write\n",924__func__);925return -1;926}927928retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,929&dev->pci->dev);930931if (retval != 0) {932printk(KERN_ERR933"ERROR: Hotplug firmware request failed (%s).\n",934CX23885_FIRM_IMAGE_NAME);935printk(KERN_ERR "Please fix your hotplug setup, the board will "936"not work without firmware loaded!\n");937return -1;938}939940if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {941printk(KERN_ERR "ERROR: Firmware size mismatch "942"(have %zd, expected %d)\n",943firmware->size, CX23885_FIRM_IMAGE_SIZE);944release_firmware(firmware);945return -1;946}947948if (0 != memcmp(firmware->data, magic, 8)) {949printk(KERN_ERR950"ERROR: Firmware magic mismatch, wrong file?\n");951release_firmware(firmware);952return -1;953}954955/* transfer to the chip */956dprintk(2, "Loading firmware ...\n");957dataptr = (u32 *)firmware->data;958for (i = 0; i < (firmware->size >> 2); i++) {959value = *dataptr;960checksum += ~value;961if (mc417_memory_write(dev, i, value) != 0) {962printk(KERN_ERR "ERROR: Loading firmware failed!\n");963release_firmware(firmware);964return -1;965}966dataptr++;967}968969/* read back to verify with the checksum */970dprintk(1, "Verifying firmware ...\n");971for (i--; i >= 0; i--) {972if (mc417_memory_read(dev, i, &value) != 0) {973printk(KERN_ERR "ERROR: Reading firmware failed!\n");974release_firmware(firmware);975return -1;976}977checksum -= ~value;978}979if (checksum) {980printk(KERN_ERR981"ERROR: Firmware load failed (checksum mismatch).\n");982release_firmware(firmware);983return -1;984}985release_firmware(firmware);986dprintk(1, "Firmware upload successful.\n");987988retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,989IVTV_CMD_HW_BLOCKS_RST);990991/* F/W power up disturbs the GPIOs, restore state */992retval |= mc417_register_write(dev, 0x9020, gpio_output);993retval |= mc417_register_write(dev, 0x900C, value);994995retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);996retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);997998if (retval < 0)999printk(KERN_ERR "%s: Error with mc417_register_write\n",1000__func__);1001return 0;1002}10031004void cx23885_417_check_encoder(struct cx23885_dev *dev)1005{1006u32 status, seq;10071008status = seq = 0;1009cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);1010dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);1011}10121013static void cx23885_codec_settings(struct cx23885_dev *dev)1014{1015dprintk(1, "%s()\n", __func__);10161017/* assign frame size */1018cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,1019dev->ts1.height, dev->ts1.width);10201021dev->mpeg_params.width = dev->ts1.width;1022dev->mpeg_params.height = dev->ts1.height;1023dev->mpeg_params.is_50hz =1024(dev->encodernorm.id & V4L2_STD_625_50) != 0;10251026cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);10271028cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);1029cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);1030}10311032static int cx23885_initialize_codec(struct cx23885_dev *dev)1033{1034int version;1035int retval;1036u32 i, data[7];10371038dprintk(1, "%s()\n", __func__);10391040retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */1041if (retval < 0) {1042dprintk(2, "%s() PING OK\n", __func__);1043retval = cx23885_load_firmware(dev);1044if (retval < 0) {1045printk(KERN_ERR "%s() f/w load failed\n", __func__);1046return retval;1047}1048retval = cx23885_find_mailbox(dev);1049if (retval < 0) {1050printk(KERN_ERR "%s() mailbox < 0, error\n",1051__func__);1052return -1;1053}1054dev->cx23417_mailbox = retval;1055retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);1056if (retval < 0) {1057printk(KERN_ERR1058"ERROR: cx23417 firmware ping failed!\n");1059return -1;1060}1061retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,1062&version);1063if (retval < 0) {1064printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"1065"version failed!\n");1066return -1;1067}1068dprintk(1, "cx23417 firmware version is 0x%08x\n", version);1069msleep(200);1070}10711072cx23885_codec_settings(dev);1073msleep(60);10741075cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,1076CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);1077cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,1078CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,10790, 0);10801081/* Setup to capture VBI */1082data[0] = 0x0001BD00;1083data[1] = 1; /* frames per interrupt */1084data[2] = 4; /* total bufs */1085data[3] = 0x91559155; /* start codes */1086data[4] = 0x206080C0; /* stop codes */1087data[5] = 6; /* lines */1088data[6] = 64; /* BPL */10891090cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],1091data[2], data[3], data[4], data[5], data[6]);10921093for (i = 2; i <= 24; i++) {1094int valid;10951096valid = ((i >= 19) && (i <= 21));1097cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,1098valid, 0 , 0, 0);1099cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,1100i | 0x80000000, valid, 0, 0, 0);1101}11021103cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);1104msleep(60);11051106/* initialize the video input */1107cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);1108msleep(60);11091110/* Enable VIP style pixel invalidation so we work with scaled mode */1111mc417_memory_write(dev, 2120, 0x00000080);11121113/* start capturing to the host interface */1114cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,1115CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);1116msleep(10);11171118return 0;1119}11201121/* ------------------------------------------------------------------ */11221123static int bb_buf_setup(struct videobuf_queue *q,1124unsigned int *count, unsigned int *size)1125{1126struct cx23885_fh *fh = q->priv_data;11271128fh->dev->ts1.ts_packet_size = mpeglinesize;1129fh->dev->ts1.ts_packet_count = mpeglines;11301131*size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;1132*count = mpegbufs;11331134return 0;1135}11361137static int bb_buf_prepare(struct videobuf_queue *q,1138struct videobuf_buffer *vb, enum v4l2_field field)1139{1140struct cx23885_fh *fh = q->priv_data;1141return cx23885_buf_prepare(q, &fh->dev->ts1,1142(struct cx23885_buffer *)vb,1143field);1144}11451146static void bb_buf_queue(struct videobuf_queue *q,1147struct videobuf_buffer *vb)1148{1149struct cx23885_fh *fh = q->priv_data;1150cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);1151}11521153static void bb_buf_release(struct videobuf_queue *q,1154struct videobuf_buffer *vb)1155{1156cx23885_free_buffer(q, (struct cx23885_buffer *)vb);1157}11581159static struct videobuf_queue_ops cx23885_qops = {1160.buf_setup = bb_buf_setup,1161.buf_prepare = bb_buf_prepare,1162.buf_queue = bb_buf_queue,1163.buf_release = bb_buf_release,1164};11651166/* ------------------------------------------------------------------ */11671168static const u32 *ctrl_classes[] = {1169cx2341x_mpeg_ctrls,1170NULL1171};11721173static int cx23885_queryctrl(struct cx23885_dev *dev,1174struct v4l2_queryctrl *qctrl)1175{1176qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);1177if (qctrl->id == 0)1178return -EINVAL;11791180/* MPEG V4L2 controls */1181if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))1182qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;11831184return 0;1185}11861187static int cx23885_querymenu(struct cx23885_dev *dev,1188struct v4l2_querymenu *qmenu)1189{1190struct v4l2_queryctrl qctrl;11911192qctrl.id = qmenu->id;1193cx23885_queryctrl(dev, &qctrl);1194return v4l2_ctrl_query_menu(qmenu, &qctrl,1195cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));1196}11971198static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)1199{1200struct cx23885_fh *fh = file->private_data;1201struct cx23885_dev *dev = fh->dev;1202unsigned int i;12031204for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)1205if (*id & cx23885_tvnorms[i].id)1206break;1207if (i == ARRAY_SIZE(cx23885_tvnorms))1208return -EINVAL;1209dev->encodernorm = cx23885_tvnorms[i];1210return 0;1211}12121213static int vidioc_enum_input(struct file *file, void *priv,1214struct v4l2_input *i)1215{1216struct cx23885_fh *fh = file->private_data;1217struct cx23885_dev *dev = fh->dev;1218struct cx23885_input *input;1219int n;12201221if (i->index >= 4)1222return -EINVAL;12231224input = &cx23885_boards[dev->board].input[i->index];12251226if (input->type == 0)1227return -EINVAL;12281229/* FIXME1230* strcpy(i->name, input->name); */1231strcpy(i->name, "unset");12321233if (input->type == CX23885_VMUX_TELEVISION ||1234input->type == CX23885_VMUX_CABLE)1235i->type = V4L2_INPUT_TYPE_TUNER;1236else1237i->type = V4L2_INPUT_TYPE_CAMERA;12381239for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)1240i->std |= cx23885_tvnorms[n].id;1241return 0;1242}12431244static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)1245{1246struct cx23885_fh *fh = file->private_data;1247struct cx23885_dev *dev = fh->dev;12481249*i = dev->input;1250return 0;1251}12521253static int vidioc_s_input(struct file *file, void *priv, unsigned int i)1254{1255if (i >= 4)1256return -EINVAL;12571258return 0;1259}12601261static int vidioc_g_tuner(struct file *file, void *priv,1262struct v4l2_tuner *t)1263{1264struct cx23885_fh *fh = file->private_data;1265struct cx23885_dev *dev = fh->dev;12661267if (UNSET == dev->tuner_type)1268return -EINVAL;1269if (0 != t->index)1270return -EINVAL;1271strcpy(t->name, "Television");1272call_all(dev, tuner, g_tuner, t);12731274dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);12751276return 0;1277}12781279static int vidioc_s_tuner(struct file *file, void *priv,1280struct v4l2_tuner *t)1281{1282struct cx23885_fh *fh = file->private_data;1283struct cx23885_dev *dev = fh->dev;12841285if (UNSET == dev->tuner_type)1286return -EINVAL;12871288/* Update the A/V core */1289call_all(dev, tuner, s_tuner, t);12901291return 0;1292}12931294static int vidioc_g_frequency(struct file *file, void *priv,1295struct v4l2_frequency *f)1296{1297struct cx23885_fh *fh = file->private_data;1298struct cx23885_dev *dev = fh->dev;12991300if (UNSET == dev->tuner_type)1301return -EINVAL;1302f->type = V4L2_TUNER_ANALOG_TV;1303f->frequency = dev->freq;13041305call_all(dev, tuner, g_frequency, f);13061307return 0;1308}13091310static int vidioc_s_frequency(struct file *file, void *priv,1311struct v4l2_frequency *f)1312{1313struct cx23885_fh *fh = file->private_data;1314struct cx23885_dev *dev = fh->dev;13151316cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,1317CX23885_END_NOW, CX23885_MPEG_CAPTURE,1318CX23885_RAW_BITS_NONE);13191320dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",1321dev->tuner_type);1322dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",1323f->tuner, f->type);1324if (UNSET == dev->tuner_type)1325return -EINVAL;1326if (f->tuner != 0)1327return -EINVAL;1328if (f->type != V4L2_TUNER_ANALOG_TV)1329return -EINVAL;1330dev->freq = f->frequency;13311332call_all(dev, tuner, s_frequency, f);13331334cx23885_initialize_codec(dev);13351336return 0;1337}13381339static int vidioc_s_ctrl(struct file *file, void *priv,1340struct v4l2_control *ctl)1341{1342struct cx23885_fh *fh = file->private_data;1343struct cx23885_dev *dev = fh->dev;13441345/* Update the A/V core */1346call_all(dev, core, s_ctrl, ctl);1347return 0;1348}13491350static int vidioc_querycap(struct file *file, void *priv,1351struct v4l2_capability *cap)1352{1353struct cx23885_fh *fh = file->private_data;1354struct cx23885_dev *dev = fh->dev;1355struct cx23885_tsport *tsport = &dev->ts1;13561357strlcpy(cap->driver, dev->name, sizeof(cap->driver));1358strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,1359sizeof(cap->card));1360sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));1361cap->version = CX23885_VERSION_CODE;1362cap->capabilities =1363V4L2_CAP_VIDEO_CAPTURE |1364V4L2_CAP_READWRITE |1365V4L2_CAP_STREAMING |13660;1367if (UNSET != dev->tuner_type)1368cap->capabilities |= V4L2_CAP_TUNER;13691370return 0;1371}13721373static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,1374struct v4l2_fmtdesc *f)1375{1376if (f->index != 0)1377return -EINVAL;13781379strlcpy(f->description, "MPEG", sizeof(f->description));1380f->pixelformat = V4L2_PIX_FMT_MPEG;13811382return 0;1383}13841385static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,1386struct v4l2_format *f)1387{1388struct cx23885_fh *fh = file->private_data;1389struct cx23885_dev *dev = fh->dev;13901391f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;1392f->fmt.pix.bytesperline = 0;1393f->fmt.pix.sizeimage =1394dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;1395f->fmt.pix.colorspace = 0;1396f->fmt.pix.width = dev->ts1.width;1397f->fmt.pix.height = dev->ts1.height;1398f->fmt.pix.field = fh->mpegq.field;1399dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",1400dev->ts1.width, dev->ts1.height, fh->mpegq.field);1401return 0;1402}14031404static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,1405struct v4l2_format *f)1406{1407struct cx23885_fh *fh = file->private_data;1408struct cx23885_dev *dev = fh->dev;14091410f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;1411f->fmt.pix.bytesperline = 0;1412f->fmt.pix.sizeimage =1413dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;1414f->fmt.pix.colorspace = 0;1415dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",1416dev->ts1.width, dev->ts1.height, fh->mpegq.field);1417return 0;1418}14191420static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,1421struct v4l2_format *f)1422{1423struct cx23885_fh *fh = file->private_data;1424struct cx23885_dev *dev = fh->dev;14251426f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;1427f->fmt.pix.bytesperline = 0;1428f->fmt.pix.sizeimage =1429dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;1430f->fmt.pix.colorspace = 0;1431dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",1432f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);1433return 0;1434}14351436static int vidioc_reqbufs(struct file *file, void *priv,1437struct v4l2_requestbuffers *p)1438{1439struct cx23885_fh *fh = file->private_data;14401441return videobuf_reqbufs(&fh->mpegq, p);1442}14431444static int vidioc_querybuf(struct file *file, void *priv,1445struct v4l2_buffer *p)1446{1447struct cx23885_fh *fh = file->private_data;14481449return videobuf_querybuf(&fh->mpegq, p);1450}14511452static int vidioc_qbuf(struct file *file, void *priv,1453struct v4l2_buffer *p)1454{1455struct cx23885_fh *fh = file->private_data;14561457return videobuf_qbuf(&fh->mpegq, p);1458}14591460static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)1461{1462struct cx23885_fh *fh = priv;14631464return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK);1465}146614671468static int vidioc_streamon(struct file *file, void *priv,1469enum v4l2_buf_type i)1470{1471struct cx23885_fh *fh = file->private_data;14721473return videobuf_streamon(&fh->mpegq);1474}14751476static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)1477{1478struct cx23885_fh *fh = file->private_data;14791480return videobuf_streamoff(&fh->mpegq);1481}14821483static int vidioc_g_ext_ctrls(struct file *file, void *priv,1484struct v4l2_ext_controls *f)1485{1486struct cx23885_fh *fh = priv;1487struct cx23885_dev *dev = fh->dev;14881489if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)1490return -EINVAL;1491return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);1492}14931494static int vidioc_s_ext_ctrls(struct file *file, void *priv,1495struct v4l2_ext_controls *f)1496{1497struct cx23885_fh *fh = priv;1498struct cx23885_dev *dev = fh->dev;1499struct cx2341x_mpeg_params p;1500int err;15011502if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)1503return -EINVAL;15041505p = dev->mpeg_params;1506err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);15071508if (err == 0) {1509err = cx2341x_update(dev, cx23885_mbox_func,1510&dev->mpeg_params, &p);1511dev->mpeg_params = p;1512}1513return err;1514}15151516static int vidioc_try_ext_ctrls(struct file *file, void *priv,1517struct v4l2_ext_controls *f)1518{1519struct cx23885_fh *fh = priv;1520struct cx23885_dev *dev = fh->dev;1521struct cx2341x_mpeg_params p;1522int err;15231524if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)1525return -EINVAL;15261527p = dev->mpeg_params;1528err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);1529return err;1530}15311532static int vidioc_log_status(struct file *file, void *priv)1533{1534struct cx23885_fh *fh = priv;1535struct cx23885_dev *dev = fh->dev;1536char name[32 + 2];15371538snprintf(name, sizeof(name), "%s/2", dev->name);1539printk(KERN_INFO1540"%s/2: ============ START LOG STATUS ============\n",1541dev->name);1542call_all(dev, core, log_status);1543cx2341x_log_status(&dev->mpeg_params, name);1544printk(KERN_INFO1545"%s/2: ============= END LOG STATUS =============\n",1546dev->name);1547return 0;1548}15491550static int vidioc_querymenu(struct file *file, void *priv,1551struct v4l2_querymenu *a)1552{1553struct cx23885_fh *fh = priv;1554struct cx23885_dev *dev = fh->dev;15551556return cx23885_querymenu(dev, a);1557}15581559static int vidioc_queryctrl(struct file *file, void *priv,1560struct v4l2_queryctrl *c)1561{1562struct cx23885_fh *fh = priv;1563struct cx23885_dev *dev = fh->dev;15641565return cx23885_queryctrl(dev, c);1566}15671568static int mpeg_open(struct file *file)1569{1570struct cx23885_dev *dev = video_drvdata(file);1571struct cx23885_fh *fh;15721573dprintk(2, "%s()\n", __func__);15741575/* allocate + initialize per filehandle data */1576fh = kzalloc(sizeof(*fh), GFP_KERNEL);1577if (!fh)1578return -ENOMEM;15791580file->private_data = fh;1581fh->dev = dev;15821583videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,1584&dev->pci->dev, &dev->ts1.slock,1585V4L2_BUF_TYPE_VIDEO_CAPTURE,1586V4L2_FIELD_INTERLACED,1587sizeof(struct cx23885_buffer),1588fh, NULL);1589return 0;1590}15911592static int mpeg_release(struct file *file)1593{1594struct cx23885_fh *fh = file->private_data;1595struct cx23885_dev *dev = fh->dev;15961597dprintk(2, "%s()\n", __func__);15981599/* FIXME: Review this crap */1600/* Shut device down on last close */1601if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {1602if (atomic_dec_return(&dev->v4l_reader_count) == 0) {1603/* stop mpeg capture */1604cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,1605CX23885_END_NOW, CX23885_MPEG_CAPTURE,1606CX23885_RAW_BITS_NONE);16071608msleep(500);1609cx23885_417_check_encoder(dev);16101611cx23885_cancel_buffers(&fh->dev->ts1);1612}1613}16141615if (fh->mpegq.streaming)1616videobuf_streamoff(&fh->mpegq);1617if (fh->mpegq.reading)1618videobuf_read_stop(&fh->mpegq);16191620videobuf_mmap_free(&fh->mpegq);1621file->private_data = NULL;1622kfree(fh);16231624return 0;1625}16261627static ssize_t mpeg_read(struct file *file, char __user *data,1628size_t count, loff_t *ppos)1629{1630struct cx23885_fh *fh = file->private_data;1631struct cx23885_dev *dev = fh->dev;16321633dprintk(2, "%s()\n", __func__);16341635/* Deal w/ A/V decoder * and mpeg encoder sync issues. */1636/* Start mpeg encoder on first read. */1637if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {1638if (atomic_inc_return(&dev->v4l_reader_count) == 1) {1639if (cx23885_initialize_codec(dev) < 0)1640return -EINVAL;1641}1642}16431644return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,1645file->f_flags & O_NONBLOCK);1646}16471648static unsigned int mpeg_poll(struct file *file,1649struct poll_table_struct *wait)1650{1651struct cx23885_fh *fh = file->private_data;1652struct cx23885_dev *dev = fh->dev;16531654dprintk(2, "%s\n", __func__);16551656return videobuf_poll_stream(file, &fh->mpegq, wait);1657}16581659static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)1660{1661struct cx23885_fh *fh = file->private_data;1662struct cx23885_dev *dev = fh->dev;16631664dprintk(2, "%s()\n", __func__);16651666return videobuf_mmap_mapper(&fh->mpegq, vma);1667}16681669static struct v4l2_file_operations mpeg_fops = {1670.owner = THIS_MODULE,1671.open = mpeg_open,1672.release = mpeg_release,1673.read = mpeg_read,1674.poll = mpeg_poll,1675.mmap = mpeg_mmap,1676.ioctl = video_ioctl2,1677};16781679static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {1680.vidioc_s_std = vidioc_s_std,1681.vidioc_enum_input = vidioc_enum_input,1682.vidioc_g_input = vidioc_g_input,1683.vidioc_s_input = vidioc_s_input,1684.vidioc_g_tuner = vidioc_g_tuner,1685.vidioc_s_tuner = vidioc_s_tuner,1686.vidioc_g_frequency = vidioc_g_frequency,1687.vidioc_s_frequency = vidioc_s_frequency,1688.vidioc_s_ctrl = vidioc_s_ctrl,1689.vidioc_querycap = vidioc_querycap,1690.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,1691.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,1692.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,1693.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,1694.vidioc_reqbufs = vidioc_reqbufs,1695.vidioc_querybuf = vidioc_querybuf,1696.vidioc_qbuf = vidioc_qbuf,1697.vidioc_dqbuf = vidioc_dqbuf,1698.vidioc_streamon = vidioc_streamon,1699.vidioc_streamoff = vidioc_streamoff,1700.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,1701.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,1702.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,1703.vidioc_log_status = vidioc_log_status,1704.vidioc_querymenu = vidioc_querymenu,1705.vidioc_queryctrl = vidioc_queryctrl,1706.vidioc_g_chip_ident = cx23885_g_chip_ident,1707#ifdef CONFIG_VIDEO_ADV_DEBUG1708.vidioc_g_register = cx23885_g_register,1709.vidioc_s_register = cx23885_s_register,1710#endif1711};17121713static struct video_device cx23885_mpeg_template = {1714.name = "cx23885",1715.fops = &mpeg_fops,1716.ioctl_ops = &mpeg_ioctl_ops,1717.tvnorms = CX23885_NORMS,1718.current_norm = V4L2_STD_NTSC_M,1719};17201721void cx23885_417_unregister(struct cx23885_dev *dev)1722{1723dprintk(1, "%s()\n", __func__);17241725if (dev->v4l_device) {1726if (video_is_registered(dev->v4l_device))1727video_unregister_device(dev->v4l_device);1728else1729video_device_release(dev->v4l_device);1730dev->v4l_device = NULL;1731}1732}17331734static struct video_device *cx23885_video_dev_alloc(1735struct cx23885_tsport *tsport,1736struct pci_dev *pci,1737struct video_device *template,1738char *type)1739{1740struct video_device *vfd;1741struct cx23885_dev *dev = tsport->dev;17421743dprintk(1, "%s()\n", __func__);17441745vfd = video_device_alloc();1746if (NULL == vfd)1747return NULL;1748*vfd = *template;1749snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,1750type, cx23885_boards[tsport->dev->board].name);1751vfd->parent = &pci->dev;1752vfd->release = video_device_release;1753return vfd;1754}17551756int cx23885_417_register(struct cx23885_dev *dev)1757{1758/* FIXME: Port1 hardcoded here */1759int err = -ENODEV;1760struct cx23885_tsport *tsport = &dev->ts1;17611762dprintk(1, "%s()\n", __func__);17631764if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)1765return err;17661767/* Set default TV standard */1768dev->encodernorm = cx23885_tvnorms[0];17691770if (dev->encodernorm.id & V4L2_STD_525_60)1771tsport->height = 480;1772else1773tsport->height = 576;17741775tsport->width = 720;1776cx2341x_fill_defaults(&dev->mpeg_params);17771778dev->mpeg_params.port = CX2341X_PORT_SERIAL;17791780/* Allocate and initialize V4L video device */1781dev->v4l_device = cx23885_video_dev_alloc(tsport,1782dev->pci, &cx23885_mpeg_template, "mpeg");1783video_set_drvdata(dev->v4l_device, dev);1784err = video_register_device(dev->v4l_device,1785VFL_TYPE_GRABBER, -1);1786if (err < 0) {1787printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);1788return err;1789}17901791printk(KERN_INFO "%s: registered device %s [mpeg]\n",1792dev->name, video_device_node_name(dev->v4l_device));17931794return 0;1795}179617971798