diff options
author | Steven Toth <stoth@kernellabs.com> | 2010-07-31 15:01:00 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 05:55:01 -0400 |
commit | 1b0e8e46297a214336d85c8e278a8a004f97889e (patch) | |
tree | 8bcfe776bfc8926b2636cf8bfe6efb630404e4f6 /drivers/media/video/saa7164 | |
parent | 7c1618227e6932fcd92597507ee63c01da73e623 (diff) |
[media] saa7164: allow DMA engine buffers to vary in size between analog and digital
Signed-off-by: Steven Toth <stoth@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7164')
-rw-r--r-- | drivers/media/video/saa7164/saa7164-buffer.c | 9 | ||||
-rw-r--r-- | drivers/media/video/saa7164/saa7164-core.c | 85 | ||||
-rw-r--r-- | drivers/media/video/saa7164/saa7164-encoder.c | 245 | ||||
-rw-r--r-- | drivers/media/video/saa7164/saa7164.h | 3 |
4 files changed, 220 insertions, 122 deletions
diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c index 5f45ea7f3d7c..187e3f60fa5a 100644 --- a/drivers/media/video/saa7164/saa7164-buffer.c +++ b/drivers/media/video/saa7164/saa7164-buffer.c | |||
@@ -134,18 +134,19 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port, | |||
134 | buf->crc = crc32(0, buf->cpu, buf->actual_size); | 134 | buf->crc = crc32(0, buf->cpu, buf->actual_size); |
135 | memset_io(buf->pt_cpu, 0xff, buf->pt_size); | 135 | memset_io(buf->pt_cpu, 0xff, buf->pt_size); |
136 | 136 | ||
137 | dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p\n", | 137 | dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p (%d pageptrs)\n", |
138 | __func__, buf); | 138 | __func__, buf, params->numpagetables); |
139 | dprintk(DBGLVL_BUF, " pci_cpu @ 0x%p dma @ 0x%08lx len = 0x%x\n", | 139 | dprintk(DBGLVL_BUF, " pci_cpu @ 0x%p dma @ 0x%08lx len = 0x%x\n", |
140 | buf->cpu, (long)buf->dma, buf->pci_size); | 140 | buf->cpu, (long)buf->dma, buf->pci_size); |
141 | dprintk(DBGLVL_BUF, " pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n", | 141 | dprintk(DBGLVL_BUF, " pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n", |
142 | buf->pt_cpu, (long)buf->pt_dma, buf->pt_size); | 142 | buf->pt_cpu, (long)buf->pt_dma, buf->pt_size); |
143 | 143 | ||
144 | /* Format the Page Table Entries to point into the data buffer */ | 144 | /* Format the Page Table Entries to point into the data buffer */ |
145 | // for (i = 0 ; i < SAA7164_PT_ENTRIES; i++) { | 145 | for (i = 0 ; i < params->numpagetables; i++) { |
146 | for (i = 0 ; i < 10; i++) { | ||
147 | 146 | ||
148 | *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */ | 147 | *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */ |
148 | dprintk(DBGLVL_BUF, " pt[%02d] = 0x%p -> 0x%llx\n", | ||
149 | i, buf->pt_cpu, (u64)*(buf->pt_cpu)); | ||
149 | 150 | ||
150 | } | 151 | } |
151 | 152 | ||
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index b54b032d56b6..8879517d974a 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c | |||
@@ -65,6 +65,14 @@ unsigned int print_histogram = 64; | |||
65 | module_param(print_histogram, int, 0644); | 65 | module_param(print_histogram, int, 0644); |
66 | MODULE_PARM_DESC(print_histogram, "print histogram values once"); | 66 | MODULE_PARM_DESC(print_histogram, "print histogram values once"); |
67 | 67 | ||
68 | unsigned int crc_checking = 1; | ||
69 | module_param(crc_checking, int, 0644); | ||
70 | MODULE_PARM_DESC(crc_checking, "enable crc sanity checking on buffers"); | ||
71 | |||
72 | unsigned int guard_checking = 1; | ||
73 | module_param(guard_checking, int, 0644); | ||
74 | MODULE_PARM_DESC(guard_checking, "enable dma sanity checking for buffer overruns"); | ||
75 | |||
68 | static unsigned int saa7164_devcount; | 76 | static unsigned int saa7164_devcount; |
69 | 77 | ||
70 | static DEFINE_MUTEX(devlist); | 78 | static DEFINE_MUTEX(devlist); |
@@ -101,17 +109,24 @@ static void saa7164_pack_verifier(struct saa7164_buffer *buf) | |||
101 | 109 | ||
102 | for (i = 0; i < buf->actual_size; i += 2048) { | 110 | for (i = 0; i < buf->actual_size; i += 2048) { |
103 | 111 | ||
104 | if ( (*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) || (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA) ) | 112 | if ( (*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) || |
113 | (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA) ) { | ||
105 | printk(KERN_ERR "No pack at 0x%x\n", i); | 114 | printk(KERN_ERR "No pack at 0x%x\n", i); |
115 | // saa7164_dumphex16FF(buf->port->dev, (p + i), 32); | ||
116 | } | ||
106 | } | 117 | } |
107 | } | 118 | } |
108 | 119 | ||
120 | #define FIXED_VIDEO_PID 0xf1 | ||
121 | #define FIXED_AUDIO_PID 0xf2 | ||
122 | |||
109 | static void saa7164_ts_verifier(struct saa7164_buffer *buf) | 123 | static void saa7164_ts_verifier(struct saa7164_buffer *buf) |
110 | { | 124 | { |
111 | struct saa7164_port *port = buf->port; | 125 | struct saa7164_port *port = buf->port; |
112 | u32 i; | 126 | u32 i; |
113 | u8 tmp, cc, a; | 127 | u8 cc, a; |
114 | u8 *bufcpu = (u8 *)buf->cpu; | 128 | u16 pid; |
129 | u8 __iomem *bufcpu = (u8 *)buf->cpu; | ||
115 | 130 | ||
116 | port->sync_errors = 0; | 131 | port->sync_errors = 0; |
117 | port->v_cc_errors = 0; | 132 | port->v_cc_errors = 0; |
@@ -121,23 +136,25 @@ static void saa7164_ts_verifier(struct saa7164_buffer *buf) | |||
121 | if (*(bufcpu + i) != 0x47) | 136 | if (*(bufcpu + i) != 0x47) |
122 | port->sync_errors++; | 137 | port->sync_errors++; |
123 | 138 | ||
124 | /* Query pid lower 8 bits */ | 139 | /* TODO: Query pid lower 8 bits, ignoring upper bits intensionally */ |
125 | tmp = *(bufcpu + i + 2); | 140 | pid = ((*(bufcpu + i + 1) & 0x1f) << 8) | *(bufcpu + i + 2); |
126 | cc = *(bufcpu + i + 3) & 0x0f; | 141 | cc = *(bufcpu + i + 3) & 0x0f; |
127 | 142 | ||
128 | if (tmp == 0xf1) { | 143 | if (pid == FIXED_VIDEO_PID) { |
129 | a = ((port->last_v_cc + 1) & 0x0f); | 144 | a = ((port->last_v_cc + 1) & 0x0f); |
130 | if (a != cc) { | 145 | if (a != cc) { |
131 | printk(KERN_ERR "video cc last = %x current = %x i = %d\n", port->last_v_cc, cc, i); | 146 | printk(KERN_ERR "video cc last = %x current = %x i = %d\n", |
147 | port->last_v_cc, cc, i); | ||
132 | port->v_cc_errors++; | 148 | port->v_cc_errors++; |
133 | } | 149 | } |
134 | 150 | ||
135 | port->last_v_cc = cc; | 151 | port->last_v_cc = cc; |
136 | } else | 152 | } else |
137 | if (tmp == 0xf2) { | 153 | if (pid == FIXED_AUDIO_PID) { |
138 | a = ((port->last_a_cc + 1) & 0x0f); | 154 | a = ((port->last_a_cc + 1) & 0x0f); |
139 | if (a != cc) { | 155 | if (a != cc) { |
140 | printk(KERN_ERR "audio cc last = %x current = %x i = %d\n", port->last_a_cc, cc, i); | 156 | printk(KERN_ERR "audio cc last = %x current = %x i = %d\n", |
157 | port->last_a_cc, cc, i); | ||
141 | port->a_cc_errors++; | 158 | port->a_cc_errors++; |
142 | } | 159 | } |
143 | 160 | ||
@@ -246,6 +263,7 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr) | |||
246 | struct saa7164_user_buffer *ubuf = 0; | 263 | struct saa7164_user_buffer *ubuf = 0; |
247 | struct list_head *c, *n; | 264 | struct list_head *c, *n; |
248 | int i = 0; | 265 | int i = 0; |
266 | u8 __iomem *p; | ||
249 | 267 | ||
250 | mutex_lock(&port->dmaqueue_lock); | 268 | mutex_lock(&port->dmaqueue_lock); |
251 | list_for_each_safe(c, n, &port->dmaqueue.list) { | 269 | list_for_each_safe(c, n, &port->dmaqueue.list) { |
@@ -260,12 +278,33 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr) | |||
260 | if (buf->idx == bufnr) { | 278 | if (buf->idx == bufnr) { |
261 | 279 | ||
262 | /* Found the buffer, deal with it */ | 280 | /* Found the buffer, deal with it */ |
263 | dprintk(DBGLVL_IRQ, "%s() rp: %d\n", __func__, bufnr); | 281 | dprintk(DBGLVL_IRQ, "%s() bufnr: %d\n", __func__, bufnr); |
282 | |||
283 | if (crc_checking) { | ||
284 | /* Throw a new checksum on the dma buffer */ | ||
285 | buf->crc = crc32(0, buf->cpu, buf->actual_size); | ||
286 | } | ||
287 | |||
288 | if (guard_checking) { | ||
289 | p = (u8 *)buf->cpu; | ||
290 | if ( (*(p + buf->actual_size + 0) != 0xff) || | ||
291 | (*(p + buf->actual_size + 1) != 0xff) || | ||
292 | (*(p + buf->actual_size + 2) != 0xff) || | ||
293 | (*(p + buf->actual_size + 3) != 0xff) || | ||
294 | (*(p + buf->actual_size + 0x10) != 0xff) || | ||
295 | (*(p + buf->actual_size + 0x11) != 0xff) || | ||
296 | (*(p + buf->actual_size + 0x12) != 0xff) || | ||
297 | (*(p + buf->actual_size + 0x13) != 0xff) ) { | ||
298 | printk(KERN_ERR "%s() buf %p guard buffer breach\n", | ||
299 | __func__, buf); | ||
300 | // saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64); | ||
301 | } | ||
302 | } | ||
264 | 303 | ||
265 | /* Validate the incoming buffer content */ | 304 | /* Validate the incoming buffer content */ |
266 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) | 305 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) |
267 | saa7164_ts_verifier(buf); | 306 | saa7164_ts_verifier(buf); |
268 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) | 307 | else if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) |
269 | saa7164_pack_verifier(buf); | 308 | saa7164_pack_verifier(buf); |
270 | 309 | ||
271 | /* find a free user buffer and clone to it */ | 310 | /* find a free user buffer and clone to it */ |
@@ -280,8 +319,10 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr) | |||
280 | memcpy_fromio(ubuf->data, buf->cpu, | 319 | memcpy_fromio(ubuf->data, buf->cpu, |
281 | ubuf->actual_size); | 320 | ubuf->actual_size); |
282 | 321 | ||
283 | /* Throw a new checksum on the read buffer */ | 322 | if (crc_checking) { |
284 | ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size); | 323 | /* Throw a new checksum on the read buffer */ |
324 | ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size); | ||
325 | } | ||
285 | 326 | ||
286 | /* Requeue the buffer on the free list */ | 327 | /* Requeue the buffer on the free list */ |
287 | ubuf->pos = 0; | 328 | ubuf->pos = 0; |
@@ -304,6 +345,10 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr) | |||
304 | * in time. */ | 345 | * in time. */ |
305 | saa7164_buffer_zero_offsets(port, bufnr); | 346 | saa7164_buffer_zero_offsets(port, bufnr); |
306 | memset_io(buf->cpu, 0xff, buf->pci_size); | 347 | memset_io(buf->cpu, 0xff, buf->pci_size); |
348 | if (crc_checking) { | ||
349 | /* Throw yet aanother new checksum on the dma buffer */ | ||
350 | buf->crc = crc32(0, buf->cpu, buf->actual_size); | ||
351 | } | ||
307 | 352 | ||
308 | break; | 353 | break; |
309 | } | 354 | } |
@@ -352,17 +397,22 @@ static void saa7164_work_enchandler(struct work_struct *w) | |||
352 | 397 | ||
353 | /* Most current complete buffer */ | 398 | /* Most current complete buffer */ |
354 | if (wp == 0) | 399 | if (wp == 0) |
355 | mcb = 7; | 400 | mcb = (port->hwcfg.buffercount - 1); |
356 | else | 401 | else |
357 | mcb = wp - 1; | 402 | mcb = wp - 1; |
358 | 403 | ||
359 | while (1) { | 404 | while (1) { |
360 | rp = (port->last_svc_rp + 1) % 8; | 405 | if (port->done_first_interrupt == 0) { |
406 | port->done_first_interrupt++; | ||
407 | rp = mcb; | ||
408 | } else | ||
409 | rp = (port->last_svc_rp + 1) % 8; | ||
361 | 410 | ||
362 | if ((rp < 0) || (rp > 7)) { | 411 | if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) { |
363 | printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp); | 412 | printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp); |
364 | break; | 413 | break; |
365 | } | 414 | } |
415 | |||
366 | saa7164_work_enchandler_helper(port, rp); | 416 | saa7164_work_enchandler_helper(port, rp); |
367 | port->last_svc_rp = rp; | 417 | port->last_svc_rp = rp; |
368 | cnt++; | 418 | cnt++; |
@@ -371,6 +421,7 @@ static void saa7164_work_enchandler(struct work_struct *w) | |||
371 | break; | 421 | break; |
372 | } | 422 | } |
373 | 423 | ||
424 | /* TODO: Convert this into a /proc/saa7164 style readable file */ | ||
374 | if (print_histogram == port->nr) { | 425 | if (print_histogram == port->nr) { |
375 | saa7164_histogram_print(port, &port->irq_interval); | 426 | saa7164_histogram_print(port, &port->irq_interval); |
376 | saa7164_histogram_print(port, &port->svc_interval); | 427 | saa7164_histogram_print(port, &port->svc_interval); |
@@ -438,7 +489,7 @@ static irqreturn_t saa7164_irq_ts(struct saa7164_port *port) | |||
438 | 489 | ||
439 | /* Find the previous buffer to the current write point */ | 490 | /* Find the previous buffer to the current write point */ |
440 | if (wp == 0) | 491 | if (wp == 0) |
441 | rp = 7; | 492 | rp = (port->hwcfg.buffercount - 1); |
442 | else | 493 | else |
443 | rp = wp - 1; | 494 | rp = wp - 1; |
444 | 495 | ||
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c index 08b62e41c466..0859448bae05 100644 --- a/drivers/media/video/saa7164/saa7164-encoder.c +++ b/drivers/media/video/saa7164/saa7164-encoder.c | |||
@@ -76,15 +76,131 @@ static void saa7164_encoder_configure(struct saa7164_port *port) | |||
76 | saa7164_api_set_audio_std(port); | 76 | saa7164_api_set_audio_std(port); |
77 | } | 77 | } |
78 | 78 | ||
79 | /* One time configuration at registration time */ | 79 | static int saa7164_encoder_buffers_dealloc(struct saa7164_port *port) |
80 | static int saa7164_encoder_initialize(struct saa7164_port *port) | 80 | { |
81 | struct list_head *c, *n, *p, *q, *l, *v; | ||
82 | struct saa7164_dev *dev = port->dev; | ||
83 | struct saa7164_buffer *buf; | ||
84 | struct saa7164_user_buffer *ubuf; | ||
85 | |||
86 | /* Remove any allocated buffers */ | ||
87 | mutex_lock(&port->dmaqueue_lock); | ||
88 | |||
89 | dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr); | ||
90 | list_for_each_safe(c, n, &port->dmaqueue.list) { | ||
91 | buf = list_entry(c, struct saa7164_buffer, list); | ||
92 | list_del(c); | ||
93 | saa7164_buffer_dealloc(buf); | ||
94 | } | ||
95 | |||
96 | dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr); | ||
97 | list_for_each_safe(p, q, &port->list_buf_used.list) { | ||
98 | ubuf = list_entry(p, struct saa7164_user_buffer, list); | ||
99 | list_del(p); | ||
100 | saa7164_buffer_dealloc_user(ubuf); | ||
101 | } | ||
102 | |||
103 | dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr); | ||
104 | list_for_each_safe(l, v, &port->list_buf_free.list) { | ||
105 | ubuf = list_entry(l, struct saa7164_user_buffer, list); | ||
106 | list_del(l); | ||
107 | saa7164_buffer_dealloc_user(ubuf); | ||
108 | } | ||
109 | |||
110 | mutex_unlock(&port->dmaqueue_lock); | ||
111 | dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | /* Dynamic buffer switch at encoder start time */ | ||
117 | static int saa7164_encoder_buffers_alloc(struct saa7164_port *port) | ||
81 | { | 118 | { |
82 | struct saa7164_dev *dev = port->dev; | 119 | struct saa7164_dev *dev = port->dev; |
120 | struct saa7164_buffer *buf; | ||
121 | struct saa7164_user_buffer *ubuf; | ||
122 | tmHWStreamParameters_t *params = &port->hw_streamingparams; | ||
123 | int result = -ENODEV, i; | ||
124 | int len = 0; | ||
83 | 125 | ||
84 | dprintk(DBGLVL_ENC, "%s()\n", __func__); | 126 | dprintk(DBGLVL_ENC, "%s()\n", __func__); |
85 | 127 | ||
86 | saa7164_encoder_configure(port); | 128 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { |
129 | dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", __func__); | ||
130 | params->samplesperline = 128; | ||
131 | params->numberoflines = 256; | ||
132 | params->pitch = 128; | ||
133 | params->numpagetables = 2 + | ||
134 | ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); | ||
135 | } else | ||
136 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) { | ||
137 | dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", __func__); | ||
138 | params->samplesperline = 188; | ||
139 | params->numberoflines = 312; | ||
140 | params->pitch = 188; | ||
141 | params->numpagetables = 2 + | ||
142 | ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE); | ||
143 | } else | ||
144 | BUG(); | ||
145 | |||
146 | /* Init and establish defaults */ | ||
147 | params->bitspersample = 8; | ||
148 | params->linethreshold = 0; | ||
149 | params->pagetablelistvirt = 0; | ||
150 | params->pagetablelistphys = 0; | ||
151 | params->numpagetableentries = port->hwcfg.buffercount; | ||
152 | |||
153 | /* Allocate the PCI resources, buffers (hard) */ | ||
154 | for (i = 0; i < port->hwcfg.buffercount; i++) { | ||
155 | buf = saa7164_buffer_alloc(port, | ||
156 | params->numberoflines * | ||
157 | params->pitch); | ||
158 | |||
159 | if (!buf) { | ||
160 | printk(KERN_ERR "%s() failed " | ||
161 | "(errno = %d), unable to allocate buffer\n", | ||
162 | __func__, result); | ||
163 | result = -ENOMEM; | ||
164 | goto failed; | ||
165 | } else { | ||
166 | |||
167 | mutex_lock(&port->dmaqueue_lock); | ||
168 | list_add_tail(&buf->list, &port->dmaqueue.list); | ||
169 | mutex_unlock(&port->dmaqueue_lock); | ||
170 | |||
171 | } | ||
172 | } | ||
173 | |||
174 | /* Allocate some kenrel kernel buffers for copying | ||
175 | * to userpsace. | ||
176 | */ | ||
177 | len = params->numberoflines * params->pitch; | ||
178 | |||
179 | if (encoder_buffers < 16) | ||
180 | encoder_buffers = 16; | ||
181 | if (encoder_buffers > 512) | ||
182 | encoder_buffers = 512; | ||
183 | |||
184 | for (i = 0; i < encoder_buffers; i++) { | ||
185 | |||
186 | ubuf = saa7164_buffer_alloc_user(dev, len); | ||
187 | if (ubuf) { | ||
188 | mutex_lock(&port->dmaqueue_lock); | ||
189 | list_add_tail(&ubuf->list, &port->list_buf_free.list); | ||
190 | mutex_unlock(&port->dmaqueue_lock); | ||
191 | } | ||
192 | |||
193 | } | ||
194 | |||
195 | result = 0; | ||
87 | 196 | ||
197 | failed: | ||
198 | return result; | ||
199 | } | ||
200 | |||
201 | static int saa7164_encoder_initialize(struct saa7164_port *port) | ||
202 | { | ||
203 | saa7164_encoder_configure(port); | ||
88 | return 0; | 204 | return 0; |
89 | } | 205 | } |
90 | 206 | ||
@@ -835,6 +951,7 @@ static int saa7164_encoder_stop_streaming(struct saa7164_port *port) | |||
835 | dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__, | 951 | dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__, |
836 | port->nr); | 952 | port->nr); |
837 | 953 | ||
954 | /* Reset the state of any allocated buffer resources */ | ||
838 | mutex_lock(&port->dmaqueue_lock); | 955 | mutex_lock(&port->dmaqueue_lock); |
839 | 956 | ||
840 | /* Reset the hard and soft buffer state */ | 957 | /* Reset the hard and soft buffer state */ |
@@ -851,6 +968,10 @@ static int saa7164_encoder_stop_streaming(struct saa7164_port *port) | |||
851 | } | 968 | } |
852 | 969 | ||
853 | mutex_unlock(&port->dmaqueue_lock); | 970 | mutex_unlock(&port->dmaqueue_lock); |
971 | |||
972 | /* Free any allocated resources */ | ||
973 | saa7164_encoder_buffers_dealloc(port); | ||
974 | |||
854 | dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr); | 975 | dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr); |
855 | 976 | ||
856 | return ret; | 977 | return ret; |
@@ -863,10 +984,19 @@ static int saa7164_encoder_start_streaming(struct saa7164_port *port) | |||
863 | 984 | ||
864 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); | 985 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); |
865 | 986 | ||
987 | port->done_first_interrupt = 0; | ||
988 | |||
989 | /* allocate all of the PCIe DMA buffer resources on the fly, | ||
990 | * allowing switching between TS and PS payloads without | ||
991 | * requiring a complete driver reload. | ||
992 | */ | ||
993 | saa7164_encoder_buffers_alloc(port); | ||
994 | |||
866 | /* Configure the encoder with any cache values */ | 995 | /* Configure the encoder with any cache values */ |
867 | saa7164_api_set_encoder(port); | 996 | saa7164_api_set_encoder(port); |
868 | saa7164_api_get_encoder(port); | 997 | saa7164_api_get_encoder(port); |
869 | 998 | ||
999 | /* Place the empty buffers on the hardware */ | ||
870 | saa7164_buffer_cfg_port(port); | 1000 | saa7164_buffer_cfg_port(port); |
871 | 1001 | ||
872 | /* Acquire the hardware */ | 1002 | /* Acquire the hardware */ |
@@ -1005,27 +1135,29 @@ static int fops_release(struct file *file) | |||
1005 | 1135 | ||
1006 | struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) | 1136 | struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) |
1007 | { | 1137 | { |
1008 | struct saa7164_user_buffer *buf = 0; | 1138 | struct saa7164_user_buffer *ubuf = 0; |
1009 | struct saa7164_dev *dev = port->dev; | 1139 | struct saa7164_dev *dev = port->dev; |
1010 | u32 crc; | 1140 | u32 crc; |
1011 | 1141 | ||
1012 | mutex_lock(&port->dmaqueue_lock); | 1142 | mutex_lock(&port->dmaqueue_lock); |
1013 | if (!list_empty(&port->list_buf_used.list)) { | 1143 | if (!list_empty(&port->list_buf_used.list)) { |
1014 | buf = list_first_entry(&port->list_buf_used.list, | 1144 | ubuf = list_first_entry(&port->list_buf_used.list, |
1015 | struct saa7164_user_buffer, list); | 1145 | struct saa7164_user_buffer, list); |
1016 | 1146 | ||
1017 | crc = crc32(0, buf->data, buf->actual_size); | 1147 | if (crc_checking) { |
1018 | if (crc != buf->crc) { | 1148 | crc = crc32(0, ubuf->data, ubuf->actual_size); |
1019 | printk(KERN_ERR "%s() buf %p crc became invalid, was 0x%x became 0x%x\n", __func__, | 1149 | if (crc != ubuf->crc) { |
1020 | buf, buf->crc, crc); | 1150 | printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__, |
1151 | ubuf, ubuf->crc, crc); | ||
1152 | } | ||
1021 | } | 1153 | } |
1022 | 1154 | ||
1023 | } | 1155 | } |
1024 | mutex_unlock(&port->dmaqueue_lock); | 1156 | mutex_unlock(&port->dmaqueue_lock); |
1025 | 1157 | ||
1026 | dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, buf); | 1158 | dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, ubuf); |
1027 | 1159 | ||
1028 | return buf; | 1160 | return ubuf; |
1029 | } | 1161 | } |
1030 | 1162 | ||
1031 | static ssize_t fops_read(struct file *file, char __user *buffer, | 1163 | static ssize_t fops_read(struct file *file, char __user *buffer, |
@@ -1292,10 +1424,7 @@ static struct video_device *saa7164_encoder_alloc( | |||
1292 | int saa7164_encoder_register(struct saa7164_port *port) | 1424 | int saa7164_encoder_register(struct saa7164_port *port) |
1293 | { | 1425 | { |
1294 | struct saa7164_dev *dev = port->dev; | 1426 | struct saa7164_dev *dev = port->dev; |
1295 | struct saa7164_buffer *buf; | 1427 | int result = -ENODEV; |
1296 | struct saa7164_user_buffer *ubuf; | ||
1297 | int result = -ENODEV, i; | ||
1298 | int len = 0; | ||
1299 | 1428 | ||
1300 | dprintk(DBGLVL_ENC, "%s()\n", __func__); | 1429 | dprintk(DBGLVL_ENC, "%s()\n", __func__); |
1301 | 1430 | ||
@@ -1311,64 +1440,6 @@ int saa7164_encoder_register(struct saa7164_port *port) | |||
1311 | goto failed; | 1440 | goto failed; |
1312 | } | 1441 | } |
1313 | 1442 | ||
1314 | /* Init and establish defaults */ | ||
1315 | /* TODO: Check the umber of lines for PS */ | ||
1316 | port->hw_streamingparams.bitspersample = 8; | ||
1317 | port->hw_streamingparams.samplesperline = 128; | ||
1318 | port->hw_streamingparams.numberoflines = 256; | ||
1319 | |||
1320 | port->hw_streamingparams.pitch = 128; | ||
1321 | port->hw_streamingparams.linethreshold = 0; | ||
1322 | port->hw_streamingparams.pagetablelistvirt = 0; | ||
1323 | port->hw_streamingparams.pagetablelistphys = 0; | ||
1324 | port->hw_streamingparams.numpagetables = 2 + | ||
1325 | ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); | ||
1326 | |||
1327 | port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount; | ||
1328 | |||
1329 | /* Allocate the PCI resources, buffers (hard) */ | ||
1330 | for (i = 0; i < port->hwcfg.buffercount; i++) { | ||
1331 | buf = saa7164_buffer_alloc(port, | ||
1332 | port->hw_streamingparams.numberoflines * | ||
1333 | port->hw_streamingparams.pitch); | ||
1334 | |||
1335 | if (!buf) { | ||
1336 | printk(KERN_ERR "%s() failed " | ||
1337 | "(errno = %d), unable to allocate buffer\n", | ||
1338 | __func__, result); | ||
1339 | result = -ENOMEM; | ||
1340 | goto failed; | ||
1341 | } else { | ||
1342 | |||
1343 | mutex_lock(&port->dmaqueue_lock); | ||
1344 | list_add_tail(&buf->list, &port->dmaqueue.list); | ||
1345 | mutex_unlock(&port->dmaqueue_lock); | ||
1346 | |||
1347 | } | ||
1348 | } | ||
1349 | |||
1350 | /* Allocate some kenrel kernel buffers for copying | ||
1351 | * to userpsace. | ||
1352 | */ | ||
1353 | len = port->hw_streamingparams.numberoflines * | ||
1354 | port->hw_streamingparams.pitch; | ||
1355 | |||
1356 | if (encoder_buffers < 16) | ||
1357 | encoder_buffers = 16; | ||
1358 | if (encoder_buffers > 512) | ||
1359 | encoder_buffers = 512; | ||
1360 | |||
1361 | for (i = 0; i < encoder_buffers; i++) { | ||
1362 | |||
1363 | ubuf = saa7164_buffer_alloc_user(dev, len); | ||
1364 | if (ubuf) { | ||
1365 | mutex_lock(&port->dmaqueue_lock); | ||
1366 | list_add_tail(&ubuf->list, &port->list_buf_free.list); | ||
1367 | mutex_unlock(&port->dmaqueue_lock); | ||
1368 | } | ||
1369 | |||
1370 | } | ||
1371 | |||
1372 | /* Establish encoder defaults here */ | 1443 | /* Establish encoder defaults here */ |
1373 | /* Set default TV standard */ | 1444 | /* Set default TV standard */ |
1374 | port->encodernorm = saa7164_tvnorms[0]; | 1445 | port->encodernorm = saa7164_tvnorms[0]; |
@@ -1446,9 +1517,6 @@ failed: | |||
1446 | void saa7164_encoder_unregister(struct saa7164_port *port) | 1517 | void saa7164_encoder_unregister(struct saa7164_port *port) |
1447 | { | 1518 | { |
1448 | struct saa7164_dev *dev = port->dev; | 1519 | struct saa7164_dev *dev = port->dev; |
1449 | struct saa7164_buffer *buf; | ||
1450 | struct saa7164_user_buffer *ubuf; | ||
1451 | struct list_head *c, *n, *p, *q, *l, *v; | ||
1452 | 1520 | ||
1453 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); | 1521 | dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr); |
1454 | 1522 | ||
@@ -1464,31 +1532,6 @@ void saa7164_encoder_unregister(struct saa7164_port *port) | |||
1464 | port->v4l_device = NULL; | 1532 | port->v4l_device = NULL; |
1465 | } | 1533 | } |
1466 | 1534 | ||
1467 | /* Remove any allocated buffers */ | ||
1468 | mutex_lock(&port->dmaqueue_lock); | ||
1469 | |||
1470 | dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr); | ||
1471 | list_for_each_safe(c, n, &port->dmaqueue.list) { | ||
1472 | buf = list_entry(c, struct saa7164_buffer, list); | ||
1473 | list_del(c); | ||
1474 | saa7164_buffer_dealloc(buf); | ||
1475 | } | ||
1476 | |||
1477 | dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr); | ||
1478 | list_for_each_safe(p, q, &port->list_buf_used.list) { | ||
1479 | ubuf = list_entry(p, struct saa7164_user_buffer, list); | ||
1480 | list_del(p); | ||
1481 | saa7164_buffer_dealloc_user(ubuf); | ||
1482 | } | ||
1483 | |||
1484 | dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr); | ||
1485 | list_for_each_safe(l, v, &port->list_buf_free.list) { | ||
1486 | ubuf = list_entry(l, struct saa7164_user_buffer, list); | ||
1487 | list_del(l); | ||
1488 | saa7164_buffer_dealloc_user(ubuf); | ||
1489 | } | ||
1490 | |||
1491 | mutex_unlock(&port->dmaqueue_lock); | ||
1492 | dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); | 1535 | dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr); |
1493 | } | 1536 | } |
1494 | 1537 | ||
diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h index 71e385328ce3..0cafe8a557e5 100644 --- a/drivers/media/video/saa7164/saa7164.h +++ b/drivers/media/video/saa7164/saa7164.h | |||
@@ -389,6 +389,7 @@ struct saa7164_port { | |||
389 | u32 a_cc_errors; | 389 | u32 a_cc_errors; |
390 | u8 last_v_cc; | 390 | u8 last_v_cc; |
391 | u8 last_a_cc; | 391 | u8 last_a_cc; |
392 | u32 done_first_interrupt; | ||
392 | }; | 393 | }; |
393 | 394 | ||
394 | struct saa7164_dev { | 395 | struct saa7164_dev { |
@@ -546,6 +547,8 @@ void saa7164_encoder_unregister(struct saa7164_port *port); | |||
546 | 547 | ||
547 | /* ----------------------------------------------------------- */ | 548 | /* ----------------------------------------------------------- */ |
548 | 549 | ||
550 | extern unsigned int crc_checking; | ||
551 | |||
549 | extern unsigned int saa_debug; | 552 | extern unsigned int saa_debug; |
550 | #define dprintk(level, fmt, arg...)\ | 553 | #define dprintk(level, fmt, arg...)\ |
551 | do { if (saa_debug & level)\ | 554 | do { if (saa_debug & level)\ |