aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:50:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 22:50:49 -0500
commit3e7468313758913c5e4d372f35b271b96bad1298 (patch)
treeeb612d252a9e2349a1173451cd779beebd18a33e /drivers/media/video/cx18
parent6825fbc4cb219f2c98bb7d157915d797cf5cb823 (diff)
parente97f4677961f68e29bd906022ebf60a6df7f530a (diff)
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (345 commits) V4L/DVB (13542): ir-keytable: Allow dynamic table change V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage V4L/DVB (13540): ir-common: Cleanup get key evdev code V4L/DVB (13539): ir-common: add __func__ for debug messages V4L/DVB (13538): ir-common: Use a dynamic keycode table V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code V4L/DVB (13534): ir-common: Remove some unused fields/structs V4L/DVB (13533): ir: use dynamic tables, instead of static ones V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it V4L/DVB (13458): go7007: subdev conversion V4L/DVB (13457): s2250: subdev conversion V4L/DVB (13456): s2250: Change module structure V4L/DVB (13528): em28xx: add support for em2800 VC211A card em28xx: don't reduce scale to half size for em2800 em28xx: don't load audio modules when AC97 is mis-detected em28xx: em2800 chips support max width of 640 V4L/DVB (13523): dvb-bt8xx: fix compile warning ... Fix up trivial conflicts due to spelling fixes from the trivial tree in Documentation/video4linux/gspca.txt drivers/media/video/cx18/cx18-mailbox.h
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c14
-rw-r--r--drivers/media/video/cx18/cx18-cards.h3
-rw-r--r--drivers/media/video/cx18/cx18-driver.c60
-rw-r--r--drivers/media/video/cx18/cx18-driver.h62
-rw-r--r--drivers/media/video/cx18/cx18-dvb.c9
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c132
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c25
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c3
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c62
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.h6
-rw-r--r--drivers/media/video/cx18/cx18-queue.c346
-rw-r--r--drivers/media/video/cx18/cx18-queue.h41
-rw-r--r--drivers/media/video/cx18/cx18-scb.h4
-rw-r--r--drivers/media/video/cx18/cx18-streams.c92
-rw-r--r--drivers/media/video/cx18/cx18-streams.h10
-rw-r--r--drivers/media/video/cx18/cx18-vbi.c35
-rw-r--r--drivers/media/video/cx18/cx18-vbi.h2
-rw-r--r--drivers/media/video/cx18/cx18-version.h2
-rw-r--r--drivers/media/video/cx18/cx23418.h2
19 files changed, 666 insertions, 244 deletions
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 536dedb23ba3..4392c76af5df 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -99,10 +99,8 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
99 or_value); 99 or_value);
100} 100}
101 101
102static int cx18_av_init(struct v4l2_subdev *sd, u32 val) 102static void cx18_av_init(struct cx18 *cx)
103{ 103{
104 struct cx18 *cx = v4l2_get_subdevdata(sd);
105
106 /* 104 /*
107 * The crystal freq used in calculations in this driver will be 105 * The crystal freq used in calculations in this driver will be
108 * 28.636360 MHz. 106 * 28.636360 MHz.
@@ -125,7 +123,6 @@ static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
125 123
126 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ 124 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
127 cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); 125 cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
128 return 0;
129} 126}
130 127
131static void cx18_av_initialize(struct v4l2_subdev *sd) 128static void cx18_av_initialize(struct v4l2_subdev *sd)
@@ -198,7 +195,7 @@ static void cx18_av_initialize(struct v4l2_subdev *sd)
198 cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000); 195 cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
199 196
200 /* Setup the Video and and Aux/Audio PLLs */ 197 /* Setup the Video and and Aux/Audio PLLs */
201 cx18_av_init(sd, 0); 198 cx18_av_init(cx);
202 199
203 /* set video to auto-detect */ 200 /* set video to auto-detect */
204 /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */ 201 /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */
@@ -1355,7 +1352,6 @@ static int cx18_av_s_register(struct v4l2_subdev *sd,
1355static const struct v4l2_subdev_core_ops cx18_av_general_ops = { 1352static const struct v4l2_subdev_core_ops cx18_av_general_ops = {
1356 .g_chip_ident = cx18_av_g_chip_ident, 1353 .g_chip_ident = cx18_av_g_chip_ident,
1357 .log_status = cx18_av_log_status, 1354 .log_status = cx18_av_log_status,
1358 .init = cx18_av_init,
1359 .load_fw = cx18_av_load_fw, 1355 .load_fw = cx18_av_load_fw,
1360 .reset = cx18_av_reset, 1356 .reset = cx18_av_reset,
1361 .queryctrl = cx18_av_queryctrl, 1357 .queryctrl = cx18_av_queryctrl,
@@ -1399,6 +1395,7 @@ int cx18_av_probe(struct cx18 *cx)
1399{ 1395{
1400 struct cx18_av_state *state = &cx->av_state; 1396 struct cx18_av_state *state = &cx->av_state;
1401 struct v4l2_subdev *sd; 1397 struct v4l2_subdev *sd;
1398 int err;
1402 1399
1403 state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; 1400 state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff;
1404 state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) 1401 state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO)
@@ -1417,5 +1414,8 @@ int cx18_av_probe(struct cx18 *cx)
1417 snprintf(sd->name, sizeof(sd->name), 1414 snprintf(sd->name, sizeof(sd->name),
1418 "%s %03x", cx->v4l2_dev.name, (state->rev >> 4)); 1415 "%s %03x", cx->v4l2_dev.name, (state->rev >> 4));
1419 sd->grp_id = CX18_HW_418_AV; 1416 sd->grp_id = CX18_HW_418_AV;
1420 return v4l2_device_register_subdev(&cx->v4l2_dev, sd); 1417 err = v4l2_device_register_subdev(&cx->v4l2_dev, sd);
1418 if (!err)
1419 cx18_av_init(cx);
1420 return err;
1421} 1421}
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index 444e3c7c563e..af3d71607dc9 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -34,6 +34,9 @@
34#define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \ 34#define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \
35 CX18_HW_Z8F0811_IR_TX_HAUP) 35 CX18_HW_Z8F0811_IR_TX_HAUP)
36 36
37#define CX18_HW_IR_ANY (CX18_HW_Z8F0811_IR_RX_HAUP | \
38 CX18_HW_Z8F0811_IR_TX_HAUP)
39
37/* video inputs */ 40/* video inputs */
38#define CX18_CARD_INPUT_VID_TUNER 1 41#define CX18_CARD_INPUT_VID_TUNER 1
39#define CX18_CARD_INPUT_SVIDEO1 2 42#define CX18_CARD_INPUT_SVIDEO1 2
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index e12082b8a08d..7f65a47f12e1 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -87,7 +87,6 @@ static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE;
87static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE; 87static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE;
88static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE; 88static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE;
89static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE; 89static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE;
90/* VBI bufsize based on standards supported by card tuner for now */
91static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; 90static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE;
92 91
93static int enc_ts_bufs = -1; 92static int enc_ts_bufs = -1;
@@ -128,7 +127,6 @@ module_param(enc_ts_bufsize, int, 0644);
128module_param(enc_mpg_bufsize, int, 0644); 127module_param(enc_mpg_bufsize, int, 0644);
129module_param(enc_idx_bufsize, int, 0644); 128module_param(enc_idx_bufsize, int, 0644);
130module_param(enc_yuv_bufsize, int, 0644); 129module_param(enc_yuv_bufsize, int, 0644);
131/* VBI bufsize based on standards supported by card tuner for now */
132module_param(enc_pcm_bufsize, int, 0644); 130module_param(enc_pcm_bufsize, int, 0644);
133 131
134module_param(enc_ts_bufs, int, 0644); 132module_param(enc_ts_bufs, int, 0644);
@@ -211,7 +209,9 @@ MODULE_PARM_DESC(enc_yuv_buffers,
211 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); 209 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
212MODULE_PARM_DESC(enc_yuv_bufsize, 210MODULE_PARM_DESC(enc_yuv_bufsize,
213 "Size of an encoder YUV buffer (kB)\n" 211 "Size of an encoder YUV buffer (kB)\n"
214 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFSIZE)); 212 "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n"
213 "\t\t\t(multiples of size required for 32 screen lines)\n"
214 "\t\t\tDefault: 102");
215MODULE_PARM_DESC(enc_yuv_bufs, 215MODULE_PARM_DESC(enc_yuv_bufs,
216 "Number of encoder YUV buffers\n" 216 "Number of encoder YUV buffers\n"
217 "\t\t\tDefault is computed from other enc_yuv_* parameters"); 217 "\t\t\tDefault is computed from other enc_yuv_* parameters");
@@ -220,7 +220,7 @@ MODULE_PARM_DESC(enc_vbi_buffers,
220 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS)); 220 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
221MODULE_PARM_DESC(enc_vbi_bufs, 221MODULE_PARM_DESC(enc_vbi_bufs,
222 "Number of encoder VBI buffers\n" 222 "Number of encoder VBI buffers\n"
223 "\t\t\tDefault is computed from enc_vbi_buffers & tuner std"); 223 "\t\t\tDefault is computed from enc_vbi_buffers");
224MODULE_PARM_DESC(enc_pcm_buffers, 224MODULE_PARM_DESC(enc_pcm_buffers,
225 "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n" 225 "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n"
226 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); 226 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
@@ -499,10 +499,27 @@ static void cx18_process_options(struct cx18 *cx)
499 continue; 499 continue;
500 } 500 }
501 /* 501 /*
502 * YUV is a special case where the stream_buf_size needs to be
503 * an integral multiple of 33.75 kB (storage for 32 screens
504 * lines to maintain alignment in case of lost buffers
505 */
506 if (i == CX18_ENC_STREAM_TYPE_YUV) {
507 cx->stream_buf_size[i] *= 1024;
508 cx->stream_buf_size[i] -=
509 (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE);
510
511 if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE)
512 cx->stream_buf_size[i] =
513 CX18_UNIT_ENC_YUV_BUFSIZE;
514 }
515 /*
516 * YUV is a special case where the stream_buf_size is
517 * now in bytes.
502 * VBI is a special case where the stream_buf_size is fixed 518 * VBI is a special case where the stream_buf_size is fixed
503 * and already in bytes 519 * and already in bytes
504 */ 520 */
505 if (i == CX18_ENC_STREAM_TYPE_VBI) { 521 if (i == CX18_ENC_STREAM_TYPE_VBI ||
522 i == CX18_ENC_STREAM_TYPE_YUV) {
506 if (cx->stream_buffers[i] < 0) { 523 if (cx->stream_buffers[i] < 0) {
507 cx->stream_buffers[i] = 524 cx->stream_buffers[i] =
508 cx->options.megabytes[i] * 1024 * 1024 525 cx->options.megabytes[i] * 1024 * 1024
@@ -513,18 +530,24 @@ static void cx18_process_options(struct cx18 *cx)
513 cx->stream_buffers[i] 530 cx->stream_buffers[i]
514 * cx->stream_buf_size[i]/(1024 * 1024); 531 * cx->stream_buf_size[i]/(1024 * 1024);
515 } 532 }
516 continue;
517 }
518 /* All other streams have stream_buf_size in kB at this point */
519 if (cx->stream_buffers[i] < 0) {
520 cx->stream_buffers[i] = cx->options.megabytes[i] * 1024
521 / cx->stream_buf_size[i];
522 } else { 533 } else {
523 /* N.B. This might round down to 0 */ 534 /* All other streams have stream_buf_size in kB here */
524 cx->options.megabytes[i] = 535 if (cx->stream_buffers[i] < 0) {
525 cx->stream_buffers[i] * cx->stream_buf_size[i] / 1024; 536 cx->stream_buffers[i] =
537 cx->options.megabytes[i] * 1024
538 / cx->stream_buf_size[i];
539 } else {
540 /* N.B. This might round down to 0 */
541 cx->options.megabytes[i] =
542 cx->stream_buffers[i]
543 * cx->stream_buf_size[i] / 1024;
544 }
545 /* convert from kB to bytes */
546 cx->stream_buf_size[i] *= 1024;
526 } 547 }
527 cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */ 548 CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, "
549 "%d bytes\n", i, cx->options.megabytes[i],
550 cx->stream_buffers[i], cx->stream_buf_size[i]);
528 } 551 }
529 552
530 cx->options.cardtype = cardtype[cx->instance]; 553 cx->options.cardtype = cardtype[cx->instance];
@@ -669,6 +692,12 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
669 cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; 692 cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
670 cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; 693 cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
671 694
695 /* IVTV style VBI insertion into MPEG streams */
696 INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list);
697 INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list);
698 INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list);
699 list_add(&cx->vbi.sliced_mpeg_buf.list,
700 &cx->vbi.sliced_mpeg_mdl.buf_list);
672 return 0; 701 return 0;
673} 702}
674 703
@@ -883,7 +912,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
883 CX18_ERR("Could not register A/V decoder subdevice\n"); 912 CX18_ERR("Could not register A/V decoder subdevice\n");
884 goto free_map; 913 goto free_map;
885 } 914 }
886 cx18_call_hw(cx, CX18_HW_418_AV, core, init, 0);
887 915
888 /* Initialize GPIO Reset Controller to do chip resets during i2c init */ 916 /* Initialize GPIO Reset Controller to do chip resets during i2c init */
889 if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) { 917 if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) {
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index c6a1e907f63a..e3f7911a7385 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -50,6 +50,7 @@
50#include <media/v4l2-ioctl.h> 50#include <media/v4l2-ioctl.h>
51#include <media/v4l2-device.h> 51#include <media/v4l2-device.h>
52#include <media/tuner.h> 52#include <media/tuner.h>
53#include <media/ir-kbd-i2c.h>
53#include "cx18-mailbox.h" 54#include "cx18-mailbox.h"
54#include "cx18-av-core.h" 55#include "cx18-av-core.h"
55#include "cx23418.h" 56#include "cx23418.h"
@@ -120,12 +121,16 @@
120/* Maximum firmware DMA buffers per stream */ 121/* Maximum firmware DMA buffers per stream */
121#define CX18_MAX_FW_MDLS_PER_STREAM 63 122#define CX18_MAX_FW_MDLS_PER_STREAM 63
122 123
124/* YUV buffer sizes in bytes to ensure integer # of frames per buffer */
125#define CX18_UNIT_ENC_YUV_BUFSIZE (720 * 32 * 3 / 2) /* bytes */
126#define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32)
127#define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32)
128
123/* DMA buffer, default size in kB allocated */ 129/* DMA buffer, default size in kB allocated */
124#define CX18_DEFAULT_ENC_TS_BUFSIZE 32 130#define CX18_DEFAULT_ENC_TS_BUFSIZE 32
125#define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 131#define CX18_DEFAULT_ENC_MPG_BUFSIZE 32
126#define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 132#define CX18_DEFAULT_ENC_IDX_BUFSIZE 32
127#define CX18_DEFAULT_ENC_YUV_BUFSIZE 128 133#define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1)
128/* Default VBI bufsize based on standards supported by card tuner for now */
129#define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 134#define CX18_DEFAULT_ENC_PCM_BUFSIZE 4
130 135
131/* i2c stuff */ 136/* i2c stuff */
@@ -246,8 +251,8 @@ struct cx18_options {
246 int radio; /* enable/disable radio */ 251 int radio; /* enable/disable radio */
247}; 252};
248 253
249/* per-buffer bit flags */ 254/* per-mdl bit flags */
250#define CX18_F_B_NEED_BUF_SWAP 0 /* this buffer should be byte swapped */ 255#define CX18_F_M_NEED_SWAP 0 /* mdl buffer data must be endianess swapped */
251 256
252/* per-stream, s_flags */ 257/* per-stream, s_flags */
253#define CX18_F_S_CLAIMED 3 /* this stream is claimed */ 258#define CX18_F_S_CLAIMED 3 /* this stream is claimed */
@@ -274,18 +279,29 @@ struct cx18_options {
274struct cx18_buffer { 279struct cx18_buffer {
275 struct list_head list; 280 struct list_head list;
276 dma_addr_t dma_handle; 281 dma_addr_t dma_handle;
277 u32 id;
278 unsigned long b_flags;
279 unsigned skipped;
280 char *buf; 282 char *buf;
281 283
282 u32 bytesused; 284 u32 bytesused;
283 u32 readpos; 285 u32 readpos;
284}; 286};
285 287
288struct cx18_mdl {
289 struct list_head list;
290 u32 id; /* index into cx->scb->cpu_mdl[] of 1st cx18_mdl_ent */
291
292 unsigned int skipped;
293 unsigned long m_flags;
294
295 struct list_head buf_list;
296 struct cx18_buffer *curr_buf; /* current buffer in list for reading */
297
298 u32 bytesused;
299 u32 readpos;
300};
301
286struct cx18_queue { 302struct cx18_queue {
287 struct list_head list; 303 struct list_head list;
288 atomic_t buffers; 304 atomic_t depth;
289 u32 bytesused; 305 u32 bytesused;
290 spinlock_t lock; 306 spinlock_t lock;
291}; 307};
@@ -337,7 +353,7 @@ struct cx18_stream {
337 const char *name; /* name of the stream */ 353 const char *name; /* name of the stream */
338 int type; /* stream type */ 354 int type; /* stream type */
339 u32 handle; /* task handle */ 355 u32 handle; /* task handle */
340 unsigned mdl_offset; 356 unsigned int mdl_base_idx;
341 357
342 u32 id; 358 u32 id;
343 unsigned long s_flags; /* status flags, see above */ 359 unsigned long s_flags; /* status flags, see above */
@@ -346,14 +362,20 @@ struct cx18_stream {
346 PCI_DMA_NONE */ 362 PCI_DMA_NONE */
347 wait_queue_head_t waitq; 363 wait_queue_head_t waitq;
348 364
349 /* Buffer Stats */ 365 /* Buffers */
350 u32 buffers; 366 struct list_head buf_pool; /* buffers not attached to an MDL */
351 u32 buf_size; 367 u32 buffers; /* total buffers owned by this stream */
368 u32 buf_size; /* size in bytes of a single buffer */
369
370 /* MDL sizes - all stream MDLs are the same size */
371 u32 bufs_per_mdl;
372 u32 mdl_size; /* total bytes in all buffers in a mdl */
352 373
353 /* Buffer Queues */ 374 /* MDL Queues */
354 struct cx18_queue q_free; /* free buffers */ 375 struct cx18_queue q_free; /* free - in rotation, not committed */
355 struct cx18_queue q_busy; /* busy buffers - in use by firmware */ 376 struct cx18_queue q_busy; /* busy - in use by firmware */
356 struct cx18_queue q_full; /* full buffers - data for user apps */ 377 struct cx18_queue q_full; /* full - data for user apps */
378 struct cx18_queue q_idle; /* idle - not in rotation */
357 379
358 struct work_struct out_work_order; 380 struct work_struct out_work_order;
359 381
@@ -481,10 +503,11 @@ struct vbi_info {
481 u32 inserted_frame; 503 u32 inserted_frame;
482 504
483 /* 505 /*
484 * A dummy driver stream transfer buffer with a copy of the next 506 * A dummy driver stream transfer mdl & buffer with a copy of the next
485 * sliced_mpeg_data[] buffer for output to userland apps. 507 * sliced_mpeg_data[] buffer for output to userland apps.
486 * Only used in cx18-fileops.c, but its state needs to persist at times. 508 * Only used in cx18-fileops.c, but its state needs to persist at times.
487 */ 509 */
510 struct cx18_mdl sliced_mpeg_mdl;
488 struct cx18_buffer sliced_mpeg_buf; 511 struct cx18_buffer sliced_mpeg_buf;
489}; 512};
490 513
@@ -511,10 +534,9 @@ struct cx18 {
511 u8 is_60hz; 534 u8 is_60hz;
512 u8 nof_inputs; /* number of video inputs */ 535 u8 nof_inputs; /* number of video inputs */
513 u8 nof_audio_inputs; /* number of audio inputs */ 536 u8 nof_audio_inputs; /* number of audio inputs */
514 u16 buffer_id; /* buffer ID counter */
515 u32 v4l2_cap; /* V4L2 capabilities of card */ 537 u32 v4l2_cap; /* V4L2 capabilities of card */
516 u32 hw_flags; /* Hardware description of the board */ 538 u32 hw_flags; /* Hardware description of the board */
517 unsigned mdl_offset; 539 unsigned int free_mdl_idx;
518 struct cx18_scb __iomem *scb; /* pointer to SCB */ 540 struct cx18_scb __iomem *scb; /* pointer to SCB */
519 struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/ 541 struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/
520 struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/ 542 struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/
@@ -585,6 +607,8 @@ struct cx18 {
585 struct i2c_algo_bit_data i2c_algo[2]; 607 struct i2c_algo_bit_data i2c_algo[2];
586 struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2]; 608 struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2];
587 609
610 struct IR_i2c_init_data ir_i2c_init_data;
611
588 /* gpio */ 612 /* gpio */
589 u32 gpio_dir; 613 u32 gpio_dir;
590 u32 gpio_val; 614 u32 gpio_val;
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index 51a0c33b25b7..71ad2d1b4c2c 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -61,6 +61,7 @@ static struct mxl5005s_config hauppauge_hvr1600_tuner = {
61 .top = MXL5005S_TOP_25P2, 61 .top = MXL5005S_TOP_25P2,
62 .mod_mode = MXL_DIGITAL_MODE, 62 .mod_mode = MXL_DIGITAL_MODE,
63 .if_mode = MXL_ZERO_IF, 63 .if_mode = MXL_ZERO_IF,
64 .qam_gain = 0x02,
64 .AgcMasterByte = 0x00, 65 .AgcMasterByte = 0x00,
65}; 66};
66 67
@@ -71,7 +72,8 @@ static struct s5h1409_config hauppauge_hvr1600_config = {
71 .qam_if = 44000, 72 .qam_if = 44000,
72 .inversion = S5H1409_INVERSION_OFF, 73 .inversion = S5H1409_INVERSION_OFF,
73 .status_mode = S5H1409_DEMODLOCKING, 74 .status_mode = S5H1409_DEMODLOCKING,
74 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 75 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
76 .hvr1600_opt = S5H1409_HVR1600_OPTIMIZE
75}; 77};
76 78
77/* 79/*
@@ -360,9 +362,10 @@ int cx18_dvb_register(struct cx18_stream *stream)
360 dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx); 362 dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
361 363
362 CX18_INFO("DVB Frontend registered\n"); 364 CX18_INFO("DVB Frontend registered\n");
363 CX18_INFO("Registered DVB adapter%d for %s (%d x %d kB)\n", 365 CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
364 stream->dvb.dvb_adapter.num, stream->name, 366 stream->dvb.dvb_adapter.num, stream->name,
365 stream->buffers, stream->buf_size/1024); 367 stream->buffers, stream->buf_size/1024,
368 (stream->buf_size * 100 / 1024) % 100);
366 369
367 mutex_init(&dvb->feedlock); 370 mutex_init(&dvb->feedlock);
368 dvb->enabled = 1; 371 dvb->enabled = 1;
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 04d9c2508b86..4e278db31cc9 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -166,11 +166,12 @@ static void cx18_dualwatch(struct cx18 *cx)
166} 166}
167 167
168 168
169static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, int *err) 169static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
170 int *err)
170{ 171{
171 struct cx18 *cx = s->cx; 172 struct cx18 *cx = s->cx;
172 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; 173 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
173 struct cx18_buffer *buf; 174 struct cx18_mdl *mdl;
174 DEFINE_WAIT(wait); 175 DEFINE_WAIT(wait);
175 176
176 *err = 0; 177 *err = 0;
@@ -185,32 +186,33 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
185 } 186 }
186 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && 187 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
187 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { 188 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
188 while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { 189 while ((mdl = cx18_dequeue(s_vbi,
190 &s_vbi->q_full))) {
189 /* byteswap and process VBI data */ 191 /* byteswap and process VBI data */
190 cx18_process_vbi_data(cx, buf, 192 cx18_process_vbi_data(cx, mdl,
191 s_vbi->type); 193 s_vbi->type);
192 cx18_stream_put_buf_fw(s_vbi, buf); 194 cx18_stream_put_mdl_fw(s_vbi, mdl);
193 } 195 }
194 } 196 }
195 buf = &cx->vbi.sliced_mpeg_buf; 197 mdl = &cx->vbi.sliced_mpeg_mdl;
196 if (buf->readpos != buf->bytesused) 198 if (mdl->readpos != mdl->bytesused)
197 return buf; 199 return mdl;
198 } 200 }
199 201
200 /* do we have new data? */ 202 /* do we have new data? */
201 buf = cx18_dequeue(s, &s->q_full); 203 mdl = cx18_dequeue(s, &s->q_full);
202 if (buf) { 204 if (mdl) {
203 if (!test_and_clear_bit(CX18_F_B_NEED_BUF_SWAP, 205 if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
204 &buf->b_flags)) 206 &mdl->m_flags))
205 return buf; 207 return mdl;
206 if (s->type == CX18_ENC_STREAM_TYPE_MPG) 208 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
207 /* byteswap MPG data */ 209 /* byteswap MPG data */
208 cx18_buf_swap(buf); 210 cx18_mdl_swap(mdl);
209 else { 211 else {
210 /* byteswap and process VBI data */ 212 /* byteswap and process VBI data */
211 cx18_process_vbi_data(cx, buf, s->type); 213 cx18_process_vbi_data(cx, mdl, s->type);
212 } 214 }
213 return buf; 215 return mdl;
214 } 216 }
215 217
216 /* return if end of stream */ 218 /* return if end of stream */
@@ -229,7 +231,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
229 prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); 231 prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
230 /* New buffers might have become available before we were added 232 /* New buffers might have become available before we were added
231 to the waitqueue */ 233 to the waitqueue */
232 if (!atomic_read(&s->q_full.buffers)) 234 if (!atomic_read(&s->q_full.depth))
233 schedule(); 235 schedule();
234 finish_wait(&s->waitq, &wait); 236 finish_wait(&s->waitq, &wait);
235 if (signal_pending(current)) { 237 if (signal_pending(current)) {
@@ -241,21 +243,28 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
241 } 243 }
242} 244}
243 245
244static void cx18_setup_sliced_vbi_buf(struct cx18 *cx) 246static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
245{ 247{
248 struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
249 struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
246 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; 250 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
247 251
248 cx->vbi.sliced_mpeg_buf.buf = cx->vbi.sliced_mpeg_data[idx]; 252 buf->buf = cx->vbi.sliced_mpeg_data[idx];
249 cx->vbi.sliced_mpeg_buf.bytesused = cx->vbi.sliced_mpeg_size[idx]; 253 buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
250 cx->vbi.sliced_mpeg_buf.readpos = 0; 254 buf->readpos = 0;
255
256 mdl->curr_buf = NULL;
257 mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
258 mdl->readpos = 0;
251} 259}
252 260
253static size_t cx18_copy_buf_to_user(struct cx18_stream *s, 261static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
254 struct cx18_buffer *buf, char __user *ubuf, size_t ucount) 262 struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
255{ 263{
256 struct cx18 *cx = s->cx; 264 struct cx18 *cx = s->cx;
257 size_t len = buf->bytesused - buf->readpos; 265 size_t len = buf->bytesused - buf->readpos;
258 266
267 *stop = false;
259 if (len > ucount) 268 if (len > ucount)
260 len = ucount; 269 len = ucount;
261 if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && 270 if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
@@ -335,7 +344,8 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
335 /* We declare we actually found a Program Pack*/ 344 /* We declare we actually found a Program Pack*/
336 cx->search_pack_header = 0; /* expect vid PES */ 345 cx->search_pack_header = 0; /* expect vid PES */
337 len = (char *)q - start; 346 len = (char *)q - start;
338 cx18_setup_sliced_vbi_buf(cx); 347 cx18_setup_sliced_vbi_mdl(cx);
348 *stop = true;
339 break; 349 break;
340 } 350 }
341 } 351 }
@@ -352,6 +362,60 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
352 return len; 362 return len;
353} 363}
354 364
365/**
366 * list_entry_is_past_end - check if a previous loop cursor is off list end
367 * @pos: the type * previously used as a loop cursor.
368 * @head: the head for your list.
369 * @member: the name of the list_struct within the struct.
370 *
371 * Check if the entry's list_head is the head of the list, thus it's not a
372 * real entry but was the loop cursor that walked past the end
373 */
374#define list_entry_is_past_end(pos, head, member) \
375 (&pos->member == (head))
376
377static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
378 struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
379{
380 size_t tot_written = 0;
381 int rc;
382 bool stop = false;
383
384 if (mdl->curr_buf == NULL)
385 mdl->curr_buf = list_first_entry(&mdl->buf_list,
386 struct cx18_buffer, list);
387
388 if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
389 /*
390 * For some reason we've exhausted the buffers, but the MDL
391 * object still said some data was unread.
392 * Fix that and bail out.
393 */
394 mdl->readpos = mdl->bytesused;
395 return 0;
396 }
397
398 list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
399
400 if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
401 continue;
402
403 rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
404 ucount - tot_written, &stop);
405 if (rc < 0)
406 return rc;
407 mdl->readpos += rc;
408 tot_written += rc;
409
410 if (stop || /* Forced stopping point for VBI insertion */
411 tot_written >= ucount || /* Reader request statisfied */
412 mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
413 mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
414 break;
415 }
416 return tot_written;
417}
418
355static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, 419static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
356 size_t tot_count, int non_block) 420 size_t tot_count, int non_block)
357{ 421{
@@ -373,12 +437,12 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
373 single_frame = 1; 437 single_frame = 1;
374 438
375 for (;;) { 439 for (;;) {
376 struct cx18_buffer *buf; 440 struct cx18_mdl *mdl;
377 int rc; 441 int rc;
378 442
379 buf = cx18_get_buffer(s, non_block, &rc); 443 mdl = cx18_get_mdl(s, non_block, &rc);
380 /* if there is no data available... */ 444 /* if there is no data available... */
381 if (buf == NULL) { 445 if (mdl == NULL) {
382 /* if we got data, then return that regardless */ 446 /* if we got data, then return that regardless */
383 if (tot_written) 447 if (tot_written)
384 break; 448 break;
@@ -392,20 +456,20 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
392 return rc; 456 return rc;
393 } 457 }
394 458
395 rc = cx18_copy_buf_to_user(s, buf, ubuf + tot_written, 459 rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
396 tot_count - tot_written); 460 tot_count - tot_written);
397 461
398 if (buf != &cx->vbi.sliced_mpeg_buf) { 462 if (mdl != &cx->vbi.sliced_mpeg_mdl) {
399 if (buf->readpos == buf->bytesused) 463 if (mdl->readpos == mdl->bytesused)
400 cx18_stream_put_buf_fw(s, buf); 464 cx18_stream_put_mdl_fw(s, mdl);
401 else 465 else
402 cx18_push(s, buf, &s->q_full); 466 cx18_push(s, mdl, &s->q_full);
403 } else if (buf->readpos == buf->bytesused) { 467 } else if (mdl->readpos == mdl->bytesused) {
404 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; 468 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
405 469
406 cx->vbi.sliced_mpeg_size[idx] = 0; 470 cx->vbi.sliced_mpeg_size[idx] = 0;
407 cx->vbi.inserted_frame++; 471 cx->vbi.inserted_frame++;
408 cx->vbi_data_inserted += buf->bytesused; 472 cx->vbi_data_inserted += mdl->bytesused;
409 } 473 }
410 if (rc < 0) 474 if (rc < 0)
411 return rc; 475 return rc;
@@ -543,7 +607,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
543 CX18_DEBUG_HI_FILE("Encoder poll\n"); 607 CX18_DEBUG_HI_FILE("Encoder poll\n");
544 poll_wait(filp, &s->waitq, wait); 608 poll_wait(filp, &s->waitq, wait);
545 609
546 if (atomic_read(&s->q_full.buffers)) 610 if (atomic_read(&s->q_full.depth))
547 return POLLIN | POLLRDNORM; 611 return POLLIN | POLLRDNORM;
548 if (eof) 612 if (eof)
549 return POLLHUP; 613 return POLLHUP;
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 2477461e84d7..eecf29af916c 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -28,7 +28,6 @@
28#include "cx18-gpio.h" 28#include "cx18-gpio.h"
29#include "cx18-i2c.h" 29#include "cx18-i2c.h"
30#include "cx18-irq.h" 30#include "cx18-irq.h"
31#include <media/ir-kbd-i2c.h>
32 31
33#define CX18_REG_I2C_1_WR 0xf15000 32#define CX18_REG_I2C_1_WR 0xf15000
34#define CX18_REG_I2C_1_RD 0xf15008 33#define CX18_REG_I2C_1_RD 0xf15008
@@ -97,17 +96,11 @@ static const char * const hw_devicenames[] = {
97 "ir_rx_z8f0811_haup", 96 "ir_rx_z8f0811_haup",
98}; 97};
99 98
100static const struct IR_i2c_init_data z8f0811_ir_init_data = { 99static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
101 .ir_codes = &ir_codes_hauppauge_new_table, 100 const char *type, u8 addr)
102 .internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR,
103 .type = IR_TYPE_RC5,
104 .name = "CX23418 Z8F0811 Hauppauge",
105};
106
107static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type,
108 u8 addr)
109{ 101{
110 struct i2c_board_info info; 102 struct i2c_board_info info;
103 struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data;
111 unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; 104 unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
112 105
113 memset(&info, 0, sizeof(struct i2c_board_info)); 106 memset(&info, 0, sizeof(struct i2c_board_info));
@@ -116,9 +109,11 @@ static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type,
116 /* Our default information for ir-kbd-i2c.c to use */ 109 /* Our default information for ir-kbd-i2c.c to use */
117 switch (hw) { 110 switch (hw) {
118 case CX18_HW_Z8F0811_IR_RX_HAUP: 111 case CX18_HW_Z8F0811_IR_RX_HAUP:
119 info.platform_data = (void *) &z8f0811_ir_init_data; 112 init_data->ir_codes = &ir_codes_hauppauge_new_table;
120 break; 113 init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
121 default: 114 init_data->type = IR_TYPE_RC5;
115 init_data->name = cx->card_name;
116 info.platform_data = init_data;
122 break; 117 break;
123 } 118 }
124 119
@@ -154,8 +149,8 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx)
154 return sd != NULL ? 0 : -1; 149 return sd != NULL ? 0 : -1;
155 } 150 }
156 151
157 if (hw & CX18_HW_Z8F0811_IR_HAUP) 152 if (hw & CX18_HW_IR_ANY)
158 return cx18_i2c_new_ir(adap, hw, type, hw_addrs[idx]); 153 return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]);
159 154
160 /* Is it not an I2C device or one we do not wish to register? */ 155 /* Is it not an I2C device or one we do not wish to register? */
161 if (!hw_addrs[idx]) 156 if (!hw_addrs[idx])
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index fc76e4d6ffa7..3e4fc192fdec 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -910,7 +910,8 @@ static int cx18_log_status(struct file *file, void *fh)
910 continue; 910 continue;
911 CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", 911 CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
912 s->name, s->s_flags, 912 s->name, s->s_flags,
913 atomic_read(&s->q_full.buffers) * 100 / s->buffers, 913 atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100
914 / s->buffers,
914 (s->buffers * s->buf_size) / 1024, s->buffers); 915 (s->buffers * s->buf_size) / 1024, s->buffers);
915 } 916 }
916 CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", 917 CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index afe46c3d4057..f231dd09c720 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -131,13 +131,39 @@ static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name)
131 * Functions that run in a work_queue work handling context 131 * Functions that run in a work_queue work handling context
132 */ 132 */
133 133
134static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
135{
136 struct cx18_buffer *buf;
137
138 if (!s->dvb.enabled || mdl->bytesused == 0)
139 return;
140
141 /* We ignore mdl and buf readpos accounting here - it doesn't matter */
142
143 /* The likely case */
144 if (list_is_singular(&mdl->buf_list)) {
145 buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
146 list);
147 if (buf->bytesused)
148 dvb_dmx_swfilter(&s->dvb.demux,
149 buf->buf, buf->bytesused);
150 return;
151 }
152
153 list_for_each_entry(buf, &mdl->buf_list, list) {
154 if (buf->bytesused == 0)
155 break;
156 dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused);
157 }
158}
159
134static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) 160static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
135{ 161{
136 u32 handle, mdl_ack_count, id; 162 u32 handle, mdl_ack_count, id;
137 struct cx18_mailbox *mb; 163 struct cx18_mailbox *mb;
138 struct cx18_mdl_ack *mdl_ack; 164 struct cx18_mdl_ack *mdl_ack;
139 struct cx18_stream *s; 165 struct cx18_stream *s;
140 struct cx18_buffer *buf; 166 struct cx18_mdl *mdl;
141 int i; 167 int i;
142 168
143 mb = &order->mb; 169 mb = &order->mb;
@@ -158,7 +184,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
158 id = mdl_ack->id; 184 id = mdl_ack->id;
159 /* 185 /*
160 * Simple integrity check for processing a stale (and possibly 186 * Simple integrity check for processing a stale (and possibly
161 * inconsistent mailbox): make sure the buffer id is in the 187 * inconsistent mailbox): make sure the MDL id is in the
162 * valid range for the stream. 188 * valid range for the stream.
163 * 189 *
164 * We go through the trouble of dealing with stale mailboxes 190 * We go through the trouble of dealing with stale mailboxes
@@ -169,44 +195,42 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
169 * There are occasions when we get a half changed mailbox, 195 * There are occasions when we get a half changed mailbox,
170 * which this check catches for a handle & id mismatch. If the 196 * which this check catches for a handle & id mismatch. If the
171 * handle and id do correspond, the worst case is that we 197 * handle and id do correspond, the worst case is that we
172 * completely lost the old buffer, but pick up the new buffer 198 * completely lost the old MDL, but pick up the new MDL
173 * early (but the new mdl_ack is guaranteed to be good in this 199 * early (but the new mdl_ack is guaranteed to be good in this
174 * case as the firmware wouldn't point us to a new mdl_ack until 200 * case as the firmware wouldn't point us to a new mdl_ack until
175 * it's filled in). 201 * it's filled in).
176 * 202 *
177 * cx18_queue_get buf() will detect the lost buffers 203 * cx18_queue_get_mdl() will detect the lost MDLs
178 * and send them back to q_free for fw rotation eventually. 204 * and send them back to q_free for fw rotation eventually.
179 */ 205 */
180 if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) && 206 if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) &&
181 !(id >= s->mdl_offset && 207 !(id >= s->mdl_base_idx &&
182 id < (s->mdl_offset + s->buffers))) { 208 id < (s->mdl_base_idx + s->buffers))) {
183 CX18_WARN("Fell behind! Ignoring stale mailbox with " 209 CX18_WARN("Fell behind! Ignoring stale mailbox with "
184 " inconsistent data. Lost buffer for mailbox " 210 " inconsistent data. Lost MDL for mailbox "
185 "seq no %d\n", mb->request); 211 "seq no %d\n", mb->request);
186 break; 212 break;
187 } 213 }
188 buf = cx18_queue_get_buf(s, id, mdl_ack->data_used); 214 mdl = cx18_queue_get_mdl(s, id, mdl_ack->data_used);
189 215
190 CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); 216 CX18_DEBUG_HI_DMA("DMA DONE for %s (MDL %d)\n", s->name, id);
191 if (buf == NULL) { 217 if (mdl == NULL) {
192 CX18_WARN("Could not find buf %d for stream %s\n", 218 CX18_WARN("Could not find MDL %d for stream %s\n",
193 id, s->name); 219 id, s->name);
194 continue; 220 continue;
195 } 221 }
196 222
197 CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", 223 CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n",
198 s->name, buf->bytesused); 224 s->name, mdl->bytesused);
199 225
200 if (s->type != CX18_ENC_STREAM_TYPE_TS) 226 if (s->type != CX18_ENC_STREAM_TYPE_TS)
201 cx18_enqueue(s, buf, &s->q_full); 227 cx18_enqueue(s, mdl, &s->q_full);
202 else { 228 else {
203 if (s->dvb.enabled) 229 cx18_mdl_send_to_dvb(s, mdl);
204 dvb_dmx_swfilter(&s->dvb.demux, buf->buf, 230 cx18_enqueue(s, mdl, &s->q_free);
205 buf->bytesused);
206 cx18_enqueue(s, buf, &s->q_free);
207 } 231 }
208 } 232 }
209 /* Put as many buffers as possible back into fw use */ 233 /* Put as many MDLs as possible back into fw use */
210 cx18_stream_load_fw_queue(s); 234 cx18_stream_load_fw_queue(s);
211 235
212 wake_up(&cx->dma_waitq); 236 wake_up(&cx->dma_waitq);
@@ -616,7 +640,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
616 640
617 /* 641 /*
618 * Wait for XPU to perform extra actions for the caller in some cases. 642 * Wait for XPU to perform extra actions for the caller in some cases.
619 * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all buffers 643 * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all MDLs
620 * back in a burst shortly thereafter 644 * back in a burst shortly thereafter
621 */ 645 */
622 if (info->flags & API_SLOW) 646 if (info->flags & API_SLOW)
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
index 522ad534034c..33a3491c4537 100644
--- a/drivers/media/video/cx18/cx18-mailbox.h
+++ b/drivers/media/video/cx18/cx18-mailbox.h
@@ -39,14 +39,14 @@
39struct cx18; 39struct cx18;
40 40
41/* 41/*
42 * This structure is used by CPU to provide completed buffers information 42 * This structure is used by CPU to provide completed MDL & buffers information.
43 * Its structure is dictrated by the layout of the SCB, required by the 43 * Its structure is dictated by the layout of the SCB, required by the
44 * firmware, but its definition needs to be here, instead of in cx18-scb.h, 44 * firmware, but its definition needs to be here, instead of in cx18-scb.h,
45 * for mailbox work order scheduling 45 * for mailbox work order scheduling
46 */ 46 */
47struct cx18_mdl_ack { 47struct cx18_mdl_ack {
48 u32 id; /* ID of a completed MDL */ 48 u32 id; /* ID of a completed MDL */
49 u32 data_used; /* Total data filled in the MDL for buffer 'id' */ 49 u32 data_used; /* Total data filled in the MDL with 'id' */
50}; 50};
51 51
52/* The cx18_mailbox struct is the mailbox structure which is used for passing 52/* The cx18_mailbox struct is the mailbox structure which is used for passing
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
index fa1ed7897d97..63304823cef5 100644
--- a/drivers/media/video/cx18/cx18-queue.c
+++ b/drivers/media/video/cx18/cx18-queue.c
@@ -26,6 +26,7 @@
26#include "cx18-queue.h" 26#include "cx18-queue.h"
27#include "cx18-streams.h" 27#include "cx18-streams.h"
28#include "cx18-scb.h" 28#include "cx18-scb.h"
29#include "cx18-io.h"
29 30
30void cx18_buf_swap(struct cx18_buffer *buf) 31void cx18_buf_swap(struct cx18_buffer *buf)
31{ 32{
@@ -35,151 +36,312 @@ void cx18_buf_swap(struct cx18_buffer *buf)
35 swab32s((u32 *)(buf->buf + i)); 36 swab32s((u32 *)(buf->buf + i));
36} 37}
37 38
39void _cx18_mdl_swap(struct cx18_mdl *mdl)
40{
41 struct cx18_buffer *buf;
42
43 list_for_each_entry(buf, &mdl->buf_list, list) {
44 if (buf->bytesused == 0)
45 break;
46 cx18_buf_swap(buf);
47 }
48}
49
38void cx18_queue_init(struct cx18_queue *q) 50void cx18_queue_init(struct cx18_queue *q)
39{ 51{
40 INIT_LIST_HEAD(&q->list); 52 INIT_LIST_HEAD(&q->list);
41 atomic_set(&q->buffers, 0); 53 atomic_set(&q->depth, 0);
42 q->bytesused = 0; 54 q->bytesused = 0;
43} 55}
44 56
45struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, 57struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
46 struct cx18_queue *q, int to_front) 58 struct cx18_queue *q, int to_front)
47{ 59{
48 /* clear the buffer if it is not to be enqueued to the full queue */ 60 /* clear the mdl if it is not to be enqueued to the full queue */
49 if (q != &s->q_full) { 61 if (q != &s->q_full) {
50 buf->bytesused = 0; 62 mdl->bytesused = 0;
51 buf->readpos = 0; 63 mdl->readpos = 0;
52 buf->b_flags = 0; 64 mdl->m_flags = 0;
53 buf->skipped = 0; 65 mdl->skipped = 0;
66 mdl->curr_buf = NULL;
54 } 67 }
55 68
56 /* q_busy is restricted to a max buffer count imposed by firmware */ 69 /* q_busy is restricted to a max buffer count imposed by firmware */
57 if (q == &s->q_busy && 70 if (q == &s->q_busy &&
58 atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) 71 atomic_read(&q->depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
59 q = &s->q_free; 72 q = &s->q_free;
60 73
61 spin_lock(&q->lock); 74 spin_lock(&q->lock);
62 75
63 if (to_front) 76 if (to_front)
64 list_add(&buf->list, &q->list); /* LIFO */ 77 list_add(&mdl->list, &q->list); /* LIFO */
65 else 78 else
66 list_add_tail(&buf->list, &q->list); /* FIFO */ 79 list_add_tail(&mdl->list, &q->list); /* FIFO */
67 q->bytesused += buf->bytesused - buf->readpos; 80 q->bytesused += mdl->bytesused - mdl->readpos;
68 atomic_inc(&q->buffers); 81 atomic_inc(&q->depth);
69 82
70 spin_unlock(&q->lock); 83 spin_unlock(&q->lock);
71 return q; 84 return q;
72} 85}
73 86
74struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) 87struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
75{ 88{
76 struct cx18_buffer *buf = NULL; 89 struct cx18_mdl *mdl = NULL;
77 90
78 spin_lock(&q->lock); 91 spin_lock(&q->lock);
79 if (!list_empty(&q->list)) { 92 if (!list_empty(&q->list)) {
80 buf = list_first_entry(&q->list, struct cx18_buffer, list); 93 mdl = list_first_entry(&q->list, struct cx18_mdl, list);
81 list_del_init(&buf->list); 94 list_del_init(&mdl->list);
82 q->bytesused -= buf->bytesused - buf->readpos; 95 q->bytesused -= mdl->bytesused - mdl->readpos;
83 buf->skipped = 0; 96 mdl->skipped = 0;
84 atomic_dec(&q->buffers); 97 atomic_dec(&q->depth);
85 } 98 }
86 spin_unlock(&q->lock); 99 spin_unlock(&q->lock);
87 return buf; 100 return mdl;
101}
102
103static void _cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
104 struct cx18_mdl *mdl)
105{
106 struct cx18_buffer *buf;
107 u32 buf_size = s->buf_size;
108 u32 bytesused = mdl->bytesused;
109
110 list_for_each_entry(buf, &mdl->buf_list, list) {
111 buf->readpos = 0;
112 if (bytesused >= buf_size) {
113 buf->bytesused = buf_size;
114 bytesused -= buf_size;
115 } else {
116 buf->bytesused = bytesused;
117 bytesused = 0;
118 }
119 cx18_buf_sync_for_cpu(s, buf);
120 }
121}
122
123static inline void cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
124 struct cx18_mdl *mdl)
125{
126 struct cx18_buffer *buf;
127
128 if (list_is_singular(&mdl->buf_list)) {
129 buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
130 list);
131 buf->bytesused = mdl->bytesused;
132 buf->readpos = 0;
133 cx18_buf_sync_for_cpu(s, buf);
134 } else {
135 _cx18_mdl_update_bufs_for_cpu(s, mdl);
136 }
88} 137}
89 138
90struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, 139struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
91 u32 bytesused) 140 u32 bytesused)
92{ 141{
93 struct cx18 *cx = s->cx; 142 struct cx18 *cx = s->cx;
94 struct cx18_buffer *buf; 143 struct cx18_mdl *mdl;
95 struct cx18_buffer *tmp; 144 struct cx18_mdl *tmp;
96 struct cx18_buffer *ret = NULL; 145 struct cx18_mdl *ret = NULL;
97 LIST_HEAD(sweep_up); 146 LIST_HEAD(sweep_up);
98 147
99 /* 148 /*
100 * We don't have to acquire multiple q locks here, because we are 149 * We don't have to acquire multiple q locks here, because we are
101 * serialized by the single threaded work handler. 150 * serialized by the single threaded work handler.
102 * Buffers from the firmware will thus remain in order as 151 * MDLs from the firmware will thus remain in order as
103 * they are moved from q_busy to q_full or to the dvb ring buffer. 152 * they are moved from q_busy to q_full or to the dvb ring buffer.
104 */ 153 */
105 spin_lock(&s->q_busy.lock); 154 spin_lock(&s->q_busy.lock);
106 list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) { 155 list_for_each_entry_safe(mdl, tmp, &s->q_busy.list, list) {
107 /* 156 /*
108 * We should find what the firmware told us is done, 157 * We should find what the firmware told us is done,
109 * right at the front of the queue. If we don't, we likely have 158 * right at the front of the queue. If we don't, we likely have
110 * missed a buffer done message from the firmware. 159 * missed an mdl done message from the firmware.
111 * Once we skip a buffer repeatedly, relative to the size of 160 * Once we skip an mdl repeatedly, relative to the size of
112 * q_busy, we have high confidence we've missed it. 161 * q_busy, we have high confidence we've missed it.
113 */ 162 */
114 if (buf->id != id) { 163 if (mdl->id != id) {
115 buf->skipped++; 164 mdl->skipped++;
116 if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { 165 if (mdl->skipped >= atomic_read(&s->q_busy.depth)-1) {
117 /* buffer must have fallen out of rotation */ 166 /* mdl must have fallen out of rotation */
118 CX18_WARN("Skipped %s, buffer %d, %d " 167 CX18_WARN("Skipped %s, MDL %d, %d "
119 "times - it must have dropped out of " 168 "times - it must have dropped out of "
120 "rotation\n", s->name, buf->id, 169 "rotation\n", s->name, mdl->id,
121 buf->skipped); 170 mdl->skipped);
122 /* Sweep it up to put it back into rotation */ 171 /* Sweep it up to put it back into rotation */
123 list_move_tail(&buf->list, &sweep_up); 172 list_move_tail(&mdl->list, &sweep_up);
124 atomic_dec(&s->q_busy.buffers); 173 atomic_dec(&s->q_busy.depth);
125 } 174 }
126 continue; 175 continue;
127 } 176 }
128 /* 177 /*
129 * We pull the desired buffer off of the queue here. Something 178 * We pull the desired mdl off of the queue here. Something
130 * will have to put it back on a queue later. 179 * will have to put it back on a queue later.
131 */ 180 */
132 list_del_init(&buf->list); 181 list_del_init(&mdl->list);
133 atomic_dec(&s->q_busy.buffers); 182 atomic_dec(&s->q_busy.depth);
134 ret = buf; 183 ret = mdl;
135 break; 184 break;
136 } 185 }
137 spin_unlock(&s->q_busy.lock); 186 spin_unlock(&s->q_busy.lock);
138 187
139 /* 188 /*
140 * We found the buffer for which we were looking. Get it ready for 189 * We found the mdl for which we were looking. Get it ready for
141 * the caller to put on q_full or in the dvb ring buffer. 190 * the caller to put on q_full or in the dvb ring buffer.
142 */ 191 */
143 if (ret != NULL) { 192 if (ret != NULL) {
144 ret->bytesused = bytesused; 193 ret->bytesused = bytesused;
145 ret->skipped = 0; 194 ret->skipped = 0;
146 /* readpos and b_flags were 0'ed when the buf went on q_busy */ 195 /* 0'ed readpos, m_flags & curr_buf when mdl went on q_busy */
147 cx18_buf_sync_for_cpu(s, ret); 196 cx18_mdl_update_bufs_for_cpu(s, ret);
148 if (s->type != CX18_ENC_STREAM_TYPE_TS) 197 if (s->type != CX18_ENC_STREAM_TYPE_TS)
149 set_bit(CX18_F_B_NEED_BUF_SWAP, &ret->b_flags); 198 set_bit(CX18_F_M_NEED_SWAP, &ret->m_flags);
150 } 199 }
151 200
152 /* Put any buffers the firmware is ignoring back into normal rotation */ 201 /* Put any mdls the firmware is ignoring back into normal rotation */
153 list_for_each_entry_safe(buf, tmp, &sweep_up, list) { 202 list_for_each_entry_safe(mdl, tmp, &sweep_up, list) {
154 list_del_init(&buf->list); 203 list_del_init(&mdl->list);
155 cx18_enqueue(s, buf, &s->q_free); 204 cx18_enqueue(s, mdl, &s->q_free);
156 } 205 }
157 return ret; 206 return ret;
158} 207}
159 208
160/* Move all buffers of a queue to q_free, while flushing the buffers */ 209/* Move all mdls of a queue, while flushing the mdl */
161static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) 210static void cx18_queue_flush(struct cx18_stream *s,
211 struct cx18_queue *q_src, struct cx18_queue *q_dst)
162{ 212{
163 struct cx18_buffer *buf; 213 struct cx18_mdl *mdl;
164 214
165 if (q == &s->q_free) 215 /* It only makes sense to flush to q_free or q_idle */
216 if (q_src == q_dst || q_dst == &s->q_full || q_dst == &s->q_busy)
166 return; 217 return;
167 218
168 spin_lock(&q->lock); 219 spin_lock(&q_src->lock);
169 while (!list_empty(&q->list)) { 220 spin_lock(&q_dst->lock);
170 buf = list_first_entry(&q->list, struct cx18_buffer, list); 221 while (!list_empty(&q_src->list)) {
171 list_move_tail(&buf->list, &s->q_free.list); 222 mdl = list_first_entry(&q_src->list, struct cx18_mdl, list);
172 buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; 223 list_move_tail(&mdl->list, &q_dst->list);
173 atomic_inc(&s->q_free.buffers); 224 mdl->bytesused = 0;
225 mdl->readpos = 0;
226 mdl->m_flags = 0;
227 mdl->skipped = 0;
228 mdl->curr_buf = NULL;
229 atomic_inc(&q_dst->depth);
174 } 230 }
175 cx18_queue_init(q); 231 cx18_queue_init(q_src);
176 spin_unlock(&q->lock); 232 spin_unlock(&q_src->lock);
233 spin_unlock(&q_dst->lock);
177} 234}
178 235
179void cx18_flush_queues(struct cx18_stream *s) 236void cx18_flush_queues(struct cx18_stream *s)
180{ 237{
181 cx18_queue_flush(s, &s->q_busy); 238 cx18_queue_flush(s, &s->q_busy, &s->q_free);
182 cx18_queue_flush(s, &s->q_full); 239 cx18_queue_flush(s, &s->q_full, &s->q_free);
240}
241
242/*
243 * Note, s->buf_pool is not protected by a lock,
244 * the stream better not have *anything* going on when calling this
245 */
246void cx18_unload_queues(struct cx18_stream *s)
247{
248 struct cx18_queue *q_idle = &s->q_idle;
249 struct cx18_mdl *mdl;
250 struct cx18_buffer *buf;
251
252 /* Move all MDLS to q_idle */
253 cx18_queue_flush(s, &s->q_busy, q_idle);
254 cx18_queue_flush(s, &s->q_full, q_idle);
255 cx18_queue_flush(s, &s->q_free, q_idle);
256
257 /* Reset MDL id's and move all buffers back to the stream's buf_pool */
258 spin_lock(&q_idle->lock);
259 list_for_each_entry(mdl, &q_idle->list, list) {
260 while (!list_empty(&mdl->buf_list)) {
261 buf = list_first_entry(&mdl->buf_list,
262 struct cx18_buffer, list);
263 list_move_tail(&buf->list, &s->buf_pool);
264 buf->bytesused = 0;
265 buf->readpos = 0;
266 }
267 mdl->id = s->mdl_base_idx; /* reset id to a "safe" value */
268 /* all other mdl fields were cleared by cx18_queue_flush() */
269 }
270 spin_unlock(&q_idle->lock);
271}
272
273/*
274 * Note, s->buf_pool is not protected by a lock,
275 * the stream better not have *anything* going on when calling this
276 */
277void cx18_load_queues(struct cx18_stream *s)
278{
279 struct cx18 *cx = s->cx;
280 struct cx18_mdl *mdl;
281 struct cx18_buffer *buf;
282 int mdl_id;
283 int i;
284 u32 partial_buf_size;
285
286 /*
287 * Attach buffers to MDLs, give the MDLs ids, and add MDLs to q_free
288 * Excess MDLs are left on q_idle
289 * Excess buffers are left in buf_pool and/or on an MDL in q_idle
290 */
291 mdl_id = s->mdl_base_idx;
292 for (mdl = cx18_dequeue(s, &s->q_idle), i = s->bufs_per_mdl;
293 mdl != NULL && i == s->bufs_per_mdl;
294 mdl = cx18_dequeue(s, &s->q_idle)) {
295
296 mdl->id = mdl_id;
297
298 for (i = 0; i < s->bufs_per_mdl; i++) {
299 if (list_empty(&s->buf_pool))
300 break;
301
302 buf = list_first_entry(&s->buf_pool, struct cx18_buffer,
303 list);
304 list_move_tail(&buf->list, &mdl->buf_list);
305
306 /* update the firmware's MDL array with this buffer */
307 cx18_writel(cx, buf->dma_handle,
308 &cx->scb->cpu_mdl[mdl_id + i].paddr);
309 cx18_writel(cx, s->buf_size,
310 &cx->scb->cpu_mdl[mdl_id + i].length);
311 }
312
313 if (i == s->bufs_per_mdl) {
314 /*
315 * The encoder doesn't honor s->mdl_size. So in the
316 * case of a non-integral number of buffers to meet
317 * mdl_size, we lie about the size of the last buffer
318 * in the MDL to get the encoder to really only send
319 * us mdl_size bytes per MDL transfer.
320 */
321 partial_buf_size = s->mdl_size % s->buf_size;
322 if (partial_buf_size) {
323 cx18_writel(cx, partial_buf_size,
324 &cx->scb->cpu_mdl[mdl_id + i - 1].length);
325 }
326 cx18_enqueue(s, mdl, &s->q_free);
327 } else {
328 /* Not enough buffers for this MDL; we won't use it */
329 cx18_push(s, mdl, &s->q_idle);
330 }
331 mdl_id += i;
332 }
333}
334
335void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl)
336{
337 int dma = s->dma;
338 u32 buf_size = s->buf_size;
339 struct pci_dev *pci_dev = s->cx->pci_dev;
340 struct cx18_buffer *buf;
341
342 list_for_each_entry(buf, &mdl->buf_list, list)
343 pci_dma_sync_single_for_device(pci_dev, buf->dma_handle,
344 buf_size, dma);
183} 345}
184 346
185int cx18_stream_alloc(struct cx18_stream *s) 347int cx18_stream_alloc(struct cx18_stream *s)
@@ -190,44 +352,62 @@ int cx18_stream_alloc(struct cx18_stream *s)
190 if (s->buffers == 0) 352 if (s->buffers == 0)
191 return 0; 353 return 0;
192 354
193 CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers (%dkB total)\n", 355 CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers "
356 "(%d.%02d kB total)\n",
194 s->name, s->buffers, s->buf_size, 357 s->name, s->buffers, s->buf_size,
195 s->buffers * s->buf_size / 1024); 358 s->buffers * s->buf_size / 1024,
359 (s->buffers * s->buf_size * 100 / 1024) % 100);
196 360
197 if (((char __iomem *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] - 361 if (((char __iomem *)&cx->scb->cpu_mdl[cx->free_mdl_idx + s->buffers] -
198 (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) { 362 (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) {
199 unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE - 363 unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE -
200 ((char __iomem *)cx->scb->cpu_mdl)); 364 ((char __iomem *)cx->scb->cpu_mdl));
201 365
202 CX18_ERR("Too many buffers, cannot fit in SCB area\n"); 366 CX18_ERR("Too many buffers, cannot fit in SCB area\n");
203 CX18_ERR("Max buffers = %zd\n", 367 CX18_ERR("Max buffers = %zd\n",
204 bufsz / sizeof(struct cx18_mdl)); 368 bufsz / sizeof(struct cx18_mdl_ent));
205 return -ENOMEM; 369 return -ENOMEM;
206 } 370 }
207 371
208 s->mdl_offset = cx->mdl_offset; 372 s->mdl_base_idx = cx->free_mdl_idx;
209 373
210 /* allocate stream buffers. Initially all buffers are in q_free. */ 374 /* allocate stream buffers and MDLs */
211 for (i = 0; i < s->buffers; i++) { 375 for (i = 0; i < s->buffers; i++) {
212 struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer), 376 struct cx18_mdl *mdl;
213 GFP_KERNEL|__GFP_NOWARN); 377 struct cx18_buffer *buf;
214 378
215 if (buf == NULL) 379 /* 1 MDL per buffer to handle the worst & also default case */
380 mdl = kzalloc(sizeof(struct cx18_mdl), GFP_KERNEL|__GFP_NOWARN);
381 if (mdl == NULL)
216 break; 382 break;
383
384 buf = kzalloc(sizeof(struct cx18_buffer),
385 GFP_KERNEL|__GFP_NOWARN);
386 if (buf == NULL) {
387 kfree(mdl);
388 break;
389 }
390
217 buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN); 391 buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN);
218 if (buf->buf == NULL) { 392 if (buf->buf == NULL) {
393 kfree(mdl);
219 kfree(buf); 394 kfree(buf);
220 break; 395 break;
221 } 396 }
222 buf->id = cx->buffer_id++; 397
398 INIT_LIST_HEAD(&mdl->list);
399 INIT_LIST_HEAD(&mdl->buf_list);
400 mdl->id = s->mdl_base_idx; /* a somewhat safe value */
401 cx18_enqueue(s, mdl, &s->q_idle);
402
223 INIT_LIST_HEAD(&buf->list); 403 INIT_LIST_HEAD(&buf->list);
224 buf->dma_handle = pci_map_single(s->cx->pci_dev, 404 buf->dma_handle = pci_map_single(s->cx->pci_dev,
225 buf->buf, s->buf_size, s->dma); 405 buf->buf, s->buf_size, s->dma);
226 cx18_buf_sync_for_cpu(s, buf); 406 cx18_buf_sync_for_cpu(s, buf);
227 cx18_enqueue(s, buf, &s->q_free); 407 list_add_tail(&buf->list, &s->buf_pool);
228 } 408 }
229 if (i == s->buffers) { 409 if (i == s->buffers) {
230 cx->mdl_offset += s->buffers; 410 cx->free_mdl_idx += s->buffers;
231 return 0; 411 return 0;
232 } 412 }
233 CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name); 413 CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name);
@@ -237,13 +417,21 @@ int cx18_stream_alloc(struct cx18_stream *s)
237 417
238void cx18_stream_free(struct cx18_stream *s) 418void cx18_stream_free(struct cx18_stream *s)
239{ 419{
420 struct cx18_mdl *mdl;
240 struct cx18_buffer *buf; 421 struct cx18_buffer *buf;
241 422
242 /* move all buffers to q_free */ 423 /* move all buffers to buf_pool and all MDLs to q_idle */
243 cx18_flush_queues(s); 424 cx18_unload_queues(s);
425
426 /* empty q_idle */
427 while ((mdl = cx18_dequeue(s, &s->q_idle)))
428 kfree(mdl);
429
430 /* empty buf_pool */
431 while (!list_empty(&s->buf_pool)) {
432 buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list);
433 list_del_init(&buf->list);
244 434
245 /* empty q_free */
246 while ((buf = cx18_dequeue(s, &s->q_free))) {
247 pci_unmap_single(s->cx->pci_dev, buf->dma_handle, 435 pci_unmap_single(s->cx->pci_dev, buf->dma_handle,
248 s->buf_size, s->dma); 436 s->buf_size, s->dma);
249 kfree(buf->buf); 437 kfree(buf->buf);
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
index 4de06269d88f..88a6d34ad3bb 100644
--- a/drivers/media/video/cx18/cx18-queue.h
+++ b/drivers/media/video/cx18/cx18-queue.h
@@ -40,32 +40,59 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
40 s->buf_size, s->dma); 40 s->buf_size, s->dma);
41} 41}
42 42
43void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl);
44
45static inline void cx18_mdl_sync_for_device(struct cx18_stream *s,
46 struct cx18_mdl *mdl)
47{
48 if (list_is_singular(&mdl->buf_list))
49 cx18_buf_sync_for_device(s, list_first_entry(&mdl->buf_list,
50 struct cx18_buffer,
51 list));
52 else
53 _cx18_mdl_sync_for_device(s, mdl);
54}
55
43void cx18_buf_swap(struct cx18_buffer *buf); 56void cx18_buf_swap(struct cx18_buffer *buf);
57void _cx18_mdl_swap(struct cx18_mdl *mdl);
58
59static inline void cx18_mdl_swap(struct cx18_mdl *mdl)
60{
61 if (list_is_singular(&mdl->buf_list))
62 cx18_buf_swap(list_first_entry(&mdl->buf_list,
63 struct cx18_buffer, list));
64 else
65 _cx18_mdl_swap(mdl);
66}
44 67
45/* cx18_queue utility functions */ 68/* cx18_queue utility functions */
46struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, 69struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
47 struct cx18_queue *q, int to_front); 70 struct cx18_queue *q, int to_front);
48 71
49static inline 72static inline
50struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, 73struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
51 struct cx18_queue *q) 74 struct cx18_queue *q)
52{ 75{
53 return _cx18_enqueue(s, buf, q, 0); /* FIFO */ 76 return _cx18_enqueue(s, mdl, q, 0); /* FIFO */
54} 77}
55 78
56static inline 79static inline
57struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, 80struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_mdl *mdl,
58 struct cx18_queue *q) 81 struct cx18_queue *q)
59{ 82{
60 return _cx18_enqueue(s, buf, q, 1); /* LIFO */ 83 return _cx18_enqueue(s, mdl, q, 1); /* LIFO */
61} 84}
62 85
63void cx18_queue_init(struct cx18_queue *q); 86void cx18_queue_init(struct cx18_queue *q);
64struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); 87struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
65struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, 88struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
66 u32 bytesused); 89 u32 bytesused);
67void cx18_flush_queues(struct cx18_stream *s); 90void cx18_flush_queues(struct cx18_stream *s);
68 91
92/* queue MDL reconfiguration helpers */
93void cx18_unload_queues(struct cx18_stream *s);
94void cx18_load_queues(struct cx18_stream *s);
95
69/* cx18_stream utility functions */ 96/* cx18_stream utility functions */
70int cx18_stream_alloc(struct cx18_stream *s); 97int cx18_stream_alloc(struct cx18_stream *s);
71void cx18_stream_free(struct cx18_stream *s); 98void cx18_stream_free(struct cx18_stream *s);
diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h
index 1dc1c431f5a1..368f23d08709 100644
--- a/drivers/media/video/cx18/cx18-scb.h
+++ b/drivers/media/video/cx18/cx18-scb.h
@@ -81,7 +81,7 @@
81 81
82 82
83/* This structure is used by EPU to provide memory descriptors in its memory */ 83/* This structure is used by EPU to provide memory descriptors in its memory */
84struct cx18_mdl { 84struct cx18_mdl_ent {
85 u32 paddr; /* Physical address of a buffer segment */ 85 u32 paddr; /* Physical address of a buffer segment */
86 u32 length; /* Length of the buffer segment */ 86 u32 length; /* Length of the buffer segment */
87}; 87};
@@ -272,7 +272,7 @@ struct cx18_scb {
272 struct cx18_mailbox ppu2epu_mb; 272 struct cx18_mailbox ppu2epu_mb;
273 273
274 struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS]; 274 struct cx18_mdl_ack cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS];
275 struct cx18_mdl cpu_mdl[1]; 275 struct cx18_mdl_ent cpu_mdl[1];
276}; 276};
277 277
278void cx18_init_scb(struct cx18 *cx); 278void cx18_init_scb(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 7df513a2dba8..c398651dd74c 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -115,6 +115,9 @@ static void cx18_stream_init(struct cx18 *cx, int type)
115 s->dma = cx18_stream_info[type].dma; 115 s->dma = cx18_stream_info[type].dma;
116 s->buffers = cx->stream_buffers[type]; 116 s->buffers = cx->stream_buffers[type];
117 s->buf_size = cx->stream_buf_size[type]; 117 s->buf_size = cx->stream_buf_size[type];
118 INIT_LIST_HEAD(&s->buf_pool);
119 s->bufs_per_mdl = 1;
120 s->mdl_size = s->buf_size * s->bufs_per_mdl;
118 121
119 init_waitqueue_head(&s->waitq); 122 init_waitqueue_head(&s->waitq);
120 s->id = -1; 123 s->id = -1;
@@ -124,6 +127,8 @@ static void cx18_stream_init(struct cx18 *cx, int type)
124 cx18_queue_init(&s->q_busy); 127 cx18_queue_init(&s->q_busy);
125 spin_lock_init(&s->q_full.lock); 128 spin_lock_init(&s->q_full.lock);
126 cx18_queue_init(&s->q_full); 129 cx18_queue_init(&s->q_full);
130 spin_lock_init(&s->q_idle.lock);
131 cx18_queue_init(&s->q_idle);
127 132
128 INIT_WORK(&s->out_work_order, cx18_out_work_handler); 133 INIT_WORK(&s->out_work_order, cx18_out_work_handler);
129} 134}
@@ -257,9 +262,11 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
257 262
258 switch (vfl_type) { 263 switch (vfl_type) {
259 case VFL_TYPE_GRABBER: 264 case VFL_TYPE_GRABBER:
260 CX18_INFO("Registered device video%d for %s (%d x %d kB)\n", 265 CX18_INFO("Registered device video%d for %s "
266 "(%d x %d.%02d kB)\n",
261 num, s->name, cx->stream_buffers[type], 267 num, s->name, cx->stream_buffers[type],
262 cx->stream_buf_size[type]/1024); 268 cx->stream_buf_size[type] / 1024,
269 (cx->stream_buf_size[type] * 100 / 1024) % 100);
263 break; 270 break;
264 271
265 case VFL_TYPE_RADIO: 272 case VFL_TYPE_RADIO:
@@ -441,8 +448,8 @@ static void cx18_vbi_setup(struct cx18_stream *s)
441} 448}
442 449
443static 450static
444struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, 451struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s,
445 struct cx18_buffer *buf) 452 struct cx18_mdl *mdl)
446{ 453{
447 struct cx18 *cx = s->cx; 454 struct cx18 *cx = s->cx;
448 struct cx18_queue *q; 455 struct cx18_queue *q;
@@ -451,16 +458,16 @@ struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s,
451 if (s->handle == CX18_INVALID_TASK_HANDLE || 458 if (s->handle == CX18_INVALID_TASK_HANDLE ||
452 test_bit(CX18_F_S_STOPPING, &s->s_flags) || 459 test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
453 !test_bit(CX18_F_S_STREAMING, &s->s_flags)) 460 !test_bit(CX18_F_S_STREAMING, &s->s_flags))
454 return cx18_enqueue(s, buf, &s->q_free); 461 return cx18_enqueue(s, mdl, &s->q_free);
455 462
456 q = cx18_enqueue(s, buf, &s->q_busy); 463 q = cx18_enqueue(s, mdl, &s->q_busy);
457 if (q != &s->q_busy) 464 if (q != &s->q_busy)
458 return q; /* The firmware has the max buffers it can handle */ 465 return q; /* The firmware has the max MDLs it can handle */
459 466
460 cx18_buf_sync_for_device(s, buf); 467 cx18_mdl_sync_for_device(s, mdl);
461 cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, 468 cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
462 (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 469 (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem,
463 1, buf->id, s->buf_size); 470 s->bufs_per_mdl, mdl->id, s->mdl_size);
464 return q; 471 return q;
465} 472}
466 473
@@ -468,19 +475,19 @@ static
468void _cx18_stream_load_fw_queue(struct cx18_stream *s) 475void _cx18_stream_load_fw_queue(struct cx18_stream *s)
469{ 476{
470 struct cx18_queue *q; 477 struct cx18_queue *q;
471 struct cx18_buffer *buf; 478 struct cx18_mdl *mdl;
472 479
473 if (atomic_read(&s->q_free.buffers) == 0 || 480 if (atomic_read(&s->q_free.depth) == 0 ||
474 atomic_read(&s->q_busy.buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) 481 atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
475 return; 482 return;
476 483
477 /* Move from q_free to q_busy notifying the firmware, until the limit */ 484 /* Move from q_free to q_busy notifying the firmware, until the limit */
478 do { 485 do {
479 buf = cx18_dequeue(s, &s->q_free); 486 mdl = cx18_dequeue(s, &s->q_free);
480 if (buf == NULL) 487 if (mdl == NULL)
481 break; 488 break;
482 q = _cx18_stream_put_buf_fw(s, buf); 489 q = _cx18_stream_put_mdl_fw(s, mdl);
483 } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM 490 } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM
484 && q == &s->q_busy); 491 && q == &s->q_busy);
485} 492}
486 493
@@ -492,11 +499,51 @@ void cx18_out_work_handler(struct work_struct *work)
492 _cx18_stream_load_fw_queue(s); 499 _cx18_stream_load_fw_queue(s);
493} 500}
494 501
502static void cx18_stream_configure_mdls(struct cx18_stream *s)
503{
504 cx18_unload_queues(s);
505
506 switch (s->type) {
507 case CX18_ENC_STREAM_TYPE_YUV:
508 /*
509 * Height should be a multiple of 32 lines.
510 * Set the MDL size to the exact size needed for one frame.
511 * Use enough buffers per MDL to cover the MDL size
512 */
513 s->mdl_size = 720 * s->cx->params.height * 3 / 2;
514 s->bufs_per_mdl = s->mdl_size / s->buf_size;
515 if (s->mdl_size % s->buf_size)
516 s->bufs_per_mdl++;
517 break;
518 case CX18_ENC_STREAM_TYPE_VBI:
519 s->bufs_per_mdl = 1;
520 if (cx18_raw_vbi(s->cx)) {
521 s->mdl_size = (s->cx->is_60hz ? 12 : 18)
522 * 2 * vbi_active_samples;
523 } else {
524 /*
525 * See comment in cx18_vbi_setup() below about the
526 * extra lines we capture in sliced VBI mode due to
527 * the lines on which EAV RP codes toggle.
528 */
529 s->mdl_size = s->cx->is_60hz
530 ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz
531 : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz;
532 }
533 break;
534 default:
535 s->bufs_per_mdl = 1;
536 s->mdl_size = s->buf_size * s->bufs_per_mdl;
537 break;
538 }
539
540 cx18_load_queues(s);
541}
542
495int cx18_start_v4l2_encode_stream(struct cx18_stream *s) 543int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
496{ 544{
497 u32 data[MAX_MB_ARGUMENTS]; 545 u32 data[MAX_MB_ARGUMENTS];
498 struct cx18 *cx = s->cx; 546 struct cx18 *cx = s->cx;
499 struct cx18_buffer *buf;
500 int captype = 0; 547 int captype = 0;
501 struct cx18_api_func_private priv; 548 struct cx18_api_func_private priv;
502 549
@@ -619,14 +666,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
619 (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); 666 (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
620 667
621 /* Init all the cpu_mdls for this stream */ 668 /* Init all the cpu_mdls for this stream */
622 cx18_flush_queues(s); 669 cx18_stream_configure_mdls(s);
623 spin_lock(&s->q_free.lock);
624 list_for_each_entry(buf, &s->q_free.list, list) {
625 cx18_writel(cx, buf->dma_handle,
626 &cx->scb->cpu_mdl[buf->id].paddr);
627 cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
628 }
629 spin_unlock(&s->q_free.lock);
630 _cx18_stream_load_fw_queue(s); 670 _cx18_stream_load_fw_queue(s);
631 671
632 /* begin_capture */ 672 /* begin_capture */
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
index 1afc3fd9d822..4a01db5e5a35 100644
--- a/drivers/media/video/cx18/cx18-streams.h
+++ b/drivers/media/video/cx18/cx18-streams.h
@@ -28,18 +28,18 @@ int cx18_streams_setup(struct cx18 *cx);
28int cx18_streams_register(struct cx18 *cx); 28int cx18_streams_register(struct cx18 *cx);
29void cx18_streams_cleanup(struct cx18 *cx, int unregister); 29void cx18_streams_cleanup(struct cx18 *cx, int unregister);
30 30
31/* Related to submission of buffers to firmware */ 31/* Related to submission of mdls to firmware */
32static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) 32static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
33{ 33{
34 struct cx18 *cx = s->cx; 34 struct cx18 *cx = s->cx;
35 queue_work(cx->out_work_queue, &s->out_work_order); 35 queue_work(cx->out_work_queue, &s->out_work_order);
36} 36}
37 37
38static inline void cx18_stream_put_buf_fw(struct cx18_stream *s, 38static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s,
39 struct cx18_buffer *buf) 39 struct cx18_mdl *mdl)
40{ 40{
41 /* Put buf on q_free; the out work handler will move buf(s) to q_busy */ 41 /* Put mdl on q_free; the out work handler will move mdl(s) to q_busy */
42 cx18_enqueue(s, buf, &s->q_free); 42 cx18_enqueue(s, mdl, &s->q_free);
43 cx18_stream_load_fw_queue(s); 43 cx18_stream_load_fw_queue(s);
44} 44}
45 45
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c
index c2aef4add31d..574c1c6974f8 100644
--- a/drivers/media/video/cx18/cx18-vbi.c
+++ b/drivers/media/video/cx18/cx18-vbi.c
@@ -105,6 +105,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
105 105
106/* Compress raw VBI format, removes leading SAV codes and surplus space 106/* Compress raw VBI format, removes leading SAV codes and surplus space
107 after the frame. Returns new compressed size. */ 107 after the frame. Returns new compressed size. */
108/* FIXME - this function ignores the input size. */
108static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size) 109static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size)
109{ 110{
110 u32 line_size = vbi_active_samples; 111 u32 line_size = vbi_active_samples;
@@ -185,8 +186,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
185 return line; 186 return line;
186} 187}
187 188
188void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, 189static void _cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf)
189 int streamtype)
190{ 190{
191 /* 191 /*
192 * The CX23418 provides a 12 byte header in its raw VBI buffers to us: 192 * The CX23418 provides a 12 byte header in its raw VBI buffers to us:
@@ -203,9 +203,6 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
203 u32 pts; 203 u32 pts;
204 int lines; 204 int lines;
205 205
206 if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
207 return;
208
209 /* 206 /*
210 * The CX23418 sends us data that is 32 bit little-endian swapped, 207 * The CX23418 sends us data that is 32 bit little-endian swapped,
211 * but we want the raw VBI bytes in the order they were in the raster 208 * but we want the raw VBI bytes in the order they were in the raster
@@ -250,3 +247,31 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
250 copy_vbi_data(cx, lines, pts); 247 copy_vbi_data(cx, lines, pts);
251 cx->vbi.frame++; 248 cx->vbi.frame++;
252} 249}
250
251void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
252 int streamtype)
253{
254 struct cx18_buffer *buf;
255 u32 orig_used;
256
257 if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
258 return;
259
260 /*
261 * Big assumption here:
262 * Every buffer hooked to the MDL's buf_list is a complete VBI frame
263 * that ends at the end of the buffer.
264 *
265 * To assume anything else would make the code in this file
266 * more complex, or require extra memcpy()'s to make the
267 * buffers satisfy the above assumption. It's just simpler to set
268 * up the encoder buffer transfers to make the assumption true.
269 */
270 list_for_each_entry(buf, &mdl->buf_list, list) {
271 orig_used = buf->bytesused;
272 if (orig_used == 0)
273 break;
274 _cx18_process_vbi_data(cx, buf);
275 mdl->bytesused -= (orig_used - buf->bytesused);
276 }
277}
diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h
index e7e1ae427f34..b365cf4b4668 100644
--- a/drivers/media/video/cx18/cx18-vbi.h
+++ b/drivers/media/video/cx18/cx18-vbi.h
@@ -21,6 +21,6 @@
21 * 02111-1307 USA 21 * 02111-1307 USA
22 */ 22 */
23 23
24void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, 24void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
25 int streamtype); 25 int streamtype);
26int cx18_used_line(struct cx18 *cx, int line, int field); 26int cx18_used_line(struct cx18 *cx, int line, int field);
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
index 45494b094e7f..9c0b5bb1b019 100644
--- a/drivers/media/video/cx18/cx18-version.h
+++ b/drivers/media/video/cx18/cx18-version.h
@@ -24,7 +24,7 @@
24 24
25#define CX18_DRIVER_NAME "cx18" 25#define CX18_DRIVER_NAME "cx18"
26#define CX18_DRIVER_VERSION_MAJOR 1 26#define CX18_DRIVER_VERSION_MAJOR 1
27#define CX18_DRIVER_VERSION_MINOR 2 27#define CX18_DRIVER_VERSION_MINOR 3
28#define CX18_DRIVER_VERSION_PATCHLEVEL 0 28#define CX18_DRIVER_VERSION_PATCHLEVEL 0
29 29
30#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) 30#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
index 9956abf576c5..868806effdcf 100644
--- a/drivers/media/video/cx18/cx23418.h
+++ b/drivers/media/video/cx18/cx23418.h
@@ -363,7 +363,7 @@
363/* Description: This command provides the offset to a Memory Descriptor List 363/* Description: This command provides the offset to a Memory Descriptor List
364 IN[0] - Task handle. Handle of the task to start 364 IN[0] - Task handle. Handle of the task to start
365 IN[1] - Offset of the MDL from the beginning of the local DDR. 365 IN[1] - Offset of the MDL from the beginning of the local DDR.
366 IN[2] - Number of cx18_mdl structures in the array pointed to by IN[1] 366 IN[2] - Number of cx18_mdl_ent structures in the array pointed to by IN[1]
367 IN[3] - Buffer ID 367 IN[3] - Buffer ID
368 IN[4] - Total buffer length 368 IN[4] - Total buffer length
369 ReturnCode - One of the ERR_DE_... */ 369 ReturnCode - One of the ERR_DE_... */