blob: 2c05c8f41527aa735d5fbfd8b3e5feee28a4da40 [file] [log] [blame]
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001/*
2 *
3 * Support for a cx23417 mpeg encoder via cx231xx host port.
4 *
5 * (c) 2004 Jelle Foks <jelle@foks.us>
6 * (c) 2004 Gerd Knorr <kraxel@bytesex.org>
7 * (c) 2008 Steven Toth <stoth@linuxtv.org>
8 * - CX23885/7/8 support
9 *
10 * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/module.h>
28#include <linux/moduleparam.h>
29#include <linux/init.h>
30#include <linux/fs.h>
31#include <linux/delay.h>
32#include <linux/device.h>
33#include <linux/firmware.h>
Stephen Rothwell94399432010-10-19 18:07:30 +110034#include <linux/vmalloc.h>
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030035#include <media/v4l2-common.h>
36#include <media/v4l2-ioctl.h>
37#include <media/cx2341x.h>
38#include <linux/usb.h>
39
40#include "cx231xx.h"
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030041
42#define CX231xx_FIRM_IMAGE_SIZE 376836
43#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
44
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -030045/* for polaris ITVC */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030046#define ITVC_WRITE_DIR 0x03FDFC00
47#define ITVC_READ_DIR 0x0001FC00
48
49#define MCI_MEMORY_DATA_BYTE0 0x00
50#define MCI_MEMORY_DATA_BYTE1 0x08
51#define MCI_MEMORY_DATA_BYTE2 0x10
52#define MCI_MEMORY_DATA_BYTE3 0x18
53
54#define MCI_MEMORY_ADDRESS_BYTE2 0x20
55#define MCI_MEMORY_ADDRESS_BYTE1 0x28
56#define MCI_MEMORY_ADDRESS_BYTE0 0x30
57
58#define MCI_REGISTER_DATA_BYTE0 0x40
59#define MCI_REGISTER_DATA_BYTE1 0x48
60#define MCI_REGISTER_DATA_BYTE2 0x50
61#define MCI_REGISTER_DATA_BYTE3 0x58
62
63#define MCI_REGISTER_ADDRESS_BYTE0 0x60
64#define MCI_REGISTER_ADDRESS_BYTE1 0x68
65
66#define MCI_REGISTER_MODE 0x70
67
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -030068/* Read and write modes for polaris ITVC */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030069#define MCI_MODE_REGISTER_READ 0x000
70#define MCI_MODE_REGISTER_WRITE 0x100
71#define MCI_MODE_MEMORY_READ 0x000
72#define MCI_MODE_MEMORY_WRITE 0x4000
73
74static unsigned int mpegbufs = 8;
75module_param(mpegbufs, int, 0644);
76MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
Hans Verkuil5b8acdc2013-01-29 12:59:50 -030077
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030078static unsigned int mpeglines = 128;
79module_param(mpeglines, int, 0644);
80MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
Hans Verkuil5b8acdc2013-01-29 12:59:50 -030081
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030082static unsigned int mpeglinesize = 512;
83module_param(mpeglinesize, int, 0644);
84MODULE_PARM_DESC(mpeglinesize,
85 "number of bytes in each line of an MPEG buffer, range 512-1024");
86
87static unsigned int v4l_debug = 1;
88module_param(v4l_debug, int, 0644);
89MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
Hans Verkuil5b8acdc2013-01-29 12:59:50 -030090
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030091#define dprintk(level, fmt, arg...)\
92 do { if (v4l_debug >= level) \
Hans Verkuil5b8acdc2013-01-29 12:59:50 -030093 pr_info("%s: " fmt, \
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -030094 (dev) ? dev->name : "cx231xx[?]", ## arg); \
95 } while (0)
96
97static struct cx231xx_tvnorm cx231xx_tvnorms[] = {
98 {
99 .name = "NTSC-M",
100 .id = V4L2_STD_NTSC_M,
101 }, {
102 .name = "NTSC-JP",
103 .id = V4L2_STD_NTSC_M_JP,
104 }, {
105 .name = "PAL-BG",
106 .id = V4L2_STD_PAL_BG,
107 }, {
108 .name = "PAL-DK",
109 .id = V4L2_STD_PAL_DK,
110 }, {
111 .name = "PAL-I",
112 .id = V4L2_STD_PAL_I,
113 }, {
114 .name = "PAL-M",
115 .id = V4L2_STD_PAL_M,
116 }, {
117 .name = "PAL-N",
118 .id = V4L2_STD_PAL_N,
119 }, {
120 .name = "PAL-Nc",
121 .id = V4L2_STD_PAL_Nc,
122 }, {
123 .name = "PAL-60",
124 .id = V4L2_STD_PAL_60,
125 }, {
126 .name = "SECAM-L",
127 .id = V4L2_STD_SECAM_L,
128 }, {
129 .name = "SECAM-DK",
130 .id = V4L2_STD_SECAM_DK,
131 }
132};
133
134/* ------------------------------------------------------------------ */
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300135
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300136enum cx231xx_capture_type {
137 CX231xx_MPEG_CAPTURE,
138 CX231xx_RAW_CAPTURE,
139 CX231xx_RAW_PASSTHRU_CAPTURE
140};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300141
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300142enum cx231xx_capture_bits {
143 CX231xx_RAW_BITS_NONE = 0x00,
144 CX231xx_RAW_BITS_YUV_CAPTURE = 0x01,
145 CX231xx_RAW_BITS_PCM_CAPTURE = 0x02,
146 CX231xx_RAW_BITS_VBI_CAPTURE = 0x04,
147 CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
148 CX231xx_RAW_BITS_TO_HOST_CAPTURE = 0x10
149};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300150
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300151enum cx231xx_capture_end {
152 CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */
153 CX231xx_END_NOW, /* stop immediately, no irq */
154};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300155
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300156enum cx231xx_framerate {
157 CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */
158 CX231xx_FRAMERATE_PAL_25 /* PAL: 25fps */
159};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300160
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300161enum cx231xx_stream_port {
162 CX231xx_OUTPUT_PORT_MEMORY,
163 CX231xx_OUTPUT_PORT_STREAMING,
164 CX231xx_OUTPUT_PORT_SERIAL
165};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300166
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300167enum cx231xx_data_xfer_status {
168 CX231xx_MORE_BUFFERS_FOLLOW,
169 CX231xx_LAST_BUFFER,
170};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300171
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300172enum cx231xx_picture_mask {
173 CX231xx_PICTURE_MASK_NONE,
174 CX231xx_PICTURE_MASK_I_FRAMES,
175 CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3,
176 CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7,
177};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300178
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300179enum cx231xx_vbi_mode_bits {
180 CX231xx_VBI_BITS_SLICED,
181 CX231xx_VBI_BITS_RAW,
182};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300183
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300184enum cx231xx_vbi_insertion_bits {
185 CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
186 CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
187 CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
188 CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
189 CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
190};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300191
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300192enum cx231xx_dma_unit {
193 CX231xx_DMA_BYTES,
194 CX231xx_DMA_FRAMES,
195};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300196
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300197enum cx231xx_dma_transfer_status_bits {
198 CX231xx_DMA_TRANSFER_BITS_DONE = 0x01,
199 CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04,
200 CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
201};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300202
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300203enum cx231xx_pause {
204 CX231xx_PAUSE_ENCODING,
205 CX231xx_RESUME_ENCODING,
206};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300207
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300208enum cx231xx_copyright {
209 CX231xx_COPYRIGHT_OFF,
210 CX231xx_COPYRIGHT_ON,
211};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300212
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300213enum cx231xx_notification_type {
214 CX231xx_NOTIFICATION_REFRESH,
215};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300216
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300217enum cx231xx_notification_status {
218 CX231xx_NOTIFICATION_OFF,
219 CX231xx_NOTIFICATION_ON,
220};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300221
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300222enum cx231xx_notification_mailbox {
223 CX231xx_NOTIFICATION_NO_MAILBOX = -1,
224};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300225
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300226enum cx231xx_field1_lines {
227 CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */
228 CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */
229 CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */
230};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300231
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300232enum cx231xx_field2_lines {
233 CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */
234 CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */
235 CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */
236};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300237
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300238enum cx231xx_custom_data_type {
239 CX231xx_CUSTOM_EXTENSION_USR_DATA,
240 CX231xx_CUSTOM_PRIVATE_PACKET,
241};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300242
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300243enum cx231xx_mute {
244 CX231xx_UNMUTE,
245 CX231xx_MUTE,
246};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300247
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300248enum cx231xx_mute_video_mask {
249 CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00,
250 CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000,
251 CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000,
252};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300253
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300254enum cx231xx_mute_video_shift {
255 CX231xx_MUTE_VIDEO_V_SHIFT = 8,
256 CX231xx_MUTE_VIDEO_U_SHIFT = 16,
257 CX231xx_MUTE_VIDEO_Y_SHIFT = 24,
258};
259
260/* defines below are from ivtv-driver.h */
261#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
262
263/* Firmware API commands */
264#define IVTV_API_STD_TIMEOUT 500
265
266/* Registers */
267/* IVTV_REG_OFFSET */
268#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
269#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
270#define IVTV_REG_SPU (0x9050)
271#define IVTV_REG_HW_BLOCKS (0x9054)
272#define IVTV_REG_VPU (0x9058)
273#define IVTV_REG_APU (0xA064)
274
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300275/*
276 * Bit definitions for MC417_RWD and MC417_OEN registers
277 *
278 * bits 31-16
279 *+-----------+
280 *| Reserved |
281 *|+-----------+
282 *| bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8
283 *|+-------+-------+-------+-------+-------+-------+-------+-------+
284 *|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
285 *|+-------+-------+-------+-------+-------+-------+-------+-------+
286 *| bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
287 *|+-------+-------+-------+-------+-------+-------+-------+-------+
288 *||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
289 *|+-------+-------+-------+-------+-------+-------+-------+-------+
290 */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300291#define MC417_MIWR 0x8000
292#define MC417_MIRD 0x4000
293#define MC417_MICS 0x2000
294#define MC417_MIRDY 0x1000
295#define MC417_MIADDR 0x0F00
296#define MC417_MIDATA 0x00FF
297
298
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300299/* Bit definitions for MC417_CTL register ****
300 *bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0
301 *+--------+-------------+--------+--------------+------------+
302 *|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
303 *+--------+-------------+--------+--------------+------------+
304 */
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300305#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030)
306#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006)
307#define MC417_UART_GPIO_EN 0x00000001
308
309/* Values for speed control */
310#define MC417_SPD_CTL_SLOW 0x1
311#define MC417_SPD_CTL_MEDIUM 0x0
312#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */
313
314/* Values for GPIO select */
315#define MC417_GPIO_SEL_GPIO3 0x3
316#define MC417_GPIO_SEL_GPIO2 0x2
317#define MC417_GPIO_SEL_GPIO1 0x1
318#define MC417_GPIO_SEL_GPIO0 0x0
319
320
321#define CX23417_GPIO_MASK 0xFC0003FF
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300322
323static int set_itvc_reg(struct cx231xx *dev, u32 gpio_direction, u32 value)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300324{
325 int status = 0;
326 u32 _gpio_direction = 0;
327
328 _gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300329 _gpio_direction = _gpio_direction | gpio_direction;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300330 status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
331 (u8 *)&value, 4, 0, 0);
332 return status;
333}
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300334
335static int get_itvc_reg(struct cx231xx *dev, u32 gpio_direction, u32 *val_ptr)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300336{
337 int status = 0;
338 u32 _gpio_direction = 0;
339
340 _gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300341 _gpio_direction = _gpio_direction | gpio_direction;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300342
343 status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300344 (u8 *)val_ptr, 4, 0, 1);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300345 return status;
346}
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -0300347
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300348static int wait_for_mci_complete(struct cx231xx *dev)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300349{
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300350 u32 gpio;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300351 u32 gpio_direction = 0;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300352 u8 count = 0;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300353 get_itvc_reg(dev, gpio_direction, &gpio);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300354
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300355 while (!(gpio&0x020000)) {
356 msleep(10);
357
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300358 get_itvc_reg(dev, gpio_direction, &gpio);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300359
360 if (count++ > 100) {
361 dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio);
362 return -1;
363 }
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300364 }
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300365 return 0;
366}
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300367
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -0300368static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300369{
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300370 u32 temp;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300371 int status = 0;
372
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300373 temp = 0x82 | MCI_REGISTER_DATA_BYTE0 | ((value & 0x000000FF) << 8);
374 temp = temp << 10;
375 status = set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300376 if (status < 0)
377 return status;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300378 temp = temp | (0x05 << 10);
379 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300380
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300381 /*write data byte 1;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300382 temp = 0x82 | MCI_REGISTER_DATA_BYTE1 | (value & 0x0000FF00);
383 temp = temp << 10;
384 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
385 temp = temp | (0x05 << 10);
386 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300387
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300388 /*write data byte 2;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300389 temp = 0x82 | MCI_REGISTER_DATA_BYTE2 | ((value & 0x00FF0000) >> 8);
390 temp = temp << 10;
391 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
392 temp = temp | (0x05 << 10);
393 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300394
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300395 /*write data byte 3;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300396 temp = 0x82 | MCI_REGISTER_DATA_BYTE3 | ((value & 0xFF000000) >> 16);
397 temp = temp << 10;
398 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
399 temp = temp | (0x05 << 10);
400 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300401
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300402 /*write address byte 0;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300403 temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x000000FF) << 8);
404 temp = temp << 10;
405 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
406 temp = temp | (0x05 << 10);
407 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300408
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300409 /*write address byte 1;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300410 temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0x0000FF00);
411 temp = temp << 10;
412 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
413 temp = temp | (0x05 << 10);
414 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300415
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300416 /*Write that the mode is write.*/
417 temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300418 temp = temp << 10;
419 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
420 temp = temp | (0x05 << 10);
421 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300422
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300423 return wait_for_mci_complete(dev);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300424}
425
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -0300426static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300427{
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300428 /*write address byte 0;*/
429 u32 temp;
430 u32 return_value = 0;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300431 int ret = 0;
432
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300433 temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
434 temp = temp << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300435 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300436 temp = temp | ((0x05) << 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300437 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300438
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300439 /*write address byte 1;*/
440 temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00);
441 temp = temp << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300442 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300443 temp = temp | ((0x05) << 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300444 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300445
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300446 /*write that the mode is read;*/
447 temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ;
448 temp = temp << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300449 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300450 temp = temp | ((0x05) << 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300451 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300452
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300453 /*wait for the MIRDY line to be asserted ,
454 signalling that the read is done;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300455 ret = wait_for_mci_complete(dev);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300456
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300457 /*switch the DATA- GPIO to input mode;*/
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300458
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300459 /*Read data byte 0;*/
460 temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300461 set_itvc_reg(dev, ITVC_READ_DIR, temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300462 temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300463 set_itvc_reg(dev, ITVC_READ_DIR, temp);
464 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300465 return_value |= ((temp & 0x03FC0000) >> 18);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300466 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300467
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300468 /* Read data byte 1;*/
469 temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300470 set_itvc_reg(dev, ITVC_READ_DIR, temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300471 temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300472 set_itvc_reg(dev, ITVC_READ_DIR, temp);
473 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300474
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300475 return_value |= ((temp & 0x03FC0000) >> 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300476 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300477
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300478 /*Read data byte 2;*/
479 temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300480 set_itvc_reg(dev, ITVC_READ_DIR, temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300481 temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300482 set_itvc_reg(dev, ITVC_READ_DIR, temp);
483 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300484 return_value |= ((temp & 0x03FC0000) >> 2);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300485 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300486
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300487 /*Read data byte 3;*/
488 temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300489 set_itvc_reg(dev, ITVC_READ_DIR, temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300490 temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300491 set_itvc_reg(dev, ITVC_READ_DIR, temp);
492 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300493 return_value |= ((temp & 0x03FC0000) << 6);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300494 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300495
496 *value = return_value;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300497 return ret;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300498}
499
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -0300500static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300501{
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300502 /*write data byte 0;*/
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300503
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300504 u32 temp;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300505 int ret = 0;
506
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300507 temp = 0x82 | MCI_MEMORY_DATA_BYTE0 | ((value & 0x000000FF) << 8);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300508 temp = temp << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300509 ret = set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300510 if (ret < 0)
511 return ret;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300512 temp = temp | (0x05 << 10);
513 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300514
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300515 /*write data byte 1;*/
516 temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00);
517 temp = temp << 10;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300518 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
519 temp = temp | (0x05 << 10);
520 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300521
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300522 /*write data byte 2;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300523 temp = 0x82 | MCI_MEMORY_DATA_BYTE2 | ((value & 0x00FF0000) >> 8);
524 temp = temp << 10;
525 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
526 temp = temp | (0x05 << 10);
527 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300528
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300529 /*write data byte 3;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300530 temp = 0x82 | MCI_MEMORY_DATA_BYTE3 | ((value & 0xFF000000) >> 16);
531 temp = temp << 10;
532 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
533 temp = temp | (0x05 << 10);
534 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300535
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300536 /* write address byte 2;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300537 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
538 ((address & 0x003F0000) >> 8);
539 temp = temp << 10;
540 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
541 temp = temp | (0x05 << 10);
542 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300543
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300544 /* write address byte 1;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300545 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
546 temp = temp << 10;
547 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
548 temp = temp | (0x05 << 10);
549 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300550
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300551 /* write address byte 0;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300552 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
553 temp = temp << 10;
554 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
555 temp = temp | (0x05 << 10);
556 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300557
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300558 /*wait for MIRDY line;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300559 wait_for_mci_complete(dev);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300560
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300561 return 0;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300562}
563
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -0300564static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300565{
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300566 u32 temp = 0;
567 u32 return_value = 0;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300568 int ret = 0;
569
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300570 /*write address byte 2;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300571 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ |
572 ((address & 0x003F0000) >> 8);
573 temp = temp << 10;
574 ret = set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300575 if (ret < 0)
576 return ret;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300577 temp = temp | (0x05 << 10);
578 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300579
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300580 /*write address byte 1*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300581 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
582 temp = temp << 10;
583 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
584 temp = temp | (0x05 << 10);
585 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300586
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300587 /*write address byte 0*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300588 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
589 temp = temp << 10;
590 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
591 temp = temp | (0x05 << 10);
592 set_itvc_reg(dev, ITVC_WRITE_DIR, temp);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300593
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300594 /*Wait for MIRDY line*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300595 ret = wait_for_mci_complete(dev);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300596
597
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300598 /*Read data byte 3;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300599 temp = (0x82 | MCI_MEMORY_DATA_BYTE3) << 10;
600 set_itvc_reg(dev, ITVC_READ_DIR, temp);
601 temp = ((0x81 | MCI_MEMORY_DATA_BYTE3) << 10);
602 set_itvc_reg(dev, ITVC_READ_DIR, temp);
603 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
604 return_value |= ((temp & 0x03FC0000) << 6);
605 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300606
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300607 /*Read data byte 2;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300608 temp = (0x82 | MCI_MEMORY_DATA_BYTE2) << 10;
609 set_itvc_reg(dev, ITVC_READ_DIR, temp);
610 temp = ((0x81 | MCI_MEMORY_DATA_BYTE2) << 10);
611 set_itvc_reg(dev, ITVC_READ_DIR, temp);
612 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
613 return_value |= ((temp & 0x03FC0000) >> 2);
614 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300615
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300616 /* Read data byte 1;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300617 temp = (0x82 | MCI_MEMORY_DATA_BYTE1) << 10;
618 set_itvc_reg(dev, ITVC_READ_DIR, temp);
619 temp = ((0x81 | MCI_MEMORY_DATA_BYTE1) << 10);
620 set_itvc_reg(dev, ITVC_READ_DIR, temp);
621 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
622 return_value |= ((temp & 0x03FC0000) >> 10);
623 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300624
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300625 /*Read data byte 0;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300626 temp = (0x82 | MCI_MEMORY_DATA_BYTE0) << 10;
627 set_itvc_reg(dev, ITVC_READ_DIR, temp);
628 temp = ((0x81 | MCI_MEMORY_DATA_BYTE0) << 10);
629 set_itvc_reg(dev, ITVC_READ_DIR, temp);
630 get_itvc_reg(dev, ITVC_READ_DIR, &temp);
631 return_value |= ((temp & 0x03FC0000) >> 18);
632 set_itvc_reg(dev, ITVC_READ_DIR, (0x87 << 10));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300633
634 *value = return_value;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300635 return ret;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300636}
637
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300638/* ------------------------------------------------------------------ */
639
640/* MPEG encoder API */
641static char *cmd_to_str(int cmd)
642{
643 switch (cmd) {
644 case CX2341X_ENC_PING_FW:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300645 return "PING_FW";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300646 case CX2341X_ENC_START_CAPTURE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300647 return "START_CAPTURE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300648 case CX2341X_ENC_STOP_CAPTURE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300649 return "STOP_CAPTURE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300650 case CX2341X_ENC_SET_AUDIO_ID:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300651 return "SET_AUDIO_ID";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300652 case CX2341X_ENC_SET_VIDEO_ID:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300653 return "SET_VIDEO_ID";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300654 case CX2341X_ENC_SET_PCR_ID:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300655 return "SET_PCR_PID";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300656 case CX2341X_ENC_SET_FRAME_RATE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300657 return "SET_FRAME_RATE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300658 case CX2341X_ENC_SET_FRAME_SIZE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300659 return "SET_FRAME_SIZE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300660 case CX2341X_ENC_SET_BIT_RATE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300661 return "SET_BIT_RATE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300662 case CX2341X_ENC_SET_GOP_PROPERTIES:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300663 return "SET_GOP_PROPERTIES";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300664 case CX2341X_ENC_SET_ASPECT_RATIO:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300665 return "SET_ASPECT_RATIO";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300666 case CX2341X_ENC_SET_DNR_FILTER_MODE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300667 return "SET_DNR_FILTER_PROPS";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300668 case CX2341X_ENC_SET_DNR_FILTER_PROPS:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300669 return "SET_DNR_FILTER_PROPS";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300670 case CX2341X_ENC_SET_CORING_LEVELS:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300671 return "SET_CORING_LEVELS";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300672 case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300673 return "SET_SPATIAL_FILTER_TYPE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300674 case CX2341X_ENC_SET_VBI_LINE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300675 return "SET_VBI_LINE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300676 case CX2341X_ENC_SET_STREAM_TYPE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300677 return "SET_STREAM_TYPE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300678 case CX2341X_ENC_SET_OUTPUT_PORT:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300679 return "SET_OUTPUT_PORT";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300680 case CX2341X_ENC_SET_AUDIO_PROPERTIES:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300681 return "SET_AUDIO_PROPERTIES";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300682 case CX2341X_ENC_HALT_FW:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300683 return "HALT_FW";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300684 case CX2341X_ENC_GET_VERSION:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300685 return "GET_VERSION";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300686 case CX2341X_ENC_SET_GOP_CLOSURE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300687 return "SET_GOP_CLOSURE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300688 case CX2341X_ENC_GET_SEQ_END:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300689 return "GET_SEQ_END";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300690 case CX2341X_ENC_SET_PGM_INDEX_INFO:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300691 return "SET_PGM_INDEX_INFO";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300692 case CX2341X_ENC_SET_VBI_CONFIG:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300693 return "SET_VBI_CONFIG";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300694 case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300695 return "SET_DMA_BLOCK_SIZE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300696 case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300697 return "GET_PREV_DMA_INFO_MB_10";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300698 case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300699 return "GET_PREV_DMA_INFO_MB_9";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300700 case CX2341X_ENC_SCHED_DMA_TO_HOST:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300701 return "SCHED_DMA_TO_HOST";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300702 case CX2341X_ENC_INITIALIZE_INPUT:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300703 return "INITIALIZE_INPUT";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300704 case CX2341X_ENC_SET_FRAME_DROP_RATE:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300705 return "SET_FRAME_DROP_RATE";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300706 case CX2341X_ENC_PAUSE_ENCODER:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300707 return "PAUSE_ENCODER";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300708 case CX2341X_ENC_REFRESH_INPUT:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300709 return "REFRESH_INPUT";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300710 case CX2341X_ENC_SET_COPYRIGHT:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300711 return "SET_COPYRIGHT";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300712 case CX2341X_ENC_SET_EVENT_NOTIFICATION:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300713 return "SET_EVENT_NOTIFICATION";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300714 case CX2341X_ENC_SET_NUM_VSYNC_LINES:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300715 return "SET_NUM_VSYNC_LINES";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300716 case CX2341X_ENC_SET_PLACEHOLDER:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300717 return "SET_PLACEHOLDER";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300718 case CX2341X_ENC_MUTE_VIDEO:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300719 return "MUTE_VIDEO";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300720 case CX2341X_ENC_MUTE_AUDIO:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300721 return "MUTE_AUDIO";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300722 case CX2341X_ENC_MISC:
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300723 return "MISC";
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300724 default:
725 return "UNKNOWN";
726 }
727}
728
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300729static int cx231xx_mbox_func(void *priv, u32 command, int in, int out,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300730 u32 data[CX2341X_MBOX_MAX_DATA])
731{
732 struct cx231xx *dev = priv;
733 unsigned long timeout;
734 u32 value, flag, retval = 0;
735 int i;
736
737 dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
738 cmd_to_str(command));
739
740 /* this may not be 100% safe if we can't read any memory location
741 without side effects */
742 mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
743 if (value != 0x12345678) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300744 dprintk(3, "Firmware and/or mailbox pointer not initialized or corrupted, signature = 0x%x, cmd = %s\n",
745 value, cmd_to_str(command));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300746 return -1;
747 }
748
749 /* This read looks at 32 bits, but flag is only 8 bits.
750 * Seems we also bail if CMD or TIMEOUT bytes are set???
751 */
752 mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
753 if (flag) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300754 dprintk(3, "ERROR: Mailbox appears to be in use (%x), cmd = %s\n",
755 flag, cmd_to_str(command));
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300756 return -1;
757 }
758
759 flag |= 1; /* tell 'em we're working on it */
760 mc417_memory_write(dev, dev->cx23417_mailbox, flag);
761
762 /* write command + args + fill remaining with zeros */
763 /* command code */
764 mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
765 mc417_memory_write(dev, dev->cx23417_mailbox + 3,
766 IVTV_API_STD_TIMEOUT); /* timeout */
767 for (i = 0; i < in; i++) {
768 mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
769 dprintk(3, "API Input %d = %d\n", i, data[i]);
770 }
771 for (; i < CX2341X_MBOX_MAX_DATA; i++)
772 mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
773
774 flag |= 3; /* tell 'em we're done writing */
775 mc417_memory_write(dev, dev->cx23417_mailbox, flag);
776
777 /* wait for firmware to handle the API command */
778 timeout = jiffies + msecs_to_jiffies(10);
779 for (;;) {
780 mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
781 if (0 != (flag & 4))
782 break;
783 if (time_after(jiffies, timeout)) {
784 dprintk(3, "ERROR: API Mailbox timeout\n");
785 return -1;
786 }
787 udelay(10);
788 }
789
790 /* read output values */
791 for (i = 0; i < out; i++) {
792 mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
793 dprintk(3, "API Output %d = %d\n", i, data[i]);
794 }
795
796 mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
797 dprintk(3, "API result = %d\n", retval);
798
799 flag = 0;
800 mc417_memory_write(dev, dev->cx23417_mailbox, flag);
801
802 return retval;
803}
804
805/* We don't need to call the API often, so using just one
806 * mailbox will probably suffice
807 */
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300808static int cx231xx_api_cmd(struct cx231xx *dev, u32 command,
809 u32 inputcnt, u32 outputcnt, ...)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300810{
811 u32 data[CX2341X_MBOX_MAX_DATA];
812 va_list vargs;
813 int i, err;
814
815 dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
816
817 va_start(vargs, outputcnt);
818 for (i = 0; i < inputcnt; i++)
819 data[i] = va_arg(vargs, int);
820
821 err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data);
822 for (i = 0; i < outputcnt; i++) {
823 int *vptr = va_arg(vargs, int *);
824 *vptr = data[i];
825 }
826 va_end(vargs);
827
828 return err;
829}
830
831static int cx231xx_find_mailbox(struct cx231xx *dev)
832{
833 u32 signature[4] = {
834 0x12345678, 0x34567812, 0x56781234, 0x78123456
835 };
836 int signaturecnt = 0;
837 u32 value;
838 int i;
839 int ret = 0;
840
841 dprintk(2, "%s()\n", __func__);
842
843 for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/
844 ret = mc417_memory_read(dev, i, &value);
845 if (ret < 0)
846 return ret;
847 if (value == signature[signaturecnt])
848 signaturecnt++;
849 else
850 signaturecnt = 0;
851 if (4 == signaturecnt) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300852 dprintk(1, "Mailbox signature found at 0x%x\n", i + 1);
853 return i + 1;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300854 }
855 }
856 dprintk(3, "Mailbox signature values not found!\n");
857 return -1;
858}
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -0300859
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300860static void mci_write_memory_to_gpio(struct cx231xx *dev, u32 address, u32 value,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300861 u32 *p_fw_image)
862{
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300863 u32 temp = 0;
864 int i = 0;
865
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300866 temp = 0x82 | MCI_MEMORY_DATA_BYTE0 | ((value & 0x000000FF) << 8);
867 temp = temp << 10;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300868 *p_fw_image = temp;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300869 p_fw_image++;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300870 temp = temp | (0x05 << 10);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300871 *p_fw_image = temp;
872 p_fw_image++;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300873
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300874 /*write data byte 1;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300875 temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00);
876 temp = temp << 10;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300877 *p_fw_image = temp;
878 p_fw_image++;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300879 temp = temp | (0x05 << 10);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300880 *p_fw_image = temp;
881 p_fw_image++;
882
883 /*write data byte 2;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300884 temp = 0x82 | MCI_MEMORY_DATA_BYTE2 | ((value & 0x00FF0000) >> 8);
885 temp = temp << 10;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300886 *p_fw_image = temp;
887 p_fw_image++;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300888 temp = temp | (0x05 << 10);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300889 *p_fw_image = temp;
890 p_fw_image++;
891
892 /*write data byte 3;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300893 temp = 0x82 | MCI_MEMORY_DATA_BYTE3 | ((value & 0xFF000000) >> 16);
894 temp = temp << 10;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300895 *p_fw_image = temp;
896 p_fw_image++;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300897 temp = temp | (0x05 << 10);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300898 *p_fw_image = temp;
899 p_fw_image++;
900
901 /* write address byte 2;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300902 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
903 ((address & 0x003F0000) >> 8);
904 temp = temp << 10;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300905 *p_fw_image = temp;
906 p_fw_image++;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300907 temp = temp | (0x05 << 10);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300908 *p_fw_image = temp;
909 p_fw_image++;
910
911 /* write address byte 1;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300912 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
913 temp = temp << 10;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300914 *p_fw_image = temp;
915 p_fw_image++;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300916 temp = temp | (0x05 << 10);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300917 *p_fw_image = temp;
918 p_fw_image++;
919
920 /* write address byte 0;*/
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300921 temp = 0x82 | MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
922 temp = temp << 10;
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300923 *p_fw_image = temp;
924 p_fw_image++;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300925 temp = temp | (0x05 << 10);
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -0300926 *p_fw_image = temp;
927 p_fw_image++;
928
929 for (i = 0; i < 6; i++) {
930 *p_fw_image = 0xFFFFFFFF;
931 p_fw_image++;
932 }
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300933}
934
935
936static int cx231xx_load_firmware(struct cx231xx *dev)
937{
938 static const unsigned char magic[8] = {
939 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
940 };
941 const struct firmware *firmware;
942 int i, retval = 0;
943 u32 value = 0;
944 u32 gpio_output = 0;
945 /*u32 checksum = 0;*/
946 /*u32 *dataptr;*/
947 u32 transfer_size = 0;
948 u32 fw_data = 0;
949 u32 address = 0;
950 /*u32 current_fw[800];*/
951 u32 *p_current_fw, *p_fw;
952 u32 *p_fw_data;
953 int frame = 0;
954 u16 _buffer_size = 4096;
955 u8 *p_buffer;
956
Jesper Juhl9a9dcb42010-11-08 20:08:41 -0300957 p_current_fw = vmalloc(1884180 * 4);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300958 p_fw = p_current_fw;
Peter Huewef72cfd82011-01-25 17:38:52 -0300959 if (p_current_fw == NULL) {
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300960 dprintk(2, "FAIL!!!\n");
961 return -1;
962 }
963
Jesper Juhl9a9dcb42010-11-08 20:08:41 -0300964 p_buffer = vmalloc(4096);
Peter Huewef72cfd82011-01-25 17:38:52 -0300965 if (p_buffer == NULL) {
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300966 dprintk(2, "FAIL!!!\n");
967 return -1;
968 }
969
970 dprintk(2, "%s()\n", __func__);
971
972 /* Save GPIO settings before reset of APU */
973 retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
974 retval |= mc417_memory_read(dev, 0x900C, &value);
975
976 retval = mc417_register_write(dev,
977 IVTV_REG_VPU, 0xFFFFFFED);
978 retval |= mc417_register_write(dev,
979 IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
980 retval |= mc417_register_write(dev,
981 IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
982 retval |= mc417_register_write(dev,
983 IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
984 retval |= mc417_register_write(dev,
985 IVTV_REG_APU, 0);
986
987 if (retval != 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300988 pr_err("%s: Error with mc417_register_write\n", __func__);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300989 return -1;
990 }
991
992 retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,
993 &dev->udev->dev);
994
995 if (retval != 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300996 pr_err("ERROR: Hotplug firmware request failed (%s).\n",
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300997 CX231xx_FIRM_IMAGE_NAME);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -0300998 pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -0300999 return -1;
1000 }
1001
1002 if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001003 pr_err("ERROR: Firmware size mismatch (have %zd, expected %d)\n",
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001004 firmware->size, CX231xx_FIRM_IMAGE_SIZE);
1005 release_firmware(firmware);
1006 return -1;
1007 }
1008
1009 if (0 != memcmp(firmware->data, magic, 8)) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001010 pr_err("ERROR: Firmware magic mismatch, wrong file?\n");
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001011 release_firmware(firmware);
1012 return -1;
1013 }
1014
1015 initGPIO(dev);
1016
1017 /* transfer to the chip */
1018 dprintk(2, "Loading firmware to GPIO...\n");
1019 p_fw_data = (u32 *)firmware->data;
Mauro Carvalho Chehab62c78c92010-09-25 23:46:08 -03001020 dprintk(2, "firmware->size=%zd\n", firmware->size);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001021 for (transfer_size = 0; transfer_size < firmware->size;
1022 transfer_size += 4) {
1023 fw_data = *p_fw_data;
1024
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001025 mci_write_memory_to_gpio(dev, address, fw_data, p_current_fw);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001026 address = address + 1;
1027 p_current_fw += 20;
1028 p_fw_data += 1;
1029 }
1030
Mauro Carvalho Chehab955e6ed2010-10-07 03:23:25 -03001031 /*download the firmware by ep5-out*/
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001032
1033 for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size);
Mauro Carvalho Chehabbae94dc2010-10-07 03:33:00 -03001034 frame++) {
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001035 for (i = 0; i < _buffer_size; i++) {
Mauro Carvalho Chehabbae94dc2010-10-07 03:33:00 -03001036 *(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF);
1037 i++;
1038 *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8);
1039 i++;
1040 *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16);
1041 i++;
1042 *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001043 }
1044 cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size);
1045 }
1046
1047 p_current_fw = p_fw;
1048 vfree(p_current_fw);
1049 p_current_fw = NULL;
1050 uninitGPIO(dev);
1051 release_firmware(firmware);
1052 dprintk(1, "Firmware upload successful.\n");
1053
1054 retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
1055 IVTV_CMD_HW_BLOCKS_RST);
1056 if (retval < 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001057 pr_err("%s: Error with mc417_register_write\n",
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001058 __func__);
1059 return retval;
1060 }
1061 /* F/W power up disturbs the GPIOs, restore state */
1062 retval |= mc417_register_write(dev, 0x9020, gpio_output);
1063 retval |= mc417_register_write(dev, 0x900C, value);
1064
1065 retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
1066 retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
1067
1068 if (retval < 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001069 pr_err("%s: Error with mc417_register_write\n",
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001070 __func__);
1071 return retval;
1072 }
1073 return 0;
1074}
1075
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -03001076static void cx231xx_417_check_encoder(struct cx231xx *dev)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001077{
1078 u32 status, seq;
1079
1080 status = 0;
1081 seq = 0;
1082 cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
1083 dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
1084}
1085
1086static void cx231xx_codec_settings(struct cx231xx *dev)
1087{
1088 dprintk(1, "%s()\n", __func__);
1089
1090 /* assign frame size */
1091 cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
1092 dev->ts1.height, dev->ts1.width);
1093
1094 dev->mpeg_params.width = dev->ts1.width;
1095 dev->mpeg_params.height = dev->ts1.height;
1096
1097 cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params);
1098
1099 cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
1100 cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
1101}
1102
1103static int cx231xx_initialize_codec(struct cx231xx *dev)
1104{
1105 int version;
1106 int retval;
Hans Verkuilda983502012-05-14 10:14:53 -03001107 u32 i;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001108 u32 val = 0;
1109
1110 dprintk(1, "%s()\n", __func__);
1111 cx231xx_disable656(dev);
1112 retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
1113 if (retval < 0) {
1114 dprintk(2, "%s() PING OK\n", __func__);
1115 retval = cx231xx_load_firmware(dev);
1116 if (retval < 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001117 pr_err("%s() f/w load failed\n", __func__);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001118 return retval;
1119 }
1120 retval = cx231xx_find_mailbox(dev);
1121 if (retval < 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001122 pr_err("%s() mailbox < 0, error\n",
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001123 __func__);
1124 return -1;
1125 }
1126 dev->cx23417_mailbox = retval;
1127 retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
1128 if (retval < 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001129 pr_err("ERROR: cx23417 firmware ping failed!\n");
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001130 return -1;
1131 }
1132 retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
1133 &version);
1134 if (retval < 0) {
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001135 pr_err("ERROR: cx23417 firmware get encoder: version failed!\n");
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001136 return -1;
1137 }
1138 dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
1139 msleep(200);
1140 }
1141
1142 for (i = 0; i < 1; i++) {
1143 retval = mc417_register_read(dev, 0x20f8, &val);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001144 dprintk(3, "***before enable656() VIM Capture Lines = %d ***\n",
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001145 val);
1146 if (retval < 0)
1147 return retval;
1148 }
1149
1150 cx231xx_enable656(dev);
1151 /* stop mpeg capture */
1152 cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE,
1153 3, 0, 1, 3, 4);
1154
1155 cx231xx_codec_settings(dev);
1156 msleep(60);
1157
1158/* cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
1159 CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115);
1160 cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
1161 CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1162 0, 0);
1163*/
Hans Verkuilda983502012-05-14 10:14:53 -03001164
1165#if 0
1166 /* TODO */
1167 u32 data[7];
1168
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001169 /* Setup to capture VBI */
1170 data[0] = 0x0001BD00;
1171 data[1] = 1; /* frames per interrupt */
1172 data[2] = 4; /* total bufs */
1173 data[3] = 0x91559155; /* start codes */
1174 data[4] = 0x206080C0; /* stop codes */
1175 data[5] = 6; /* lines */
1176 data[6] = 64; /* BPL */
Hans Verkuilda983502012-05-14 10:14:53 -03001177
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001178 cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
1179 data[2], data[3], data[4], data[5], data[6]);
1180
1181 for (i = 2; i <= 24; i++) {
1182 int valid;
1183
1184 valid = ((i >= 19) && (i <= 21));
1185 cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
1186 valid, 0 , 0, 0);
1187 cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
1188 i | 0x80000000, valid, 0, 0, 0);
1189 }
Hans Verkuilda983502012-05-14 10:14:53 -03001190#endif
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001191/* cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE);
1192 msleep(60);
1193*/
1194 /* initialize the video input */
1195 retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
1196 if (retval < 0)
1197 return retval;
1198 msleep(60);
1199
1200 /* Enable VIP style pixel invalidation so we work with scaled mode */
1201 mc417_memory_write(dev, 2120, 0x00000080);
1202
1203 /* start capturing to the host interface */
1204 retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
1205 CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE);
1206 if (retval < 0)
1207 return retval;
1208 msleep(10);
1209
1210 for (i = 0; i < 1; i++) {
1211 mc417_register_read(dev, 0x20f8, &val);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001212 dprintk(3, "***VIM Capture Lines =%d ***\n", val);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001213 }
1214
1215 return 0;
1216}
1217
1218/* ------------------------------------------------------------------ */
1219
1220static int bb_buf_setup(struct videobuf_queue *q,
1221 unsigned int *count, unsigned int *size)
1222{
1223 struct cx231xx_fh *fh = q->priv_data;
1224
1225 fh->dev->ts1.ts_packet_size = mpeglinesize;
1226 fh->dev->ts1.ts_packet_count = mpeglines;
1227
1228 *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
1229 *count = mpegbufs;
1230
1231 return 0;
1232}
Hans Verkuil5aa95992013-01-29 13:02:15 -03001233
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001234static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
1235{
1236 struct cx231xx_fh *fh = vq->priv_data;
1237 struct cx231xx *dev = fh->dev;
1238 unsigned long flags = 0;
1239
1240 if (in_interrupt())
1241 BUG();
1242
1243 spin_lock_irqsave(&dev->video_mode.slock, flags);
1244 if (dev->USE_ISO) {
1245 if (dev->video_mode.isoc_ctl.buf == buf)
1246 dev->video_mode.isoc_ctl.buf = NULL;
1247 } else {
1248 if (dev->video_mode.bulk_ctl.buf == buf)
1249 dev->video_mode.bulk_ctl.buf = NULL;
1250 }
1251 spin_unlock_irqrestore(&dev->video_mode.slock, flags);
1252 videobuf_waiton(vq, &buf->vb, 0, 0);
1253 videobuf_vmalloc_free(&buf->vb);
1254 buf->vb.state = VIDEOBUF_NEEDS_INIT;
1255}
1256
Mauro Carvalho Chehab82c3cca2010-10-07 21:01:31 -03001257static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001258 struct cx231xx_dmaqueue *dma_q)
1259{
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001260 void *vbuf;
1261 struct cx231xx_buffer *buf;
1262 u32 tail_data = 0;
1263 char *p_data;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001264
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001265 if (dma_q->mpeg_buffer_done == 0) {
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001266 if (list_empty(&dma_q->active))
1267 return;
1268
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001269 buf = list_entry(dma_q->active.next,
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001270 struct cx231xx_buffer, vb.queue);
1271 dev->video_mode.isoc_ctl.buf = buf;
1272 dma_q->mpeg_buffer_done = 1;
1273 }
1274 /* Fill buffer */
1275 buf = dev->video_mode.isoc_ctl.buf;
1276 vbuf = videobuf_to_vmalloc(&buf->vb);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001277
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001278 if ((dma_q->mpeg_buffer_completed+len) <
1279 mpeglines*mpeglinesize) {
1280 if (dma_q->add_ps_package_head ==
1281 CX231XX_NEED_ADD_PS_PACKAGE_HEAD) {
1282 memcpy(vbuf+dma_q->mpeg_buffer_completed,
1283 dma_q->ps_head, 3);
1284 dma_q->mpeg_buffer_completed =
1285 dma_q->mpeg_buffer_completed + 3;
1286 dma_q->add_ps_package_head =
1287 CX231XX_NONEED_PS_PACKAGE_HEAD;
1288 }
1289 memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len);
1290 dma_q->mpeg_buffer_completed =
1291 dma_q->mpeg_buffer_completed + len;
1292 } else {
1293 dma_q->mpeg_buffer_done = 0;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001294
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001295 tail_data =
1296 mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed;
1297 memcpy(vbuf+dma_q->mpeg_buffer_completed,
1298 data, tail_data);
1299
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001300 buf->vb.state = VIDEOBUF_DONE;
1301 buf->vb.field_count++;
Sakari Ailus8e6057b2012-09-15 15:14:42 -03001302 v4l2_get_timestamp(&buf->vb.ts);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001303 list_del(&buf->vb.queue);
1304 wake_up(&buf->vb.done);
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001305 dma_q->mpeg_buffer_completed = 0;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001306
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001307 if (len - tail_data > 0) {
1308 p_data = data + tail_data;
1309 dma_q->left_data_count = len - tail_data;
1310 memcpy(dma_q->p_left_data,
1311 p_data, len - tail_data);
1312 }
1313 }
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001314}
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001315
1316static void buffer_filled(char *data, int len, struct urb *urb,
1317 struct cx231xx_dmaqueue *dma_q)
1318{
1319 void *vbuf;
1320 struct cx231xx_buffer *buf;
1321
1322 if (list_empty(&dma_q->active))
1323 return;
1324
1325 buf = list_entry(dma_q->active.next,
1326 struct cx231xx_buffer, vb.queue);
1327
1328 /* Fill buffer */
1329 vbuf = videobuf_to_vmalloc(&buf->vb);
1330 memcpy(vbuf, data, len);
1331 buf->vb.state = VIDEOBUF_DONE;
1332 buf->vb.field_count++;
1333 v4l2_get_timestamp(&buf->vb.ts);
1334 list_del(&buf->vb.queue);
1335 wake_up(&buf->vb.done);
1336}
1337
1338static int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001339{
1340 struct cx231xx_dmaqueue *dma_q = urb->context;
1341 unsigned char *p_buffer;
1342 u32 buffer_size = 0;
1343 u32 i = 0;
1344
1345 for (i = 0; i < urb->number_of_packets; i++) {
1346 if (dma_q->left_data_count > 0) {
1347 buffer_copy(dev, dma_q->p_left_data,
1348 dma_q->left_data_count, urb, dma_q);
1349 dma_q->mpeg_buffer_completed = dma_q->left_data_count;
1350 dma_q->left_data_count = 0;
1351 }
1352
1353 p_buffer = urb->transfer_buffer +
1354 urb->iso_frame_desc[i].offset;
1355 buffer_size = urb->iso_frame_desc[i].actual_length;
1356
1357 if (buffer_size > 0)
1358 buffer_copy(dev, p_buffer, buffer_size, urb, dma_q);
1359 }
1360
1361 return 0;
1362}
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001363
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001364static int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
1365{
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001366 struct cx231xx_dmaqueue *dma_q = urb->context;
1367 unsigned char *p_buffer, *buffer;
1368 u32 buffer_size = 0;
1369
1370 p_buffer = urb->transfer_buffer;
1371 buffer_size = urb->actual_length;
1372
1373 buffer = kmalloc(buffer_size, GFP_ATOMIC);
1374
1375 memcpy(buffer, dma_q->ps_head, 3);
1376 memcpy(buffer+3, p_buffer, buffer_size-3);
1377 memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3);
1378
1379 p_buffer = buffer;
1380 buffer_filled(p_buffer, buffer_size, urb, dma_q);
1381
1382 kfree(buffer);
1383 return 0;
1384}
1385
1386static int bb_buf_prepare(struct videobuf_queue *q,
1387 struct videobuf_buffer *vb, enum v4l2_field field)
1388{
1389 struct cx231xx_fh *fh = q->priv_data;
1390 struct cx231xx_buffer *buf =
1391 container_of(vb, struct cx231xx_buffer, vb);
1392 struct cx231xx *dev = fh->dev;
1393 int rc = 0, urb_init = 0;
1394 int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
1395
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001396 if (0 != buf->vb.baddr && buf->vb.bsize < size)
1397 return -EINVAL;
1398 buf->vb.width = fh->dev->ts1.ts_packet_size;
1399 buf->vb.height = fh->dev->ts1.ts_packet_count;
1400 buf->vb.size = size;
1401 buf->vb.field = field;
1402
1403 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
1404 rc = videobuf_iolock(q, &buf->vb, NULL);
1405 if (rc < 0)
1406 goto fail;
1407 }
1408
1409 if (dev->USE_ISO) {
1410 if (!dev->video_mode.isoc_ctl.num_bufs)
1411 urb_init = 1;
1412 } else {
1413 if (!dev->video_mode.bulk_ctl.num_bufs)
1414 urb_init = 1;
1415 }
1416 /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
1417 urb_init, dev->video_mode.max_pkt_size);*/
1418 dev->mode_tv = 1;
1419
1420 if (urb_init) {
1421 rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
1422 rc = cx231xx_unmute_audio(dev);
1423 if (dev->USE_ISO) {
1424 cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
1425 rc = cx231xx_init_isoc(dev, mpeglines,
1426 mpegbufs,
1427 dev->ts1_mode.max_pkt_size,
1428 cx231xx_isoc_copy);
1429 } else {
1430 cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
1431 rc = cx231xx_init_bulk(dev, mpeglines,
1432 mpegbufs,
1433 dev->ts1_mode.max_pkt_size,
1434 cx231xx_bulk_copy);
1435 }
1436 if (rc < 0)
1437 goto fail;
1438 }
1439
1440 buf->vb.state = VIDEOBUF_PREPARED;
1441 return 0;
1442
1443fail:
1444 free_buffer(q, buf);
1445 return rc;
1446}
1447
1448static void bb_buf_queue(struct videobuf_queue *q,
1449 struct videobuf_buffer *vb)
1450{
1451 struct cx231xx_fh *fh = q->priv_data;
1452
1453 struct cx231xx_buffer *buf =
1454 container_of(vb, struct cx231xx_buffer, vb);
1455 struct cx231xx *dev = fh->dev;
1456 struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
1457
1458 buf->vb.state = VIDEOBUF_QUEUED;
1459 list_add_tail(&buf->vb.queue, &vidq->active);
1460
1461}
1462
1463static void bb_buf_release(struct videobuf_queue *q,
1464 struct videobuf_buffer *vb)
1465{
1466 struct cx231xx_buffer *buf =
1467 container_of(vb, struct cx231xx_buffer, vb);
1468 /*struct cx231xx_fh *fh = q->priv_data;*/
1469 /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/
1470
1471 free_buffer(q, buf);
1472}
1473
1474static struct videobuf_queue_ops cx231xx_qops = {
1475 .buf_setup = bb_buf_setup,
1476 .buf_prepare = bb_buf_prepare,
1477 .buf_queue = bb_buf_queue,
1478 .buf_release = bb_buf_release,
1479};
1480
1481/* ------------------------------------------------------------------ */
1482
1483static const u32 *ctrl_classes[] = {
1484 cx2341x_mpeg_ctrls,
1485 NULL
1486};
1487
1488static int cx231xx_queryctrl(struct cx231xx *dev,
1489 struct v4l2_queryctrl *qctrl)
1490{
1491 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
1492 if (qctrl->id == 0)
1493 return -EINVAL;
1494
1495 /* MPEG V4L2 controls */
1496 if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
1497 qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
1498
1499 return 0;
1500}
1501
1502static int cx231xx_querymenu(struct cx231xx *dev,
1503 struct v4l2_querymenu *qmenu)
1504{
1505 struct v4l2_queryctrl qctrl;
1506
1507 qctrl.id = qmenu->id;
1508 cx231xx_queryctrl(dev, &qctrl);
1509 return v4l2_ctrl_query_menu(qmenu, &qctrl,
1510 cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
1511}
1512
1513static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
1514{
1515 struct cx231xx_fh *fh = file->private_data;
1516 struct cx231xx *dev = fh->dev;
1517
1518 *norm = dev->encodernorm.id;
1519 return 0;
1520}
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001521
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001522static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
1523{
1524 struct cx231xx_fh *fh = file->private_data;
1525 struct cx231xx *dev = fh->dev;
1526 unsigned int i;
1527
1528 for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++)
1529 if (*id & cx231xx_tvnorms[i].id)
1530 break;
1531 if (i == ARRAY_SIZE(cx231xx_tvnorms))
1532 return -EINVAL;
1533 dev->encodernorm = cx231xx_tvnorms[i];
1534
1535 if (dev->encodernorm.id & 0xb000) {
1536 dprintk(3, "encodernorm set to NTSC\n");
1537 dev->norm = V4L2_STD_NTSC;
1538 dev->ts1.height = 480;
1539 dev->mpeg_params.is_50hz = 0;
1540 } else {
1541 dprintk(3, "encodernorm set to PAL\n");
1542 dev->norm = V4L2_STD_PAL_B;
1543 dev->ts1.height = 576;
1544 dev->mpeg_params.is_50hz = 1;
1545 }
1546 call_all(dev, core, s_std, dev->norm);
1547 /* do mode control overrides */
1548 cx231xx_do_mode_ctrl_overrides(dev);
1549
1550 dprintk(3, "exit vidioc_s_std() i=0x%x\n", i);
1551 return 0;
1552}
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001553
1554static const char * const iname[] = {
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001555 [CX231XX_VMUX_COMPOSITE1] = "Composite1",
1556 [CX231XX_VMUX_SVIDEO] = "S-Video",
1557 [CX231XX_VMUX_TELEVISION] = "Television",
1558 [CX231XX_VMUX_CABLE] = "Cable TV",
1559 [CX231XX_VMUX_DVB] = "DVB",
1560 [CX231XX_VMUX_DEBUG] = "for debug only",
1561};
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001562
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001563static int vidioc_enum_input(struct file *file, void *priv,
1564 struct v4l2_input *i)
1565{
1566 struct cx231xx_fh *fh = file->private_data;
1567 struct cx231xx *dev = fh->dev;
1568 struct cx231xx_input *input;
1569 int n;
1570 dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index);
1571
1572 if (i->index >= 4)
1573 return -EINVAL;
1574
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001575 input = &cx231xx_boards[dev->model].input[i->index];
1576
1577 if (input->type == 0)
1578 return -EINVAL;
1579
1580 /* FIXME
1581 * strcpy(i->name, input->name); */
1582
1583 n = i->index;
1584 strcpy(i->name, iname[INPUT(n)->type]);
1585
1586 if (input->type == CX231XX_VMUX_TELEVISION ||
1587 input->type == CX231XX_VMUX_CABLE)
1588 i->type = V4L2_INPUT_TYPE_TUNER;
1589 else
1590 i->type = V4L2_INPUT_TYPE_CAMERA;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001591 return 0;
1592}
1593
1594static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1595{
1596 *i = 0;
1597 return 0;
1598}
1599
1600static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1601{
1602 struct cx231xx_fh *fh = file->private_data;
1603 struct cx231xx *dev = fh->dev;
1604
1605 dprintk(3, "enter vidioc_s_input() i=%d\n", i);
1606
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001607 video_mux(dev, i);
1608
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001609 if (i >= 4)
1610 return -EINVAL;
1611 dev->input = i;
1612 dprintk(3, "exit vidioc_s_input()\n");
1613 return 0;
1614}
1615
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001616static int vidioc_s_ctrl(struct file *file, void *priv,
1617 struct v4l2_control *ctl)
1618{
1619 struct cx231xx_fh *fh = file->private_data;
1620 struct cx231xx *dev = fh->dev;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001621
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001622 dprintk(3, "enter vidioc_s_ctrl()\n");
1623 /* Update the A/V core */
1624 call_all(dev, core, s_ctrl, ctl);
1625 dprintk(3, "exit vidioc_s_ctrl()\n");
1626 return 0;
1627}
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001628
1629static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1630 struct v4l2_fmtdesc *f)
1631{
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001632 if (f->index != 0)
1633 return -EINVAL;
1634
1635 strlcpy(f->description, "MPEG", sizeof(f->description));
1636 f->pixelformat = V4L2_PIX_FMT_MPEG;
1637
1638 return 0;
1639}
1640
1641static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1642 struct v4l2_format *f)
1643{
1644 struct cx231xx_fh *fh = file->private_data;
1645 struct cx231xx *dev = fh->dev;
Hans Verkuil5aa95992013-01-29 13:02:15 -03001646
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001647 dprintk(3, "enter vidioc_g_fmt_vid_cap()\n");
Hans Verkuil5aa95992013-01-29 13:02:15 -03001648 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001649 f->fmt.pix.bytesperline = 0;
Hans Verkuil5aa95992013-01-29 13:02:15 -03001650 f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
1651 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1652 f->fmt.pix.width = dev->ts1.width;
1653 f->fmt.pix.height = dev->ts1.height;
1654 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1655 f->fmt.pix.priv = 0;
1656 dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
1657 dev->ts1.width, dev->ts1.height);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001658 dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
1659 return 0;
1660}
1661
1662static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1663 struct v4l2_format *f)
1664{
1665 struct cx231xx_fh *fh = file->private_data;
1666 struct cx231xx *dev = fh->dev;
Hans Verkuil5aa95992013-01-29 13:02:15 -03001667
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001668 dprintk(3, "enter vidioc_try_fmt_vid_cap()\n");
Hans Verkuil5aa95992013-01-29 13:02:15 -03001669 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001670 f->fmt.pix.bytesperline = 0;
Hans Verkuil5aa95992013-01-29 13:02:15 -03001671 f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
1672 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1673 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1674 f->fmt.pix.priv = 0;
1675 dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
1676 dev->ts1.width, dev->ts1.height);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001677 dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
1678 return 0;
1679}
1680
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001681static int vidioc_reqbufs(struct file *file, void *priv,
1682 struct v4l2_requestbuffers *p)
1683{
1684 struct cx231xx_fh *fh = file->private_data;
1685
1686 return videobuf_reqbufs(&fh->vidq, p);
1687}
1688
1689static int vidioc_querybuf(struct file *file, void *priv,
1690 struct v4l2_buffer *p)
1691{
1692 struct cx231xx_fh *fh = file->private_data;
1693
1694 return videobuf_querybuf(&fh->vidq, p);
1695}
1696
1697static int vidioc_qbuf(struct file *file, void *priv,
1698 struct v4l2_buffer *p)
1699{
1700 struct cx231xx_fh *fh = file->private_data;
1701
1702 return videobuf_qbuf(&fh->vidq, p);
1703}
1704
1705static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1706{
1707 struct cx231xx_fh *fh = priv;
1708
1709 return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK);
1710}
1711
1712
1713static int vidioc_streamon(struct file *file, void *priv,
1714 enum v4l2_buf_type i)
1715{
1716 struct cx231xx_fh *fh = file->private_data;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001717 struct cx231xx *dev = fh->dev;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001718
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001719 dprintk(3, "enter vidioc_streamon()\n");
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001720 cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
1721 cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
1722 if (dev->USE_ISO)
1723 cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
1724 CX231XX_NUM_BUFS,
1725 dev->video_mode.max_pkt_size,
1726 cx231xx_isoc_copy);
1727 else {
1728 cx231xx_init_bulk(dev, 320,
1729 5,
1730 dev->ts1_mode.max_pkt_size,
1731 cx231xx_bulk_copy);
1732 }
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001733 dprintk(3, "exit vidioc_streamon()\n");
1734 return videobuf_streamon(&fh->vidq);
1735}
1736
1737static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1738{
1739 struct cx231xx_fh *fh = file->private_data;
1740
1741 return videobuf_streamoff(&fh->vidq);
1742}
1743
1744static int vidioc_g_ext_ctrls(struct file *file, void *priv,
1745 struct v4l2_ext_controls *f)
1746{
1747 struct cx231xx_fh *fh = priv;
1748 struct cx231xx *dev = fh->dev;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001749
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001750 dprintk(3, "enter vidioc_g_ext_ctrls()\n");
1751 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
1752 return -EINVAL;
1753 dprintk(3, "exit vidioc_g_ext_ctrls()\n");
1754 return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
1755}
1756
1757static int vidioc_s_ext_ctrls(struct file *file, void *priv,
1758 struct v4l2_ext_controls *f)
1759{
1760 struct cx231xx_fh *fh = priv;
1761 struct cx231xx *dev = fh->dev;
1762 struct cx2341x_mpeg_params p;
1763 int err;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001764
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001765 dprintk(3, "enter vidioc_s_ext_ctrls()\n");
1766 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
1767 return -EINVAL;
1768
1769 p = dev->mpeg_params;
1770 err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
1771 if (err == 0) {
1772 err = cx2341x_update(dev, cx231xx_mbox_func,
1773 &dev->mpeg_params, &p);
1774 dev->mpeg_params = p;
1775 }
1776
1777 return err;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001778}
1779
1780static int vidioc_try_ext_ctrls(struct file *file, void *priv,
1781 struct v4l2_ext_controls *f)
1782{
1783 struct cx231xx_fh *fh = priv;
1784 struct cx231xx *dev = fh->dev;
1785 struct cx2341x_mpeg_params p;
1786 int err;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001787
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001788 dprintk(3, "enter vidioc_try_ext_ctrls()\n");
1789 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
1790 return -EINVAL;
1791
1792 p = dev->mpeg_params;
1793 err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
1794 dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err);
1795 return err;
1796}
1797
1798static int vidioc_log_status(struct file *file, void *priv)
1799{
1800 struct cx231xx_fh *fh = priv;
1801 struct cx231xx *dev = fh->dev;
1802 char name[32 + 2];
1803
1804 snprintf(name, sizeof(name), "%s/2", dev->name);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001805 call_all(dev, core, log_status);
1806 cx2341x_log_status(&dev->mpeg_params, name);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001807 return 0;
1808}
1809
1810static int vidioc_querymenu(struct file *file, void *priv,
1811 struct v4l2_querymenu *a)
1812{
1813 struct cx231xx_fh *fh = priv;
1814 struct cx231xx *dev = fh->dev;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001815
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001816 dprintk(3, "enter vidioc_querymenu()\n");
1817 dprintk(3, "exit vidioc_querymenu()\n");
1818 return cx231xx_querymenu(dev, a);
1819}
1820
1821static int vidioc_queryctrl(struct file *file, void *priv,
1822 struct v4l2_queryctrl *c)
1823{
1824 struct cx231xx_fh *fh = priv;
1825 struct cx231xx *dev = fh->dev;
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001826
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001827 dprintk(3, "enter vidioc_queryctrl()\n");
1828 dprintk(3, "exit vidioc_queryctrl()\n");
1829 return cx231xx_queryctrl(dev, c);
1830}
1831
1832static int mpeg_open(struct file *file)
1833{
1834 int minor = video_devdata(file)->minor;
1835 struct cx231xx *h, *dev = NULL;
1836 /*struct list_head *list;*/
1837 struct cx231xx_fh *fh;
1838 /*u32 value = 0;*/
1839
1840 dprintk(2, "%s()\n", __func__);
1841
1842 list_for_each_entry(h, &cx231xx_devlist, devlist) {
1843 if (h->v4l_device->minor == minor)
1844 dev = h;
1845 }
1846
Arnd Bergmann0edf2e52010-10-27 09:30:32 -03001847 if (dev == NULL)
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001848 return -ENODEV;
Arnd Bergmann0edf2e52010-10-27 09:30:32 -03001849
Hans Verkuil1265f082012-09-17 09:26:46 -03001850 if (mutex_lock_interruptible(&dev->lock))
1851 return -ERESTARTSYS;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001852
1853 /* allocate + initialize per filehandle data */
1854 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1855 if (NULL == fh) {
1856 mutex_unlock(&dev->lock);
1857 return -ENOMEM;
1858 }
1859
1860 file->private_data = fh;
1861 fh->dev = dev;
1862
1863
1864 videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops,
1865 NULL, &dev->video_mode.slock,
1866 V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,
Hans Verkuil1265f082012-09-17 09:26:46 -03001867 sizeof(struct cx231xx_buffer), fh, &dev->lock);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001868/*
1869 videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
1870 &dev->udev->dev, &dev->ts1.slock,
1871 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1872 V4L2_FIELD_INTERLACED,
1873 sizeof(struct cx231xx_buffer),
Hans Verkuil1265f082012-09-17 09:26:46 -03001874 fh, &dev->lock);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001875*/
1876
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001877 cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
1878 cx231xx_set_gpio_value(dev, 2, 0);
1879
1880 cx231xx_initialize_codec(dev);
1881
1882 mutex_unlock(&dev->lock);
1883 cx231xx_start_TS1(dev);
1884
1885 return 0;
1886}
1887
1888static int mpeg_release(struct file *file)
1889{
1890 struct cx231xx_fh *fh = file->private_data;
1891 struct cx231xx *dev = fh->dev;
1892
Devin Heitmuellerdd067a82010-07-07 19:28:23 -03001893 dprintk(3, "mpeg_release()! dev=0x%p\n", dev);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001894
1895 if (!dev) {
1896 dprintk(3, "abort!!!\n");
1897 return 0;
1898 }
1899
1900 mutex_lock(&dev->lock);
1901
1902 cx231xx_stop_TS1(dev);
1903
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001904 /* do this before setting alternate! */
1905 if (dev->USE_ISO)
1906 cx231xx_uninit_isoc(dev);
1907 else
1908 cx231xx_uninit_bulk(dev);
1909 cx231xx_set_mode(dev, CX231XX_SUSPEND);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001910
Hans Verkuil5b8acdc2013-01-29 12:59:50 -03001911 cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
1912 CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
1913 CX231xx_RAW_BITS_NONE);
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001914
1915 /* FIXME: Review this crap */
1916 /* Shut device down on last close */
1917 if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
1918 if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
1919 /* stop mpeg capture */
1920
1921 msleep(500);
1922 cx231xx_417_check_encoder(dev);
1923
1924 }
1925 }
1926
1927 if (fh->vidq.streaming)
1928 videobuf_streamoff(&fh->vidq);
1929 if (fh->vidq.reading)
1930 videobuf_read_stop(&fh->vidq);
1931
1932 videobuf_mmap_free(&fh->vidq);
1933 file->private_data = NULL;
1934 kfree(fh);
1935 mutex_unlock(&dev->lock);
1936 return 0;
1937}
1938
1939static ssize_t mpeg_read(struct file *file, char __user *data,
1940 size_t count, loff_t *ppos)
1941{
1942 struct cx231xx_fh *fh = file->private_data;
1943 struct cx231xx *dev = fh->dev;
1944
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001945 /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
1946 /* Start mpeg encoder on first read. */
1947 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1948 if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
1949 if (cx231xx_initialize_codec(dev) < 0)
1950 return -EINVAL;
1951 }
1952 }
1953
1954 return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
1955 file->f_flags & O_NONBLOCK);
1956}
1957
1958static unsigned int mpeg_poll(struct file *file,
1959 struct poll_table_struct *wait)
1960{
1961 struct cx231xx_fh *fh = file->private_data;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001962
1963 return videobuf_poll_stream(file, &fh->vidq, wait);
1964}
1965
1966static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
1967{
1968 struct cx231xx_fh *fh = file->private_data;
1969 struct cx231xx *dev = fh->dev;
1970
1971 dprintk(2, "%s()\n", __func__);
1972
1973 return videobuf_mmap_mapper(&fh->vidq, vma);
1974}
1975
1976static struct v4l2_file_operations mpeg_fops = {
1977 .owner = THIS_MODULE,
1978 .open = mpeg_open,
1979 .release = mpeg_release,
1980 .read = mpeg_read,
1981 .poll = mpeg_poll,
1982 .mmap = mpeg_mmap,
Hans Verkuil1265f082012-09-17 09:26:46 -03001983 .unlocked_ioctl = video_ioctl2,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001984};
1985
1986static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
1987 .vidioc_s_std = vidioc_s_std,
1988 .vidioc_g_std = vidioc_g_std,
1989 .vidioc_enum_input = vidioc_enum_input,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001990 .vidioc_g_input = vidioc_g_input,
1991 .vidioc_s_input = vidioc_s_input,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001992 .vidioc_s_ctrl = vidioc_s_ctrl,
Hans Verkuilbc087342013-01-29 12:52:33 -03001993 .vidioc_querycap = cx231xx_querycap,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001994 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1995 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1996 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
Hans Verkuil3f926e32013-01-29 12:50:18 -03001997 .vidioc_s_fmt_vid_cap = vidioc_try_fmt_vid_cap,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03001998 .vidioc_reqbufs = vidioc_reqbufs,
1999 .vidioc_querybuf = vidioc_querybuf,
2000 .vidioc_qbuf = vidioc_qbuf,
2001 .vidioc_dqbuf = vidioc_dqbuf,
2002 .vidioc_streamon = vidioc_streamon,
2003 .vidioc_streamoff = vidioc_streamoff,
2004 .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
2005 .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
2006 .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
2007 .vidioc_log_status = vidioc_log_status,
2008 .vidioc_querymenu = vidioc_querymenu,
2009 .vidioc_queryctrl = vidioc_queryctrl,
2010/* .vidioc_g_chip_ident = cx231xx_g_chip_ident,*/
2011#ifdef CONFIG_VIDEO_ADV_DEBUG
2012/* .vidioc_g_register = cx231xx_g_register,*/
2013/* .vidioc_s_register = cx231xx_s_register,*/
2014#endif
2015};
2016
2017static struct video_device cx231xx_mpeg_template = {
2018 .name = "cx231xx",
2019 .fops = &mpeg_fops,
2020 .ioctl_ops = &mpeg_ioctl_ops,
2021 .minor = -1,
2022 .tvnorms = CX231xx_NORMS,
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03002023};
2024
2025void cx231xx_417_unregister(struct cx231xx *dev)
2026{
2027 dprintk(1, "%s()\n", __func__);
2028 dprintk(3, "%s()\n", __func__);
2029
2030 if (dev->v4l_device) {
2031 if (-1 != dev->v4l_device->minor)
2032 video_unregister_device(dev->v4l_device);
2033 else
2034 video_device_release(dev->v4l_device);
2035 dev->v4l_device = NULL;
2036 }
2037}
2038
2039static struct video_device *cx231xx_video_dev_alloc(
2040 struct cx231xx *dev,
2041 struct usb_device *usbdev,
2042 struct video_device *template,
2043 char *type)
2044{
2045 struct video_device *vfd;
2046
2047 dprintk(1, "%s()\n", __func__);
2048 vfd = video_device_alloc();
2049 if (NULL == vfd)
2050 return NULL;
2051 *vfd = *template;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03002052 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
2053 type, cx231xx_boards[dev->model].name);
2054
2055 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuil1265f082012-09-17 09:26:46 -03002056 vfd->lock = &dev->lock;
Palash Bandyopadhyay64fbf442010-07-06 18:12:25 -03002057 vfd->release = video_device_release;
2058
2059 return vfd;
2060
2061}
2062
2063int cx231xx_417_register(struct cx231xx *dev)
2064{
2065 /* FIXME: Port1 hardcoded here */
2066 int err = -ENODEV;
2067 struct cx231xx_tsport *tsport = &dev->ts1;
2068
2069 dprintk(1, "%s()\n", __func__);
2070
2071 /* Set default TV standard */
2072 dev->encodernorm = cx231xx_tvnorms[0];
2073
2074 if (dev->encodernorm.id & V4L2_STD_525_60)
2075 tsport->height = 480;
2076 else
2077 tsport->height = 576;
2078
2079 tsport->width = 720;
2080 cx2341x_fill_defaults(&dev->mpeg_params);
2081 dev->norm = V4L2_STD_NTSC;
2082
2083 dev->mpeg_params.port = CX2341X_PORT_SERIAL;
2084
2085 /* Allocate and initialize V4L video device */
2086 dev->v4l_device = cx231xx_video_dev_alloc(dev,
2087 dev->udev, &cx231xx_mpeg_template, "mpeg");
2088 err = video_register_device(dev->v4l_device,
2089 VFL_TYPE_GRABBER, -1);
2090 if (err < 0) {
2091 dprintk(3, "%s: can't register mpeg device\n", dev->name);
2092 return err;
2093 }
2094
2095 dprintk(3, "%s: registered device video%d [mpeg]\n",
2096 dev->name, dev->v4l_device->num);
2097
2098 return 0;
2099}
Tim Gardnerb8320e92012-07-26 14:34:22 -03002100
2101MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME);