Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
media
pci
saa7164
saa7164-buffer.c
Go to the documentation of this file.
1
/*
2
* Driver for the NXP SAA7164 PCIe bridge
3
*
4
* Copyright (c) 2010 Steven Toth <
[email protected]
>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
*
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
*/
21
22
#include <linux/slab.h>
23
24
#include "
saa7164.h
"
25
26
/* The PCI address space for buffer handling looks like this:
27
*
28
* +-u32 wide-------------+
29
* | +
30
* +-u64 wide------------------------------------+
31
* + +
32
* +----------------------+
33
* | CurrentBufferPtr + Pointer to current PCI buffer >-+
34
* +----------------------+ |
35
* | Unused + |
36
* +----------------------+ |
37
* | Pitch + = 188 (bytes) |
38
* +----------------------+ |
39
* | PCI buffer size + = pitch * number of lines (312) |
40
* +----------------------+ |
41
* |0| Buf0 Write Offset + |
42
* +----------------------+ v
43
* |1| Buf1 Write Offset + |
44
* +----------------------+ |
45
* |2| Buf2 Write Offset + |
46
* +----------------------+ |
47
* |3| Buf3 Write Offset + |
48
* +----------------------+ |
49
* ... More write offsets |
50
* +---------------------------------------------+ |
51
* +0| set of ptrs to PCI pagetables + |
52
* +---------------------------------------------+ |
53
* +1| set of ptrs to PCI pagetables + <--------+
54
* +---------------------------------------------+
55
* +2| set of ptrs to PCI pagetables +
56
* +---------------------------------------------+
57
* +3| set of ptrs to PCI pagetables + >--+
58
* +---------------------------------------------+ |
59
* ... More buffer pointers | +----------------+
60
* +->| pt[0] TS data |
61
* | +----------------+
62
* |
63
* | +----------------+
64
* +->| pt[1] TS data |
65
* | +----------------+
66
* | etc
67
*/
68
69
void
saa7164_buffer_display
(
struct
saa7164_buffer
*
buf
)
70
{
71
struct
saa7164_dev
*
dev
= buf->
port
->dev;
72
int
i
;
73
74
dprintk
(
DBGLVL_BUF
,
"%s() buffer @ 0x%p nr=%d\n"
,
75
__func__, buf, buf->
idx
);
76
dprintk
(
DBGLVL_BUF
,
" pci_cpu @ 0x%p dma @ 0x%08llx len = 0x%x\n"
,
77
buf->
cpu
, (
long
long
)buf->
dma
, buf->
pci_size
);
78
dprintk
(
DBGLVL_BUF
,
" pt_cpu @ 0x%p pt_dma @ 0x%08llx len = 0x%x\n"
,
79
buf->
pt_cpu
, (
long
long
)buf->
pt_dma
, buf->
pt_size
);
80
81
/* Format the Page Table Entries to point into the data buffer */
82
for
(i = 0 ; i <
SAA7164_PT_ENTRIES
; i++) {
83
84
dprintk
(
DBGLVL_BUF
,
" pt[%02d] = 0x%p -> 0x%llx\n"
,
85
i, buf->
pt_cpu
, (
u64
)*(buf->
pt_cpu
));
86
87
}
88
}
89
/* Allocate a new buffer structure and associated PCI space in bytes.
90
* len must be a multiple of sizeof(u64)
91
*/
92
struct
saa7164_buffer
*
saa7164_buffer_alloc
(
struct
saa7164_port
*
port
,
93
u32
len)
94
{
95
struct
tmHWStreamParameters
*
params
= &port->
hw_streamingparams
;
96
struct
saa7164_buffer
*
buf
=
NULL
;
97
struct
saa7164_dev
*
dev
= port->
dev
;
98
int
i
;
99
100
if
((len == 0) || (len >= 65536) || (len %
sizeof
(
u64
))) {
101
log_warn
(
"%s() SAA_ERR_BAD_PARAMETER\n"
, __func__);
102
goto
ret
;
103
}
104
105
buf = kzalloc(
sizeof
(
struct
saa7164_buffer
),
GFP_KERNEL
);
106
if
(!buf) {
107
log_warn
(
"%s() SAA_ERR_NO_RESOURCES\n"
, __func__);
108
goto
ret
;
109
}
110
111
buf->
idx
= -1;
112
buf->
port
=
port
;
113
buf->
flags
=
SAA7164_BUFFER_FREE
;
114
buf->
pos
= 0;
115
buf->
actual_size
= params->
pitch
* params->
numberoflines
;
116
buf->
crc
= 0;
117
/* TODO: arg len is being ignored */
118
buf->
pci_size
=
SAA7164_PT_ENTRIES
* 0x1000;
119
buf->
pt_size
= (
SAA7164_PT_ENTRIES
*
sizeof
(
u64
)) + 0x1000;
120
121
/* Allocate contiguous memory */
122
buf->
cpu
=
pci_alloc_consistent
(port->
dev
->pci, buf->
pci_size
,
123
&buf->
dma
);
124
if
(!buf->
cpu
)
125
goto
fail1;
126
127
buf->
pt_cpu
=
pci_alloc_consistent
(port->
dev
->pci, buf->
pt_size
,
128
&buf->
pt_dma
);
129
if
(!buf->
pt_cpu
)
130
goto
fail2;
131
132
/* init the buffers to a known pattern, easier during debugging */
133
memset_io
(buf->
cpu
, 0xff, buf->
pci_size
);
134
buf->
crc
=
crc32
(0, buf->
cpu
, buf->
actual_size
);
135
memset_io
(buf->
pt_cpu
, 0xff, buf->
pt_size
);
136
137
dprintk
(
DBGLVL_BUF
,
"%s() allocated buffer @ 0x%p (%d pageptrs)\n"
,
138
__func__, buf, params->
numpagetables
);
139
dprintk
(
DBGLVL_BUF
,
" pci_cpu @ 0x%p dma @ 0x%08lx len = 0x%x\n"
,
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"
,
142
buf->
pt_cpu
, (
long
)buf->
pt_dma
, buf->
pt_size
);
143
144
/* Format the Page Table Entries to point into the data buffer */
145
for
(i = 0 ; i < params->
numpagetables
; i++) {
146
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
));
150
151
}
152
153
goto
ret
;
154
155
fail2:
156
pci_free_consistent
(port->
dev
->pci, buf->
pci_size
, buf->
cpu
, buf->
dma
);
157
fail1:
158
kfree
(buf);
159
160
buf =
NULL
;
161
ret
:
162
return
buf
;
163
}
164
165
int
saa7164_buffer_dealloc
(
struct
saa7164_buffer
*
buf
)
166
{
167
struct
saa7164_dev
*
dev
;
168
169
if
(!buf || !buf->
port
)
170
return
SAA_ERR_BAD_PARAMETER
;
171
dev = buf->
port
->dev;
172
173
dprintk
(
DBGLVL_BUF
,
"%s() deallocating buffer @ 0x%p\n"
,
174
__func__, buf);
175
176
if
(buf->
flags
!=
SAA7164_BUFFER_FREE
)
177
log_warn
(
" freeing a non-free buffer\n"
);
178
179
pci_free_consistent
(dev->
pci
, buf->
pci_size
, buf->
cpu
, buf->
dma
);
180
pci_free_consistent
(dev->
pci
, buf->
pt_size
, buf->
pt_cpu
, buf->
pt_dma
);
181
182
kfree
(buf);
183
184
return
SAA_OK
;
185
}
186
187
int
saa7164_buffer_zero_offsets
(
struct
saa7164_port
*
port
,
int
i
)
188
{
189
struct
saa7164_dev
*
dev
= port->
dev
;
190
191
if
((i < 0) || (i >= port->
hwcfg
.buffercount))
192
return
-
EINVAL
;
193
194
dprintk
(
DBGLVL_BUF
,
"%s(idx = %d)\n"
, __func__, i);
195
196
saa7164_writel
(port->
bufoffset
+ (
sizeof
(
u32
) * i), 0);
197
198
return
0;
199
}
200
201
/* Write a buffer into the hardware */
202
int
saa7164_buffer_activate
(
struct
saa7164_buffer
*
buf
,
int
i
)
203
{
204
struct
saa7164_port
*
port
= buf->
port
;
205
struct
saa7164_dev
*
dev
= port->
dev
;
206
207
if
((i < 0) || (i >= port->
hwcfg
.buffercount))
208
return
-
EINVAL
;
209
210
dprintk
(
DBGLVL_BUF
,
"%s(idx = %d)\n"
, __func__, i);
211
212
buf->
idx
=
i
;
/* Note of which buffer list index position we occupy */
213
buf->
flags
=
SAA7164_BUFFER_BUSY
;
214
buf->
pos
= 0;
215
216
/* TODO: Review this in light of 32v64 assignments */
217
saa7164_writel
(port->
bufoffset
+ (
sizeof
(
u32
) * i), 0);
218
saa7164_writel
(port->
bufptr32h
+ ((
sizeof
(
u32
) * 2) * i), buf->
pt_dma
);
219
saa7164_writel
(port->
bufptr32l
+ ((
sizeof
(
u32
) * 2) * i), 0);
220
221
dprintk
(
DBGLVL_BUF
,
" buf[%d] offset 0x%llx (0x%x) "
222
"buf 0x%llx/%llx (0x%x/%x) nr=%d\n"
,
223
buf->
idx
,
224
(
u64
)port->
bufoffset
+ (i *
sizeof
(
u32
)),
225
saa7164_readl
(port->
bufoffset
+ (
sizeof
(
u32
) * i)),
226
(
u64
)port->
bufptr32h
+ ((
sizeof
(
u32
) * 2) * i),
227
(
u64
)port->
bufptr32l
+ ((
sizeof
(
u32
) * 2) * i),
228
saa7164_readl
(port->
bufptr32h
+ ((
sizeof
(
u32
) * i) * 2)),
229
saa7164_readl
(port->
bufptr32l
+ ((
sizeof
(
u32
) * i) * 2)),
230
buf->
idx
);
231
232
return
0;
233
}
234
235
int
saa7164_buffer_cfg_port
(
struct
saa7164_port
*
port
)
236
{
237
struct
tmHWStreamParameters
*
params
= &port->
hw_streamingparams
;
238
struct
saa7164_dev
*
dev
= port->
dev
;
239
struct
saa7164_buffer
*
buf
;
240
struct
list_head
*
c
, *
n
;
241
int
i
= 0;
242
243
dprintk
(
DBGLVL_BUF
,
"%s(port=%d)\n"
, __func__, port->
nr
);
244
245
saa7164_writel
(port->
bufcounter
, 0);
246
saa7164_writel
(port->
pitch
, params->
pitch
);
247
saa7164_writel
(port->
bufsize
, params->
pitch
* params->
numberoflines
);
248
249
dprintk
(
DBGLVL_BUF
,
" configured:\n"
);
250
dprintk
(
DBGLVL_BUF
,
" lmmio 0x%p\n"
, dev->
lmmio
);
251
dprintk
(
DBGLVL_BUF
,
" bufcounter 0x%x = 0x%x\n"
, port->
bufcounter
,
252
saa7164_readl
(port->
bufcounter
));
253
254
dprintk
(
DBGLVL_BUF
,
" pitch 0x%x = %d\n"
, port->
pitch
,
255
saa7164_readl
(port->
pitch
));
256
257
dprintk
(
DBGLVL_BUF
,
" bufsize 0x%x = %d\n"
, port->
bufsize
,
258
saa7164_readl
(port->
bufsize
));
259
260
dprintk
(
DBGLVL_BUF
,
" buffercount = %d\n"
, port->
hwcfg
.buffercount);
261
dprintk
(
DBGLVL_BUF
,
" bufoffset = 0x%x\n"
, port->
bufoffset
);
262
dprintk
(
DBGLVL_BUF
,
" bufptr32h = 0x%x\n"
, port->
bufptr32h
);
263
dprintk
(
DBGLVL_BUF
,
" bufptr32l = 0x%x\n"
, port->
bufptr32l
);
264
265
/* Poke the buffers and offsets into PCI space */
266
mutex_lock
(&port->
dmaqueue_lock
);
267
list_for_each_safe
(c, n, &port->
dmaqueue
.list) {
268
buf =
list_entry
(c,
struct
saa7164_buffer
,
list
);
269
270
if
(buf->
flags
!=
SAA7164_BUFFER_FREE
)
271
BUG
();
272
273
/* Place the buffer in the h/w queue */
274
saa7164_buffer_activate
(buf, i);
275
276
/* Don't exceed the device maximum # bufs */
277
if
(i++ > port->
hwcfg
.buffercount)
278
BUG
();
279
280
}
281
mutex_unlock
(&port->
dmaqueue_lock
);
282
283
return
0;
284
}
285
286
struct
saa7164_user_buffer
*
saa7164_buffer_alloc_user
(
struct
saa7164_dev
*
dev
,
287
u32
len)
288
{
289
struct
saa7164_user_buffer
*
buf
;
290
291
buf = kzalloc(
sizeof
(
struct
saa7164_user_buffer
),
GFP_KERNEL
);
292
if
(!buf)
293
return
NULL
;
294
295
buf->
data
= kzalloc(len,
GFP_KERNEL
);
296
297
if
(!buf->
data
) {
298
kfree
(buf);
299
return
NULL
;
300
}
301
302
buf->
actual_size
= len;
303
buf->
pos
= 0;
304
buf->
crc
= 0;
305
306
dprintk
(
DBGLVL_BUF
,
"%s() allocated user buffer @ 0x%p\n"
,
307
__func__, buf);
308
309
return
buf
;
310
}
311
312
void
saa7164_buffer_dealloc_user
(
struct
saa7164_user_buffer
*
buf
)
313
{
314
if
(!buf)
315
return
;
316
317
kfree
(buf->
data
);
318
buf->
data
=
NULL
;
319
320
kfree
(buf);
321
}
322
Generated on Thu Jan 10 2013 13:48:47 for Linux Kernel by
1.8.2