diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index a893caff0aa9..255d5477567d 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -83,12 +83,28 @@ static char secam[] = "--";
 static char ntsc[] = "-";
 
 /* Buffers */
-static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
 static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
+static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
+static int enc_idx_buffers = CX18_DEFAULT_ENC_IDX_BUFFERS;
 static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
 static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
 static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
 
+static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE;
+static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE;
+static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE;
+static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE;
+/* VBI bufsize based on standards supported by card tuner for now */
+static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE;
+
+static int enc_ts_bufs = -1;
+static int enc_mpg_bufs = -1;
+static int enc_idx_bufs = -1;
+static int enc_yuv_bufs = -1;
+static int enc_vbi_bufs = -1;
+static int enc_pcm_bufs = -1;
+
+
 static int cx18_pci_latency = 1;
 
 static int mmio_ndelay;
@@ -108,12 +124,27 @@ module_param(retry_mmio, int, 0644);
 module_param(cx18_pci_latency, int, 0644);
 module_param(cx18_first_minor, int, 0644);
 
-module_param(enc_mpg_buffers, int, 0644);
 module_param(enc_ts_buffers, int, 0644);
+module_param(enc_mpg_buffers, int, 0644);
+module_param(enc_idx_buffers, int, 0644);
 module_param(enc_yuv_buffers, int, 0644);
 module_param(enc_vbi_buffers, int, 0644);
 module_param(enc_pcm_buffers, int, 0644);
 
+module_param(enc_ts_bufsize, int, 0644);
+module_param(enc_mpg_bufsize, int, 0644);
+module_param(enc_idx_bufsize, int, 0644);
+module_param(enc_yuv_bufsize, int, 0644);
+/* VBI bufsize based on standards supported by card tuner for now */
+module_param(enc_pcm_bufsize, int, 0644);
+
+module_param(enc_ts_bufs, int, 0644);
+module_param(enc_mpg_bufs, int, 0644);
+module_param(enc_idx_bufs, int, 0644);
+module_param(enc_yuv_bufs, int, 0644);
+module_param(enc_vbi_bufs, int, 0644);
+module_param(enc_pcm_bufs, int, 0644);
+
 MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
 			"\t\t\tsee tuner.h for values");
 MODULE_PARM_DESC(radio,
@@ -154,21 +185,57 @@ MODULE_PARM_DESC(retry_mmio,
 MODULE_PARM_DESC(mmio_ndelay,
 		 "(Deprecated) MMIO accesses are now never purposely delayed\n"
 		 "\t\t\tEffectively: 0 ns");
-MODULE_PARM_DESC(enc_mpg_buffers,
-		 "Encoder MPG Buffers (in MB)\n"
-		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
 MODULE_PARM_DESC(enc_ts_buffers,
-		 "Encoder TS Buffers (in MB)\n"
+		 "Encoder TS buffer memory (MB). (enc_ts_bufs can override)\n"
 		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
+MODULE_PARM_DESC(enc_ts_bufsize,
+		 "Size of an encoder TS buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFSIZE));
+MODULE_PARM_DESC(enc_ts_bufs,
+		 "Number of encoder TS buffers\n"
+		 "\t\t\tDefault is computed from other enc_ts_* parameters");
+MODULE_PARM_DESC(enc_mpg_buffers,
+		 "Encoder MPG buffer memory (MB). (enc_mpg_bufs can override)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
+MODULE_PARM_DESC(enc_mpg_bufsize,
+		 "Size of an encoder MPG buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFSIZE));
+MODULE_PARM_DESC(enc_mpg_bufs,
+		 "Number of encoder MPG buffers\n"
+		 "\t\t\tDefault is computed from other enc_mpg_* parameters");
+MODULE_PARM_DESC(enc_idx_buffers,
+		 "Encoder IDX buffer memory (MB). (enc_idx_bufs can override)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFFERS));
+MODULE_PARM_DESC(enc_idx_bufsize,
+		 "Size of an encoder IDX buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFSIZE));
+MODULE_PARM_DESC(enc_idx_bufs,
+		 "Number of encoder IDX buffers\n"
+		 "\t\t\tDefault is computed from other enc_idx_* parameters");
 MODULE_PARM_DESC(enc_yuv_buffers,
-		 "Encoder YUV Buffers (in MB)\n"
+		 "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n"
 		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
+MODULE_PARM_DESC(enc_yuv_bufsize,
+		 "Size of an encoder YUV buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFSIZE));
+MODULE_PARM_DESC(enc_yuv_bufs,
+		 "Number of encoder YUV buffers\n"
+		 "\t\t\tDefault is computed from other enc_yuv_* parameters");
 MODULE_PARM_DESC(enc_vbi_buffers,
-		 "Encoder VBI Buffers (in MB)\n"
+		 "Encoder VBI buffer memory (MB). (enc_vbi_bufs can override)\n"
 		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
+MODULE_PARM_DESC(enc_vbi_bufs,
+		 "Number of encoder VBI buffers\n"
+		 "\t\t\tDefault is computed from enc_vbi_buffers & tuner std");
 MODULE_PARM_DESC(enc_pcm_buffers,
-		 "Encoder PCM buffers (in MB)\n"
+		 "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n"
 		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
+MODULE_PARM_DESC(enc_pcm_bufsize,
+		 "Size of an encoder PCM buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFSIZE));
+MODULE_PARM_DESC(enc_pcm_bufs,
+		 "Number of encoder PCM buffers\n"
+		 "\t\t\tDefault is computed from other enc_pcm_* parameters");
 
 MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card");
 
@@ -361,11 +428,65 @@ static void cx18_process_options(struct cx18 *cx)
 {
 	int i, j;
 
-	cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
 	cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_buffers;
 	cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
 	cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
 	cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control only */
+
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control, no data */
+
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufsize;
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize;
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize;
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize;
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = 0; /* computed later */
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize;
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */
+
+	/* Except for VBI ensure stream_buffers & stream_buf_size are valid */
+	for (i = 0; i < CX18_MAX_STREAMS; i++) {
+		/* User said to use 0 buffers */
+		if (cx->stream_buffers[i] == 0) {
+			cx->options.megabytes[i] = 0;
+			cx->stream_buf_size[i] = 0;
+			continue;
+		}
+		/* User said to use 0 MB total */
+		if (cx->options.megabytes[i] <= 0) {
+			cx->options.megabytes[i] = 0;
+			cx->stream_buffers[i] = 0;
+			cx->stream_buf_size[i] = 0;
+			continue;
+		}
+		/* VBI is computed later or user said buffer has size 0 */
+		if (cx->stream_buf_size[i] <= 0) {
+			if (i != CX18_ENC_STREAM_TYPE_VBI) {
+				cx->options.megabytes[i] = 0;
+				cx->stream_buffers[i] = 0;
+				cx->stream_buf_size[i] = 0;
+			}
+			continue;
+		}
+		if (cx->stream_buffers[i] < 0) {
+			cx->stream_buffers[i] = cx->options.megabytes[i] * 1024
+						/ cx->stream_buf_size[i];
+		} else {
+			/* N.B. This might round down to 0 */
+			cx->options.megabytes[i] =
+			  cx->stream_buffers[i] * cx->stream_buf_size[i] / 1024;
+		}
+		cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */
+	}
+
 	cx->options.cardtype = cardtype[cx->num];
 	cx->options.tuner = tuner[cx->num];
 	cx->options.radio = radio[cx->num];
@@ -768,13 +889,18 @@ static int __devinit cx18_probe(struct pci_dev *dev,
 	}
 	cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
 
-	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = 0x08000;
-	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = 0x08000;
-	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = 0x01200;
-	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = 0x20000;
 	vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2;
 	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
 
+	if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0)
+		cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] =
+		   cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] * 1024 * 1024
+		   / vbi_buf_size;
+	else
+		cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] =
+		     cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] * vbi_buf_size
+		     / (1024 * 1024);
+
 	if (cx->options.radio > 0)
 		cx->v4l2_cap |= V4L2_CAP_RADIO;
 
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 4d56d07195b6..29c296f39f91 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -115,6 +115,17 @@
 #define CX18_DEFAULT_ENC_VBI_BUFFERS 1
 #define CX18_DEFAULT_ENC_PCM_BUFFERS 1
 
+/* Maximum firmware DMA buffers per stream */
+#define CX18_MAX_MDLS_PER_STREAM 63
+
+/* DMA buffer, default size in kB allocated */
+#define CX18_DEFAULT_ENC_TS_BUFSIZE   32
+#define CX18_DEFAULT_ENC_MPG_BUFSIZE  32
+#define CX18_DEFAULT_ENC_IDX_BUFSIZE  32
+#define CX18_DEFAULT_ENC_YUV_BUFSIZE 128
+/* Default VBI bufsize based on standards supported by card tuner for now */
+#define CX18_DEFAULT_ENC_PCM_BUFSIZE   4
+
 /* i2c stuff */
 #define I2C_CLIENTS_MAX 16
 
@@ -408,6 +419,7 @@ struct cx18 {
 
 	struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
 	struct cx18_options options; 	/* User options */
+	int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */
 	int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
 	struct cx18_stream streams[CX18_MAX_STREAMS]; 	/* Stream data */
 	unsigned long i_flags;  /* global cx18 flags */
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index 034e09a372f1..bd5e6f3fd4d0 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -217,6 +217,10 @@ int cx18_dvb_register(struct cx18_stream *stream)
 	dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
 
 	CX18_INFO("DVB Frontend registered\n");
+	CX18_INFO("Registered DVB adapter%d for %s (%d x %d kB)\n",
+		  stream->dvb.dvb_adapter.num, stream->name,
+		  stream->buffers, stream->buf_size/1024);
+
 	mutex_init(&dvb->feedlock);
 	dvb->enabled = 1;
 	return ret;
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 6b0b7f751f20..d2690ccdf327 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -111,7 +111,6 @@ static void cx18_stream_init(struct cx18 *cx, int type)
 {
 	struct cx18_stream *s = &cx->streams[type];
 	struct video_device *dev = s->v4l2dev;
-	u32 max_size = cx->options.megabytes[type] * 1024 * 1024;
 
 	/* we need to keep v4l2dev, so restore it afterwards */
 	memset(s, 0, sizeof(*s));
@@ -124,9 +123,9 @@ static void cx18_stream_init(struct cx18 *cx, int type)
 	s->handle = CX18_INVALID_TASK_HANDLE;
 
 	s->dma = cx18_stream_info[type].dma;
+	s->buffers = cx->stream_buffers[type];
 	s->buf_size = cx->stream_buf_size[type];
-	if (s->buf_size)
-		s->buffers = max_size / s->buf_size;
+
 	mutex_init(&s->qlock);
 	init_waitqueue_head(&s->waitq);
 	s->id = -1;
@@ -162,7 +161,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 	/* User explicitly selected 0 buffers for these streams, so don't
 	   create them. */
 	if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
-	    cx->options.megabytes[type] == 0) {
+	    cx->stream_buffers[type] == 0) {
 		CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
 		return 0;
 	}
@@ -262,8 +261,9 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
 
 	switch (vfl_type) {
 	case VFL_TYPE_GRABBER:
-		CX18_INFO("Registered device video%d for %s (%d MB)\n",
-			num, s->name, cx->options.megabytes[type]);
+		CX18_INFO("Registered device video%d for %s (%d x %d kB)\n",
+			  num, s->name, cx->stream_buffers[type],
+			  cx->stream_buf_size[type]/1024);
 		break;
 
 	case VFL_TYPE_RADIO:
@@ -272,10 +272,11 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
 		break;
 
 	case VFL_TYPE_VBI:
-		if (cx->options.megabytes[type])
-			CX18_INFO("Registered device vbi%d for %s (%d MB)\n",
-				num,
-				s->name, cx->options.megabytes[type]);
+		if (cx->stream_buffers[type])
+			CX18_INFO("Registered device vbi%d for %s "
+				  "(%d x %d bytes)\n",
+				  num, s->name, cx->stream_buffers[type],
+				  cx->stream_buf_size[type]);
 		else
 			CX18_INFO("Registered device vbi%d for %s\n",
 				num, s->name);