blob: 7fc97110d973eabee2e70b1132810f892f799106 [file] [log] [blame]
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -03001/*
2 * Driver for the Conexant CX25821 PCIe bridge
3 *
4 * Copyright (C) 2009 Conexant Systems Inc.
5 * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 *
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
Joe Perches36d89f72010-11-07 17:48:21 -030023#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030025#include "cx25821-video.h"
26#include "cx25821-video-upstream.h"
27
28#include <linux/fs.h>
29#include <linux/errno.h>
30#include <linux/kernel.h>
31#include <linux/init.h>
32#include <linux/module.h>
33#include <linux/syscalls.h>
34#include <linux/file.h>
35#include <linux/fcntl.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Olimpiu Pascariu10991232010-04-06 02:09:00 -030037#include <linux/uaccess.h>
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030038
39MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
40MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
41MODULE_LICENSE("GPL");
42
Leonid V. Fedorenchik2b2d0392011-09-02 11:55:46 +080043static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
44 FLD_VID_SRC_OPC_ERR;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030045
46int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
47 struct sram_channel *ch,
48 unsigned int bpl, u32 risc)
49{
50 unsigned int i, lines;
51 u32 cdt;
52
53 if (ch->cmds_start == 0) {
54 cx_write(ch->ptr1_reg, 0);
55 cx_write(ch->ptr2_reg, 0);
56 cx_write(ch->cnt2_reg, 0);
57 cx_write(ch->cnt1_reg, 0);
58 return 0;
59 }
60
61 bpl = (bpl + 7) & ~7; /* alignment */
62 cdt = ch->cdt;
63 lines = ch->fifo_size / bpl;
64
Olimpiu Pascariu10991232010-04-06 02:09:00 -030065 if (lines > 4)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030066 lines = 4;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -030067
68 BUG_ON(lines < 2);
69
70 /* write CDT */
71 for (i = 0; i < lines; i++) {
72 cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
73 cx_write(cdt + 16 * i + 4, 0);
74 cx_write(cdt + 16 * i + 8, 0);
75 cx_write(cdt + 16 * i + 12, 0);
76 }
77
78 /* write CMDS */
79 cx_write(ch->cmds_start + 0, risc);
80
81 cx_write(ch->cmds_start + 4, 0);
82 cx_write(ch->cmds_start + 8, cdt);
83 cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
84 cx_write(ch->cmds_start + 16, ch->ctrl_start);
85
86 cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);
87
88 for (i = 24; i < 80; i += 4)
89 cx_write(ch->cmds_start + i, 0);
90
91 /* fill registers */
92 cx_write(ch->ptr1_reg, ch->fifo_start);
93 cx_write(ch->ptr2_reg, cdt);
94 cx_write(ch->cnt2_reg, (lines * 16) >> 3);
95 cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
96
97 return 0;
98}
99
100static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev,
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300101 __le32 *rp, unsigned int offset,
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300102 unsigned int bpl, u32 sync_line,
103 unsigned int lines, int fifo_enable,
104 int field_type)
105{
106 unsigned int line, i;
107 int dist_betwn_starts = bpl * 2;
108
109 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
110
111 if (USE_RISC_NOOP_VIDEO) {
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300112 for (i = 0; i < NUM_NO_OPS; i++)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300113 *(rp++) = cpu_to_le32(RISC_NOOP);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300114 }
115
116 /* scan lines */
117 for (line = 0; line < lines; line++) {
118 *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
119 *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset);
120 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
121
122 if ((lines <= NTSC_FIELD_HEIGHT)
123 || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
124 offset += dist_betwn_starts;
125 }
126 }
127
128 return rp;
129}
130
131static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
132 dma_addr_t databuf_phys_addr,
133 unsigned int offset, u32 sync_line,
134 unsigned int bpl, unsigned int lines,
135 int fifo_enable, int field_type)
136{
137 unsigned int line, i;
138 struct sram_channel *sram_ch =
Leonid V. Fedorenchik2c68e932011-10-22 01:43:47 -0300139 dev->channels[dev->_channel_upstream_select].sram_channels;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300140 int dist_betwn_starts = bpl * 2;
141
142 /* sync instruction */
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300143 if (sync_line != NO_SYNC_LINE)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300144 *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300145
146 if (USE_RISC_NOOP_VIDEO) {
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300147 for (i = 0; i < NUM_NO_OPS; i++)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300148 *(rp++) = cpu_to_le32(RISC_NOOP);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300149 }
150
151 /* scan lines */
152 for (line = 0; line < lines; line++) {
153 *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
154 *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
155 *(rp++) = cpu_to_le32(0); /* bits 63-32 */
156
157 if ((lines <= NTSC_FIELD_HEIGHT)
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300158 || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC))
159 /* to skip the other field line */
160 offset += dist_betwn_starts;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300161
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300162 /* check if we need to enable the FIFO after the first 4 lines
163 * For the upstream video channel, the risc engine will enable
164 * the FIFO. */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300165 if (fifo_enable && line == 3) {
166 *(rp++) = RISC_WRITECR;
167 *(rp++) = sram_ch->dma_ctl;
168 *(rp++) = FLD_VID_FIFO_EN;
169 *(rp++) = 0x00000001;
170 }
171 }
172
173 return rp;
174}
175
Mauro Carvalho Chehabdafc4562012-10-27 12:42:59 -0300176static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
177 struct pci_dev *pci,
178 unsigned int top_offset,
179 unsigned int bpl, unsigned int lines)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300180{
181 __le32 *rp;
182 int fifo_enable = 0;
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300183 /* get line count for single field */
184 int singlefield_lines = lines >> 1;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300185 int odd_num_lines = singlefield_lines;
186 int frame = 0;
187 int frame_size = 0;
188 int databuf_offset = 0;
189 int risc_program_size = 0;
190 int risc_flag = RISC_CNT_RESET;
191 unsigned int bottom_offset = bpl;
192 dma_addr_t risc_phys_jump_addr;
193
194 if (dev->_isNTSC) {
195 odd_num_lines = singlefield_lines + 1;
196 risc_program_size = FRAME1_VID_PROG_SIZE;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300197 frame_size = (bpl == Y411_LINE_SZ) ?
198 FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300199 } else {
200 risc_program_size = PAL_VID_PROG_SIZE;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300201 frame_size = (bpl == Y411_LINE_SZ) ?
202 FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300203 }
204
205 /* Virtual address of Risc buffer program */
206 rp = dev->_dma_virt_addr;
207
208 for (frame = 0; frame < NUM_FRAMES; frame++) {
209 databuf_offset = frame_size * frame;
210
211 if (UNSET != top_offset) {
212 fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
213 rp = cx25821_risc_field_upstream(dev, rp,
Leonid V. Fedorenchik2c68e932011-10-22 01:43:47 -0300214 dev->_data_buf_phys_addr +
215 databuf_offset, top_offset, 0, bpl,
216 odd_num_lines, fifo_enable, ODD_FIELD);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300217 }
218
219 fifo_enable = FIFO_DISABLE;
220
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300221 /* Even Field */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300222 rp = cx25821_risc_field_upstream(dev, rp,
223 dev->_data_buf_phys_addr +
224 databuf_offset, bottom_offset,
225 0x200, bpl, singlefield_lines,
226 fifo_enable, EVEN_FIELD);
227
228 if (frame == 0) {
229 risc_flag = RISC_CNT_RESET;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300230 risc_phys_jump_addr = dev->_dma_phys_start_addr +
231 risc_program_size;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300232 } else {
233 risc_phys_jump_addr = dev->_dma_phys_start_addr;
234 risc_flag = RISC_CNT_INC;
235 }
236
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300237 /* Loop to 2ndFrameRISC or to Start of Risc
238 * program & generate IRQ
239 */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300240 *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
241 *(rp++) = cpu_to_le32(risc_phys_jump_addr);
242 *(rp++) = cpu_to_le32(0);
243 }
244
245 return 0;
246}
247
248void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
249{
250 struct sram_channel *sram_ch =
Leonid V. Fedorenchik2c68e932011-10-22 01:43:47 -0300251 dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300252 u32 tmp = 0;
253
254 if (!dev->_is_running) {
Joe Perches36d89f72010-11-07 17:48:21 -0300255 pr_info("No video file is currently running so return!\n");
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300256 return;
257 }
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300258 /* Disable RISC interrupts */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300259 tmp = cx_read(sram_ch->int_msk);
260 cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
261
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300262 /* Turn OFF risc and fifo enable */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300263 tmp = cx_read(sram_ch->dma_ctl);
264 cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
265
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300266 /* Clear data buffer memory */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300267 if (dev->_data_buf_virt_addr)
268 memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
269
270 dev->_is_running = 0;
271 dev->_is_first_frame = 0;
272 dev->_frame_count = 0;
273 dev->_file_status = END_OF_FILE;
274
Ilia Mirkinb0091782011-03-13 00:28:58 -0500275 kfree(dev->_irq_queues);
276 dev->_irq_queues = NULL;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300277
Ilia Mirkinb0091782011-03-13 00:28:58 -0500278 kfree(dev->_filename);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300279
280 tmp = cx_read(VID_CH_MODE_SEL);
281 cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
282}
283
284void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
285{
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300286 if (dev->_is_running)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300287 cx25821_stop_upstream_video_ch1(dev);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300288
289 if (dev->_dma_virt_addr) {
290 pci_free_consistent(dev->pci, dev->_risc_size,
291 dev->_dma_virt_addr, dev->_dma_phys_addr);
292 dev->_dma_virt_addr = NULL;
293 }
294
295 if (dev->_data_buf_virt_addr) {
296 pci_free_consistent(dev->pci, dev->_data_buf_size,
297 dev->_data_buf_virt_addr,
298 dev->_data_buf_phys_addr);
299 dev->_data_buf_virt_addr = NULL;
300 }
301}
302
Mauro Carvalho Chehabdafc4562012-10-27 12:42:59 -0300303static int cx25821_get_frame(struct cx25821_dev *dev,
304 struct sram_channel *sram_ch)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300305{
306 struct file *myfile;
307 int frame_index_temp = dev->_frame_index;
308 int i = 0;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300309 int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
310 Y411_LINE_SZ : Y422_LINE_SZ;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300311 int frame_size = 0;
312 int frame_offset = 0;
313 ssize_t vfs_read_retval = 0;
314 char mybuf[line_size];
315 loff_t file_offset;
316 loff_t pos;
317 mm_segment_t old_fs;
318
319 if (dev->_file_status == END_OF_FILE)
320 return 0;
321
Leonid V. Fedorenchik16f0fda2011-10-22 01:43:46 -0300322 if (dev->_isNTSC)
323 frame_size = (line_size == Y411_LINE_SZ) ?
324 FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
325 else
326 frame_size = (line_size == Y411_LINE_SZ) ?
327 FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300328
329 frame_offset = (frame_index_temp > 0) ? frame_size : 0;
330 file_offset = dev->_frame_count * frame_size;
331
332 myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
333
334 if (IS_ERR(myfile)) {
335 const int open_errno = -PTR_ERR(myfile);
Joe Perches36d89f72010-11-07 17:48:21 -0300336 pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
337 __func__, dev->_filename, open_errno);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300338 return PTR_ERR(myfile);
339 } else {
340 if (!(myfile->f_op)) {
Joe Perches36d89f72010-11-07 17:48:21 -0300341 pr_err("%s(): File has no file operations registered!\n",
342 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300343 filp_close(myfile, NULL);
344 return -EIO;
345 }
346
347 if (!myfile->f_op->read) {
Joe Perches36d89f72010-11-07 17:48:21 -0300348 pr_err("%s(): File has no READ operations registered!\n",
349 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300350 filp_close(myfile, NULL);
351 return -EIO;
352 }
353
354 pos = myfile->f_pos;
355 old_fs = get_fs();
356 set_fs(KERNEL_DS);
357
358 for (i = 0; i < dev->_lines_count; i++) {
359 pos = file_offset;
360
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300361 vfs_read_retval = vfs_read(myfile, mybuf, line_size,
362 &pos);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300363
364 if (vfs_read_retval > 0 && vfs_read_retval == line_size
365 && dev->_data_buf_virt_addr != NULL) {
366 memcpy((void *)(dev->_data_buf_virt_addr +
367 frame_offset / 4), mybuf,
368 vfs_read_retval);
369 }
370
371 file_offset += vfs_read_retval;
372 frame_offset += vfs_read_retval;
373
374 if (vfs_read_retval < line_size) {
Joe Perches36d89f72010-11-07 17:48:21 -0300375 pr_info("Done: exit %s() since no more bytes to read from Video file\n",
376 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300377 break;
378 }
379 }
380
381 if (i > 0)
382 dev->_frame_count++;
383
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300384 dev->_file_status = (vfs_read_retval == line_size) ?
385 IN_PROGRESS : END_OF_FILE;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300386
387 set_fs(old_fs);
388 filp_close(myfile, NULL);
389 }
390
391 return 0;
392}
393
394static void cx25821_vidups_handler(struct work_struct *work)
395{
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300396 struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
397 _irq_work_entry);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300398
399 if (!dev) {
Joe Perches36d89f72010-11-07 17:48:21 -0300400 pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
401 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300402 return;
403 }
404
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300405 cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select].
406 sram_channels);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300407}
408
Mauro Carvalho Chehabdafc4562012-10-27 12:42:59 -0300409static int cx25821_openfile(struct cx25821_dev *dev,
410 struct sram_channel *sram_ch)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300411{
412 struct file *myfile;
413 int i = 0, j = 0;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300414 int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
415 Y411_LINE_SZ : Y422_LINE_SZ;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300416 ssize_t vfs_read_retval = 0;
417 char mybuf[line_size];
418 loff_t pos;
419 loff_t offset = (unsigned long)0;
420 mm_segment_t old_fs;
421
422 myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
423
424 if (IS_ERR(myfile)) {
425 const int open_errno = -PTR_ERR(myfile);
Joe Perches36d89f72010-11-07 17:48:21 -0300426 pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300427 __func__, dev->_filename, open_errno);
428 return PTR_ERR(myfile);
429 } else {
430 if (!(myfile->f_op)) {
Joe Perches36d89f72010-11-07 17:48:21 -0300431 pr_err("%s(): File has no file operations registered!\n",
432 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300433 filp_close(myfile, NULL);
434 return -EIO;
435 }
436
437 if (!myfile->f_op->read) {
Joe Perches36d89f72010-11-07 17:48:21 -0300438 pr_err("%s(): File has no READ operations registered! Returning\n",
439 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300440 filp_close(myfile, NULL);
441 return -EIO;
442 }
443
444 pos = myfile->f_pos;
445 old_fs = get_fs();
446 set_fs(KERNEL_DS);
447
448 for (j = 0; j < NUM_FRAMES; j++) {
449 for (i = 0; i < dev->_lines_count; i++) {
450 pos = offset;
451
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300452 vfs_read_retval = vfs_read(myfile, mybuf,
453 line_size, &pos);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300454
455 if (vfs_read_retval > 0
456 && vfs_read_retval == line_size
457 && dev->_data_buf_virt_addr != NULL) {
458 memcpy((void *)(dev->
459 _data_buf_virt_addr +
460 offset / 4), mybuf,
461 vfs_read_retval);
462 }
463
464 offset += vfs_read_retval;
465
466 if (vfs_read_retval < line_size) {
Joe Perches36d89f72010-11-07 17:48:21 -0300467 pr_info("Done: exit %s() since no more bytes to read from Video file\n",
468 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300469 break;
470 }
471 }
472
473 if (i > 0)
474 dev->_frame_count++;
475
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300476 if (vfs_read_retval < line_size)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300477 break;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300478 }
479
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300480 dev->_file_status = (vfs_read_retval == line_size) ?
481 IN_PROGRESS : END_OF_FILE;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300482
483 set_fs(old_fs);
484 myfile->f_pos = 0;
485 filp_close(myfile, NULL);
486 }
487
488 return 0;
489}
490
Mauro Carvalho Chehabdafc4562012-10-27 12:42:59 -0300491static int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
492 struct sram_channel *sram_ch,
493 int bpl)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300494{
495 int ret = 0;
496 dma_addr_t dma_addr;
497 dma_addr_t data_dma_addr;
498
Leonid V. Fedorenchik16f0fda2011-10-22 01:43:46 -0300499 if (dev->_dma_virt_addr != NULL)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300500 pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
Leonid V. Fedorenchik16f0fda2011-10-22 01:43:46 -0300501 dev->_dma_virt_addr, dev->_dma_phys_addr);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300502
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300503 dev->_dma_virt_addr = pci_alloc_consistent(dev->pci,
504 dev->upstream_riscbuf_size, &dma_addr);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300505 dev->_dma_virt_start_addr = dev->_dma_virt_addr;
506 dev->_dma_phys_start_addr = dma_addr;
507 dev->_dma_phys_addr = dma_addr;
508 dev->_risc_size = dev->upstream_riscbuf_size;
509
510 if (!dev->_dma_virt_addr) {
Joe Perches36d89f72010-11-07 17:48:21 -0300511 pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300512 return -ENOMEM;
513 }
514
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300515 /* Clear memory at address */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300516 memset(dev->_dma_virt_addr, 0, dev->_risc_size);
517
Leonid V. Fedorenchik16f0fda2011-10-22 01:43:46 -0300518 if (dev->_data_buf_virt_addr != NULL)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300519 pci_free_consistent(dev->pci, dev->upstream_databuf_size,
Leonid V. Fedorenchik16f0fda2011-10-22 01:43:46 -0300520 dev->_data_buf_virt_addr,
521 dev->_data_buf_phys_addr);
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300522 /* For Video Data buffer allocation */
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300523 dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci,
524 dev->upstream_databuf_size, &data_dma_addr);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300525 dev->_data_buf_phys_addr = data_dma_addr;
526 dev->_data_buf_size = dev->upstream_databuf_size;
527
528 if (!dev->_data_buf_virt_addr) {
Joe Perches36d89f72010-11-07 17:48:21 -0300529 pr_err("FAILED to allocate memory for data buffer! Returning\n");
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300530 return -ENOMEM;
531 }
532
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300533 /* Clear memory at address */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300534 memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
535
536 ret = cx25821_openfile(dev, sram_ch);
537 if (ret < 0)
538 return ret;
539
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300540 /* Create RISC programs */
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300541 ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
542 dev->_lines_count);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300543 if (ret < 0) {
Joe Perches36d89f72010-11-07 17:48:21 -0300544 pr_info("Failed creating Video Upstream Risc programs!\n");
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300545 goto error;
546 }
547
548 return 0;
549
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300550error:
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300551 return ret;
552}
553
Mauro Carvalho Chehabdafc4562012-10-27 12:42:59 -0300554static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
555 u32 status)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300556{
557 u32 int_msk_tmp;
Ruslan Pisareve4115bb2010-09-27 10:01:36 -0300558 struct sram_channel *channel = dev->channels[chan_num].sram_channels;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300559 int singlefield_lines = NTSC_FIELD_HEIGHT;
560 int line_size_in_bytes = Y422_LINE_SZ;
561 int odd_risc_prog_size = 0;
562 dma_addr_t risc_phys_jump_addr;
563 __le32 *rp;
564
565 if (status & FLD_VID_SRC_RISC1) {
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300566 /* We should only process one program per call */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300567 u32 prog_cnt = cx_read(channel->gpcnt);
568
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300569 /* Since we've identified our IRQ, clear our bits from the
570 * interrupt mask and interrupt status registers */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300571 int_msk_tmp = cx_read(channel->int_msk);
572 cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
573 cx_write(channel->int_stat, _intr_msk);
574
575 spin_lock(&dev->slock);
576
577 dev->_frame_index = prog_cnt;
578
579 queue_work(dev->_irq_queues, &dev->_irq_work_entry);
580
581 if (dev->_is_first_frame) {
582 dev->_is_first_frame = 0;
583
584 if (dev->_isNTSC) {
585 singlefield_lines += 1;
586 odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
587 } else {
588 singlefield_lines = PAL_FIELD_HEIGHT;
589 odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
590 }
591
592 if (dev->_dma_virt_start_addr != NULL) {
593 line_size_in_bytes =
594 (dev->_pixel_format ==
595 PIXEL_FRMT_411) ? Y411_LINE_SZ :
596 Y422_LINE_SZ;
597 risc_phys_jump_addr =
598 dev->_dma_phys_start_addr +
599 odd_risc_prog_size;
600
601 rp = cx25821_update_riscprogram(dev,
Leonid V. Fedorenchik2b2d0392011-09-02 11:55:46 +0800602 dev->_dma_virt_start_addr, TOP_OFFSET,
603 line_size_in_bytes, 0x0,
604 singlefield_lines, FIFO_DISABLE,
605 ODD_FIELD);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300606
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300607 /* Jump to Even Risc program of 1st Frame */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300608 *(rp++) = cpu_to_le32(RISC_JUMP);
609 *(rp++) = cpu_to_le32(risc_phys_jump_addr);
610 *(rp++) = cpu_to_le32(0);
611 }
612 }
613
614 spin_unlock(&dev->slock);
615 } else {
616 if (status & FLD_VID_SRC_UF)
Joe Perches36d89f72010-11-07 17:48:21 -0300617 pr_err("%s(): Video Received Underflow Error Interrupt!\n",
618 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300619
620 if (status & FLD_VID_SRC_SYNC)
Joe Perches36d89f72010-11-07 17:48:21 -0300621 pr_err("%s(): Video Received Sync Error Interrupt!\n",
622 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300623
624 if (status & FLD_VID_SRC_OPC_ERR)
Joe Perches36d89f72010-11-07 17:48:21 -0300625 pr_err("%s(): Video Received OpCode Error Interrupt!\n",
626 __func__);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300627 }
628
629 if (dev->_file_status == END_OF_FILE) {
Joe Perches36d89f72010-11-07 17:48:21 -0300630 pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300631 return -1;
632 }
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300633 /* ElSE, set the interrupt mask register, re-enable irq. */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300634 int_msk_tmp = cx_read(channel->int_msk);
635 cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
636
637 return 0;
638}
639
640static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
641{
642 struct cx25821_dev *dev = dev_id;
Hans Verkuil30fdf032012-04-20 06:26:19 -0300643 u32 vid_status;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300644 int handled = 0;
645 int channel_num = 0;
646 struct sram_channel *sram_ch;
647
648 if (!dev)
649 return -1;
650
651 channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;
652
Ruslan Pisareve4115bb2010-09-27 10:01:36 -0300653 sram_ch = dev->channels[channel_num].sram_channels;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300654
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300655 vid_status = cx_read(sram_ch->int_stat);
656
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300657 /* Only deal with our interrupt */
Leonid V. Fedorenchik16f0fda2011-10-22 01:43:46 -0300658 if (vid_status)
659 handled = cx25821_video_upstream_irq(dev, channel_num,
660 vid_status);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300661
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300662 if (handled < 0)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300663 cx25821_stop_upstream_video_ch1(dev);
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300664 else
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300665 handled += handled;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300666
667 return IRQ_RETVAL(handled);
668}
669
Mauro Carvalho Chehabdafc4562012-10-27 12:42:59 -0300670static void cx25821_set_pixelengine(struct cx25821_dev *dev,
671 struct sram_channel *ch,
672 int pix_format)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300673{
674 int width = WIDTH_D1;
675 int height = dev->_lines_count;
676 int num_lines, odd_num_lines;
677 u32 value;
678 int vip_mode = OUTPUT_FRMT_656;
679
680 value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
681 value &= 0xFFFFFFEF;
682 value |= dev->_isNTSC ? 0 : 0x10;
683 cx_write(ch->vid_fmt_ctl, value);
684
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300685 /* set number of active pixels in each line.
686 * Default is 720 pixels in both NTSC and PAL format */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300687 cx_write(ch->vid_active_ctl1, width);
688
689 num_lines = (height / 2) & 0x3FF;
690 odd_num_lines = num_lines;
691
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300692 if (dev->_isNTSC)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300693 odd_num_lines += 1;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300694
695 value = (num_lines << 16) | odd_num_lines;
696
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300697 /* set number of active lines in field 0 (top) and field 1 (bottom) */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300698 cx_write(ch->vid_active_ctl2, value);
699
700 cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
701}
702
Mauro Carvalho Chehabdafc4562012-10-27 12:42:59 -0300703static int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
704 struct sram_channel *sram_ch)
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300705{
706 u32 tmp = 0;
707 int err = 0;
708
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300709 /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
710 * channel A-C
711 */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300712 tmp = cx_read(VID_CH_MODE_SEL);
713 cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
714
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300715 /* Set the physical start address of the RISC program in the initial
716 * program counter(IPC) member of the cmds.
717 */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300718 cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300719 /* Risc IPC High 64 bits 63-32 */
720 cx_write(sram_ch->cmds_start + 4, 0);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300721
722 /* reset counter */
723 cx_write(sram_ch->gpcnt_ctl, 3);
724
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300725 /* Clear our bits from the interrupt status register. */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300726 cx_write(sram_ch->int_stat, _intr_msk);
727
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300728 /* Set the interrupt mask register, enable irq. */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300729 cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
730 tmp = cx_read(sram_ch->int_msk);
731 cx_write(sram_ch->int_msk, tmp |= _intr_msk);
732
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300733 err = request_irq(dev->pci->irq, cx25821_upstream_irq,
Yong Zhang18e93512011-09-07 16:10:22 +0800734 IRQF_SHARED, dev->name, dev);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300735 if (err < 0) {
Joe Perches36d89f72010-11-07 17:48:21 -0300736 pr_err("%s: can't get upstream IRQ %d\n",
737 dev->name, dev->pci->irq);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300738 goto fail_irq;
739 }
740
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300741 /* Start the DMA engine */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300742 tmp = cx_read(sram_ch->dma_ctl);
743 cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
744
745 dev->_is_running = 1;
746 dev->_is_first_frame = 1;
747
748 return 0;
749
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300750fail_irq:
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300751 cx25821_dev_unregister(dev);
752 return err;
753}
754
755int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
756 int pixel_format)
757{
758 struct sram_channel *sram_ch;
759 u32 tmp;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300760 int err = 0;
761 int data_frame_size = 0;
762 int risc_buffer_size = 0;
763 int str_length = 0;
764
765 if (dev->_is_running) {
Joe Perches36d89f72010-11-07 17:48:21 -0300766 pr_info("Video Channel is still running so return!\n");
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300767 return 0;
768 }
769
770 dev->_channel_upstream_select = channel_select;
Ruslan Pisareve4115bb2010-09-27 10:01:36 -0300771 sram_ch = dev->channels[channel_select].sram_channels;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300772
773 INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);
774 dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
775
776 if (!dev->_irq_queues) {
Joe Perches36d89f72010-11-07 17:48:21 -0300777 pr_err("create_singlethread_workqueue() for Video FAILED!\n");
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300778 return -ENOMEM;
779 }
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300780 /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
781 * channel A-C
782 */
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300783 tmp = cx_read(VID_CH_MODE_SEL);
784 cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
785
786 dev->_is_running = 0;
787 dev->_frame_count = 0;
788 dev->_file_status = RESET_STATUS;
789 dev->_lines_count = dev->_isNTSC ? 480 : 576;
790 dev->_pixel_format = pixel_format;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300791 dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
792 (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300793 data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300794 risc_buffer_size = dev->_isNTSC ?
795 NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300796
797 if (dev->input_filename) {
798 str_length = strlen(dev->input_filename);
Thomas Meyer0ceaec12011-11-17 19:12:18 -0300799 dev->_filename = kmemdup(dev->input_filename, str_length + 1,
800 GFP_KERNEL);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300801
Peter Senna Tschudin216f3932012-09-06 11:23:56 -0300802 if (!dev->_filename) {
803 err = -ENOENT;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300804 goto error;
Peter Senna Tschudin216f3932012-09-06 11:23:56 -0300805 }
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300806 } else {
807 str_length = strlen(dev->_defaultname);
Thomas Meyer0ceaec12011-11-17 19:12:18 -0300808 dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
809 GFP_KERNEL);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300810
Peter Senna Tschudin216f3932012-09-06 11:23:56 -0300811 if (!dev->_filename) {
812 err = -ENOENT;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300813 goto error;
Peter Senna Tschudin216f3932012-09-06 11:23:56 -0300814 }
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300815 }
816
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300817 /* Default if filename is empty string */
Dan Carpenter546196a2012-09-29 03:12:53 -0300818 if (strcmp(dev->_filename, "") == 0) {
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300819 if (dev->_isNTSC) {
820 dev->_filename =
Leonid V. Fedorenchik2c68e932011-10-22 01:43:47 -0300821 (dev->_pixel_format == PIXEL_FRMT_411) ?
822 "/root/vid411.yuv" : "/root/vidtest.yuv";
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300823 } else {
824 dev->_filename =
Leonid V. Fedorenchik2c68e932011-10-22 01:43:47 -0300825 (dev->_pixel_format == PIXEL_FRMT_411) ?
826 "/root/pal411.yuv" : "/root/pal422.yuv";
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300827 }
828 }
829
830 dev->_is_running = 0;
831 dev->_frame_count = 0;
832 dev->_file_status = RESET_STATUS;
833 dev->_lines_count = dev->_isNTSC ? 480 : 576;
834 dev->_pixel_format = pixel_format;
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300835 dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
836 (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300837
Peter Senna Tschudin216f3932012-09-06 11:23:56 -0300838 err = cx25821_sram_channel_setup_upstream(dev, sram_ch,
Leonid V. Fedorenchik8eb1fdf2011-10-22 01:43:48 -0300839 dev->_line_size, 0);
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300840
841 /* setup fifo + format */
842 cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
843
844 dev->upstream_riscbuf_size = risc_buffer_size * 2;
845 dev->upstream_databuf_size = data_frame_size * 2;
846
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300847 /* Allocating buffers and prepare RISC program */
Peter Senna Tschudin216f3932012-09-06 11:23:56 -0300848 err = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
849 if (err < 0) {
Joe Perches36d89f72010-11-07 17:48:21 -0300850 pr_err("%s: Failed to set up Video upstream buffers!\n",
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300851 dev->name);
852 goto error;
853 }
854
855 cx25821_start_video_dma_upstream(dev, sram_ch);
856
857 return 0;
858
Olimpiu Pascariu10991232010-04-06 02:09:00 -0300859error:
Mauro Carvalho Chehab1a9fc852009-09-13 11:30:11 -0300860 cx25821_dev_unregister(dev);
861
862 return err;
863}