Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (9802): cx18: Add module parameters for finer control over buffer allocations

cx18: Add module parameters for finer control over buffer allocations.
User now has the option of setting smaller buffers to get lower
latency transfers from the encoder. User can also now set the number
of buffers used for a stream explicitly.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Andy Walls and committed by
Mauro Carvalho Chehab
6ecd86dc 66c2a6b0

+167 -24
+140 -14
drivers/media/video/cx18/cx18-driver.c
··· 83 83 static char ntsc[] = "-"; 84 84 85 85 /* Buffers */ 86 - static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS; 87 86 static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS; 87 + static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS; 88 + static int enc_idx_buffers = CX18_DEFAULT_ENC_IDX_BUFFERS; 88 89 static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS; 89 90 static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS; 90 91 static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS; 92 + 93 + static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE; 94 + static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE; 95 + static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE; 96 + static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE; 97 + /* VBI bufsize based on standards supported by card tuner for now */ 98 + static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; 99 + 100 + static int enc_ts_bufs = -1; 101 + static int enc_mpg_bufs = -1; 102 + static int enc_idx_bufs = -1; 103 + static int enc_yuv_bufs = -1; 104 + static int enc_vbi_bufs = -1; 105 + static int enc_pcm_bufs = -1; 106 + 91 107 92 108 static int cx18_pci_latency = 1; 93 109 ··· 124 108 module_param(cx18_pci_latency, int, 0644); 125 109 module_param(cx18_first_minor, int, 0644); 126 110 127 - module_param(enc_mpg_buffers, int, 0644); 128 111 module_param(enc_ts_buffers, int, 0644); 112 + module_param(enc_mpg_buffers, int, 0644); 113 + module_param(enc_idx_buffers, int, 0644); 129 114 module_param(enc_yuv_buffers, int, 0644); 130 115 module_param(enc_vbi_buffers, int, 0644); 131 116 module_param(enc_pcm_buffers, int, 0644); 117 + 118 + module_param(enc_ts_bufsize, int, 0644); 119 + module_param(enc_mpg_bufsize, int, 0644); 120 + module_param(enc_idx_bufsize, int, 0644); 121 + module_param(enc_yuv_bufsize, int, 0644); 122 + /* VBI bufsize based on standards supported by card tuner for now */ 123 + module_param(enc_pcm_bufsize, int, 0644); 124 + 125 + module_param(enc_ts_bufs, int, 0644); 126 + module_param(enc_mpg_bufs, int, 0644); 127 + module_param(enc_idx_bufs, int, 0644); 128 + module_param(enc_yuv_bufs, int, 0644); 129 + module_param(enc_vbi_bufs, int, 0644); 130 + module_param(enc_pcm_bufs, int, 0644); 132 131 133 132 MODULE_PARM_DESC(tuner, "Tuner type selection,\n" 134 133 "\t\t\tsee tuner.h for values"); ··· 185 154 MODULE_PARM_DESC(mmio_ndelay, 186 155 "(Deprecated) MMIO accesses are now never purposely delayed\n" 187 156 "\t\t\tEffectively: 0 ns"); 188 - MODULE_PARM_DESC(enc_mpg_buffers, 189 - "Encoder MPG Buffers (in MB)\n" 190 - "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); 191 157 MODULE_PARM_DESC(enc_ts_buffers, 192 - "Encoder TS Buffers (in MB)\n" 158 + "Encoder TS buffer memory (MB). (enc_ts_bufs can override)\n" 193 159 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS)); 160 + MODULE_PARM_DESC(enc_ts_bufsize, 161 + "Size of an encoder TS buffer (kB)\n" 162 + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFSIZE)); 163 + MODULE_PARM_DESC(enc_ts_bufs, 164 + "Number of encoder TS buffers\n" 165 + "\t\t\tDefault is computed from other enc_ts_* parameters"); 166 + MODULE_PARM_DESC(enc_mpg_buffers, 167 + "Encoder MPG buffer memory (MB). (enc_mpg_bufs can override)\n" 168 + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); 169 + MODULE_PARM_DESC(enc_mpg_bufsize, 170 + "Size of an encoder MPG buffer (kB)\n" 171 + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFSIZE)); 172 + MODULE_PARM_DESC(enc_mpg_bufs, 173 + "Number of encoder MPG buffers\n" 174 + "\t\t\tDefault is computed from other enc_mpg_* parameters"); 175 + MODULE_PARM_DESC(enc_idx_buffers, 176 + "Encoder IDX buffer memory (MB). (enc_idx_bufs can override)\n" 177 + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFFERS)); 178 + MODULE_PARM_DESC(enc_idx_bufsize, 179 + "Size of an encoder IDX buffer (kB)\n" 180 + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFSIZE)); 181 + MODULE_PARM_DESC(enc_idx_bufs, 182 + "Number of encoder IDX buffers\n" 183 + "\t\t\tDefault is computed from other enc_idx_* parameters"); 194 184 MODULE_PARM_DESC(enc_yuv_buffers, 195 - "Encoder YUV Buffers (in MB)\n" 185 + "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n" 196 186 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); 187 + MODULE_PARM_DESC(enc_yuv_bufsize, 188 + "Size of an encoder YUV buffer (kB)\n" 189 + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFSIZE)); 190 + MODULE_PARM_DESC(enc_yuv_bufs, 191 + "Number of encoder YUV buffers\n" 192 + "\t\t\tDefault is computed from other enc_yuv_* parameters"); 197 193 MODULE_PARM_DESC(enc_vbi_buffers, 198 - "Encoder VBI Buffers (in MB)\n" 194 + "Encoder VBI buffer memory (MB). (enc_vbi_bufs can override)\n" 199 195 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS)); 196 + MODULE_PARM_DESC(enc_vbi_bufs, 197 + "Number of encoder VBI buffers\n" 198 + "\t\t\tDefault is computed from enc_vbi_buffers & tuner std"); 200 199 MODULE_PARM_DESC(enc_pcm_buffers, 201 - "Encoder PCM buffers (in MB)\n" 200 + "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n" 202 201 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); 202 + MODULE_PARM_DESC(enc_pcm_bufsize, 203 + "Size of an encoder PCM buffer (kB)\n" 204 + "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFSIZE)); 205 + MODULE_PARM_DESC(enc_pcm_bufs, 206 + "Number of encoder PCM buffers\n" 207 + "\t\t\tDefault is computed from other enc_pcm_* parameters"); 203 208 204 209 MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card"); 205 210 ··· 428 361 { 429 362 int i, j; 430 363 431 - cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers; 432 364 cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers; 365 + cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers; 366 + cx->options.megabytes[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_buffers; 433 367 cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers; 434 368 cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers; 435 369 cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; 370 + cx->options.megabytes[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control only */ 371 + 372 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufs; 373 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufs; 374 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufs; 375 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufs; 376 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_bufs; 377 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufs; 378 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control, no data */ 379 + 380 + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufsize; 381 + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize; 382 + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize; 383 + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize; 384 + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = 0; /* computed later */ 385 + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize; 386 + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */ 387 + 388 + /* Except for VBI ensure stream_buffers & stream_buf_size are valid */ 389 + for (i = 0; i < CX18_MAX_STREAMS; i++) { 390 + /* User said to use 0 buffers */ 391 + if (cx->stream_buffers[i] == 0) { 392 + cx->options.megabytes[i] = 0; 393 + cx->stream_buf_size[i] = 0; 394 + continue; 395 + } 396 + /* User said to use 0 MB total */ 397 + if (cx->options.megabytes[i] <= 0) { 398 + cx->options.megabytes[i] = 0; 399 + cx->stream_buffers[i] = 0; 400 + cx->stream_buf_size[i] = 0; 401 + continue; 402 + } 403 + /* VBI is computed later or user said buffer has size 0 */ 404 + if (cx->stream_buf_size[i] <= 0) { 405 + if (i != CX18_ENC_STREAM_TYPE_VBI) { 406 + cx->options.megabytes[i] = 0; 407 + cx->stream_buffers[i] = 0; 408 + cx->stream_buf_size[i] = 0; 409 + } 410 + continue; 411 + } 412 + if (cx->stream_buffers[i] < 0) { 413 + cx->stream_buffers[i] = cx->options.megabytes[i] * 1024 414 + / cx->stream_buf_size[i]; 415 + } else { 416 + /* N.B. This might round down to 0 */ 417 + cx->options.megabytes[i] = 418 + cx->stream_buffers[i] * cx->stream_buf_size[i] / 1024; 419 + } 420 + cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */ 421 + } 422 + 436 423 cx->options.cardtype = cardtype[cx->num]; 437 424 cx->options.tuner = tuner[cx->num]; 438 425 cx->options.radio = radio[cx->num]; ··· 889 768 } 890 769 cx->params.video_gop_size = cx->is_60hz ? 15 : 12; 891 770 892 - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = 0x08000; 893 - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = 0x08000; 894 - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = 0x01200; 895 - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = 0x20000; 896 771 vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2; 897 772 cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; 773 + 774 + if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) 775 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = 776 + cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] * 1024 * 1024 777 + / vbi_buf_size; 778 + else 779 + cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = 780 + cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] * vbi_buf_size 781 + / (1024 * 1024); 898 782 899 783 if (cx->options.radio > 0) 900 784 cx->v4l2_cap |= V4L2_CAP_RADIO;
+12
drivers/media/video/cx18/cx18-driver.h
··· 115 115 #define CX18_DEFAULT_ENC_VBI_BUFFERS 1 116 116 #define CX18_DEFAULT_ENC_PCM_BUFFERS 1 117 117 118 + /* Maximum firmware DMA buffers per stream */ 119 + #define CX18_MAX_MDLS_PER_STREAM 63 120 + 121 + /* DMA buffer, default size in kB allocated */ 122 + #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 123 + #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 124 + #define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 125 + #define CX18_DEFAULT_ENC_YUV_BUFSIZE 128 126 + /* Default VBI bufsize based on standards supported by card tuner for now */ 127 + #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 128 + 118 129 /* i2c stuff */ 119 130 #define I2C_CLIENTS_MAX 16 120 131 ··· 419 408 420 409 struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ 421 410 struct cx18_options options; /* User options */ 411 + int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ 422 412 int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ 423 413 struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ 424 414 unsigned long i_flags; /* global cx18 flags */
+4
drivers/media/video/cx18/cx18-dvb.c
··· 217 217 dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx); 218 218 219 219 CX18_INFO("DVB Frontend registered\n"); 220 + CX18_INFO("Registered DVB adapter%d for %s (%d x %d kB)\n", 221 + stream->dvb.dvb_adapter.num, stream->name, 222 + stream->buffers, stream->buf_size/1024); 223 + 220 224 mutex_init(&dvb->feedlock); 221 225 dvb->enabled = 1; 222 226 return ret;
+11 -10
drivers/media/video/cx18/cx18-streams.c
··· 111 111 { 112 112 struct cx18_stream *s = &cx->streams[type]; 113 113 struct video_device *dev = s->v4l2dev; 114 - u32 max_size = cx->options.megabytes[type] * 1024 * 1024; 115 114 116 115 /* we need to keep v4l2dev, so restore it afterwards */ 117 116 memset(s, 0, sizeof(*s)); ··· 123 124 s->handle = CX18_INVALID_TASK_HANDLE; 124 125 125 126 s->dma = cx18_stream_info[type].dma; 127 + s->buffers = cx->stream_buffers[type]; 126 128 s->buf_size = cx->stream_buf_size[type]; 127 - if (s->buf_size) 128 - s->buffers = max_size / s->buf_size; 129 + 129 130 mutex_init(&s->qlock); 130 131 init_waitqueue_head(&s->waitq); 131 132 s->id = -1; ··· 161 162 /* User explicitly selected 0 buffers for these streams, so don't 162 163 create them. */ 163 164 if (cx18_stream_info[type].dma != PCI_DMA_NONE && 164 - cx->options.megabytes[type] == 0) { 165 + cx->stream_buffers[type] == 0) { 165 166 CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name); 166 167 return 0; 167 168 } ··· 261 262 262 263 switch (vfl_type) { 263 264 case VFL_TYPE_GRABBER: 264 - CX18_INFO("Registered device video%d for %s (%d MB)\n", 265 - num, s->name, cx->options.megabytes[type]); 265 + CX18_INFO("Registered device video%d for %s (%d x %d kB)\n", 266 + num, s->name, cx->stream_buffers[type], 267 + cx->stream_buf_size[type]/1024); 266 268 break; 267 269 268 270 case VFL_TYPE_RADIO: ··· 272 272 break; 273 273 274 274 case VFL_TYPE_VBI: 275 - if (cx->options.megabytes[type]) 276 - CX18_INFO("Registered device vbi%d for %s (%d MB)\n", 277 - num, 278 - s->name, cx->options.megabytes[type]); 275 + if (cx->stream_buffers[type]) 276 + CX18_INFO("Registered device vbi%d for %s " 277 + "(%d x %d bytes)\n", 278 + num, s->name, cx->stream_buffers[type], 279 + cx->stream_buf_size[type]); 279 280 else 280 281 CX18_INFO("Registered device vbi%d for %s\n", 281 282 num, s->name);