aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7164
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2010-10-30 16:16:56 -0400
committerJiri Kosina <jkosina@suse.cz>2010-10-30 16:16:56 -0400
commitf1e095f1d206b81b44160f41278ce5c78641e9b7 (patch)
treebd293d46d2d3e4cdf435a22ddb2877c6ba1b8acc /drivers/media/video/saa7164
parentb0438a1b71955c425c304a2a483765ef24841766 (diff)
parent1792f17b7210280a3d7ff29da9614ba779cfcedb (diff)
Merge branch 'master' into for-next
Diffstat (limited to 'drivers/media/video/saa7164')
-rw-r--r--drivers/media/video/saa7164/Makefile2
-rw-r--r--drivers/media/video/saa7164/saa7164-api.c973
-rw-r--r--drivers/media/video/saa7164/saa7164-buffer.c194
-rw-r--r--drivers/media/video/saa7164/saa7164-bus.c131
-rw-r--r--drivers/media/video/saa7164/saa7164-cards.c33
-rw-r--r--drivers/media/video/saa7164/saa7164-cmd.c35
-rw-r--r--drivers/media/video/saa7164/saa7164-core.c890
-rw-r--r--drivers/media/video/saa7164/saa7164-dvb.c109
-rw-r--r--drivers/media/video/saa7164/saa7164-encoder.c1503
-rw-r--r--drivers/media/video/saa7164/saa7164-fw.c11
-rw-r--r--drivers/media/video/saa7164/saa7164-i2c.c2
-rw-r--r--drivers/media/video/saa7164/saa7164-reg.h59
-rw-r--r--drivers/media/video/saa7164/saa7164-types.h255
-rw-r--r--drivers/media/video/saa7164/saa7164-vbi.c1375
-rw-r--r--drivers/media/video/saa7164/saa7164.h295
15 files changed, 5522 insertions, 345 deletions
diff --git a/drivers/media/video/saa7164/Makefile b/drivers/media/video/saa7164/Makefile
index 4b329fd42add..6303a8e60eac 100644
--- a/drivers/media/video/saa7164/Makefile
+++ b/drivers/media/video/saa7164/Makefile
@@ -1,6 +1,6 @@
1saa7164-objs := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \ 1saa7164-objs := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \
2 saa7164-fw.o saa7164-bus.o saa7164-cmd.o saa7164-api.o \ 2 saa7164-fw.o saa7164-bus.o saa7164-cmd.o saa7164-api.o \
3 saa7164-buffer.o 3 saa7164-buffer.o saa7164-encoder.o saa7164-vbi.o
4 4
5obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o 5obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o
6 6
diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c
index 3f1262b00cc0..ad3bc4154176 100644
--- a/drivers/media/video/saa7164/saa7164-api.c
+++ b/drivers/media/video/saa7164/saa7164-api.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -24,14 +24,750 @@
24 24
25#include "saa7164.h" 25#include "saa7164.h"
26 26
27int saa7164_api_transition_port(struct saa7164_tsport *port, u8 mode) 27int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i)
28{ 28{
29 int ret; 29 int ret;
30 30
31 if (!(saa_debug & DBGLVL_CPU))
32 return 0;
33
34 dprintk(DBGLVL_API, "%s()\n", __func__);
35
36 i->deviceinst = 0;
37 i->devicespec = 0;
38 i->mode = 0;
39 i->status = 0;
40
41 ret = saa7164_cmd_send(dev, 0, GET_CUR,
42 GET_FW_STATUS_CONTROL, sizeof(struct tmFwInfoStruct), i);
43 if (ret != SAA_OK) {
44 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
45 }
46
47 printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad);
48
49 return ret;
50}
51
52int saa7164_api_collect_debug(struct saa7164_dev *dev)
53{
54 struct tmComResDebugGetData d;
55 u8 more = 255;
56 int ret;
57
58 dprintk(DBGLVL_API, "%s()\n", __func__);
59
60 while (more--) {
61
62 memset(&d, 0, sizeof(d));
63
64 ret = saa7164_cmd_send(dev, 0, GET_CUR,
65 GET_DEBUG_DATA_CONTROL, sizeof(d), &d);
66 if (ret != SAA_OK) {
67 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
68 }
69
70 if (d.dwResult != SAA_OK)
71 break;
72
73 printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr, d.ucDebugData);
74 }
75
76 return 0;
77}
78
79int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level)
80{
81 struct tmComResDebugSetLevel lvl;
82 int ret;
83
84 dprintk(DBGLVL_API, "%s(level=%d)\n", __func__, level);
85
86 /* Retrieve current state */
87 ret = saa7164_cmd_send(dev, 0, GET_CUR,
88 SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
89 if (ret != SAA_OK) {
90 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
91 }
92 dprintk(DBGLVL_API, "%s() Was %d\n", __func__, lvl.dwDebugLevel);
93
94 lvl.dwDebugLevel = level;
95
96 /* set new state */
97 ret = saa7164_cmd_send(dev, 0, SET_CUR,
98 SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
99 if (ret != SAA_OK) {
100 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
101 }
102
103 return ret;
104}
105
106int saa7164_api_set_vbi_format(struct saa7164_port *port)
107{
108 struct saa7164_dev *dev = port->dev;
109 struct tmComResProbeCommit fmt, rsp;
110 int ret;
111
112 dprintk(DBGLVL_API, "%s(nr=%d, unitid=0x%x)\n", __func__,
113 port->nr, port->hwcfg.unitid);
114
115 fmt.bmHint = 0;
116 fmt.bFormatIndex = 1;
117 fmt.bFrameIndex = 1;
118
119 /* Probe, see if it can support this format */
120 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
121 SET_CUR, SAA_PROBE_CONTROL, sizeof(fmt), &fmt);
122 if (ret != SAA_OK)
123 printk(KERN_ERR "%s() set error, ret = 0x%x\n", __func__, ret);
124
125 /* See of the format change was successful */
126 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
127 GET_CUR, SAA_PROBE_CONTROL, sizeof(rsp), &rsp);
128 if (ret != SAA_OK) {
129 printk(KERN_ERR "%s() get error, ret = 0x%x\n", __func__, ret);
130 } else {
131 /* Compare requested vs received, should be same */
132 if (memcmp(&fmt, &rsp, sizeof(rsp)) == 0) {
133 dprintk(DBGLVL_API, "SET/PROBE Verified\n");
134
135 /* Ask the device to select the negotiated format */
136 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
137 SET_CUR, SAA_COMMIT_CONTROL, sizeof(fmt), &fmt);
138 if (ret != SAA_OK)
139 printk(KERN_ERR "%s() commit error, ret = 0x%x\n",
140 __func__, ret);
141
142 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
143 GET_CUR, SAA_COMMIT_CONTROL, sizeof(rsp), &rsp);
144 if (ret != SAA_OK)
145 printk(KERN_ERR "%s() GET commit error, ret = 0x%x\n",
146 __func__, ret);
147
148 if (memcmp(&fmt, &rsp, sizeof(rsp)) != 0) {
149 printk(KERN_ERR "%s() memcmp error, ret = 0x%x\n",
150 __func__, ret);
151 } else
152 dprintk(DBGLVL_API, "SET/COMMIT Verified\n");
153
154 dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint);
155 dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n", rsp.bFormatIndex);
156 dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n", rsp.bFrameIndex);
157 } else
158 printk(KERN_ERR "%s() compare failed\n", __func__);
159 }
160
161 if (ret == SAA_OK)
162 dprintk(DBGLVL_API, "%s(nr=%d) Success\n", __func__, port->nr);
163
164 return ret;
165}
166
167int saa7164_api_set_gop_size(struct saa7164_port *port)
168{
169 struct saa7164_dev *dev = port->dev;
170 struct tmComResEncVideoGopStructure gs;
171 int ret;
172
173 dprintk(DBGLVL_ENC, "%s()\n", __func__);
174
175 gs.ucRefFrameDist = port->encoder_params.refdist;
176 gs.ucGOPSize = port->encoder_params.gop_size;
177 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
178 EU_VIDEO_GOP_STRUCTURE_CONTROL,
179 sizeof(gs), &gs);
180 if (ret != SAA_OK)
181 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
182
183 return ret;
184}
185
186int saa7164_api_set_encoder(struct saa7164_port *port)
187{
188 struct saa7164_dev *dev = port->dev;
189 struct tmComResEncVideoBitRate vb;
190 struct tmComResEncAudioBitRate ab;
191 int ret;
192
193 dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,
194 port->hwcfg.sourceid);
195
196 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
197 port->encoder_profile = EU_PROFILE_PS_DVD;
198 else
199 port->encoder_profile = EU_PROFILE_TS_HQ;
200
201 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
202 EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
203 if (ret != SAA_OK)
204 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
205
206 /* Resolution */
207 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
208 EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
209 if (ret != SAA_OK)
210 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
211
212 /* Establish video bitrates */
213 if (port->encoder_params.bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
214 vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT;
215 else
216 vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK;
217 vb.dwVideoBitRate = port->encoder_params.bitrate;
218 vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak;
219 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
220 EU_VIDEO_BIT_RATE_CONTROL, sizeof(struct tmComResEncVideoBitRate), &vb);
221 if (ret != SAA_OK)
222 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
223
224 /* Establish audio bitrates */
225 ab.ucAudioBitRateMode = 0;
226 ab.dwAudioBitRate = 384000;
227 ab.dwAudioBitRatePeak = ab.dwAudioBitRate;
228 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
229 EU_AUDIO_BIT_RATE_CONTROL, sizeof(struct tmComResEncAudioBitRate), &ab);
230 if (ret != SAA_OK)
231 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
232
233 saa7164_api_set_aspect_ratio(port);
234 saa7164_api_set_gop_size(port);
235
236 return ret;
237}
238
239int saa7164_api_get_encoder(struct saa7164_port *port)
240{
241 struct saa7164_dev *dev = port->dev;
242 struct tmComResEncVideoBitRate v;
243 struct tmComResEncAudioBitRate a;
244 struct tmComResEncVideoInputAspectRatio ar;
245 int ret;
246
247 dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, port->hwcfg.sourceid);
248
249 port->encoder_profile = 0;
250 port->video_format = 0;
251 port->video_resolution = 0;
252 port->audio_format = 0;
253
254 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
255 EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
256 if (ret != SAA_OK)
257 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
258
259 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
260 EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), &port->video_resolution);
261 if (ret != SAA_OK)
262 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
263
264 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
265 EU_VIDEO_FORMAT_CONTROL, sizeof(u8), &port->video_format);
266 if (ret != SAA_OK)
267 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
268
269 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
270 EU_VIDEO_BIT_RATE_CONTROL, sizeof(v), &v);
271 if (ret != SAA_OK)
272 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
273
274 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
275 EU_AUDIO_FORMAT_CONTROL, sizeof(u8), &port->audio_format);
276 if (ret != SAA_OK)
277 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
278
279 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
280 EU_AUDIO_BIT_RATE_CONTROL, sizeof(a), &a);
281 if (ret != SAA_OK)
282 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
283
284 /* Aspect Ratio */
285 ar.width = 0;
286 ar.height = 0;
287 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
288 EU_VIDEO_INPUT_ASPECT_CONTROL,
289 sizeof(struct tmComResEncVideoInputAspectRatio), &ar);
290 if (ret != SAA_OK)
291 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
292
293 dprintk(DBGLVL_ENC, "encoder_profile = %d\n", port->encoder_profile);
294 dprintk(DBGLVL_ENC, "video_format = %d\n", port->video_format);
295 dprintk(DBGLVL_ENC, "audio_format = %d\n", port->audio_format);
296 dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution);
297 dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", v.ucVideoBitRateMode);
298 dprintk(DBGLVL_ENC, "v.dwVideoBitRate = %d\n", v.dwVideoBitRate);
299 dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", v.dwVideoBitRatePeak);
300 dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", a.ucAudioBitRateMode);
301 dprintk(DBGLVL_ENC, "a.dwVideoBitRate = %d\n", a.dwAudioBitRate);
302 dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", a.dwAudioBitRatePeak);
303 dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", ar.width, ar.height);
304
305 return ret;
306}
307
308int saa7164_api_set_aspect_ratio(struct saa7164_port *port)
309{
310 struct saa7164_dev *dev = port->dev;
311 struct tmComResEncVideoInputAspectRatio ar;
312 int ret;
313
314 dprintk(DBGLVL_ENC, "%s(%d)\n", __func__,
315 port->encoder_params.ctl_aspect);
316
317 switch (port->encoder_params.ctl_aspect) {
318 case V4L2_MPEG_VIDEO_ASPECT_1x1:
319 ar.width = 1;
320 ar.height = 1;
321 break;
322 case V4L2_MPEG_VIDEO_ASPECT_4x3:
323 ar.width = 4;
324 ar.height = 3;
325 break;
326 case V4L2_MPEG_VIDEO_ASPECT_16x9:
327 ar.width = 16;
328 ar.height = 9;
329 break;
330 case V4L2_MPEG_VIDEO_ASPECT_221x100:
331 ar.width = 221;
332 ar.height = 100;
333 break;
334 default:
335 BUG();
336 }
337
338 dprintk(DBGLVL_ENC, "%s(%d) now %d:%d\n", __func__,
339 port->encoder_params.ctl_aspect,
340 ar.width, ar.height);
341
342 /* Aspect Ratio */
343 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
344 EU_VIDEO_INPUT_ASPECT_CONTROL,
345 sizeof(struct tmComResEncVideoInputAspectRatio), &ar);
346 if (ret != SAA_OK)
347 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
348
349 return ret;
350}
351
352int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl)
353{
354 struct saa7164_dev *dev = port->dev;
355 int ret;
356 u16 val;
357
358 if (ctl == PU_BRIGHTNESS_CONTROL)
359 val = port->ctl_brightness;
360 else
361 if (ctl == PU_CONTRAST_CONTROL)
362 val = port->ctl_contrast;
363 else
364 if (ctl == PU_HUE_CONTROL)
365 val = port->ctl_hue;
366 else
367 if (ctl == PU_SATURATION_CONTROL)
368 val = port->ctl_saturation;
369 else
370 if (ctl == PU_SHARPNESS_CONTROL)
371 val = port->ctl_sharpness;
372 else
373 return -EINVAL;
374
375 dprintk(DBGLVL_ENC, "%s() unitid=0x%x ctl=%d, val=%d\n",
376 __func__, port->encunit.vsourceid, ctl, val);
377
378 ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, SET_CUR,
379 ctl, sizeof(u16), &val);
380 if (ret != SAA_OK)
381 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
382
383 return ret;
384}
385
386int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl)
387{
388 struct saa7164_dev *dev = port->dev;
389 int ret;
390 u16 val;
391
392 ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, GET_CUR,
393 ctl, sizeof(u16), &val);
394 if (ret != SAA_OK) {
395 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
396 return ret;
397 }
398
399 dprintk(DBGLVL_ENC, "%s() ctl=%d, val=%d\n",
400 __func__, ctl, val);
401
402 if (ctl == PU_BRIGHTNESS_CONTROL)
403 port->ctl_brightness = val;
404 else
405 if (ctl == PU_CONTRAST_CONTROL)
406 port->ctl_contrast = val;
407 else
408 if (ctl == PU_HUE_CONTROL)
409 port->ctl_hue = val;
410 else
411 if (ctl == PU_SATURATION_CONTROL)
412 port->ctl_saturation = val;
413 else
414 if (ctl == PU_SHARPNESS_CONTROL)
415 port->ctl_sharpness = val;
416
417 return ret;
418}
419
420int saa7164_api_set_videomux(struct saa7164_port *port)
421{
422 struct saa7164_dev *dev = port->dev;
423 u8 inputs[] = { 1, 2, 2, 2, 5, 5, 5 };
424 int ret;
425
426 dprintk(DBGLVL_ENC, "%s() v_mux=%d a_mux=%d\n",
427 __func__, port->mux_input, inputs[port->mux_input - 1]);
428
429 /* Audio Mute */
430 ret = saa7164_api_audio_mute(port, 1);
431 if (ret != SAA_OK)
432 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
433
434 /* Video Mux */
435 ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, SET_CUR,
436 SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
437 if (ret != SAA_OK)
438 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
439
440 /* Audio Mux */
441 ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR,
442 SU_INPUT_SELECT_CONTROL, sizeof(u8), &inputs[port->mux_input - 1]);
443 if (ret != SAA_OK)
444 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
445
446 /* Audio UnMute */
447 ret = saa7164_api_audio_mute(port, 0);
448 if (ret != SAA_OK)
449 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
450
451 return ret;
452}
453
454int saa7164_api_audio_mute(struct saa7164_port *port, int mute)
455{
456 struct saa7164_dev *dev = port->dev;
457 u8 v = mute;
458 int ret;
459
460 dprintk(DBGLVL_API, "%s(%d)\n", __func__, mute);
461
462 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
463 MUTE_CONTROL, sizeof(u8), &v);
464 if (ret != SAA_OK)
465 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
466
467 return ret;
468}
469
470/* 0 = silence, 0xff = full */
471int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level)
472{
473 struct saa7164_dev *dev = port->dev;
474 s16 v, min, max;
475 int ret;
476
477 dprintk(DBGLVL_API, "%s(%d)\n", __func__, level);
478
479 /* Obtain the min/max ranges */
480 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MIN,
481 VOLUME_CONTROL, sizeof(u16), &min);
482 if (ret != SAA_OK)
483 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
484
485 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MAX,
486 VOLUME_CONTROL, sizeof(u16), &max);
487 if (ret != SAA_OK)
488 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
489
490 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
491 (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
492 if (ret != SAA_OK)
493 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
494
495 dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v);
496
497 v = level;
498 if (v < min)
499 v = min;
500 if (v > max)
501 v = max;
502
503 /* Left */
504 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
505 (0x01 << 8) | VOLUME_CONTROL, sizeof(s16), &v);
506 if (ret != SAA_OK)
507 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
508
509 /* Right */
510 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
511 (0x02 << 8) | VOLUME_CONTROL, sizeof(s16), &v);
512 if (ret != SAA_OK)
513 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
514
515 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
516 (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
517 if (ret != SAA_OK)
518 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
519
520 dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v);
521
522 return ret;
523}
524
525int saa7164_api_set_audio_std(struct saa7164_port *port)
526{
527 struct saa7164_dev *dev = port->dev;
528 struct tmComResAudioDefaults lvl;
529 struct tmComResTunerStandard tvaudio;
530 int ret;
531
532 dprintk(DBGLVL_API, "%s()\n", __func__);
533
534 /* Establish default levels */
535 lvl.ucDecoderLevel = TMHW_LEV_ADJ_DECLEV_DEFAULT;
536 lvl.ucDecoderFM_Level = TMHW_LEV_ADJ_DECLEV_DEFAULT;
537 lvl.ucMonoLevel = TMHW_LEV_ADJ_MONOLEV_DEFAULT;
538 lvl.ucNICAM_Level = TMHW_LEV_ADJ_NICLEV_DEFAULT;
539 lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT;
540 lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT;
541 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
542 AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults), &lvl);
543 if (ret != SAA_OK)
544 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
545
546 /* Manually select the appropriate TV audio standard */
547 if (port->encodernorm.id & V4L2_STD_NTSC) {
548 tvaudio.std = TU_STANDARD_NTSC_M;
549 tvaudio.country = 1;
550 } else {
551 tvaudio.std = TU_STANDARD_PAL_I;
552 tvaudio.country = 44;
553 }
554
555 ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
556 TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio);
557 if (ret != SAA_OK)
558 printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", __func__, ret);
559 return ret;
560}
561
562int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect)
563{
564 struct saa7164_dev *dev = port->dev;
565 struct tmComResTunerStandardAuto p;
566 int ret;
567
568 dprintk(DBGLVL_API, "%s(%d)\n", __func__, autodetect);
569
570 /* Disable TV Audio autodetect if not already set (buggy) */
571 if (autodetect)
572 p.mode = TU_STANDARD_AUTO;
573 else
574 p.mode = TU_STANDARD_MANUAL;
575 ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
576 TU_STANDARD_AUTO_CONTROL, sizeof(p), &p);
577 if (ret != SAA_OK)
578 printk(KERN_ERR "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", __func__, ret);
579
580 return ret;
581}
582
583int saa7164_api_get_videomux(struct saa7164_port *port)
584{
585 struct saa7164_dev *dev = port->dev;
586 int ret;
587
588 ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, GET_CUR,
589 SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
590 if (ret != SAA_OK)
591 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
592
593 dprintk(DBGLVL_ENC, "%s() v_mux=%d\n",
594 __func__, port->mux_input);
595
596 return ret;
597}
598
599int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
600{
601 struct saa7164_dev *dev = port->dev;
602
603 u16 len = 0;
604 u8 buf[256];
605 int ret;
606 u8 mas;
607
608 dprintk(DBGLVL_API, "%s(nr=%d type=%d val=%x)\n", __func__,
609 port->nr, port->type, val);
610
611 if (port->nr == 0)
612 mas = 0xd0;
613 else
614 mas = 0xe0;
615
616 memset(buf, 0, sizeof(buf));
617
618 buf[0x00] = 0x04;
619 buf[0x01] = 0x00;
620 buf[0x02] = 0x00;
621 buf[0x03] = 0x00;
622
623 buf[0x04] = 0x04;
624 buf[0x05] = 0x00;
625 buf[0x06] = 0x00;
626 buf[0x07] = 0x00;
627
628 buf[0x08] = reg;
629 buf[0x09] = 0x26;
630 buf[0x0a] = mas;
631 buf[0x0b] = 0xb0;
632
633 buf[0x0c] = val;
634 buf[0x0d] = 0x00;
635 buf[0x0e] = 0x00;
636 buf[0x0f] = 0x00;
637
638 ret = saa7164_cmd_send(dev, port->ifunit.unitid, GET_LEN,
639 EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
640 if (ret != SAA_OK) {
641 printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
642 return -EIO;
643 }
644
645 ret = saa7164_cmd_send(dev, port->ifunit.unitid, SET_CUR,
646 EXU_REGISTER_ACCESS_CONTROL, len, &buf);
647 if (ret != SAA_OK)
648 printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
649
650 //saa7164_dumphex16(dev, buf, 16);
651
652 return ret == SAA_OK ? 0 : -EIO;
653}
654
655/* Disable the IF block AGC controls */
656int saa7164_api_configure_dif(struct saa7164_port *port, u32 std)
657{
658 struct saa7164_dev *dev = port->dev;
659 int ret = 0;
660 u8 agc_disable;
661
662 dprintk(DBGLVL_API, "%s(nr=%d, 0x%x)\n", __func__, port->nr, std);
663
664 if (std & V4L2_STD_NTSC) {
665 dprintk(DBGLVL_API, " NTSC\n");
666 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
667 agc_disable = 0;
668 } else if (std & V4L2_STD_PAL_I) {
669 dprintk(DBGLVL_API, " PAL-I\n");
670 saa7164_api_set_dif(port, 0x00, 0x08); /* Video Standard */
671 agc_disable = 0;
672 } else if (std & V4L2_STD_PAL_M) {
673 dprintk(DBGLVL_API, " PAL-M\n");
674 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
675 agc_disable = 0;
676 } else if (std & V4L2_STD_PAL_N) {
677 dprintk(DBGLVL_API, " PAL-N\n");
678 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
679 agc_disable = 0;
680 } else if (std & V4L2_STD_PAL_Nc) {
681 dprintk(DBGLVL_API, " PAL-Nc\n");
682 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
683 agc_disable = 0;
684 } else if (std & V4L2_STD_PAL_B) {
685 dprintk(DBGLVL_API, " PAL-B\n");
686 saa7164_api_set_dif(port, 0x00, 0x02); /* Video Standard */
687 agc_disable = 0;
688 } else if (std & V4L2_STD_PAL_DK) {
689 dprintk(DBGLVL_API, " PAL-DK\n");
690 saa7164_api_set_dif(port, 0x00, 0x10); /* Video Standard */
691 agc_disable = 0;
692 } else if (std & V4L2_STD_SECAM_L) {
693 dprintk(DBGLVL_API, " SECAM-L\n");
694 saa7164_api_set_dif(port, 0x00, 0x20); /* Video Standard */
695 agc_disable = 0;
696 } else {
697 /* Unknown standard, assume DTV */
698 dprintk(DBGLVL_API, " Unknown (assuming DTV)\n");
699 saa7164_api_set_dif(port, 0x00, 0x80); /* Undefined Video Standard */
700 agc_disable = 1;
701 }
702
703 saa7164_api_set_dif(port, 0x48, 0xa0); /* AGC Functions 1 */
704 saa7164_api_set_dif(port, 0xc0, agc_disable); /* AGC Output Disable */
705 saa7164_api_set_dif(port, 0x7c, 0x04); /* CVBS EQ */
706 saa7164_api_set_dif(port, 0x04, 0x01); /* Active */
707 msleep(100);
708 saa7164_api_set_dif(port, 0x04, 0x00); /* Active (again) */
709 msleep(100);
710
711 return ret;
712}
713
714/* Ensure the dif is in the correct state for the operating mode
715 * (analog / dtv). We only configure the diff through the analog encoder
716 * so when we're in digital mode we need to find the appropriate encoder
717 * and use it to configure the DIF.
718 */
719int saa7164_api_initialize_dif(struct saa7164_port *port)
720{
721 struct saa7164_dev *dev = port->dev;
722 struct saa7164_port *p = 0;
723 int ret = -EINVAL;
724 u32 std = 0;
725
726 dprintk(DBGLVL_API, "%s(nr=%d type=%d)\n", __func__,
727 port->nr, port->type);
728
729 if (port->type == SAA7164_MPEG_ENCODER) {
730 /* Pick any analog standard to init the diff.
731 * we'll come back during encoder_init'
732 * and set the correct standard if requried.
733 */
734 std = V4L2_STD_NTSC;
735 } else
736 if (port->type == SAA7164_MPEG_DVB) {
737 if (port->nr == SAA7164_PORT_TS1)
738 p = &dev->ports[SAA7164_PORT_ENC1];
739 else
740 p = &dev->ports[SAA7164_PORT_ENC2];
741 } else
742 if (port->type == SAA7164_MPEG_VBI) {
743 std = V4L2_STD_NTSC;
744 if (port->nr == SAA7164_PORT_VBI1)
745 p = &dev->ports[SAA7164_PORT_ENC1];
746 else
747 p = &dev->ports[SAA7164_PORT_ENC2];
748 } else
749 BUG();
750
751 if (p)
752 ret = saa7164_api_configure_dif(p, std);
753
754 return ret;
755}
756
757int saa7164_api_transition_port(struct saa7164_port *port, u8 mode)
758{
759 struct saa7164_dev *dev = port->dev;
760
761 int ret;
762
763 dprintk(DBGLVL_API, "%s(nr=%d unitid=0x%x,%d)\n",
764 __func__, port->nr, port->hwcfg.unitid, mode);
765
31 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR, 766 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR,
32 SAA_STATE_CONTROL, sizeof(mode), &mode); 767 SAA_STATE_CONTROL, sizeof(mode), &mode);
33 if (ret != SAA_OK) 768 if (ret != SAA_OK)
34 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); 769 printk(KERN_ERR "%s(portnr %d unitid 0x%x) error, ret = 0x%x\n",
770 __func__, port->nr, port->hwcfg.unitid, ret);
35 771
36 return ret; 772 return ret;
37} 773}
@@ -61,10 +797,45 @@ int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)
61 &reg[0], 128, buf); 797 &reg[0], 128, buf);
62} 798}
63 799
800int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
801 struct saa7164_port *port)
802{
803 struct tmComResVBIFormatDescrHeader *fmt = &port->vbi_fmt_ntsc;
804
805 dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", fmt->bFormatIndex);
806 dprintk(DBGLVL_API, " VideoStandard = 0x%x\n", fmt->VideoStandard);
807 dprintk(DBGLVL_API, " StartLine = %d\n", fmt->StartLine);
808 dprintk(DBGLVL_API, " EndLine = %d\n", fmt->EndLine);
809 dprintk(DBGLVL_API, " FieldRate = %d\n", fmt->FieldRate);
810 dprintk(DBGLVL_API, " bNumLines = %d\n", fmt->bNumLines);
811
812 /* Cache the hardware configuration in the port */
813
814 port->bufcounter = port->hwcfg.BARLocation;
815 port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
816 port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
817 port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
818 port->bufptr32l = port->hwcfg.BARLocation +
819 (4 * sizeof(u32)) +
820 (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
821 port->bufptr32h = port->hwcfg.BARLocation +
822 (4 * sizeof(u32)) +
823 (sizeof(u32) * port->hwcfg.buffercount);
824 port->bufptr64 = port->hwcfg.BARLocation +
825 (4 * sizeof(u32)) +
826 (sizeof(u32) * port->hwcfg.buffercount);
827 dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n",
828 port->hwcfg.BARLocation);
829
830 dprintk(DBGLVL_API, " = VS_FORMAT_VBI (becomes dev->en[%d])\n",
831 port->nr);
832
833 return 0;
834}
64 835
65int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev, 836int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
66 struct saa7164_tsport *port, 837 struct saa7164_port *port,
67 tmComResTSFormatDescrHeader_t *tsfmt) 838 struct tmComResTSFormatDescrHeader *tsfmt)
68{ 839{
69 dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", tsfmt->bFormatIndex); 840 dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);
70 dprintk(DBGLVL_API, " bDataOffset = 0x%x\n", tsfmt->bDataOffset); 841 dprintk(DBGLVL_API, " bDataOffset = 0x%x\n", tsfmt->bDataOffset);
@@ -96,27 +867,68 @@ int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
96 return 0; 867 return 0;
97} 868}
98 869
870int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
871 struct saa7164_port *port,
872 struct tmComResPSFormatDescrHeader *fmt)
873{
874 dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", fmt->bFormatIndex);
875 dprintk(DBGLVL_API, " wPacketLength= 0x%x\n", fmt->wPacketLength);
876 dprintk(DBGLVL_API, " wPackLength= 0x%x\n", fmt->wPackLength);
877 dprintk(DBGLVL_API, " bPackDataType= 0x%x\n", fmt->bPackDataType);
878
879 /* Cache the hardware configuration in the port */
880 /* TODO: CHECK THIS in the port config */
881 port->bufcounter = port->hwcfg.BARLocation;
882 port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
883 port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
884 port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
885 port->bufptr32l = port->hwcfg.BARLocation +
886 (4 * sizeof(u32)) +
887 (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
888 port->bufptr32h = port->hwcfg.BARLocation +
889 (4 * sizeof(u32)) +
890 (sizeof(u32) * port->hwcfg.buffercount);
891 port->bufptr64 = port->hwcfg.BARLocation +
892 (4 * sizeof(u32)) +
893 (sizeof(u32) * port->hwcfg.buffercount);
894 dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n",
895 port->hwcfg.BARLocation);
896
897 dprintk(DBGLVL_API, " = VS_FORMAT_MPEGPS (becomes dev->enc[%d])\n",
898 port->nr);
899
900 return 0;
901}
902
99int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) 903int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
100{ 904{
101 struct saa7164_tsport *port = 0; 905 struct saa7164_port *tsport = 0;
906 struct saa7164_port *encport = 0;
907 struct saa7164_port *vbiport = 0;
102 u32 idx, next_offset; 908 u32 idx, next_offset;
103 int i; 909 int i;
104 tmComResDescrHeader_t *hdr, *t; 910 struct tmComResDescrHeader *hdr, *t;
105 tmComResExtDevDescrHeader_t *exthdr; 911 struct tmComResExtDevDescrHeader *exthdr;
106 tmComResPathDescrHeader_t *pathhdr; 912 struct tmComResPathDescrHeader *pathhdr;
107 tmComResAntTermDescrHeader_t *anttermhdr; 913 struct tmComResAntTermDescrHeader *anttermhdr;
108 tmComResTunerDescrHeader_t *tunerunithdr; 914 struct tmComResTunerDescrHeader *tunerunithdr;
109 tmComResDMATermDescrHeader_t *vcoutputtermhdr; 915 struct tmComResDMATermDescrHeader *vcoutputtermhdr;
110 tmComResTSFormatDescrHeader_t *tsfmt; 916 struct tmComResTSFormatDescrHeader *tsfmt;
917 struct tmComResPSFormatDescrHeader *psfmt;
918 struct tmComResSelDescrHeader *psel;
919 struct tmComResProcDescrHeader *pdh;
920 struct tmComResAFeatureDescrHeader *afd;
921 struct tmComResEncoderDescrHeader *edh;
922 struct tmComResVBIFormatDescrHeader *vbifmt;
111 u32 currpath = 0; 923 u32 currpath = 0;
112 924
113 dprintk(DBGLVL_API, 925 dprintk(DBGLVL_API,
114 "%s(?,?,%d) sizeof(tmComResDescrHeader_t) = %d bytes\n", 926 "%s(?,?,%d) sizeof(struct tmComResDescrHeader) = %d bytes\n",
115 __func__, len, (u32)sizeof(tmComResDescrHeader_t)); 927 __func__, len, (u32)sizeof(struct tmComResDescrHeader));
116 928
117 for (idx = 0; idx < (len - sizeof(tmComResDescrHeader_t)); ) { 929 for (idx = 0; idx < (len - sizeof(struct tmComResDescrHeader));) {
118 930
119 hdr = (tmComResDescrHeader_t *)(buf + idx); 931 hdr = (struct tmComResDescrHeader *)(buf + idx);
120 932
121 if (hdr->type != CS_INTERFACE) 933 if (hdr->type != CS_INTERFACE)
122 return SAA_ERR_NOT_SUPPORTED; 934 return SAA_ERR_NOT_SUPPORTED;
@@ -128,7 +940,7 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
128 break; 940 break;
129 case VC_TUNER_PATH: 941 case VC_TUNER_PATH:
130 dprintk(DBGLVL_API, " VC_TUNER_PATH\n"); 942 dprintk(DBGLVL_API, " VC_TUNER_PATH\n");
131 pathhdr = (tmComResPathDescrHeader_t *)(buf + idx); 943 pathhdr = (struct tmComResPathDescrHeader *)(buf + idx);
132 dprintk(DBGLVL_API, " pathid = 0x%x\n", 944 dprintk(DBGLVL_API, " pathid = 0x%x\n",
133 pathhdr->pathid); 945 pathhdr->pathid);
134 currpath = pathhdr->pathid; 946 currpath = pathhdr->pathid;
@@ -136,7 +948,7 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
136 case VC_INPUT_TERMINAL: 948 case VC_INPUT_TERMINAL:
137 dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n"); 949 dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n");
138 anttermhdr = 950 anttermhdr =
139 (tmComResAntTermDescrHeader_t *)(buf + idx); 951 (struct tmComResAntTermDescrHeader *)(buf + idx);
140 dprintk(DBGLVL_API, " terminalid = 0x%x\n", 952 dprintk(DBGLVL_API, " terminalid = 0x%x\n",
141 anttermhdr->terminalid); 953 anttermhdr->terminalid);
142 dprintk(DBGLVL_API, " terminaltype = 0x%x\n", 954 dprintk(DBGLVL_API, " terminaltype = 0x%x\n",
@@ -179,7 +991,7 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
179 case VC_OUTPUT_TERMINAL: 991 case VC_OUTPUT_TERMINAL:
180 dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n"); 992 dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n");
181 vcoutputtermhdr = 993 vcoutputtermhdr =
182 (tmComResDMATermDescrHeader_t *)(buf + idx); 994 (struct tmComResDMATermDescrHeader *)(buf + idx);
183 dprintk(DBGLVL_API, " unitid = 0x%x\n", 995 dprintk(DBGLVL_API, " unitid = 0x%x\n",
184 vcoutputtermhdr->unitid); 996 vcoutputtermhdr->unitid);
185 dprintk(DBGLVL_API, " terminaltype = 0x%x\n", 997 dprintk(DBGLVL_API, " terminaltype = 0x%x\n",
@@ -233,32 +1045,49 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
233 dprintk(DBGLVL_API, " numformats = 0x%x\n", 1045 dprintk(DBGLVL_API, " numformats = 0x%x\n",
234 vcoutputtermhdr->numformats); 1046 vcoutputtermhdr->numformats);
235 1047
236 t = (tmComResDescrHeader_t *) 1048 t = (struct tmComResDescrHeader *)
237 ((tmComResDMATermDescrHeader_t *)(buf + idx)); 1049 ((struct tmComResDMATermDescrHeader *)(buf + idx));
238 next_offset = idx + (vcoutputtermhdr->len); 1050 next_offset = idx + (vcoutputtermhdr->len);
239 for (i = 0; i < vcoutputtermhdr->numformats; i++) { 1051 for (i = 0; i < vcoutputtermhdr->numformats; i++) {
240 t = (tmComResDescrHeader_t *) 1052 t = (struct tmComResDescrHeader *)
241 (buf + next_offset); 1053 (buf + next_offset);
242 switch (t->subtype) { 1054 switch (t->subtype) {
243 case VS_FORMAT_MPEG2TS: 1055 case VS_FORMAT_MPEG2TS:
244 tsfmt = 1056 tsfmt =
245 (tmComResTSFormatDescrHeader_t *)t; 1057 (struct tmComResTSFormatDescrHeader *)t;
246 if (currpath == 1) 1058 if (currpath == 1)
247 port = &dev->ts1; 1059 tsport = &dev->ports[SAA7164_PORT_TS1];
248 else 1060 else
249 port = &dev->ts2; 1061 tsport = &dev->ports[SAA7164_PORT_TS2];
250 memcpy(&port->hwcfg, vcoutputtermhdr, 1062 memcpy(&tsport->hwcfg, vcoutputtermhdr,
251 sizeof(*vcoutputtermhdr)); 1063 sizeof(*vcoutputtermhdr));
252 saa7164_api_configure_port_mpeg2ts(dev, 1064 saa7164_api_configure_port_mpeg2ts(dev,
253 port, tsfmt); 1065 tsport, tsfmt);
254 break; 1066 break;
255 case VS_FORMAT_MPEG2PS: 1067 case VS_FORMAT_MPEG2PS:
256 dprintk(DBGLVL_API, 1068 psfmt =
257 " = VS_FORMAT_MPEG2PS\n"); 1069 (struct tmComResPSFormatDescrHeader *)t;
1070 if (currpath == 1)
1071 encport = &dev->ports[SAA7164_PORT_ENC1];
1072 else
1073 encport = &dev->ports[SAA7164_PORT_ENC2];
1074 memcpy(&encport->hwcfg, vcoutputtermhdr,
1075 sizeof(*vcoutputtermhdr));
1076 saa7164_api_configure_port_mpeg2ps(dev,
1077 encport, psfmt);
258 break; 1078 break;
259 case VS_FORMAT_VBI: 1079 case VS_FORMAT_VBI:
260 dprintk(DBGLVL_API, 1080 vbifmt =
261 " = VS_FORMAT_VBI\n"); 1081 (struct tmComResVBIFormatDescrHeader *)t;
1082 if (currpath == 1)
1083 vbiport = &dev->ports[SAA7164_PORT_VBI1];
1084 else
1085 vbiport = &dev->ports[SAA7164_PORT_VBI2];
1086 memcpy(&vbiport->hwcfg, vcoutputtermhdr,
1087 sizeof(*vcoutputtermhdr));
1088 memcpy(&vbiport->vbi_fmt_ntsc, vbifmt, sizeof(*vbifmt));
1089 saa7164_api_configure_port_vbi(dev,
1090 vbiport);
262 break; 1091 break;
263 case VS_FORMAT_RDS: 1092 case VS_FORMAT_RDS:
264 dprintk(DBGLVL_API, 1093 dprintk(DBGLVL_API,
@@ -284,7 +1113,7 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
284 case TUNER_UNIT: 1113 case TUNER_UNIT:
285 dprintk(DBGLVL_API, " TUNER_UNIT\n"); 1114 dprintk(DBGLVL_API, " TUNER_UNIT\n");
286 tunerunithdr = 1115 tunerunithdr =
287 (tmComResTunerDescrHeader_t *)(buf + idx); 1116 (struct tmComResTunerDescrHeader *)(buf + idx);
288 dprintk(DBGLVL_API, " unitid = 0x%x\n", 1117 dprintk(DBGLVL_API, " unitid = 0x%x\n",
289 tunerunithdr->unitid); 1118 tunerunithdr->unitid);
290 dprintk(DBGLVL_API, " sourceid = 0x%x\n", 1119 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
@@ -297,22 +1126,84 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
297 tunerunithdr->controlsize); 1126 tunerunithdr->controlsize);
298 dprintk(DBGLVL_API, " controls = 0x%x\n", 1127 dprintk(DBGLVL_API, " controls = 0x%x\n",
299 tunerunithdr->controls); 1128 tunerunithdr->controls);
1129
1130 if (tunerunithdr->unitid == tunerunithdr->iunit) {
1131 if (currpath == 1)
1132 encport = &dev->ports[SAA7164_PORT_ENC1];
1133 else
1134 encport = &dev->ports[SAA7164_PORT_ENC2];
1135 memcpy(&encport->tunerunit, tunerunithdr,
1136 sizeof(struct tmComResTunerDescrHeader));
1137 dprintk(DBGLVL_API, " (becomes dev->enc[%d] tuner)\n", encport->nr);
1138 }
300 break; 1139 break;
301 case VC_SELECTOR_UNIT: 1140 case VC_SELECTOR_UNIT:
1141 psel = (struct tmComResSelDescrHeader *)(buf + idx);
302 dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n"); 1142 dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n");
1143 dprintk(DBGLVL_API, " unitid = 0x%x\n",
1144 psel->unitid);
1145 dprintk(DBGLVL_API, " nrinpins = 0x%x\n",
1146 psel->nrinpins);
1147 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
1148 psel->sourceid);
303 break; 1149 break;
304 case VC_PROCESSING_UNIT: 1150 case VC_PROCESSING_UNIT:
1151 pdh = (struct tmComResProcDescrHeader *)(buf + idx);
305 dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n"); 1152 dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n");
1153 dprintk(DBGLVL_API, " unitid = 0x%x\n",
1154 pdh->unitid);
1155 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
1156 pdh->sourceid);
1157 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
1158 pdh->controlsize);
1159 if (pdh->controlsize == 0x04) {
1160 if (currpath == 1)
1161 encport = &dev->ports[SAA7164_PORT_ENC1];
1162 else
1163 encport = &dev->ports[SAA7164_PORT_ENC2];
1164 memcpy(&encport->vidproc, pdh,
1165 sizeof(struct tmComResProcDescrHeader));
1166 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
1167 }
306 break; 1168 break;
307 case FEATURE_UNIT: 1169 case FEATURE_UNIT:
1170 afd = (struct tmComResAFeatureDescrHeader *)(buf + idx);
308 dprintk(DBGLVL_API, " FEATURE_UNIT\n"); 1171 dprintk(DBGLVL_API, " FEATURE_UNIT\n");
1172 dprintk(DBGLVL_API, " unitid = 0x%x\n",
1173 afd->unitid);
1174 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
1175 afd->sourceid);
1176 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
1177 afd->controlsize);
1178 if (currpath == 1)
1179 encport = &dev->ports[SAA7164_PORT_ENC1];
1180 else
1181 encport = &dev->ports[SAA7164_PORT_ENC2];
1182 memcpy(&encport->audfeat, afd,
1183 sizeof(struct tmComResAFeatureDescrHeader));
1184 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
309 break; 1185 break;
310 case ENCODER_UNIT: 1186 case ENCODER_UNIT:
1187 edh = (struct tmComResEncoderDescrHeader *)(buf + idx);
311 dprintk(DBGLVL_API, " ENCODER_UNIT\n"); 1188 dprintk(DBGLVL_API, " ENCODER_UNIT\n");
1189 dprintk(DBGLVL_API, " subtype = 0x%x\n", edh->subtype);
1190 dprintk(DBGLVL_API, " unitid = 0x%x\n", edh->unitid);
1191 dprintk(DBGLVL_API, " vsourceid = 0x%x\n", edh->vsourceid);
1192 dprintk(DBGLVL_API, " asourceid = 0x%x\n", edh->asourceid);
1193 dprintk(DBGLVL_API, " iunit = 0x%x\n", edh->iunit);
1194 if (edh->iunit == edh->unitid) {
1195 if (currpath == 1)
1196 encport = &dev->ports[SAA7164_PORT_ENC1];
1197 else
1198 encport = &dev->ports[SAA7164_PORT_ENC2];
1199 memcpy(&encport->encunit, edh,
1200 sizeof(struct tmComResEncoderDescrHeader));
1201 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
1202 }
312 break; 1203 break;
313 case EXTENSION_UNIT: 1204 case EXTENSION_UNIT:
314 dprintk(DBGLVL_API, " EXTENSION_UNIT\n"); 1205 dprintk(DBGLVL_API, " EXTENSION_UNIT\n");
315 exthdr = (tmComResExtDevDescrHeader_t *)(buf + idx); 1206 exthdr = (struct tmComResExtDevDescrHeader *)(buf + idx);
316 dprintk(DBGLVL_API, " unitid = 0x%x\n", 1207 dprintk(DBGLVL_API, " unitid = 0x%x\n",
317 exthdr->unitid); 1208 exthdr->unitid);
318 dprintk(DBGLVL_API, " deviceid = 0x%x\n", 1209 dprintk(DBGLVL_API, " deviceid = 0x%x\n",
@@ -364,6 +1255,15 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
364 exthdr->numgpiogroups); 1255 exthdr->numgpiogroups);
365 dprintk(DBGLVL_API, " controlsize = 0x%x\n", 1256 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
366 exthdr->controlsize); 1257 exthdr->controlsize);
1258 if (exthdr->devicetype & 0x80) {
1259 if (currpath == 1)
1260 encport = &dev->ports[SAA7164_PORT_ENC1];
1261 else
1262 encport = &dev->ports[SAA7164_PORT_ENC2];
1263 memcpy(&encport->ifunit, exthdr,
1264 sizeof(struct tmComResExtDevDescrHeader));
1265 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
1266 }
367 break; 1267 break;
368 case PVC_INFRARED_UNIT: 1268 case PVC_INFRARED_UNIT:
369 dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n"); 1269 dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n");
@@ -560,12 +1460,11 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
560 return ret == SAA_OK ? 0 : -EIO; 1460 return ret == SAA_OK ? 0 : -EIO;
561} 1461}
562 1462
563
564int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid, 1463int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
565 u8 pin, u8 state) 1464 u8 pin, u8 state)
566{ 1465{
567 int ret; 1466 int ret;
568 tmComResGPIO_t t; 1467 struct tmComResGPIO t;
569 1468
570 dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n", 1469 dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n",
571 __func__, unitid, pin, state); 1470 __func__, unitid, pin, state);
@@ -597,5 +1496,3 @@ int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid,
597 return saa7164_api_modify_gpio(dev, unitid, pin, 0); 1496 return saa7164_api_modify_gpio(dev, unitid, pin, 0);
598} 1497}
599 1498
600
601
diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c
index ddd25d32723d..7230912acc7d 100644
--- a/drivers/media/video/saa7164/saa7164-buffer.c
+++ b/drivers/media/video/saa7164/saa7164-buffer.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -66,12 +66,33 @@
66 | etc 66 | etc
67 */ 67 */
68 68
69void 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}
69/* Allocate a new buffer structure and associated PCI space in bytes. 89/* Allocate a new buffer structure and associated PCI space in bytes.
70 * len must be a multiple of sizeof(u64) 90 * len must be a multiple of sizeof(u64)
71 */ 91 */
72struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_tsport *port, 92struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
73 u32 len) 93 u32 len)
74{ 94{
95 struct tmHWStreamParameters *params = &port->hw_streamingparams;
75 struct saa7164_buffer *buf = 0; 96 struct saa7164_buffer *buf = 0;
76 struct saa7164_dev *dev = port->dev; 97 struct saa7164_dev *dev = port->dev;
77 int i; 98 int i;
@@ -87,8 +108,12 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_tsport *port,
87 goto ret; 108 goto ret;
88 } 109 }
89 110
111 buf->idx = -1;
90 buf->port = port; 112 buf->port = port;
91 buf->flags = SAA7164_BUFFER_FREE; 113 buf->flags = SAA7164_BUFFER_FREE;
114 buf->pos = 0;
115 buf->actual_size = params->pitch * params->numberoflines;
116 buf->crc = 0;
92 /* TODO: arg len is being ignored */ 117 /* TODO: arg len is being ignored */
93 buf->pci_size = SAA7164_PT_ENTRIES * 0x1000; 118 buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
94 buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000; 119 buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
@@ -105,19 +130,23 @@ struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_tsport *port,
105 goto fail2; 130 goto fail2;
106 131
107 /* init the buffers to a known pattern, easier during debugging */ 132 /* init the buffers to a known pattern, easier during debugging */
108 memset(buf->cpu, 0xff, buf->pci_size); 133 memset_io(buf->cpu, 0xff, buf->pci_size);
109 memset(buf->pt_cpu, 0xff, buf->pt_size); 134 buf->crc = crc32(0, buf->cpu, buf->actual_size);
135 memset_io(buf->pt_cpu, 0xff, buf->pt_size);
110 136
111 dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p\n", __func__, buf); 137 dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p (%d pageptrs)\n",
138 __func__, buf, params->numpagetables);
112 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",
113 buf->cpu, (long)buf->dma, buf->pci_size); 140 buf->cpu, (long)buf->dma, buf->pci_size);
114 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",
115 buf->pt_cpu, (long)buf->pt_dma, buf->pt_size); 142 buf->pt_cpu, (long)buf->pt_dma, buf->pt_size);
116 143
117 /* Format the Page Table Entries to point into the data buffer */ 144 /* Format the Page Table Entries to point into the data buffer */
118 for (i = 0 ; i < SAA7164_PT_ENTRIES; i++) { 145 for (i = 0 ; i < params->numpagetables; i++) {
119 146
120 *(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));
121 150
122 } 151 }
123 152
@@ -133,26 +162,163 @@ ret:
133 return buf; 162 return buf;
134} 163}
135 164
136int saa7164_buffer_dealloc(struct saa7164_tsport *port, 165int saa7164_buffer_dealloc(struct saa7164_buffer *buf)
137 struct saa7164_buffer *buf)
138{ 166{
139 struct saa7164_dev *dev; 167 struct saa7164_dev *dev;
140 168
141 if (!buf || !port) 169 if (!buf || !buf->port)
142 return SAA_ERR_BAD_PARAMETER; 170 return SAA_ERR_BAD_PARAMETER;
143 dev = port->dev; 171 dev = buf->port->dev;
144 172
145 dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n", __func__, buf); 173 dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n",
174 __func__, buf);
146 175
147 if (buf->flags != SAA7164_BUFFER_FREE) 176 if (buf->flags != SAA7164_BUFFER_FREE)
148 log_warn(" freeing a non-free buffer\n"); 177 log_warn(" freeing a non-free buffer\n");
149 178
150 pci_free_consistent(port->dev->pci, buf->pci_size, buf->cpu, buf->dma); 179 pci_free_consistent(dev->pci, buf->pci_size, buf->cpu, buf->dma);
151 pci_free_consistent(port->dev->pci, buf->pt_size, buf->pt_cpu, 180 pci_free_consistent(dev->pci, buf->pt_size, buf->pt_cpu, buf->pt_dma);
152 buf->pt_dma);
153 181
154 kfree(buf); 182 kfree(buf);
155 183
156 return SAA_OK; 184 return SAA_OK;
157} 185}
158 186
187int 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 */
202int 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
235int 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
286struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, u32 len)
287{
288 struct saa7164_user_buffer *buf;
289
290 buf = kzalloc(sizeof(struct saa7164_user_buffer), GFP_KERNEL);
291 if (buf == 0)
292 return 0;
293
294 buf->data = kzalloc(len, GFP_KERNEL);
295
296 if (buf->data == 0) {
297 kfree(buf);
298 return 0;
299 }
300
301 buf->actual_size = len;
302 buf->pos = 0;
303 buf->crc = 0;
304
305 dprintk(DBGLVL_BUF, "%s() allocated user buffer @ 0x%p\n",
306 __func__, buf);
307
308 return buf;
309}
310
311void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf)
312{
313 if (!buf)
314 return;
315
316 if (buf->data) {
317 kfree(buf->data);
318 buf->data = 0;
319 }
320
321 if (buf)
322 kfree(buf);
323}
324
diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c
index 83a04640a25a..30d5283da41e 100644
--- a/drivers/media/video/saa7164/saa7164-bus.c
+++ b/drivers/media/video/saa7164/saa7164-bus.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@
26 */ 26 */
27int saa7164_bus_setup(struct saa7164_dev *dev) 27int saa7164_bus_setup(struct saa7164_dev *dev)
28{ 28{
29 tmComResBusInfo_t *b = &dev->bus; 29 struct tmComResBusInfo *b = &dev->bus;
30 30
31 mutex_init(&b->lock); 31 mutex_init(&b->lock);
32 32
@@ -43,24 +43,18 @@ int saa7164_bus_setup(struct saa7164_dev *dev)
43 43
44 b->m_dwSizeGetRing = SAA_DEVICE_BUFFERBLOCKSIZE; 44 b->m_dwSizeGetRing = SAA_DEVICE_BUFFERBLOCKSIZE;
45 45
46 b->m_pdwSetWritePos = (u32 *)((u8 *)(dev->bmmio + 46 b->m_dwSetWritePos = ((u32)dev->intfdesc.BARLocation) + (2 * sizeof(u64));
47 ((u32)dev->intfdesc.BARLocation) + (2 * sizeof(u64)))); 47 b->m_dwSetReadPos = b->m_dwSetWritePos + (1 * sizeof(u32));
48 48
49 b->m_pdwSetReadPos = (u32 *)((u8 *)b->m_pdwSetWritePos + 49 b->m_dwGetWritePos = b->m_dwSetWritePos + (2 * sizeof(u32));
50 1 * sizeof(u32)); 50 b->m_dwGetReadPos = b->m_dwSetWritePos + (3 * sizeof(u32));
51
52 b->m_pdwGetWritePos = (u32 *)((u8 *)b->m_pdwSetWritePos +
53 2 * sizeof(u32));
54
55 b->m_pdwGetReadPos = (u32 *)((u8 *)b->m_pdwSetWritePos +
56 3 * sizeof(u32));
57 51
58 return 0; 52 return 0;
59} 53}
60 54
61void saa7164_bus_dump(struct saa7164_dev *dev) 55void saa7164_bus_dump(struct saa7164_dev *dev)
62{ 56{
63 tmComResBusInfo_t *b = &dev->bus; 57 struct tmComResBusInfo *b = &dev->bus;
64 58
65 dprintk(DBGLVL_BUS, "Dumping the bus structure:\n"); 59 dprintk(DBGLVL_BUS, "Dumping the bus structure:\n");
66 dprintk(DBGLVL_BUS, " .type = %d\n", b->Type); 60 dprintk(DBGLVL_BUS, " .type = %d\n", b->Type);
@@ -71,20 +65,47 @@ void saa7164_bus_dump(struct saa7164_dev *dev)
71 dprintk(DBGLVL_BUS, " .m_pdwGetRing = 0x%p\n", b->m_pdwGetRing); 65 dprintk(DBGLVL_BUS, " .m_pdwGetRing = 0x%p\n", b->m_pdwGetRing);
72 dprintk(DBGLVL_BUS, " .m_dwSizeGetRing = 0x%x\n", b->m_dwSizeGetRing); 66 dprintk(DBGLVL_BUS, " .m_dwSizeGetRing = 0x%x\n", b->m_dwSizeGetRing);
73 67
74 dprintk(DBGLVL_BUS, " .m_pdwSetWritePos = 0x%p (0x%08x)\n", 68 dprintk(DBGLVL_BUS, " .m_dwSetReadPos = 0x%x (0x%08x)\n",
75 b->m_pdwSetWritePos, *b->m_pdwSetWritePos); 69 b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
70
71 dprintk(DBGLVL_BUS, " .m_dwSetWritePos = 0x%x (0x%08x)\n",
72 b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
73
74 dprintk(DBGLVL_BUS, " .m_dwGetReadPos = 0x%x (0x%08x)\n",
75 b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
76
77 dprintk(DBGLVL_BUS, " .m_dwGetWritePos = 0x%x (0x%08x)\n",
78 b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
79
80}
81
82/* Intensionally throw a BUG() if the state of the message bus looks corrupt */
83void saa7164_bus_verify(struct saa7164_dev *dev)
84{
85 struct tmComResBusInfo *b = &dev->bus;
86 int bug = 0;
76 87
77 dprintk(DBGLVL_BUS, " .m_pdwSetReadPos = 0x%p (0x%08x)\n", 88 if (saa7164_readl(b->m_dwSetReadPos) > b->m_dwSizeSetRing)
78 b->m_pdwSetReadPos, *b->m_pdwSetReadPos); 89 bug++;
79 90
80 dprintk(DBGLVL_BUS, " .m_pdwGetWritePos = 0x%p (0x%08x)\n", 91 if (saa7164_readl(b->m_dwSetWritePos) > b->m_dwSizeSetRing)
81 b->m_pdwGetWritePos, *b->m_pdwGetWritePos); 92 bug++;
82 93
83 dprintk(DBGLVL_BUS, " .m_pdwGetReadPos = 0x%p (0x%08x)\n", 94 if (saa7164_readl(b->m_dwGetReadPos) > b->m_dwSizeGetRing)
84 b->m_pdwGetReadPos, *b->m_pdwGetReadPos); 95 bug++;
96
97 if (saa7164_readl(b->m_dwGetWritePos) > b->m_dwSizeGetRing)
98 bug++;
99
100 if (bug) {
101 saa_debug = 0xffff; /* Ensure we get the bus dump */
102 saa7164_bus_dump(dev);
103 saa_debug = 1024; /* Ensure we get the bus dump */
104 BUG();
105 }
85} 106}
86 107
87void saa7164_bus_dumpmsg(struct saa7164_dev *dev, tmComResInfo_t* m, void *buf) 108void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, void *buf)
88{ 109{
89 dprintk(DBGLVL_BUS, "Dumping msg structure:\n"); 110 dprintk(DBGLVL_BUS, "Dumping msg structure:\n");
90 dprintk(DBGLVL_BUS, " .id = %d\n", m->id); 111 dprintk(DBGLVL_BUS, " .id = %d\n", m->id);
@@ -100,7 +121,7 @@ void saa7164_bus_dumpmsg(struct saa7164_dev *dev, tmComResInfo_t* m, void *buf)
100/* 121/*
101 * Places a command or a response on the bus. The implementation does not 122 * Places a command or a response on the bus. The implementation does not
102 * know if it is a command or a response it just places the data on the 123 * know if it is a command or a response it just places the data on the
103 * bus depending on the bus information given in the tmComResBusInfo_t 124 * bus depending on the bus information given in the struct tmComResBusInfo
104 * structure. If the command or response does not fit into the bus ring 125 * structure. If the command or response does not fit into the bus ring
105 * buffer it will be refused. 126 * buffer it will be refused.
106 * 127 *
@@ -108,10 +129,10 @@ void saa7164_bus_dumpmsg(struct saa7164_dev *dev, tmComResInfo_t* m, void *buf)
108 * SAA_OK The function executed successfully. 129 * SAA_OK The function executed successfully.
109 * < 0 One or more members are not initialized. 130 * < 0 One or more members are not initialized.
110 */ 131 */
111int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf) 132int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf)
112{ 133{
113 tmComResBusInfo_t *bus = &dev->bus; 134 struct tmComResBusInfo *bus = &dev->bus;
114 u32 bytes_to_write, read_distance, timeout, curr_srp, curr_swp; 135 u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
115 u32 new_swp, space_rem; 136 u32 new_swp, space_rem;
116 int ret = SAA_ERR_BAD_PARAMETER; 137 int ret = SAA_ERR_BAD_PARAMETER;
117 138
@@ -122,6 +143,8 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
122 143
123 dprintk(DBGLVL_BUS, "%s()\n", __func__); 144 dprintk(DBGLVL_BUS, "%s()\n", __func__);
124 145
146 saa7164_bus_verify(dev);
147
125 msg->size = cpu_to_le16(msg->size); 148 msg->size = cpu_to_le16(msg->size);
126 msg->command = cpu_to_le16(msg->command); 149 msg->command = cpu_to_le16(msg->command);
127 msg->controlselector = cpu_to_le16(msg->controlselector); 150 msg->controlselector = cpu_to_le16(msg->controlselector);
@@ -141,30 +164,30 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
141 mutex_lock(&bus->lock); 164 mutex_lock(&bus->lock);
142 165
143 bytes_to_write = sizeof(*msg) + msg->size; 166 bytes_to_write = sizeof(*msg) + msg->size;
144 read_distance = 0; 167 free_write_space = 0;
145 timeout = SAA_BUS_TIMEOUT; 168 timeout = SAA_BUS_TIMEOUT;
146 curr_srp = le32_to_cpu(*bus->m_pdwSetReadPos); 169 curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
147 curr_swp = le32_to_cpu(*bus->m_pdwSetWritePos); 170 curr_swp = le32_to_cpu(saa7164_readl(bus->m_dwSetWritePos));
148 171
149 /* Deal with ring wrapping issues */ 172 /* Deal with ring wrapping issues */
150 if (curr_srp > curr_swp) 173 if (curr_srp > curr_swp)
151 /* The ring has not wrapped yet */
152 read_distance = curr_srp - curr_swp;
153 else
154 /* Deal with the wrapped ring */ 174 /* Deal with the wrapped ring */
155 read_distance = (curr_srp + bus->m_dwSizeSetRing) - curr_swp; 175 free_write_space = curr_srp - curr_swp;
176 else
177 /* The ring has not wrapped yet */
178 free_write_space = (curr_srp + bus->m_dwSizeSetRing) - curr_swp;
156 179
157 dprintk(DBGLVL_BUS, "%s() bytes_to_write = %d\n", __func__, 180 dprintk(DBGLVL_BUS, "%s() bytes_to_write = %d\n", __func__,
158 bytes_to_write); 181 bytes_to_write);
159 182
160 dprintk(DBGLVL_BUS, "%s() read_distance = %d\n", __func__, 183 dprintk(DBGLVL_BUS, "%s() free_write_space = %d\n", __func__,
161 read_distance); 184 free_write_space);
162 185
163 dprintk(DBGLVL_BUS, "%s() curr_srp = %x\n", __func__, curr_srp); 186 dprintk(DBGLVL_BUS, "%s() curr_srp = %x\n", __func__, curr_srp);
164 dprintk(DBGLVL_BUS, "%s() curr_swp = %x\n", __func__, curr_swp); 187 dprintk(DBGLVL_BUS, "%s() curr_swp = %x\n", __func__, curr_swp);
165 188
166 /* Process the msg and write the content onto the bus */ 189 /* Process the msg and write the content onto the bus */
167 while (bytes_to_write >= read_distance) { 190 while (bytes_to_write >= free_write_space) {
168 191
169 if (timeout-- == 0) { 192 if (timeout-- == 0) {
170 printk(KERN_ERR "%s() bus timeout\n", __func__); 193 printk(KERN_ERR "%s() bus timeout\n", __func__);
@@ -177,15 +200,15 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
177 mdelay(1); 200 mdelay(1);
178 201
179 /* Check the space usage again */ 202 /* Check the space usage again */
180 curr_srp = le32_to_cpu(*bus->m_pdwSetReadPos); 203 curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
181 204
182 /* Deal with ring wrapping issues */ 205 /* Deal with ring wrapping issues */
183 if (curr_srp > curr_swp) 206 if (curr_srp > curr_swp)
184 /* Read didn't wrap around the buffer */
185 read_distance = curr_srp - curr_swp;
186 else
187 /* Deal with the wrapped ring */ 207 /* Deal with the wrapped ring */
188 read_distance = (curr_srp + bus->m_dwSizeSetRing) - 208 free_write_space = curr_srp - curr_swp;
209 else
210 /* Read didn't wrap around the buffer */
211 free_write_space = (curr_srp + bus->m_dwSizeSetRing) -
189 curr_swp; 212 curr_swp;
190 213
191 } 214 }
@@ -257,37 +280,37 @@ int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf)
257 280
258 dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp); 281 dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
259 282
260 /* TODO: Convert all of the direct PCI writes into
261 * saa7164_writel/b calls for consistency.
262 */
263
264 /* Update the bus write position */ 283 /* Update the bus write position */
265 *bus->m_pdwSetWritePos = cpu_to_le32(new_swp); 284 saa7164_writel(bus->m_dwSetWritePos, cpu_to_le32(new_swp));
266 ret = SAA_OK; 285 ret = SAA_OK;
267 286
268out: 287out:
288 saa7164_bus_dump(dev);
269 mutex_unlock(&bus->lock); 289 mutex_unlock(&bus->lock);
290 saa7164_bus_verify(dev);
270 return ret; 291 return ret;
271} 292}
272 293
273/* 294/*
274 * Receive a command or a response from the bus. The implementation does not 295 * Receive a command or a response from the bus. The implementation does not
275 * know if it is a command or a response it simply dequeues the data, 296 * know if it is a command or a response it simply dequeues the data,
276 * depending on the bus information given in the tmComResBusInfo_t structure. 297 * depending on the bus information given in the struct tmComResBusInfo structure.
277 * 298 *
278 * Return Value: 299 * Return Value:
279 * 0 The function executed successfully. 300 * 0 The function executed successfully.
280 * < 0 One or more members are not initialized. 301 * < 0 One or more members are not initialized.
281 */ 302 */
282int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf, 303int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf,
283 int peekonly) 304 int peekonly)
284{ 305{
285 tmComResBusInfo_t *bus = &dev->bus; 306 struct tmComResBusInfo *bus = &dev->bus;
286 u32 bytes_to_read, write_distance, curr_grp, curr_gwp, 307 u32 bytes_to_read, write_distance, curr_grp, curr_gwp,
287 new_grp, buf_size, space_rem; 308 new_grp, buf_size, space_rem;
288 tmComResInfo_t msg_tmp; 309 struct tmComResInfo msg_tmp;
289 int ret = SAA_ERR_BAD_PARAMETER; 310 int ret = SAA_ERR_BAD_PARAMETER;
290 311
312 saa7164_bus_verify(dev);
313
291 if (msg == 0) 314 if (msg == 0)
292 return ret; 315 return ret;
293 316
@@ -309,11 +332,10 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
309 /* Peek the bus to see if a msg exists, if it's not what we're expecting 332 /* Peek the bus to see if a msg exists, if it's not what we're expecting
310 * then return cleanly else read the message from the bus. 333 * then return cleanly else read the message from the bus.
311 */ 334 */
312 curr_gwp = le32_to_cpu(*bus->m_pdwGetWritePos); 335 curr_gwp = le32_to_cpu(saa7164_readl(bus->m_dwGetWritePos));
313 curr_grp = le32_to_cpu(*bus->m_pdwGetReadPos); 336 curr_grp = le32_to_cpu(saa7164_readl(bus->m_dwGetReadPos));
314 337
315 if (curr_gwp == curr_grp) { 338 if (curr_gwp == curr_grp) {
316 dprintk(DBGLVL_BUS, "%s() No message on the bus\n", __func__);
317 ret = SAA_ERR_EMPTY; 339 ret = SAA_ERR_EMPTY;
318 goto out; 340 goto out;
319 } 341 }
@@ -434,7 +456,7 @@ int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf,
434 } 456 }
435 457
436 /* Update the read positions, adjusting the ring */ 458 /* Update the read positions, adjusting the ring */
437 *bus->m_pdwGetReadPos = cpu_to_le32(new_grp); 459 saa7164_writel(bus->m_dwGetReadPos, cpu_to_le32(new_grp));
438 460
439peekout: 461peekout:
440 msg->size = le16_to_cpu(msg->size); 462 msg->size = le16_to_cpu(msg->size);
@@ -443,6 +465,7 @@ peekout:
443 ret = SAA_OK; 465 ret = SAA_OK;
444out: 466out:
445 mutex_unlock(&bus->lock); 467 mutex_unlock(&bus->lock);
468 saa7164_bus_verify(dev);
446 return ret; 469 return ret;
447} 470}
448 471
diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c
index a3c299405f46..4cb634e952a6 100644
--- a/drivers/media/video/saa7164/saa7164-cards.c
+++ b/drivers/media/video/saa7164/saa7164-cards.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -55,6 +55,10 @@ struct saa7164_board saa7164_boards[] = {
55 .name = "Hauppauge WinTV-HVR2200", 55 .name = "Hauppauge WinTV-HVR2200",
56 .porta = SAA7164_MPEG_DVB, 56 .porta = SAA7164_MPEG_DVB,
57 .portb = SAA7164_MPEG_DVB, 57 .portb = SAA7164_MPEG_DVB,
58 .portc = SAA7164_MPEG_ENCODER,
59 .portd = SAA7164_MPEG_ENCODER,
60 .porte = SAA7164_MPEG_VBI,
61 .portf = SAA7164_MPEG_VBI,
58 .chiprev = SAA7164_CHIP_REV3, 62 .chiprev = SAA7164_CHIP_REV3,
59 .unit = {{ 63 .unit = {{
60 .id = 0x1d, 64 .id = 0x1d,
@@ -97,6 +101,10 @@ struct saa7164_board saa7164_boards[] = {
97 .name = "Hauppauge WinTV-HVR2200", 101 .name = "Hauppauge WinTV-HVR2200",
98 .porta = SAA7164_MPEG_DVB, 102 .porta = SAA7164_MPEG_DVB,
99 .portb = SAA7164_MPEG_DVB, 103 .portb = SAA7164_MPEG_DVB,
104 .portc = SAA7164_MPEG_ENCODER,
105 .portd = SAA7164_MPEG_ENCODER,
106 .porte = SAA7164_MPEG_VBI,
107 .portf = SAA7164_MPEG_VBI,
100 .chiprev = SAA7164_CHIP_REV2, 108 .chiprev = SAA7164_CHIP_REV2,
101 .unit = {{ 109 .unit = {{
102 .id = 0x06, 110 .id = 0x06,
@@ -139,6 +147,10 @@ struct saa7164_board saa7164_boards[] = {
139 .name = "Hauppauge WinTV-HVR2200", 147 .name = "Hauppauge WinTV-HVR2200",
140 .porta = SAA7164_MPEG_DVB, 148 .porta = SAA7164_MPEG_DVB,
141 .portb = SAA7164_MPEG_DVB, 149 .portb = SAA7164_MPEG_DVB,
150 .portc = SAA7164_MPEG_ENCODER,
151 .portd = SAA7164_MPEG_ENCODER,
152 .porte = SAA7164_MPEG_VBI,
153 .portf = SAA7164_MPEG_VBI,
142 .chiprev = SAA7164_CHIP_REV2, 154 .chiprev = SAA7164_CHIP_REV2,
143 .unit = {{ 155 .unit = {{
144 .id = 0x1d, 156 .id = 0x1d,
@@ -195,6 +207,12 @@ struct saa7164_board saa7164_boards[] = {
195 .name = "Hauppauge WinTV-HVR2250", 207 .name = "Hauppauge WinTV-HVR2250",
196 .porta = SAA7164_MPEG_DVB, 208 .porta = SAA7164_MPEG_DVB,
197 .portb = SAA7164_MPEG_DVB, 209 .portb = SAA7164_MPEG_DVB,
210 .portc = SAA7164_MPEG_ENCODER,
211 .portd = SAA7164_MPEG_ENCODER,
212 .portc = SAA7164_MPEG_ENCODER,
213 .portd = SAA7164_MPEG_ENCODER,
214 .porte = SAA7164_MPEG_VBI,
215 .portf = SAA7164_MPEG_VBI,
198 .chiprev = SAA7164_CHIP_REV3, 216 .chiprev = SAA7164_CHIP_REV3,
199 .unit = {{ 217 .unit = {{
200 .id = 0x22, 218 .id = 0x22,
@@ -251,6 +269,12 @@ struct saa7164_board saa7164_boards[] = {
251 .name = "Hauppauge WinTV-HVR2250", 269 .name = "Hauppauge WinTV-HVR2250",
252 .porta = SAA7164_MPEG_DVB, 270 .porta = SAA7164_MPEG_DVB,
253 .portb = SAA7164_MPEG_DVB, 271 .portb = SAA7164_MPEG_DVB,
272 .portc = SAA7164_MPEG_ENCODER,
273 .portd = SAA7164_MPEG_ENCODER,
274 .porte = SAA7164_MPEG_VBI,
275 .portf = SAA7164_MPEG_VBI,
276 .porte = SAA7164_MPEG_VBI,
277 .portf = SAA7164_MPEG_VBI,
254 .chiprev = SAA7164_CHIP_REV3, 278 .chiprev = SAA7164_CHIP_REV3,
255 .unit = {{ 279 .unit = {{
256 .id = 0x28, 280 .id = 0x28,
@@ -307,6 +331,10 @@ struct saa7164_board saa7164_boards[] = {
307 .name = "Hauppauge WinTV-HVR2250", 331 .name = "Hauppauge WinTV-HVR2250",
308 .porta = SAA7164_MPEG_DVB, 332 .porta = SAA7164_MPEG_DVB,
309 .portb = SAA7164_MPEG_DVB, 333 .portb = SAA7164_MPEG_DVB,
334 .portc = SAA7164_MPEG_ENCODER,
335 .portd = SAA7164_MPEG_ENCODER,
336 .porte = SAA7164_MPEG_VBI,
337 .portf = SAA7164_MPEG_VBI,
310 .chiprev = SAA7164_CHIP_REV3, 338 .chiprev = SAA7164_CHIP_REV3,
311 .unit = {{ 339 .unit = {{
312 .id = 0x26, 340 .id = 0x26,
@@ -437,8 +465,6 @@ void saa7164_card_list(struct saa7164_dev *dev)
437 465
438void saa7164_gpio_setup(struct saa7164_dev *dev) 466void saa7164_gpio_setup(struct saa7164_dev *dev)
439{ 467{
440
441
442 switch (dev->board) { 468 switch (dev->board) {
443 case SAA7164_BOARD_HAUPPAUGE_HVR2200: 469 case SAA7164_BOARD_HAUPPAUGE_HVR2200:
444 case SAA7164_BOARD_HAUPPAUGE_HVR2200_2: 470 case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
@@ -462,7 +488,6 @@ void saa7164_gpio_setup(struct saa7164_dev *dev)
462 saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3); 488 saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
463 break; 489 break;
464 } 490 }
465
466} 491}
467 492
468static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data) 493static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
diff --git a/drivers/media/video/saa7164/saa7164-cmd.c b/drivers/media/video/saa7164/saa7164-cmd.c
index 9c1d3ac43869..301a9e302f45 100644
--- a/drivers/media/video/saa7164/saa7164-cmd.c
+++ b/drivers/media/video/saa7164/saa7164-cmd.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -82,16 +82,17 @@ u32 saa7164_cmd_timeout_get(struct saa7164_dev *dev, u8 seqno)
82 * -bus/c running buffer. */ 82 * -bus/c running buffer. */
83int saa7164_irq_dequeue(struct saa7164_dev *dev) 83int saa7164_irq_dequeue(struct saa7164_dev *dev)
84{ 84{
85 int ret = SAA_OK; 85 int ret = SAA_OK, i = 0;
86 u32 timeout; 86 u32 timeout;
87 wait_queue_head_t *q = 0; 87 wait_queue_head_t *q = 0;
88 u8 tmp[512];
88 dprintk(DBGLVL_CMD, "%s()\n", __func__); 89 dprintk(DBGLVL_CMD, "%s()\n", __func__);
89 90
90 /* While any outstand message on the bus exists... */ 91 /* While any outstand message on the bus exists... */
91 do { 92 do {
92 93
93 /* Peek the msg bus */ 94 /* Peek the msg bus */
94 tmComResInfo_t tRsp = { 0, 0, 0, 0, 0, 0 }; 95 struct tmComResInfo tRsp = { 0, 0, 0, 0, 0, 0 };
95 ret = saa7164_bus_get(dev, &tRsp, NULL, 1); 96 ret = saa7164_bus_get(dev, &tRsp, NULL, 1);
96 if (ret != SAA_OK) 97 if (ret != SAA_OK)
97 break; 98 break;
@@ -109,8 +110,22 @@ int saa7164_irq_dequeue(struct saa7164_dev *dev)
109 printk(KERN_ERR 110 printk(KERN_ERR
110 "%s() found timed out command on the bus\n", 111 "%s() found timed out command on the bus\n",
111 __func__); 112 __func__);
113
114 /* Clean the bus */
115 ret = saa7164_bus_get(dev, &tRsp, &tmp, 0);
116 printk(KERN_ERR "%s() ret = %x\n", __func__, ret);
117 if (ret == SAA_ERR_EMPTY)
118 /* Someone else already fetched the response */
119 return SAA_OK;
120
121 if (ret != SAA_OK)
122 return ret;
112 } 123 }
113 } while (0); 124
125 /* It's unlikely to have more than 4 or 5 pending messages, ensure we exit
126 * at some point regardles.
127 */
128 } while (i++ < 32);
114 129
115 return ret; 130 return ret;
116} 131}
@@ -128,7 +143,7 @@ int saa7164_cmd_dequeue(struct saa7164_dev *dev)
128 143
129 while (loop) { 144 while (loop) {
130 145
131 tmComResInfo_t tRsp = { 0, 0, 0, 0, 0, 0 }; 146 struct tmComResInfo tRsp = { 0, 0, 0, 0, 0, 0 };
132 ret = saa7164_bus_get(dev, &tRsp, NULL, 1); 147 ret = saa7164_bus_get(dev, &tRsp, NULL, 1);
133 if (ret == SAA_ERR_EMPTY) 148 if (ret == SAA_ERR_EMPTY)
134 return SAA_OK; 149 return SAA_OK;
@@ -171,9 +186,9 @@ int saa7164_cmd_dequeue(struct saa7164_dev *dev)
171 return SAA_OK; 186 return SAA_OK;
172} 187}
173 188
174int saa7164_cmd_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf) 189int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf)
175{ 190{
176 tmComResBusInfo_t *bus = &dev->bus; 191 struct tmComResBusInfo *bus = &dev->bus;
177 u8 cmd_sent; 192 u8 cmd_sent;
178 u16 size, idx; 193 u16 size, idx;
179 u32 cmds; 194 u32 cmds;
@@ -324,11 +339,11 @@ void saa7164_cmd_signal(struct saa7164_dev *dev, u8 seqno)
324 mutex_unlock(&dev->lock); 339 mutex_unlock(&dev->lock);
325} 340}
326 341
327int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, tmComResCmd_t command, 342int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, enum tmComResCmd command,
328 u16 controlselector, u16 size, void *buf) 343 u16 controlselector, u16 size, void *buf)
329{ 344{
330 tmComResInfo_t command_t, *pcommand_t; 345 struct tmComResInfo command_t, *pcommand_t;
331 tmComResInfo_t response_t, *presponse_t; 346 struct tmComResInfo response_t, *presponse_t;
332 u8 errdata[256]; 347 u8 errdata[256];
333 u16 resp_dsize; 348 u16 resp_dsize;
334 u16 data_recd; 349 u16 data_recd;
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c
index e6aa0fbd1e91..e1bac5051460 100644
--- a/drivers/media/video/saa7164/saa7164-core.c
+++ b/drivers/media/video/saa7164/saa7164-core.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -30,6 +30,9 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <asm/div64.h> 31#include <asm/div64.h>
32 32
33#ifdef CONFIG_PROC_FS
34#include <linux/proc_fs.h>
35#endif
33#include "saa7164.h" 36#include "saa7164.h"
34 37
35MODULE_DESCRIPTION("Driver for NXP SAA7164 based TV cards"); 38MODULE_DESCRIPTION("Driver for NXP SAA7164 based TV cards");
@@ -49,14 +52,38 @@ unsigned int saa_debug;
49module_param_named(debug, saa_debug, int, 0644); 52module_param_named(debug, saa_debug, int, 0644);
50MODULE_PARM_DESC(debug, "enable debug messages"); 53MODULE_PARM_DESC(debug, "enable debug messages");
51 54
55unsigned int fw_debug;
56module_param(fw_debug, int, 0644);
57MODULE_PARM_DESC(fw_debug, "Firware debug level def:2");
58
59unsigned int encoder_buffers = SAA7164_MAX_ENCODER_BUFFERS;
60module_param(encoder_buffers, int, 0644);
61MODULE_PARM_DESC(encoder_buffers, "Total buffers in read queue 16-512 def:64");
62
63unsigned int vbi_buffers = SAA7164_MAX_VBI_BUFFERS;
64module_param(vbi_buffers, int, 0644);
65MODULE_PARM_DESC(vbi_buffers, "Total buffers in read queue 16-512 def:64");
66
52unsigned int waitsecs = 10; 67unsigned int waitsecs = 10;
53module_param(waitsecs, int, 0644); 68module_param(waitsecs, int, 0644);
54MODULE_PARM_DESC(debug, "timeout on firmware messages"); 69MODULE_PARM_DESC(waitsecs, "timeout on firmware messages");
55 70
56static unsigned int card[] = {[0 ... (SAA7164_MAXBOARDS - 1)] = UNSET }; 71static unsigned int card[] = {[0 ... (SAA7164_MAXBOARDS - 1)] = UNSET };
57module_param_array(card, int, NULL, 0444); 72module_param_array(card, int, NULL, 0444);
58MODULE_PARM_DESC(card, "card type"); 73MODULE_PARM_DESC(card, "card type");
59 74
75unsigned int print_histogram = 64;
76module_param(print_histogram, int, 0644);
77MODULE_PARM_DESC(print_histogram, "print histogram values once");
78
79unsigned int crc_checking = 1;
80module_param(crc_checking, int, 0644);
81MODULE_PARM_DESC(crc_checking, "enable crc sanity checking on buffers");
82
83unsigned int guard_checking = 1;
84module_param(guard_checking, int, 0644);
85MODULE_PARM_DESC(guard_checking, "enable dma sanity checking for buffer overruns");
86
60static unsigned int saa7164_devcount; 87static unsigned int saa7164_devcount;
61 88
62static DEFINE_MUTEX(devlist); 89static DEFINE_MUTEX(devlist);
@@ -64,6 +91,444 @@ LIST_HEAD(saa7164_devlist);
64 91
65#define INT_SIZE 16 92#define INT_SIZE 16
66 93
94void saa7164_dumphex16FF(struct saa7164_dev *dev, u8 *buf, int len)
95{
96 int i;
97 u8 tmp[16];
98 memset(&tmp[0], 0xff, sizeof(tmp));
99
100 printk(KERN_INFO "--------------------> "
101 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
102
103 for (i = 0; i < len; i += 16) {
104 if (memcmp(&tmp, buf + i, sizeof(tmp)) != 0) {
105 printk(KERN_INFO " [0x%08x] "
106 "%02x %02x %02x %02x %02x %02x %02x %02x "
107 "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
108 *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3),
109 *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7),
110 *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11),
111 *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15));
112 }
113 }
114}
115
116static void saa7164_pack_verifier(struct saa7164_buffer *buf)
117{
118 u8 *p = (u8 *)buf->cpu;
119 int i;
120
121 for (i = 0; i < buf->actual_size; i += 2048) {
122
123 if ((*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) ||
124 (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) {
125 printk(KERN_ERR "No pack at 0x%x\n", i);
126// saa7164_dumphex16FF(buf->port->dev, (p + i), 32);
127 }
128 }
129}
130
131#define FIXED_VIDEO_PID 0xf1
132#define FIXED_AUDIO_PID 0xf2
133
134static void saa7164_ts_verifier(struct saa7164_buffer *buf)
135{
136 struct saa7164_port *port = buf->port;
137 u32 i;
138 u8 cc, a;
139 u16 pid;
140 u8 __iomem *bufcpu = (u8 *)buf->cpu;
141
142 port->sync_errors = 0;
143 port->v_cc_errors = 0;
144 port->a_cc_errors = 0;
145
146 for (i = 0; i < buf->actual_size; i += 188) {
147 if (*(bufcpu + i) != 0x47)
148 port->sync_errors++;
149
150 /* TODO: Query pid lower 8 bits, ignoring upper bits intensionally */
151 pid = ((*(bufcpu + i + 1) & 0x1f) << 8) | *(bufcpu + i + 2);
152 cc = *(bufcpu + i + 3) & 0x0f;
153
154 if (pid == FIXED_VIDEO_PID) {
155 a = ((port->last_v_cc + 1) & 0x0f);
156 if (a != cc) {
157 printk(KERN_ERR "video cc last = %x current = %x i = %d\n",
158 port->last_v_cc, cc, i);
159 port->v_cc_errors++;
160 }
161
162 port->last_v_cc = cc;
163 } else
164 if (pid == FIXED_AUDIO_PID) {
165 a = ((port->last_a_cc + 1) & 0x0f);
166 if (a != cc) {
167 printk(KERN_ERR "audio cc last = %x current = %x i = %d\n",
168 port->last_a_cc, cc, i);
169 port->a_cc_errors++;
170 }
171
172 port->last_a_cc = cc;
173 }
174
175 }
176
177 /* Only report errors if we've been through this function atleast
178 * once already and the cached cc values are primed. First time through
179 * always generates errors.
180 */
181 if (port->v_cc_errors && (port->done_first_interrupt > 1))
182 printk(KERN_ERR "video pid cc, %d errors\n", port->v_cc_errors);
183
184 if (port->a_cc_errors && (port->done_first_interrupt > 1))
185 printk(KERN_ERR "audio pid cc, %d errors\n", port->a_cc_errors);
186
187 if (port->sync_errors && (port->done_first_interrupt > 1))
188 printk(KERN_ERR "sync_errors = %d\n", port->sync_errors);
189
190 if (port->done_first_interrupt == 1)
191 port->done_first_interrupt++;
192}
193
194static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name)
195{
196 int i;
197
198 memset(hg, 0, sizeof(struct saa7164_histogram));
199 strcpy(hg->name, name);
200
201 /* First 30ms x 1ms */
202 for (i = 0; i < 30; i++) {
203 hg->counter1[0 + i].val = i;
204 }
205
206 /* 30 - 200ms x 10ms */
207 for (i = 0; i < 18; i++) {
208 hg->counter1[30 + i].val = 30 + (i * 10);
209 }
210
211 /* 200 - 2000ms x 100ms */
212 for (i = 0; i < 15; i++) {
213 hg->counter1[48 + i].val = 200 + (i * 200);
214 }
215
216 /* Catch all massive value (2secs) */
217 hg->counter1[55].val = 2000;
218
219 /* Catch all massive value (4secs) */
220 hg->counter1[56].val = 4000;
221
222 /* Catch all massive value (8secs) */
223 hg->counter1[57].val = 8000;
224
225 /* Catch all massive value (15secs) */
226 hg->counter1[58].val = 15000;
227
228 /* Catch all massive value (30secs) */
229 hg->counter1[59].val = 30000;
230
231 /* Catch all massive value (60secs) */
232 hg->counter1[60].val = 60000;
233
234 /* Catch all massive value (5mins) */
235 hg->counter1[61].val = 300000;
236
237 /* Catch all massive value (15mins) */
238 hg->counter1[62].val = 900000;
239
240 /* Catch all massive values (1hr) */
241 hg->counter1[63].val = 3600000;
242}
243
244void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val)
245{
246 int i;
247 for (i = 0; i < 64; i++) {
248 if (val <= hg->counter1[i].val) {
249 hg->counter1[i].count++;
250 hg->counter1[i].update_time = jiffies;
251 break;
252 }
253 }
254}
255
256static void saa7164_histogram_print(struct saa7164_port *port,
257 struct saa7164_histogram *hg)
258{
259 u32 entries = 0;
260 int i;
261
262 printk(KERN_ERR "Histogram named %s (ms, count, last_update_jiffy)\n", hg->name);
263 for (i = 0; i < 64; i++) {
264 if (hg->counter1[i].count == 0)
265 continue;
266
267 printk(KERN_ERR " %4d %12d %Ld\n",
268 hg->counter1[i].val,
269 hg->counter1[i].count,
270 hg->counter1[i].update_time);
271
272 entries++;
273 }
274 printk(KERN_ERR "Total: %d\n", entries);
275}
276
277static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
278{
279 struct saa7164_dev *dev = port->dev;
280 struct saa7164_buffer *buf = 0;
281 struct saa7164_user_buffer *ubuf = 0;
282 struct list_head *c, *n;
283 int i = 0;
284 u8 __iomem *p;
285
286 mutex_lock(&port->dmaqueue_lock);
287 list_for_each_safe(c, n, &port->dmaqueue.list) {
288
289 buf = list_entry(c, struct saa7164_buffer, list);
290 if (i++ > port->hwcfg.buffercount) {
291 printk(KERN_ERR "%s() illegal i count %d\n",
292 __func__, i);
293 break;
294 }
295
296 if (buf->idx == bufnr) {
297
298 /* Found the buffer, deal with it */
299 dprintk(DBGLVL_IRQ, "%s() bufnr: %d\n", __func__, bufnr);
300
301 if (crc_checking) {
302 /* Throw a new checksum on the dma buffer */
303 buf->crc = crc32(0, buf->cpu, buf->actual_size);
304 }
305
306 if (guard_checking) {
307 p = (u8 *)buf->cpu;
308 if ((*(p + buf->actual_size + 0) != 0xff) ||
309 (*(p + buf->actual_size + 1) != 0xff) ||
310 (*(p + buf->actual_size + 2) != 0xff) ||
311 (*(p + buf->actual_size + 3) != 0xff) ||
312 (*(p + buf->actual_size + 0x10) != 0xff) ||
313 (*(p + buf->actual_size + 0x11) != 0xff) ||
314 (*(p + buf->actual_size + 0x12) != 0xff) ||
315 (*(p + buf->actual_size + 0x13) != 0xff)) {
316 printk(KERN_ERR "%s() buf %p guard buffer breach\n",
317 __func__, buf);
318// saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64);
319 }
320 }
321
322 if ((port->nr != SAA7164_PORT_VBI1) && (port->nr != SAA7164_PORT_VBI2)) {
323 /* Validate the incoming buffer content */
324 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
325 saa7164_ts_verifier(buf);
326 else if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
327 saa7164_pack_verifier(buf);
328 }
329
330 /* find a free user buffer and clone to it */
331 if (!list_empty(&port->list_buf_free.list)) {
332
333 /* Pull the first buffer from the used list */
334 ubuf = list_first_entry(&port->list_buf_free.list,
335 struct saa7164_user_buffer, list);
336
337 if (buf->actual_size <= ubuf->actual_size) {
338
339 memcpy_fromio(ubuf->data, buf->cpu,
340 ubuf->actual_size);
341
342 if (crc_checking) {
343 /* Throw a new checksum on the read buffer */
344 ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);
345 }
346
347 /* Requeue the buffer on the free list */
348 ubuf->pos = 0;
349
350 list_move_tail(&ubuf->list,
351 &port->list_buf_used.list);
352
353 /* Flag any userland waiters */
354 wake_up_interruptible(&port->wait_read);
355
356 } else {
357 printk(KERN_ERR "buf %p bufsize fails match\n", buf);
358 }
359
360 } else
361 printk(KERN_ERR "encirq no free buffers, increase param encoder_buffers\n");
362
363 /* Ensure offset into buffer remains 0, fill buffer
364 * with known bad data. We check for this data at a later point
365 * in time. */
366 saa7164_buffer_zero_offsets(port, bufnr);
367 memset_io(buf->cpu, 0xff, buf->pci_size);
368 if (crc_checking) {
369 /* Throw yet aanother new checksum on the dma buffer */
370 buf->crc = crc32(0, buf->cpu, buf->actual_size);
371 }
372
373 break;
374 }
375 }
376 mutex_unlock(&port->dmaqueue_lock);
377}
378
379static void saa7164_work_enchandler(struct work_struct *w)
380{
381 struct saa7164_port *port =
382 container_of(w, struct saa7164_port, workenc);
383 struct saa7164_dev *dev = port->dev;
384
385 u32 wp, mcb, rp, cnt = 0;
386
387 port->last_svc_msecs_diff = port->last_svc_msecs;
388 port->last_svc_msecs = jiffies_to_msecs(jiffies);
389
390 port->last_svc_msecs_diff = port->last_svc_msecs -
391 port->last_svc_msecs_diff;
392
393 saa7164_histogram_update(&port->svc_interval,
394 port->last_svc_msecs_diff);
395
396 port->last_irq_svc_msecs_diff = port->last_svc_msecs -
397 port->last_irq_msecs;
398
399 saa7164_histogram_update(&port->irq_svc_interval,
400 port->last_irq_svc_msecs_diff);
401
402 dprintk(DBGLVL_IRQ,
403 "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
404 __func__,
405 port->last_svc_msecs_diff,
406 port->last_irq_svc_msecs_diff,
407 port->last_svc_wp,
408 port->last_svc_rp
409 );
410
411 /* Current write position */
412 wp = saa7164_readl(port->bufcounter);
413 if (wp > (port->hwcfg.buffercount - 1)) {
414 printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
415 return;
416 }
417
418 /* Most current complete buffer */
419 if (wp == 0)
420 mcb = (port->hwcfg.buffercount - 1);
421 else
422 mcb = wp - 1;
423
424 while (1) {
425 if (port->done_first_interrupt == 0) {
426 port->done_first_interrupt++;
427 rp = mcb;
428 } else
429 rp = (port->last_svc_rp + 1) % 8;
430
431 if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
432 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
433 break;
434 }
435
436 saa7164_work_enchandler_helper(port, rp);
437 port->last_svc_rp = rp;
438 cnt++;
439
440 if (rp == mcb)
441 break;
442 }
443
444 /* TODO: Convert this into a /proc/saa7164 style readable file */
445 if (print_histogram == port->nr) {
446 saa7164_histogram_print(port, &port->irq_interval);
447 saa7164_histogram_print(port, &port->svc_interval);
448 saa7164_histogram_print(port, &port->irq_svc_interval);
449 saa7164_histogram_print(port, &port->read_interval);
450 saa7164_histogram_print(port, &port->poll_interval);
451 /* TODO: fix this to preserve any previous state */
452 print_histogram = 64 + port->nr;
453 }
454}
455
456static void saa7164_work_vbihandler(struct work_struct *w)
457{
458 struct saa7164_port *port =
459 container_of(w, struct saa7164_port, workenc);
460 struct saa7164_dev *dev = port->dev;
461
462 u32 wp, mcb, rp, cnt = 0;
463
464 port->last_svc_msecs_diff = port->last_svc_msecs;
465 port->last_svc_msecs = jiffies_to_msecs(jiffies);
466 port->last_svc_msecs_diff = port->last_svc_msecs -
467 port->last_svc_msecs_diff;
468
469 saa7164_histogram_update(&port->svc_interval,
470 port->last_svc_msecs_diff);
471
472 port->last_irq_svc_msecs_diff = port->last_svc_msecs -
473 port->last_irq_msecs;
474
475 saa7164_histogram_update(&port->irq_svc_interval,
476 port->last_irq_svc_msecs_diff);
477
478 dprintk(DBGLVL_IRQ,
479 "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
480 __func__,
481 port->last_svc_msecs_diff,
482 port->last_irq_svc_msecs_diff,
483 port->last_svc_wp,
484 port->last_svc_rp
485 );
486
487 /* Current write position */
488 wp = saa7164_readl(port->bufcounter);
489 if (wp > (port->hwcfg.buffercount - 1)) {
490 printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
491 return;
492 }
493
494 /* Most current complete buffer */
495 if (wp == 0)
496 mcb = (port->hwcfg.buffercount - 1);
497 else
498 mcb = wp - 1;
499
500 while (1) {
501 if (port->done_first_interrupt == 0) {
502 port->done_first_interrupt++;
503 rp = mcb;
504 } else
505 rp = (port->last_svc_rp + 1) % 8;
506
507 if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
508 printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
509 break;
510 }
511
512 saa7164_work_enchandler_helper(port, rp);
513 port->last_svc_rp = rp;
514 cnt++;
515
516 if (rp == mcb)
517 break;
518 }
519
520 /* TODO: Convert this into a /proc/saa7164 style readable file */
521 if (print_histogram == port->nr) {
522 saa7164_histogram_print(port, &port->irq_interval);
523 saa7164_histogram_print(port, &port->svc_interval);
524 saa7164_histogram_print(port, &port->irq_svc_interval);
525 saa7164_histogram_print(port, &port->read_interval);
526 saa7164_histogram_print(port, &port->poll_interval);
527 /* TODO: fix this to preserve any previous state */
528 print_histogram = 64 + port->nr;
529 }
530}
531
67static void saa7164_work_cmdhandler(struct work_struct *w) 532static void saa7164_work_cmdhandler(struct work_struct *w)
68{ 533{
69 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd); 534 struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
@@ -74,7 +539,7 @@ static void saa7164_work_cmdhandler(struct work_struct *w)
74 539
75static void saa7164_buffer_deliver(struct saa7164_buffer *buf) 540static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
76{ 541{
77 struct saa7164_tsport *port = buf->port; 542 struct saa7164_port *port = buf->port;
78 543
79 /* Feed the transport payload into the kernel demux */ 544 /* Feed the transport payload into the kernel demux */
80 dvb_dmx_swfilter_packets(&port->dvb.demux, (u8 *)buf->cpu, 545 dvb_dmx_swfilter_packets(&port->dvb.demux, (u8 *)buf->cpu,
@@ -82,7 +547,56 @@ static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
82 547
83} 548}
84 549
85static irqreturn_t saa7164_irq_ts(struct saa7164_tsport *port) 550static irqreturn_t saa7164_irq_vbi(struct saa7164_port *port)
551{
552 struct saa7164_dev *dev = port->dev;
553
554 /* Store old time */
555 port->last_irq_msecs_diff = port->last_irq_msecs;
556
557 /* Collect new stats */
558 port->last_irq_msecs = jiffies_to_msecs(jiffies);
559
560 /* Calculate stats */
561 port->last_irq_msecs_diff = port->last_irq_msecs -
562 port->last_irq_msecs_diff;
563
564 saa7164_histogram_update(&port->irq_interval,
565 port->last_irq_msecs_diff);
566
567 dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
568 port->last_irq_msecs_diff);
569
570 /* Tis calls the vbi irq handler */
571 schedule_work(&port->workenc);
572 return 0;
573}
574
575static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
576{
577 struct saa7164_dev *dev = port->dev;
578
579 /* Store old time */
580 port->last_irq_msecs_diff = port->last_irq_msecs;
581
582 /* Collect new stats */
583 port->last_irq_msecs = jiffies_to_msecs(jiffies);
584
585 /* Calculate stats */
586 port->last_irq_msecs_diff = port->last_irq_msecs -
587 port->last_irq_msecs_diff;
588
589 saa7164_histogram_update(&port->irq_interval,
590 port->last_irq_msecs_diff);
591
592 dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
593 port->last_irq_msecs_diff);
594
595 schedule_work(&port->workenc);
596 return 0;
597}
598
599static irqreturn_t saa7164_irq_ts(struct saa7164_port *port)
86{ 600{
87 struct saa7164_dev *dev = port->dev; 601 struct saa7164_dev *dev = port->dev;
88 struct saa7164_buffer *buf; 602 struct saa7164_buffer *buf;
@@ -96,7 +610,7 @@ static irqreturn_t saa7164_irq_ts(struct saa7164_tsport *port)
96 610
97 /* Find the previous buffer to the current write point */ 611 /* Find the previous buffer to the current write point */
98 if (wp == 0) 612 if (wp == 0)
99 rp = 7; 613 rp = (port->hwcfg.buffercount - 1);
100 else 614 else
101 rp = wp - 1; 615 rp = wp - 1;
102 616
@@ -107,7 +621,7 @@ static irqreturn_t saa7164_irq_ts(struct saa7164_tsport *port)
107 if (i++ > port->hwcfg.buffercount) 621 if (i++ > port->hwcfg.buffercount)
108 BUG(); 622 BUG();
109 623
110 if (buf->nr == rp) { 624 if (buf->idx == rp) {
111 /* Found the buffer, deal with it */ 625 /* Found the buffer, deal with it */
112 dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n", 626 dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n",
113 __func__, wp, rp); 627 __func__, wp, rp);
@@ -123,6 +637,13 @@ static irqreturn_t saa7164_irq_ts(struct saa7164_tsport *port)
123static irqreturn_t saa7164_irq(int irq, void *dev_id) 637static irqreturn_t saa7164_irq(int irq, void *dev_id)
124{ 638{
125 struct saa7164_dev *dev = dev_id; 639 struct saa7164_dev *dev = dev_id;
640 struct saa7164_port *porta = &dev->ports[SAA7164_PORT_TS1];
641 struct saa7164_port *portb = &dev->ports[SAA7164_PORT_TS2];
642 struct saa7164_port *portc = &dev->ports[SAA7164_PORT_ENC1];
643 struct saa7164_port *portd = &dev->ports[SAA7164_PORT_ENC2];
644 struct saa7164_port *porte = &dev->ports[SAA7164_PORT_VBI1];
645 struct saa7164_port *portf = &dev->ports[SAA7164_PORT_VBI2];
646
126 u32 intid, intstat[INT_SIZE/4]; 647 u32 intid, intstat[INT_SIZE/4];
127 int i, handled = 0, bit; 648 int i, handled = 0, bit;
128 649
@@ -168,17 +689,35 @@ static irqreturn_t saa7164_irq(int irq, void *dev_id)
168 if (intid == dev->intfdesc.bInterruptId) { 689 if (intid == dev->intfdesc.bInterruptId) {
169 /* A response to an cmd/api call */ 690 /* A response to an cmd/api call */
170 schedule_work(&dev->workcmd); 691 schedule_work(&dev->workcmd);
171 } else if (intid == 692 } else if (intid == porta->hwcfg.interruptid) {
172 dev->ts1.hwcfg.interruptid) {
173 693
174 /* Transport path 1 */ 694 /* Transport path 1 */
175 saa7164_irq_ts(&dev->ts1); 695 saa7164_irq_ts(porta);
176 696
177 } else if (intid == 697 } else if (intid == portb->hwcfg.interruptid) {
178 dev->ts2.hwcfg.interruptid) {
179 698
180 /* Transport path 2 */ 699 /* Transport path 2 */
181 saa7164_irq_ts(&dev->ts2); 700 saa7164_irq_ts(portb);
701
702 } else if (intid == portc->hwcfg.interruptid) {
703
704 /* Encoder path 1 */
705 saa7164_irq_encoder(portc);
706
707 } else if (intid == portd->hwcfg.interruptid) {
708
709 /* Encoder path 2 */
710 saa7164_irq_encoder(portd);
711
712 } else if (intid == porte->hwcfg.interruptid) {
713
714 /* VBI path 1 */
715 saa7164_irq_vbi(porte);
716
717 } else if (intid == portf->hwcfg.interruptid) {
718
719 /* VBI path 2 */
720 saa7164_irq_vbi(portf);
182 721
183 } else { 722 } else {
184 /* Find the function */ 723 /* Find the function */
@@ -286,8 +825,8 @@ void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr)
286 825
287static void saa7164_dump_hwdesc(struct saa7164_dev *dev) 826static void saa7164_dump_hwdesc(struct saa7164_dev *dev)
288{ 827{
289 dprintk(1, "@0x%p hwdesc sizeof(tmComResHWDescr_t) = %d bytes\n", 828 dprintk(1, "@0x%p hwdesc sizeof(struct tmComResHWDescr) = %d bytes\n",
290 &dev->hwdesc, (u32)sizeof(tmComResHWDescr_t)); 829 &dev->hwdesc, (u32)sizeof(struct tmComResHWDescr));
291 830
292 dprintk(1, " .bLength = 0x%x\n", dev->hwdesc.bLength); 831 dprintk(1, " .bLength = 0x%x\n", dev->hwdesc.bLength);
293 dprintk(1, " .bDescriptorType = 0x%x\n", dev->hwdesc.bDescriptorType); 832 dprintk(1, " .bDescriptorType = 0x%x\n", dev->hwdesc.bDescriptorType);
@@ -317,8 +856,8 @@ static void saa7164_dump_hwdesc(struct saa7164_dev *dev)
317static void saa7164_dump_intfdesc(struct saa7164_dev *dev) 856static void saa7164_dump_intfdesc(struct saa7164_dev *dev)
318{ 857{
319 dprintk(1, "@0x%p intfdesc " 858 dprintk(1, "@0x%p intfdesc "
320 "sizeof(tmComResInterfaceDescr_t) = %d bytes\n", 859 "sizeof(struct tmComResInterfaceDescr) = %d bytes\n",
321 &dev->intfdesc, (u32)sizeof(tmComResInterfaceDescr_t)); 860 &dev->intfdesc, (u32)sizeof(struct tmComResInterfaceDescr));
322 861
323 dprintk(1, " .bLength = 0x%x\n", dev->intfdesc.bLength); 862 dprintk(1, " .bLength = 0x%x\n", dev->intfdesc.bLength);
324 dprintk(1, " .bDescriptorType = 0x%x\n", dev->intfdesc.bDescriptorType); 863 dprintk(1, " .bDescriptorType = 0x%x\n", dev->intfdesc.bDescriptorType);
@@ -338,8 +877,8 @@ static void saa7164_dump_intfdesc(struct saa7164_dev *dev)
338 877
339static void saa7164_dump_busdesc(struct saa7164_dev *dev) 878static void saa7164_dump_busdesc(struct saa7164_dev *dev)
340{ 879{
341 dprintk(1, "@0x%p busdesc sizeof(tmComResBusDescr_t) = %d bytes\n", 880 dprintk(1, "@0x%p busdesc sizeof(struct tmComResBusDescr) = %d bytes\n",
342 &dev->busdesc, (u32)sizeof(tmComResBusDescr_t)); 881 &dev->busdesc, (u32)sizeof(struct tmComResBusDescr));
343 882
344 dprintk(1, " .CommandRing = 0x%016Lx\n", dev->busdesc.CommandRing); 883 dprintk(1, " .CommandRing = 0x%016Lx\n", dev->busdesc.CommandRing);
345 dprintk(1, " .ResponseRing = 0x%016Lx\n", dev->busdesc.ResponseRing); 884 dprintk(1, " .ResponseRing = 0x%016Lx\n", dev->busdesc.ResponseRing);
@@ -356,23 +895,23 @@ static void saa7164_dump_busdesc(struct saa7164_dev *dev)
356 */ 895 */
357static void saa7164_get_descriptors(struct saa7164_dev *dev) 896static void saa7164_get_descriptors(struct saa7164_dev *dev)
358{ 897{
359 memcpy(&dev->hwdesc, dev->bmmio, sizeof(tmComResHWDescr_t)); 898 memcpy_fromio(&dev->hwdesc, dev->bmmio, sizeof(struct tmComResHWDescr));
360 memcpy(&dev->intfdesc, dev->bmmio + sizeof(tmComResHWDescr_t), 899 memcpy_fromio(&dev->intfdesc, dev->bmmio + sizeof(struct tmComResHWDescr),
361 sizeof(tmComResInterfaceDescr_t)); 900 sizeof(struct tmComResInterfaceDescr));
362 memcpy(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation, 901 memcpy_fromio(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,
363 sizeof(tmComResBusDescr_t)); 902 sizeof(struct tmComResBusDescr));
364 903
365 if (dev->hwdesc.bLength != sizeof(tmComResHWDescr_t)) { 904 if (dev->hwdesc.bLength != sizeof(struct tmComResHWDescr)) {
366 printk(KERN_ERR "Structure tmComResHWDescr_t is mangled\n"); 905 printk(KERN_ERR "Structure struct tmComResHWDescr is mangled\n");
367 printk(KERN_ERR "Need %x got %d\n", dev->hwdesc.bLength, 906 printk(KERN_ERR "Need %x got %d\n", dev->hwdesc.bLength,
368 (u32)sizeof(tmComResHWDescr_t)); 907 (u32)sizeof(struct tmComResHWDescr));
369 } else 908 } else
370 saa7164_dump_hwdesc(dev); 909 saa7164_dump_hwdesc(dev);
371 910
372 if (dev->intfdesc.bLength != sizeof(tmComResInterfaceDescr_t)) { 911 if (dev->intfdesc.bLength != sizeof(struct tmComResInterfaceDescr)) {
373 printk(KERN_ERR "struct tmComResInterfaceDescr_t is mangled\n"); 912 printk(KERN_ERR "struct struct tmComResInterfaceDescr is mangled\n");
374 printk(KERN_ERR "Need %x got %d\n", dev->intfdesc.bLength, 913 printk(KERN_ERR "Need %x got %d\n", dev->intfdesc.bLength,
375 (u32)sizeof(tmComResInterfaceDescr_t)); 914 (u32)sizeof(struct tmComResInterfaceDescr));
376 } else 915 } else
377 saa7164_dump_intfdesc(dev); 916 saa7164_dump_intfdesc(dev);
378 917
@@ -402,6 +941,58 @@ static int get_resources(struct saa7164_dev *dev)
402 return -EBUSY; 941 return -EBUSY;
403} 942}
404 943
944static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
945{
946 struct saa7164_port *port = 0;
947
948 if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
949 BUG();
950
951 port = &dev->ports[portnr];
952
953 port->dev = dev;
954 port->nr = portnr;
955
956 if ((portnr == SAA7164_PORT_TS1) || (portnr == SAA7164_PORT_TS2))
957 port->type = SAA7164_MPEG_DVB;
958 else
959 if ((portnr == SAA7164_PORT_ENC1) || (portnr == SAA7164_PORT_ENC2)) {
960 port->type = SAA7164_MPEG_ENCODER;
961
962 /* We need a deferred interrupt handler for cmd handling */
963 INIT_WORK(&port->workenc, saa7164_work_enchandler);
964 }
965 else
966 if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) {
967 port->type = SAA7164_MPEG_VBI;
968
969 /* We need a deferred interrupt handler for cmd handling */
970 INIT_WORK(&port->workenc, saa7164_work_vbihandler);
971 } else
972 BUG();
973
974 /* Init all the critical resources */
975 mutex_init(&port->dvb.lock);
976 INIT_LIST_HEAD(&port->dmaqueue.list);
977 mutex_init(&port->dmaqueue_lock);
978
979 INIT_LIST_HEAD(&port->list_buf_used.list);
980 INIT_LIST_HEAD(&port->list_buf_free.list);
981 init_waitqueue_head(&port->wait_read);
982
983
984 saa7164_histogram_reset(&port->irq_interval, "irq intervals");
985 saa7164_histogram_reset(&port->svc_interval, "deferred intervals");
986 saa7164_histogram_reset(&port->irq_svc_interval,
987 "irq to deferred intervals");
988 saa7164_histogram_reset(&port->read_interval,
989 "encoder/vbi read() intervals");
990 saa7164_histogram_reset(&port->poll_interval,
991 "encoder/vbi poll() intervals");
992
993 return 0;
994}
995
405static int saa7164_dev_setup(struct saa7164_dev *dev) 996static int saa7164_dev_setup(struct saa7164_dev *dev)
406{ 997{
407 int i; 998 int i;
@@ -443,23 +1034,13 @@ static int saa7164_dev_setup(struct saa7164_dev *dev)
443 dev->i2c_bus[2].dev = dev; 1034 dev->i2c_bus[2].dev = dev;
444 dev->i2c_bus[2].nr = 2; 1035 dev->i2c_bus[2].nr = 2;
445 1036
446 /* Transport port A Defaults / setup */ 1037 /* Transport + Encoder ports 1, 2, 3, 4 - Defaults / setup */
447 dev->ts1.dev = dev; 1038 saa7164_port_init(dev, SAA7164_PORT_TS1);
448 dev->ts1.nr = 0; 1039 saa7164_port_init(dev, SAA7164_PORT_TS2);
449 mutex_init(&dev->ts1.dvb.lock); 1040 saa7164_port_init(dev, SAA7164_PORT_ENC1);
450 INIT_LIST_HEAD(&dev->ts1.dmaqueue.list); 1041 saa7164_port_init(dev, SAA7164_PORT_ENC2);
451 INIT_LIST_HEAD(&dev->ts1.dummy_dmaqueue.list); 1042 saa7164_port_init(dev, SAA7164_PORT_VBI1);
452 mutex_init(&dev->ts1.dmaqueue_lock); 1043 saa7164_port_init(dev, SAA7164_PORT_VBI2);
453 mutex_init(&dev->ts1.dummy_dmaqueue_lock);
454
455 /* Transport port B Defaults / setup */
456 dev->ts2.dev = dev;
457 dev->ts2.nr = 1;
458 mutex_init(&dev->ts2.dvb.lock);
459 INIT_LIST_HEAD(&dev->ts2.dmaqueue.list);
460 INIT_LIST_HEAD(&dev->ts2.dummy_dmaqueue.list);
461 mutex_init(&dev->ts2.dmaqueue_lock);
462 mutex_init(&dev->ts2.dummy_dmaqueue_lock);
463 1044
464 if (get_resources(dev) < 0) { 1045 if (get_resources(dev) < 0) {
465 printk(KERN_ERR "CORE %s No more PCIe resources for " 1046 printk(KERN_ERR "CORE %s No more PCIe resources for "
@@ -516,6 +1097,132 @@ static void saa7164_dev_unregister(struct saa7164_dev *dev)
516 return; 1097 return;
517} 1098}
518 1099
1100#ifdef CONFIG_PROC_FS
1101static int saa7164_proc_show(struct seq_file *m, void *v)
1102{
1103 struct saa7164_dev *dev;
1104 struct tmComResBusInfo *b;
1105 struct list_head *list;
1106 int i, c;
1107
1108 if (saa7164_devcount == 0)
1109 return 0;
1110
1111 list_for_each(list, &saa7164_devlist) {
1112 dev = list_entry(list, struct saa7164_dev, devlist);
1113 seq_printf(m, "%s = %p\n", dev->name, dev);
1114
1115 /* Lock the bus from any other access */
1116 b = &dev->bus;
1117 mutex_lock(&b->lock);
1118
1119 seq_printf(m, " .m_pdwSetWritePos = 0x%x (0x%08x)\n",
1120 b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
1121
1122 seq_printf(m, " .m_pdwSetReadPos = 0x%x (0x%08x)\n",
1123 b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
1124
1125 seq_printf(m, " .m_pdwGetWritePos = 0x%x (0x%08x)\n",
1126 b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
1127
1128 seq_printf(m, " .m_pdwGetReadPos = 0x%x (0x%08x)\n",
1129 b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
1130 c = 0;
1131 seq_printf(m, "\n Set Ring:\n");
1132 seq_printf(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
1133 for (i = 0; i < b->m_dwSizeSetRing; i++) {
1134 if (c == 0)
1135 seq_printf(m, " %04x:", i);
1136
1137 seq_printf(m, " %02x", *(b->m_pdwSetRing + i));
1138
1139 if (++c == 16) {
1140 seq_printf(m, "\n");
1141 c = 0;
1142 }
1143 }
1144
1145 c = 0;
1146 seq_printf(m, "\n Get Ring:\n");
1147 seq_printf(m, "\n addr 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
1148 for (i = 0; i < b->m_dwSizeGetRing; i++) {
1149 if (c == 0)
1150 seq_printf(m, " %04x:", i);
1151
1152 seq_printf(m, " %02x", *(b->m_pdwGetRing + i));
1153
1154 if (++c == 16) {
1155 seq_printf(m, "\n");
1156 c = 0;
1157 }
1158 }
1159
1160 mutex_unlock(&b->lock);
1161
1162 }
1163
1164 return 0;
1165}
1166
1167static int saa7164_proc_open(struct inode *inode, struct file *filp)
1168{
1169 return single_open(filp, saa7164_proc_show, NULL);
1170}
1171
1172static struct file_operations saa7164_proc_fops = {
1173 .open = saa7164_proc_open,
1174 .read = seq_read,
1175 .llseek = seq_lseek,
1176 .release = single_release,
1177};
1178
1179static int saa7164_proc_create(void)
1180{
1181 struct proc_dir_entry *pe;
1182
1183 pe = proc_create("saa7164", S_IRUGO, NULL, &saa7164_proc_fops);
1184 if (!pe)
1185 return -ENOMEM;
1186
1187 return 0;
1188}
1189#endif
1190
1191static int saa7164_thread_function(void *data)
1192{
1193 struct saa7164_dev *dev = data;
1194 struct tmFwInfoStruct fwinfo;
1195 u64 last_poll_time = 0;
1196
1197 dprintk(DBGLVL_THR, "thread started\n");
1198
1199 set_freezable();
1200
1201 while (1) {
1202 msleep_interruptible(100);
1203 if (kthread_should_stop())
1204 break;
1205 try_to_freeze();
1206
1207 dprintk(DBGLVL_THR, "thread running\n");
1208
1209 /* Dump the firmware debug message to console */
1210 /* Polling this costs us 1-2% of the arm CPU */
1211 /* convert this into a respnde to interrupt 0x7a */
1212 saa7164_api_collect_debug(dev);
1213
1214 /* Monitor CPU load every 1 second */
1215 if ((last_poll_time + 1000 /* ms */) < jiffies_to_msecs(jiffies)) {
1216 saa7164_api_get_load_info(dev, &fwinfo);
1217 last_poll_time = jiffies_to_msecs(jiffies);
1218 }
1219
1220 }
1221
1222 dprintk(DBGLVL_THR, "thread exiting\n");
1223 return 0;
1224}
1225
519static int __devinit saa7164_initdev(struct pci_dev *pci_dev, 1226static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
520 const struct pci_device_id *pci_id) 1227 const struct pci_device_id *pci_id)
521{ 1228{
@@ -622,7 +1329,6 @@ static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
622 saa7164_gpio_setup(dev); 1329 saa7164_gpio_setup(dev);
623 saa7164_card_setup(dev); 1330 saa7164_card_setup(dev);
624 1331
625
626 /* Parse the dynamic device configuration, find various 1332 /* Parse the dynamic device configuration, find various
627 * media endpoints (MPEG, WMV, PS, TS) and cache their 1333 * media endpoints (MPEG, WMV, PS, TS) and cache their
628 * configuration details into the driver, so we can 1334 * configuration details into the driver, so we can
@@ -633,7 +1339,7 @@ static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
633 1339
634 /* Begin to create the video sub-systems and register funcs */ 1340 /* Begin to create the video sub-systems and register funcs */
635 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) { 1341 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) {
636 if (saa7164_dvb_register(&dev->ts1) < 0) { 1342 if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS1]) < 0) {
637 printk(KERN_ERR "%s() Failed to register " 1343 printk(KERN_ERR "%s() Failed to register "
638 "dvb adapters on porta\n", 1344 "dvb adapters on porta\n",
639 __func__); 1345 __func__);
@@ -641,13 +1347,50 @@ static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
641 } 1347 }
642 1348
643 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) { 1349 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) {
644 if (saa7164_dvb_register(&dev->ts2) < 0) { 1350 if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS2]) < 0) {
645 printk(KERN_ERR"%s() Failed to register " 1351 printk(KERN_ERR"%s() Failed to register "
646 "dvb adapters on portb\n", 1352 "dvb adapters on portb\n",
647 __func__); 1353 __func__);
648 } 1354 }
649 } 1355 }
650 1356
1357 if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) {
1358 if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC1]) < 0) {
1359 printk(KERN_ERR"%s() Failed to register "
1360 "mpeg encoder\n", __func__);
1361 }
1362 }
1363
1364 if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) {
1365 if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC2]) < 0) {
1366 printk(KERN_ERR"%s() Failed to register "
1367 "mpeg encoder\n", __func__);
1368 }
1369 }
1370
1371 if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI) {
1372 if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI1]) < 0) {
1373 printk(KERN_ERR"%s() Failed to register "
1374 "vbi device\n", __func__);
1375 }
1376 }
1377
1378 if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI) {
1379 if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI2]) < 0) {
1380 printk(KERN_ERR"%s() Failed to register "
1381 "vbi device\n", __func__);
1382 }
1383 }
1384 saa7164_api_set_debug(dev, fw_debug);
1385
1386 if (fw_debug) {
1387 dev->kthread = kthread_run(saa7164_thread_function, dev,
1388 "saa7164 debug");
1389 if (!dev->kthread)
1390 printk(KERN_ERR "%s() Failed to create "
1391 "debug kernel thread\n", __func__);
1392 }
1393
651 } /* != BOARD_UNKNOWN */ 1394 } /* != BOARD_UNKNOWN */
652 else 1395 else
653 printk(KERN_ERR "%s() Unsupported board detected, " 1396 printk(KERN_ERR "%s() Unsupported board detected, "
@@ -675,13 +1418,49 @@ static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
675{ 1418{
676 struct saa7164_dev *dev = pci_get_drvdata(pci_dev); 1419 struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
677 1420
1421 if (dev->board != SAA7164_BOARD_UNKNOWN) {
1422 if (fw_debug && dev->kthread) {
1423 kthread_stop(dev->kthread);
1424 dev->kthread = NULL;
1425 }
1426 if (dev->firmwareloaded)
1427 saa7164_api_set_debug(dev, 0x00);
1428 }
1429
1430 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
1431 &dev->ports[SAA7164_PORT_ENC1].irq_interval);
1432 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
1433 &dev->ports[SAA7164_PORT_ENC1].svc_interval);
1434 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
1435 &dev->ports[SAA7164_PORT_ENC1].irq_svc_interval);
1436 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
1437 &dev->ports[SAA7164_PORT_ENC1].read_interval);
1438 saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
1439 &dev->ports[SAA7164_PORT_ENC1].poll_interval);
1440 saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI1],
1441 &dev->ports[SAA7164_PORT_VBI1].read_interval);
1442 saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI2],
1443 &dev->ports[SAA7164_PORT_VBI2].poll_interval);
1444
678 saa7164_shutdown(dev); 1445 saa7164_shutdown(dev);
679 1446
680 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) 1447 if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)
681 saa7164_dvb_unregister(&dev->ts1); 1448 saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS1]);
682 1449
683 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) 1450 if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB)
684 saa7164_dvb_unregister(&dev->ts2); 1451 saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS2]);
1452
1453 if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER)
1454 saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC1]);
1455
1456 if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER)
1457 saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC2]);
1458
1459 if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI)
1460 saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI1]);
1461
1462 if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI)
1463 saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI2]);
685 1464
686 saa7164_i2c_unregister(&dev->i2c_bus[0]); 1465 saa7164_i2c_unregister(&dev->i2c_bus[0]);
687 saa7164_i2c_unregister(&dev->i2c_bus[1]); 1466 saa7164_i2c_unregister(&dev->i2c_bus[1]);
@@ -727,11 +1506,18 @@ static struct pci_driver saa7164_pci_driver = {
727static int __init saa7164_init(void) 1506static int __init saa7164_init(void)
728{ 1507{
729 printk(KERN_INFO "saa7164 driver loaded\n"); 1508 printk(KERN_INFO "saa7164 driver loaded\n");
1509
1510#ifdef CONFIG_PROC_FS
1511 saa7164_proc_create();
1512#endif
730 return pci_register_driver(&saa7164_pci_driver); 1513 return pci_register_driver(&saa7164_pci_driver);
731} 1514}
732 1515
733static void __exit saa7164_fini(void) 1516static void __exit saa7164_fini(void)
734{ 1517{
1518#ifdef CONFIG_PROC_FS
1519 remove_proc_entry("saa7164", NULL);
1520#endif
735 pci_unregister_driver(&saa7164_pci_driver); 1521 pci_unregister_driver(&saa7164_pci_driver);
736} 1522}
737 1523
diff --git a/drivers/media/video/saa7164/saa7164-dvb.c b/drivers/media/video/saa7164/saa7164-dvb.c
index cf099c59b38e..b305a01b3bde 100644
--- a/drivers/media/video/saa7164/saa7164-dvb.c
+++ b/drivers/media/video/saa7164/saa7164-dvb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -82,7 +82,7 @@ static struct s5h1411_config hauppauge_s5h1411_config = {
82 .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, 82 .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
83}; 83};
84 84
85static int saa7164_dvb_stop_tsport(struct saa7164_tsport *port) 85static int saa7164_dvb_stop_port(struct saa7164_port *port)
86{ 86{
87 struct saa7164_dev *dev = port->dev; 87 struct saa7164_dev *dev = port->dev;
88 int ret; 88 int ret;
@@ -100,7 +100,7 @@ static int saa7164_dvb_stop_tsport(struct saa7164_tsport *port)
100 return ret; 100 return ret;
101} 101}
102 102
103static int saa7164_dvb_acquire_tsport(struct saa7164_tsport *port) 103static int saa7164_dvb_acquire_port(struct saa7164_port *port)
104{ 104{
105 struct saa7164_dev *dev = port->dev; 105 struct saa7164_dev *dev = port->dev;
106 int ret; 106 int ret;
@@ -118,7 +118,7 @@ static int saa7164_dvb_acquire_tsport(struct saa7164_tsport *port)
118 return ret; 118 return ret;
119} 119}
120 120
121static int saa7164_dvb_pause_tsport(struct saa7164_tsport *port) 121static int saa7164_dvb_pause_port(struct saa7164_port *port)
122{ 122{
123 struct saa7164_dev *dev = port->dev; 123 struct saa7164_dev *dev = port->dev;
124 int ret; 124 int ret;
@@ -140,90 +140,38 @@ static int saa7164_dvb_pause_tsport(struct saa7164_tsport *port)
140 * the part through AVStream / KS Windows stages, forwards or backwards. 140 * the part through AVStream / KS Windows stages, forwards or backwards.
141 * States are: stopped, acquired (h/w), paused, started. 141 * States are: stopped, acquired (h/w), paused, started.
142 */ 142 */
143static int saa7164_dvb_stop_streaming(struct saa7164_tsport *port) 143static int saa7164_dvb_stop_streaming(struct saa7164_port *port)
144{ 144{
145 struct saa7164_dev *dev = port->dev; 145 struct saa7164_dev *dev = port->dev;
146 int ret;
147
148 dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
149
150 ret = saa7164_dvb_pause_tsport(port);
151 ret = saa7164_dvb_acquire_tsport(port);
152 ret = saa7164_dvb_stop_tsport(port);
153
154 return ret;
155}
156
157static int saa7164_dvb_cfg_tsport(struct saa7164_tsport *port)
158{
159 tmHWStreamParameters_t *params = &port->hw_streamingparams;
160 struct saa7164_dev *dev = port->dev;
161 struct saa7164_buffer *buf; 146 struct saa7164_buffer *buf;
162 struct list_head *c, *n; 147 struct list_head *p, *q;
163 int i = 0; 148 int ret;
164 149
165 dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr); 150 dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
166 151
167 saa7164_writel(port->pitch, params->pitch); 152 ret = saa7164_dvb_pause_port(port);
168 saa7164_writel(port->bufsize, params->pitch * params->numberoflines); 153 ret = saa7164_dvb_acquire_port(port);
154 ret = saa7164_dvb_stop_port(port);
169 155
170 dprintk(DBGLVL_DVB, " configured:\n"); 156 /* Mark the hardware buffers as free */
171 dprintk(DBGLVL_DVB, " lmmio 0x%p\n", dev->lmmio);
172 dprintk(DBGLVL_DVB, " bufcounter 0x%x = 0x%x\n", port->bufcounter,
173 saa7164_readl(port->bufcounter));
174
175 dprintk(DBGLVL_DVB, " pitch 0x%x = %d\n", port->pitch,
176 saa7164_readl(port->pitch));
177
178 dprintk(DBGLVL_DVB, " bufsize 0x%x = %d\n", port->bufsize,
179 saa7164_readl(port->bufsize));
180
181 dprintk(DBGLVL_DVB, " buffercount = %d\n", port->hwcfg.buffercount);
182 dprintk(DBGLVL_DVB, " bufoffset = 0x%x\n", port->bufoffset);
183 dprintk(DBGLVL_DVB, " bufptr32h = 0x%x\n", port->bufptr32h);
184 dprintk(DBGLVL_DVB, " bufptr32l = 0x%x\n", port->bufptr32l);
185
186 /* Poke the buffers and offsets into PCI space */
187 mutex_lock(&port->dmaqueue_lock); 157 mutex_lock(&port->dmaqueue_lock);
188 list_for_each_safe(c, n, &port->dmaqueue.list) { 158 list_for_each_safe(p, q, &port->dmaqueue.list) {
189 buf = list_entry(c, struct saa7164_buffer, list); 159 buf = list_entry(p, struct saa7164_buffer, list);
190 160 buf->flags = SAA7164_BUFFER_FREE;
191 /* TODO: Review this in light of 32v64 assignments */
192 saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
193 saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i),
194 buf->pt_dma);
195 saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0);
196
197 dprintk(DBGLVL_DVB,
198 " buf[%d] offset 0x%llx (0x%x) "
199 "buf 0x%llx/%llx (0x%x/%x)\n",
200 i,
201 (u64)port->bufoffset + (i * sizeof(u32)),
202 saa7164_readl(port->bufoffset + (sizeof(u32) * i)),
203 (u64)port->bufptr32h + ((sizeof(u32) * 2) * i),
204 (u64)port->bufptr32l + ((sizeof(u32) * 2) * i),
205 saa7164_readl(port->bufptr32h + ((sizeof(u32) * i)
206 * 2)),
207 saa7164_readl(port->bufptr32l + ((sizeof(u32) * i)
208 * 2)));
209
210 if (i++ > port->hwcfg.buffercount)
211 BUG();
212
213 } 161 }
214 mutex_unlock(&port->dmaqueue_lock); 162 mutex_unlock(&port->dmaqueue_lock);
215 163
216 return 0; 164 return ret;
217} 165}
218 166
219static int saa7164_dvb_start_tsport(struct saa7164_tsport *port) 167static int saa7164_dvb_start_port(struct saa7164_port *port)
220{ 168{
221 struct saa7164_dev *dev = port->dev; 169 struct saa7164_dev *dev = port->dev;
222 int ret = 0, result; 170 int ret = 0, result;
223 171
224 dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr); 172 dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
225 173
226 saa7164_dvb_cfg_tsport(port); 174 saa7164_buffer_cfg_port(port);
227 175
228 /* Acquire the hardware */ 176 /* Acquire the hardware */
229 result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE); 177 result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
@@ -284,7 +232,7 @@ out:
284static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed) 232static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
285{ 233{
286 struct dvb_demux *demux = feed->demux; 234 struct dvb_demux *demux = feed->demux;
287 struct saa7164_tsport *port = (struct saa7164_tsport *) demux->priv; 235 struct saa7164_port *port = (struct saa7164_port *) demux->priv;
288 struct saa7164_dvb *dvb = &port->dvb; 236 struct saa7164_dvb *dvb = &port->dvb;
289 struct saa7164_dev *dev = port->dev; 237 struct saa7164_dev *dev = port->dev;
290 int ret = 0; 238 int ret = 0;
@@ -298,7 +246,7 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
298 mutex_lock(&dvb->lock); 246 mutex_lock(&dvb->lock);
299 if (dvb->feeding++ == 0) { 247 if (dvb->feeding++ == 0) {
300 /* Start transport */ 248 /* Start transport */
301 ret = saa7164_dvb_start_tsport(port); 249 ret = saa7164_dvb_start_port(port);
302 } 250 }
303 mutex_unlock(&dvb->lock); 251 mutex_unlock(&dvb->lock);
304 dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n", 252 dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
@@ -311,7 +259,7 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
311static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed) 259static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
312{ 260{
313 struct dvb_demux *demux = feed->demux; 261 struct dvb_demux *demux = feed->demux;
314 struct saa7164_tsport *port = (struct saa7164_tsport *) demux->priv; 262 struct saa7164_port *port = (struct saa7164_port *) demux->priv;
315 struct saa7164_dvb *dvb = &port->dvb; 263 struct saa7164_dvb *dvb = &port->dvb;
316 struct saa7164_dev *dev = port->dev; 264 struct saa7164_dev *dev = port->dev;
317 int ret = 0; 265 int ret = 0;
@@ -332,7 +280,7 @@ static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
332 return ret; 280 return ret;
333} 281}
334 282
335static int dvb_register(struct saa7164_tsport *port) 283static int dvb_register(struct saa7164_port *port)
336{ 284{
337 struct saa7164_dvb *dvb = &port->dvb; 285 struct saa7164_dvb *dvb = &port->dvb;
338 struct saa7164_dev *dev = port->dev; 286 struct saa7164_dev *dev = port->dev;
@@ -341,6 +289,9 @@ static int dvb_register(struct saa7164_tsport *port)
341 289
342 dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr); 290 dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
343 291
292 if (port->type != SAA7164_MPEG_DVB)
293 BUG();
294
344 /* Sanity check that the PCI configuration space is active */ 295 /* Sanity check that the PCI configuration space is active */
345 if (port->hwcfg.BARLocation == 0) { 296 if (port->hwcfg.BARLocation == 0) {
346 result = -ENOMEM; 297 result = -ENOMEM;
@@ -378,7 +329,6 @@ static int dvb_register(struct saa7164_tsport *port)
378 DRIVER_NAME, result); 329 DRIVER_NAME, result);
379 goto fail_adapter; 330 goto fail_adapter;
380 } 331 }
381 buf->nr = i;
382 332
383 mutex_lock(&port->dmaqueue_lock); 333 mutex_lock(&port->dmaqueue_lock);
384 list_add_tail(&buf->list, &port->dmaqueue.list); 334 list_add_tail(&buf->list, &port->dmaqueue.list);
@@ -473,7 +423,7 @@ fail_adapter:
473 return result; 423 return result;
474} 424}
475 425
476int saa7164_dvb_unregister(struct saa7164_tsport *port) 426int saa7164_dvb_unregister(struct saa7164_port *port)
477{ 427{
478 struct saa7164_dvb *dvb = &port->dvb; 428 struct saa7164_dvb *dvb = &port->dvb;
479 struct saa7164_dev *dev = port->dev; 429 struct saa7164_dev *dev = port->dev;
@@ -482,12 +432,15 @@ int saa7164_dvb_unregister(struct saa7164_tsport *port)
482 432
483 dprintk(DBGLVL_DVB, "%s()\n", __func__); 433 dprintk(DBGLVL_DVB, "%s()\n", __func__);
484 434
435 if (port->type != SAA7164_MPEG_DVB)
436 BUG();
437
485 /* Remove any allocated buffers */ 438 /* Remove any allocated buffers */
486 mutex_lock(&port->dmaqueue_lock); 439 mutex_lock(&port->dmaqueue_lock);
487 list_for_each_safe(c, n, &port->dmaqueue.list) { 440 list_for_each_safe(c, n, &port->dmaqueue.list) {
488 b = list_entry(c, struct saa7164_buffer, list); 441 b = list_entry(c, struct saa7164_buffer, list);
489 list_del(c); 442 list_del(c);
490 saa7164_buffer_dealloc(port, b); 443 saa7164_buffer_dealloc(b);
491 } 444 }
492 mutex_unlock(&port->dmaqueue_lock); 445 mutex_unlock(&port->dmaqueue_lock);
493 446
@@ -508,7 +461,7 @@ int saa7164_dvb_unregister(struct saa7164_tsport *port)
508/* All the DVB attach calls go here, this function get's modified 461/* All the DVB attach calls go here, this function get's modified
509 * for each new card. 462 * for each new card.
510 */ 463 */
511int saa7164_dvb_register(struct saa7164_tsport *port) 464int saa7164_dvb_register(struct saa7164_port *port)
512{ 465{
513 struct saa7164_dev *dev = port->dev; 466 struct saa7164_dev *dev = port->dev;
514 struct saa7164_dvb *dvb = &port->dvb; 467 struct saa7164_dvb *dvb = &port->dvb;
@@ -588,8 +541,6 @@ int saa7164_dvb_register(struct saa7164_tsport *port)
588 return -1; 541 return -1;
589 } 542 }
590 543
591 /* Put the analog decoder in standby to keep it quiet */
592
593 /* register everything */ 544 /* register everything */
594 ret = dvb_register(port); 545 ret = dvb_register(port);
595 if (ret < 0) { 546 if (ret < 0) {
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c
new file mode 100644
index 000000000000..cbb53d0ee979
--- /dev/null
+++ b/drivers/media/video/saa7164/saa7164-encoder.c
@@ -0,0 +1,1503 @@
1/*
2 * Driver for the NXP SAA7164 PCIe bridge
3 *
4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
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 "saa7164.h"
23
24#define ENCODER_MAX_BITRATE 6500000
25#define ENCODER_MIN_BITRATE 1000000
26#define ENCODER_DEF_BITRATE 5000000
27
28static struct saa7164_tvnorm saa7164_tvnorms[] = {
29 {
30 .name = "NTSC-M",
31 .id = V4L2_STD_NTSC_M,
32 }, {
33 .name = "NTSC-JP",
34 .id = V4L2_STD_NTSC_M_JP,
35 }
36};
37
38static const u32 saa7164_v4l2_ctrls[] = {
39 V4L2_CID_BRIGHTNESS,
40 V4L2_CID_CONTRAST,
41 V4L2_CID_SATURATION,
42 V4L2_CID_HUE,
43 V4L2_CID_AUDIO_VOLUME,
44 V4L2_CID_SHARPNESS,
45 V4L2_CID_MPEG_STREAM_TYPE,
46 V4L2_CID_MPEG_VIDEO_ASPECT,
47 V4L2_CID_MPEG_VIDEO_B_FRAMES,
48 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
49 V4L2_CID_MPEG_AUDIO_MUTE,
50 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
51 V4L2_CID_MPEG_VIDEO_BITRATE,
52 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
53 0
54};
55
56/* Take the encoder configuration form the port struct and
57 * flush it to the hardware.
58 */
59static void saa7164_encoder_configure(struct saa7164_port *port)
60{
61 struct saa7164_dev *dev = port->dev;
62 dprintk(DBGLVL_ENC, "%s()\n", __func__);
63
64 port->encoder_params.width = port->width;
65 port->encoder_params.height = port->height;
66 port->encoder_params.is_50hz =
67 (port->encodernorm.id & V4L2_STD_625_50) != 0;
68
69 /* Set up the DIF (enable it) for analog mode by default */
70 saa7164_api_initialize_dif(port);
71
72 /* Configure the correct video standard */
73 saa7164_api_configure_dif(port, port->encodernorm.id);
74
75 /* Ensure the audio decoder is correct configured */
76 saa7164_api_set_audio_std(port);
77}
78
79static int saa7164_encoder_buffers_dealloc(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 */
117static int saa7164_encoder_buffers_alloc(struct saa7164_port *port)
118{
119 struct saa7164_dev *dev = port->dev;
120 struct saa7164_buffer *buf;
121 struct saa7164_user_buffer *ubuf;
122 struct tmHWStreamParameters *params = &port->hw_streamingparams;
123 int result = -ENODEV, i;
124 int len = 0;
125
126 dprintk(DBGLVL_ENC, "%s()\n", __func__);
127
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;
196
197failed:
198 return result;
199}
200
201static int saa7164_encoder_initialize(struct saa7164_port *port)
202{
203 saa7164_encoder_configure(port);
204 return 0;
205}
206
207/* -- V4L2 --------------------------------------------------------- */
208static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
209{
210 struct saa7164_encoder_fh *fh = file->private_data;
211 struct saa7164_port *port = fh->port;
212 struct saa7164_dev *dev = port->dev;
213 unsigned int i;
214
215 dprintk(DBGLVL_ENC, "%s(id=0x%x)\n", __func__, (u32)*id);
216
217 for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
218 if (*id & saa7164_tvnorms[i].id)
219 break;
220 }
221 if (i == ARRAY_SIZE(saa7164_tvnorms))
222 return -EINVAL;
223
224 port->encodernorm = saa7164_tvnorms[i];
225
226 /* Update the audio decoder while is not running in
227 * auto detect mode.
228 */
229 saa7164_api_set_audio_std(port);
230
231 dprintk(DBGLVL_ENC, "%s(id=0x%x) OK\n", __func__, (u32)*id);
232
233 return 0;
234}
235
236static int vidioc_enum_input(struct file *file, void *priv,
237 struct v4l2_input *i)
238{
239 int n;
240
241 char *inputs[] = { "tuner", "composite", "svideo", "aux",
242 "composite 2", "svideo 2", "aux 2" };
243
244 if (i->index >= 7)
245 return -EINVAL;
246
247 strcpy(i->name, inputs[i->index]);
248
249 if (i->index == 0)
250 i->type = V4L2_INPUT_TYPE_TUNER;
251 else
252 i->type = V4L2_INPUT_TYPE_CAMERA;
253
254 for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
255 i->std |= saa7164_tvnorms[n].id;
256
257 return 0;
258}
259
260static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
261{
262 struct saa7164_encoder_fh *fh = file->private_data;
263 struct saa7164_port *port = fh->port;
264 struct saa7164_dev *dev = port->dev;
265
266 if (saa7164_api_get_videomux(port) != SAA_OK)
267 return -EIO;
268
269 *i = (port->mux_input - 1);
270
271 dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, *i);
272
273 return 0;
274}
275
276static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
277{
278 struct saa7164_encoder_fh *fh = file->private_data;
279 struct saa7164_port *port = fh->port;
280 struct saa7164_dev *dev = port->dev;
281
282 dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i);
283
284 if (i >= 7)
285 return -EINVAL;
286
287 port->mux_input = i + 1;
288
289 if (saa7164_api_set_videomux(port) != SAA_OK)
290 return -EIO;
291
292 return 0;
293}
294
295static int vidioc_g_tuner(struct file *file, void *priv,
296 struct v4l2_tuner *t)
297{
298 struct saa7164_encoder_fh *fh = file->private_data;
299 struct saa7164_port *port = fh->port;
300 struct saa7164_dev *dev = port->dev;
301
302 if (0 != t->index)
303 return -EINVAL;
304
305 strcpy(t->name, "tuner");
306 t->type = V4L2_TUNER_ANALOG_TV;
307 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
308
309 dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
310
311 return 0;
312}
313
314static int vidioc_s_tuner(struct file *file, void *priv,
315 struct v4l2_tuner *t)
316{
317 /* Update the A/V core */
318 return 0;
319}
320
321static int vidioc_g_frequency(struct file *file, void *priv,
322 struct v4l2_frequency *f)
323{
324 struct saa7164_encoder_fh *fh = file->private_data;
325 struct saa7164_port *port = fh->port;
326
327 f->type = V4L2_TUNER_ANALOG_TV;
328 f->frequency = port->freq;
329
330 return 0;
331}
332
333static int vidioc_s_frequency(struct file *file, void *priv,
334 struct v4l2_frequency *f)
335{
336 struct saa7164_encoder_fh *fh = file->private_data;
337 struct saa7164_port *port = fh->port;
338 struct saa7164_dev *dev = port->dev;
339 struct saa7164_port *tsport;
340 struct dvb_frontend *fe;
341
342 /* TODO: Pull this for the std */
343 struct analog_parameters params = {
344 .mode = V4L2_TUNER_ANALOG_TV,
345 .audmode = V4L2_TUNER_MODE_STEREO,
346 .std = port->encodernorm.id,
347 .frequency = f->frequency
348 };
349
350 /* Stop the encoder */
351 dprintk(DBGLVL_ENC, "%s() frequency=%d tuner=%d\n", __func__,
352 f->frequency, f->tuner);
353
354 if (f->tuner != 0)
355 return -EINVAL;
356
357 if (f->type != V4L2_TUNER_ANALOG_TV)
358 return -EINVAL;
359
360 port->freq = f->frequency;
361
362 /* Update the hardware */
363 if (port->nr == SAA7164_PORT_ENC1)
364 tsport = &dev->ports[SAA7164_PORT_TS1];
365 else
366 if (port->nr == SAA7164_PORT_ENC2)
367 tsport = &dev->ports[SAA7164_PORT_TS2];
368 else
369 BUG();
370
371 fe = tsport->dvb.frontend;
372
373 if (fe && fe->ops.tuner_ops.set_analog_params)
374 fe->ops.tuner_ops.set_analog_params(fe, &params);
375 else
376 printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
377
378 saa7164_encoder_initialize(port);
379
380 return 0;
381}
382
383static int vidioc_g_ctrl(struct file *file, void *priv,
384 struct v4l2_control *ctl)
385{
386 struct saa7164_encoder_fh *fh = file->private_data;
387 struct saa7164_port *port = fh->port;
388 struct saa7164_dev *dev = port->dev;
389
390 dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
391 ctl->id, ctl->value);
392
393 switch (ctl->id) {
394 case V4L2_CID_BRIGHTNESS:
395 ctl->value = port->ctl_brightness;
396 break;
397 case V4L2_CID_CONTRAST:
398 ctl->value = port->ctl_contrast;
399 break;
400 case V4L2_CID_SATURATION:
401 ctl->value = port->ctl_saturation;
402 break;
403 case V4L2_CID_HUE:
404 ctl->value = port->ctl_hue;
405 break;
406 case V4L2_CID_SHARPNESS:
407 ctl->value = port->ctl_sharpness;
408 break;
409 case V4L2_CID_AUDIO_VOLUME:
410 ctl->value = port->ctl_volume;
411 break;
412 default:
413 return -EINVAL;
414 }
415
416 return 0;
417}
418
419static int vidioc_s_ctrl(struct file *file, void *priv,
420 struct v4l2_control *ctl)
421{
422 struct saa7164_encoder_fh *fh = file->private_data;
423 struct saa7164_port *port = fh->port;
424 struct saa7164_dev *dev = port->dev;
425 int ret = 0;
426
427 dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
428 ctl->id, ctl->value);
429
430 switch (ctl->id) {
431 case V4L2_CID_BRIGHTNESS:
432 if ((ctl->value >= 0) && (ctl->value <= 255)) {
433 port->ctl_brightness = ctl->value;
434 saa7164_api_set_usercontrol(port,
435 PU_BRIGHTNESS_CONTROL);
436 } else
437 ret = -EINVAL;
438 break;
439 case V4L2_CID_CONTRAST:
440 if ((ctl->value >= 0) && (ctl->value <= 255)) {
441 port->ctl_contrast = ctl->value;
442 saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
443 } else
444 ret = -EINVAL;
445 break;
446 case V4L2_CID_SATURATION:
447 if ((ctl->value >= 0) && (ctl->value <= 255)) {
448 port->ctl_saturation = ctl->value;
449 saa7164_api_set_usercontrol(port,
450 PU_SATURATION_CONTROL);
451 } else
452 ret = -EINVAL;
453 break;
454 case V4L2_CID_HUE:
455 if ((ctl->value >= 0) && (ctl->value <= 255)) {
456 port->ctl_hue = ctl->value;
457 saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
458 } else
459 ret = -EINVAL;
460 break;
461 case V4L2_CID_SHARPNESS:
462 if ((ctl->value >= 0) && (ctl->value <= 255)) {
463 port->ctl_sharpness = ctl->value;
464 saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
465 } else
466 ret = -EINVAL;
467 break;
468 case V4L2_CID_AUDIO_VOLUME:
469 if ((ctl->value >= -83) && (ctl->value <= 24)) {
470 port->ctl_volume = ctl->value;
471 saa7164_api_set_audio_volume(port, port->ctl_volume);
472 } else
473 ret = -EINVAL;
474 break;
475 default:
476 ret = -EINVAL;
477 }
478
479 return ret;
480}
481
482static int saa7164_get_ctrl(struct saa7164_port *port,
483 struct v4l2_ext_control *ctrl)
484{
485 struct saa7164_encoder_params *params = &port->encoder_params;
486
487 switch (ctrl->id) {
488 case V4L2_CID_MPEG_VIDEO_BITRATE:
489 ctrl->value = params->bitrate;
490 break;
491 case V4L2_CID_MPEG_STREAM_TYPE:
492 ctrl->value = params->stream_type;
493 break;
494 case V4L2_CID_MPEG_AUDIO_MUTE:
495 ctrl->value = params->ctl_mute;
496 break;
497 case V4L2_CID_MPEG_VIDEO_ASPECT:
498 ctrl->value = params->ctl_aspect;
499 break;
500 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
501 ctrl->value = params->bitrate_mode;
502 break;
503 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
504 ctrl->value = params->refdist;
505 break;
506 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
507 ctrl->value = params->bitrate_peak;
508 break;
509 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
510 ctrl->value = params->gop_size;
511 break;
512 default:
513 return -EINVAL;
514 }
515 return 0;
516}
517
518static int vidioc_g_ext_ctrls(struct file *file, void *priv,
519 struct v4l2_ext_controls *ctrls)
520{
521 struct saa7164_encoder_fh *fh = file->private_data;
522 struct saa7164_port *port = fh->port;
523 int i, err = 0;
524
525 if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
526 for (i = 0; i < ctrls->count; i++) {
527 struct v4l2_ext_control *ctrl = ctrls->controls + i;
528
529 err = saa7164_get_ctrl(port, ctrl);
530 if (err) {
531 ctrls->error_idx = i;
532 break;
533 }
534 }
535 return err;
536
537 }
538
539 return -EINVAL;
540}
541
542static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
543{
544 int ret = -EINVAL;
545
546 switch (ctrl->id) {
547 case V4L2_CID_MPEG_VIDEO_BITRATE:
548 if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
549 (ctrl->value <= ENCODER_MAX_BITRATE))
550 ret = 0;
551 break;
552 case V4L2_CID_MPEG_STREAM_TYPE:
553 if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
554 (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
555 ret = 0;
556 break;
557 case V4L2_CID_MPEG_AUDIO_MUTE:
558 if ((ctrl->value >= 0) &&
559 (ctrl->value <= 1))
560 ret = 0;
561 break;
562 case V4L2_CID_MPEG_VIDEO_ASPECT:
563 if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
564 (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
565 ret = 0;
566 break;
567 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
568 if ((ctrl->value >= 0) &&
569 (ctrl->value <= 255))
570 ret = 0;
571 break;
572 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
573 if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ||
574 (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))
575 ret = 0;
576 break;
577 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
578 if ((ctrl->value >= 1) &&
579 (ctrl->value <= 3))
580 ret = 0;
581 break;
582 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
583 if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
584 (ctrl->value <= ENCODER_MAX_BITRATE))
585 ret = 0;
586 break;
587 default:
588 ret = -EINVAL;
589 }
590
591 return ret;
592}
593
594static int vidioc_try_ext_ctrls(struct file *file, void *priv,
595 struct v4l2_ext_controls *ctrls)
596{
597 int i, err = 0;
598
599 if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
600 for (i = 0; i < ctrls->count; i++) {
601 struct v4l2_ext_control *ctrl = ctrls->controls + i;
602
603 err = saa7164_try_ctrl(ctrl, 0);
604 if (err) {
605 ctrls->error_idx = i;
606 break;
607 }
608 }
609 return err;
610 }
611
612 return -EINVAL;
613}
614
615static int saa7164_set_ctrl(struct saa7164_port *port,
616 struct v4l2_ext_control *ctrl)
617{
618 struct saa7164_encoder_params *params = &port->encoder_params;
619 int ret = 0;
620
621 switch (ctrl->id) {
622 case V4L2_CID_MPEG_VIDEO_BITRATE:
623 params->bitrate = ctrl->value;
624 break;
625 case V4L2_CID_MPEG_STREAM_TYPE:
626 params->stream_type = ctrl->value;
627 break;
628 case V4L2_CID_MPEG_AUDIO_MUTE:
629 params->ctl_mute = ctrl->value;
630 ret = saa7164_api_audio_mute(port, params->ctl_mute);
631 if (ret != SAA_OK) {
632 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
633 ret);
634 ret = -EIO;
635 }
636 break;
637 case V4L2_CID_MPEG_VIDEO_ASPECT:
638 params->ctl_aspect = ctrl->value;
639 ret = saa7164_api_set_aspect_ratio(port);
640 if (ret != SAA_OK) {
641 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
642 ret);
643 ret = -EIO;
644 }
645 break;
646 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
647 params->bitrate_mode = ctrl->value;
648 break;
649 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
650 params->refdist = ctrl->value;
651 break;
652 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
653 params->bitrate_peak = ctrl->value;
654 break;
655 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
656 params->gop_size = ctrl->value;
657 break;
658 default:
659 return -EINVAL;
660 }
661
662 /* TODO: Update the hardware */
663
664 return ret;
665}
666
667static int vidioc_s_ext_ctrls(struct file *file, void *priv,
668 struct v4l2_ext_controls *ctrls)
669{
670 struct saa7164_encoder_fh *fh = file->private_data;
671 struct saa7164_port *port = fh->port;
672 int i, err = 0;
673
674 if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
675 for (i = 0; i < ctrls->count; i++) {
676 struct v4l2_ext_control *ctrl = ctrls->controls + i;
677
678 err = saa7164_try_ctrl(ctrl, 0);
679 if (err) {
680 ctrls->error_idx = i;
681 break;
682 }
683 err = saa7164_set_ctrl(port, ctrl);
684 if (err) {
685 ctrls->error_idx = i;
686 break;
687 }
688 }
689 return err;
690
691 }
692
693 return -EINVAL;
694}
695
696static int vidioc_querycap(struct file *file, void *priv,
697 struct v4l2_capability *cap)
698{
699 struct saa7164_encoder_fh *fh = file->private_data;
700 struct saa7164_port *port = fh->port;
701 struct saa7164_dev *dev = port->dev;
702
703 strcpy(cap->driver, dev->name);
704 strlcpy(cap->card, saa7164_boards[dev->board].name,
705 sizeof(cap->card));
706 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
707
708 cap->capabilities =
709 V4L2_CAP_VIDEO_CAPTURE |
710 V4L2_CAP_READWRITE |
711 0;
712
713 cap->capabilities |= V4L2_CAP_TUNER;
714 cap->version = 0;
715
716 return 0;
717}
718
719static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
720 struct v4l2_fmtdesc *f)
721{
722 if (f->index != 0)
723 return -EINVAL;
724
725 strlcpy(f->description, "MPEG", sizeof(f->description));
726 f->pixelformat = V4L2_PIX_FMT_MPEG;
727
728 return 0;
729}
730
731static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
732 struct v4l2_format *f)
733{
734 struct saa7164_encoder_fh *fh = file->private_data;
735 struct saa7164_port *port = fh->port;
736 struct saa7164_dev *dev = port->dev;
737
738 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
739 f->fmt.pix.bytesperline = 0;
740 f->fmt.pix.sizeimage =
741 port->ts_packet_size * port->ts_packet_count;
742 f->fmt.pix.colorspace = 0;
743 f->fmt.pix.width = port->width;
744 f->fmt.pix.height = port->height;
745
746 dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n",
747 port->width, port->height);
748
749 return 0;
750}
751
752static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
753 struct v4l2_format *f)
754{
755 struct saa7164_encoder_fh *fh = file->private_data;
756 struct saa7164_port *port = fh->port;
757 struct saa7164_dev *dev = port->dev;
758
759 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
760 f->fmt.pix.bytesperline = 0;
761 f->fmt.pix.sizeimage =
762 port->ts_packet_size * port->ts_packet_count;
763 f->fmt.pix.colorspace = 0;
764 dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
765 port->width, port->height);
766 return 0;
767}
768
769static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
770 struct v4l2_format *f)
771{
772 struct saa7164_encoder_fh *fh = file->private_data;
773 struct saa7164_port *port = fh->port;
774 struct saa7164_dev *dev = port->dev;
775
776 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
777 f->fmt.pix.bytesperline = 0;
778 f->fmt.pix.sizeimage =
779 port->ts_packet_size * port->ts_packet_count;
780 f->fmt.pix.colorspace = 0;
781
782 dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
783 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
784
785 return 0;
786}
787
788static int vidioc_log_status(struct file *file, void *priv)
789{
790 return 0;
791}
792
793static int fill_queryctrl(struct saa7164_encoder_params *params,
794 struct v4l2_queryctrl *c)
795{
796 switch (c->id) {
797 case V4L2_CID_BRIGHTNESS:
798 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
799 case V4L2_CID_CONTRAST:
800 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
801 case V4L2_CID_SATURATION:
802 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
803 case V4L2_CID_HUE:
804 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
805 case V4L2_CID_SHARPNESS:
806 return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
807 case V4L2_CID_MPEG_AUDIO_MUTE:
808 return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
809 case V4L2_CID_AUDIO_VOLUME:
810 return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
811 case V4L2_CID_MPEG_VIDEO_BITRATE:
812 return v4l2_ctrl_query_fill(c,
813 ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
814 100000, ENCODER_DEF_BITRATE);
815 case V4L2_CID_MPEG_STREAM_TYPE:
816 return v4l2_ctrl_query_fill(c,
817 V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
818 V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
819 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
820 case V4L2_CID_MPEG_VIDEO_ASPECT:
821 return v4l2_ctrl_query_fill(c,
822 V4L2_MPEG_VIDEO_ASPECT_1x1,
823 V4L2_MPEG_VIDEO_ASPECT_221x100,
824 1, V4L2_MPEG_VIDEO_ASPECT_4x3);
825 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
826 return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
827 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
828 return v4l2_ctrl_query_fill(c,
829 V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
830 1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
831 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
832 return v4l2_ctrl_query_fill(c,
833 1, 3, 1, 1);
834 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
835 return v4l2_ctrl_query_fill(c,
836 ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
837 100000, ENCODER_DEF_BITRATE);
838 default:
839 return -EINVAL;
840 }
841}
842
843static int vidioc_queryctrl(struct file *file, void *priv,
844 struct v4l2_queryctrl *c)
845{
846 struct saa7164_encoder_fh *fh = priv;
847 struct saa7164_port *port = fh->port;
848 int i, next;
849 u32 id = c->id;
850
851 memset(c, 0, sizeof(*c));
852
853 next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
854 c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
855
856 for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
857 if (next) {
858 if (c->id < saa7164_v4l2_ctrls[i])
859 c->id = saa7164_v4l2_ctrls[i];
860 else
861 continue;
862 }
863
864 if (c->id == saa7164_v4l2_ctrls[i])
865 return fill_queryctrl(&port->encoder_params, c);
866
867 if (c->id < saa7164_v4l2_ctrls[i])
868 break;
869 }
870
871 return -EINVAL;
872}
873
874static int saa7164_encoder_stop_port(struct saa7164_port *port)
875{
876 struct saa7164_dev *dev = port->dev;
877 int ret;
878
879 ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
880 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
881 printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
882 __func__, ret);
883 ret = -EIO;
884 } else {
885 dprintk(DBGLVL_ENC, "%s() Stopped\n", __func__);
886 ret = 0;
887 }
888
889 return ret;
890}
891
892static int saa7164_encoder_acquire_port(struct saa7164_port *port)
893{
894 struct saa7164_dev *dev = port->dev;
895 int ret;
896
897 ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
898 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
899 printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
900 __func__, ret);
901 ret = -EIO;
902 } else {
903 dprintk(DBGLVL_ENC, "%s() Acquired\n", __func__);
904 ret = 0;
905 }
906
907 return ret;
908}
909
910static int saa7164_encoder_pause_port(struct saa7164_port *port)
911{
912 struct saa7164_dev *dev = port->dev;
913 int ret;
914
915 ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
916 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
917 printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
918 __func__, ret);
919 ret = -EIO;
920 } else {
921 dprintk(DBGLVL_ENC, "%s() Paused\n", __func__);
922 ret = 0;
923 }
924
925 return ret;
926}
927
928/* Firmware is very windows centric, meaning you have to transition
929 * the part through AVStream / KS Windows stages, forwards or backwards.
930 * States are: stopped, acquired (h/w), paused, started.
931 * We have to leave here will all of the soft buffers on the free list,
932 * else the cfg_post() func won't have soft buffers to correctly configure.
933 */
934static int saa7164_encoder_stop_streaming(struct saa7164_port *port)
935{
936 struct saa7164_dev *dev = port->dev;
937 struct saa7164_buffer *buf;
938 struct saa7164_user_buffer *ubuf;
939 struct list_head *c, *n;
940 int ret;
941
942 dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
943
944 ret = saa7164_encoder_pause_port(port);
945 ret = saa7164_encoder_acquire_port(port);
946 ret = saa7164_encoder_stop_port(port);
947
948 dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__,
949 port->nr);
950
951 /* Reset the state of any allocated buffer resources */
952 mutex_lock(&port->dmaqueue_lock);
953
954 /* Reset the hard and soft buffer state */
955 list_for_each_safe(c, n, &port->dmaqueue.list) {
956 buf = list_entry(c, struct saa7164_buffer, list);
957 buf->flags = SAA7164_BUFFER_FREE;
958 buf->pos = 0;
959 }
960
961 list_for_each_safe(c, n, &port->list_buf_used.list) {
962 ubuf = list_entry(c, struct saa7164_user_buffer, list);
963 ubuf->pos = 0;
964 list_move_tail(&ubuf->list, &port->list_buf_free.list);
965 }
966
967 mutex_unlock(&port->dmaqueue_lock);
968
969 /* Free any allocated resources */
970 saa7164_encoder_buffers_dealloc(port);
971
972 dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr);
973
974 return ret;
975}
976
977static int saa7164_encoder_start_streaming(struct saa7164_port *port)
978{
979 struct saa7164_dev *dev = port->dev;
980 int result, ret = 0;
981
982 dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
983
984 port->done_first_interrupt = 0;
985
986 /* allocate all of the PCIe DMA buffer resources on the fly,
987 * allowing switching between TS and PS payloads without
988 * requiring a complete driver reload.
989 */
990 saa7164_encoder_buffers_alloc(port);
991
992 /* Configure the encoder with any cache values */
993 saa7164_api_set_encoder(port);
994 saa7164_api_get_encoder(port);
995
996 /* Place the empty buffers on the hardware */
997 saa7164_buffer_cfg_port(port);
998
999 /* Acquire the hardware */
1000 result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
1001 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
1002 printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
1003 __func__, result);
1004
1005 /* Stop the hardware, regardless */
1006 result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
1007 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
1008 printk(KERN_ERR "%s() acquire/forced stop transition "
1009 "failed, res = 0x%x\n", __func__, result);
1010 }
1011 ret = -EIO;
1012 goto out;
1013 } else
1014 dprintk(DBGLVL_ENC, "%s() Acquired\n", __func__);
1015
1016 /* Pause the hardware */
1017 result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
1018 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
1019 printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
1020 __func__, result);
1021
1022 /* Stop the hardware, regardless */
1023 result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
1024 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
1025 printk(KERN_ERR "%s() pause/forced stop transition "
1026 "failed, res = 0x%x\n", __func__, result);
1027 }
1028
1029 ret = -EIO;
1030 goto out;
1031 } else
1032 dprintk(DBGLVL_ENC, "%s() Paused\n", __func__);
1033
1034 /* Start the hardware */
1035 result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
1036 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
1037 printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
1038 __func__, result);
1039
1040 /* Stop the hardware, regardless */
1041 result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
1042 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
1043 printk(KERN_ERR "%s() run/forced stop transition "
1044 "failed, res = 0x%x\n", __func__, result);
1045 }
1046
1047 ret = -EIO;
1048 } else
1049 dprintk(DBGLVL_ENC, "%s() Running\n", __func__);
1050
1051out:
1052 return ret;
1053}
1054
1055static int fops_open(struct file *file)
1056{
1057 struct saa7164_dev *dev;
1058 struct saa7164_port *port;
1059 struct saa7164_encoder_fh *fh;
1060
1061 port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
1062 if (!port)
1063 return -ENODEV;
1064
1065 dev = port->dev;
1066
1067 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1068
1069 /* allocate + initialize per filehandle data */
1070 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1071 if (NULL == fh)
1072 return -ENOMEM;
1073
1074 file->private_data = fh;
1075 fh->port = port;
1076
1077 return 0;
1078}
1079
1080static int fops_release(struct file *file)
1081{
1082 struct saa7164_encoder_fh *fh = file->private_data;
1083 struct saa7164_port *port = fh->port;
1084 struct saa7164_dev *dev = port->dev;
1085
1086 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1087
1088 /* Shut device down on last close */
1089 if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
1090 if (atomic_dec_return(&port->v4l_reader_count) == 0) {
1091 /* stop mpeg capture then cancel buffers */
1092 saa7164_encoder_stop_streaming(port);
1093 }
1094 }
1095
1096 file->private_data = NULL;
1097 kfree(fh);
1098
1099 return 0;
1100}
1101
1102struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
1103{
1104 struct saa7164_user_buffer *ubuf = 0;
1105 struct saa7164_dev *dev = port->dev;
1106 u32 crc;
1107
1108 mutex_lock(&port->dmaqueue_lock);
1109 if (!list_empty(&port->list_buf_used.list)) {
1110 ubuf = list_first_entry(&port->list_buf_used.list,
1111 struct saa7164_user_buffer, list);
1112
1113 if (crc_checking) {
1114 crc = crc32(0, ubuf->data, ubuf->actual_size);
1115 if (crc != ubuf->crc) {
1116 printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__,
1117 ubuf, ubuf->crc, crc);
1118 }
1119 }
1120
1121 }
1122 mutex_unlock(&port->dmaqueue_lock);
1123
1124 dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, ubuf);
1125
1126 return ubuf;
1127}
1128
1129static ssize_t fops_read(struct file *file, char __user *buffer,
1130 size_t count, loff_t *pos)
1131{
1132 struct saa7164_encoder_fh *fh = file->private_data;
1133 struct saa7164_port *port = fh->port;
1134 struct saa7164_user_buffer *ubuf = NULL;
1135 struct saa7164_dev *dev = port->dev;
1136 int ret = 0;
1137 int rem, cnt;
1138 u8 *p;
1139
1140 port->last_read_msecs_diff = port->last_read_msecs;
1141 port->last_read_msecs = jiffies_to_msecs(jiffies);
1142 port->last_read_msecs_diff = port->last_read_msecs -
1143 port->last_read_msecs_diff;
1144
1145 saa7164_histogram_update(&port->read_interval,
1146 port->last_read_msecs_diff);
1147
1148 if (*pos) {
1149 printk(KERN_ERR "%s() ESPIPE\n", __func__);
1150 return -ESPIPE;
1151 }
1152
1153 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1154 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1155
1156 if (saa7164_encoder_initialize(port) < 0) {
1157 printk(KERN_ERR "%s() EINVAL\n", __func__);
1158 return -EINVAL;
1159 }
1160
1161 saa7164_encoder_start_streaming(port);
1162 msleep(200);
1163 }
1164 }
1165
1166 /* blocking wait for buffer */
1167 if ((file->f_flags & O_NONBLOCK) == 0) {
1168 if (wait_event_interruptible(port->wait_read,
1169 saa7164_enc_next_buf(port))) {
1170 printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
1171 return -ERESTARTSYS;
1172 }
1173 }
1174
1175 /* Pull the first buffer from the used list */
1176 ubuf = saa7164_enc_next_buf(port);
1177
1178 while ((count > 0) && ubuf) {
1179
1180 /* set remaining bytes to copy */
1181 rem = ubuf->actual_size - ubuf->pos;
1182 cnt = rem > count ? count : rem;
1183
1184 p = ubuf->data + ubuf->pos;
1185
1186 dprintk(DBGLVL_ENC,
1187 "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
1188 __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
1189
1190 if (copy_to_user(buffer, p, cnt)) {
1191 printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
1192 if (!ret) {
1193 printk(KERN_ERR "%s() EFAULT\n", __func__);
1194 ret = -EFAULT;
1195 }
1196 goto err;
1197 }
1198
1199 ubuf->pos += cnt;
1200 count -= cnt;
1201 buffer += cnt;
1202 ret += cnt;
1203
1204 if (ubuf->pos > ubuf->actual_size) {
1205 printk(KERN_ERR "read() pos > actual, huh?\n");
1206 }
1207
1208 if (ubuf->pos == ubuf->actual_size) {
1209
1210 /* finished with current buffer, take next buffer */
1211
1212 /* Requeue the buffer on the free list */
1213 ubuf->pos = 0;
1214
1215 mutex_lock(&port->dmaqueue_lock);
1216 list_move_tail(&ubuf->list, &port->list_buf_free.list);
1217 mutex_unlock(&port->dmaqueue_lock);
1218
1219 /* Dequeue next */
1220 if ((file->f_flags & O_NONBLOCK) == 0) {
1221 if (wait_event_interruptible(port->wait_read,
1222 saa7164_enc_next_buf(port))) {
1223 break;
1224 }
1225 }
1226 ubuf = saa7164_enc_next_buf(port);
1227 }
1228 }
1229err:
1230 if (!ret && !ubuf) {
1231 ret = -EAGAIN;
1232 }
1233
1234 return ret;
1235}
1236
1237static unsigned int fops_poll(struct file *file, poll_table *wait)
1238{
1239 struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data;
1240 struct saa7164_port *port = fh->port;
1241 struct saa7164_user_buffer *ubuf;
1242 unsigned int mask = 0;
1243
1244 port->last_poll_msecs_diff = port->last_poll_msecs;
1245 port->last_poll_msecs = jiffies_to_msecs(jiffies);
1246 port->last_poll_msecs_diff = port->last_poll_msecs -
1247 port->last_poll_msecs_diff;
1248
1249 saa7164_histogram_update(&port->poll_interval,
1250 port->last_poll_msecs_diff);
1251
1252 if (!video_is_registered(port->v4l_device)) {
1253 return -EIO;
1254 }
1255
1256 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1257 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1258 if (saa7164_encoder_initialize(port) < 0)
1259 return -EINVAL;
1260 saa7164_encoder_start_streaming(port);
1261 msleep(200);
1262 }
1263 }
1264
1265 /* blocking wait for buffer */
1266 if ((file->f_flags & O_NONBLOCK) == 0) {
1267 if (wait_event_interruptible(port->wait_read,
1268 saa7164_enc_next_buf(port))) {
1269 return -ERESTARTSYS;
1270 }
1271 }
1272
1273 /* Pull the first buffer from the used list */
1274 ubuf = list_first_entry(&port->list_buf_used.list,
1275 struct saa7164_user_buffer, list);
1276
1277 if (ubuf)
1278 mask |= POLLIN | POLLRDNORM;
1279
1280 return mask;
1281}
1282
1283static const struct v4l2_file_operations mpeg_fops = {
1284 .owner = THIS_MODULE,
1285 .open = fops_open,
1286 .release = fops_release,
1287 .read = fops_read,
1288 .poll = fops_poll,
1289 .unlocked_ioctl = video_ioctl2,
1290};
1291
1292int saa7164_g_chip_ident(struct file *file, void *fh,
1293 struct v4l2_dbg_chip_ident *chip)
1294{
1295 struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
1296 struct saa7164_dev *dev = port->dev;
1297 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1298
1299 return 0;
1300}
1301
1302int saa7164_g_register(struct file *file, void *fh,
1303 struct v4l2_dbg_register *reg)
1304{
1305 struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
1306 struct saa7164_dev *dev = port->dev;
1307 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1308
1309 if (!capable(CAP_SYS_ADMIN))
1310 return -EPERM;
1311
1312 return 0;
1313}
1314
1315int saa7164_s_register(struct file *file, void *fh,
1316 struct v4l2_dbg_register *reg)
1317{
1318 struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
1319 struct saa7164_dev *dev = port->dev;
1320 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1321
1322 if (!capable(CAP_SYS_ADMIN))
1323 return -EPERM;
1324
1325 return 0;
1326}
1327
1328static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
1329 .vidioc_s_std = vidioc_s_std,
1330 .vidioc_enum_input = vidioc_enum_input,
1331 .vidioc_g_input = vidioc_g_input,
1332 .vidioc_s_input = vidioc_s_input,
1333 .vidioc_g_tuner = vidioc_g_tuner,
1334 .vidioc_s_tuner = vidioc_s_tuner,
1335 .vidioc_g_frequency = vidioc_g_frequency,
1336 .vidioc_s_frequency = vidioc_s_frequency,
1337 .vidioc_s_ctrl = vidioc_s_ctrl,
1338 .vidioc_g_ctrl = vidioc_g_ctrl,
1339 .vidioc_querycap = vidioc_querycap,
1340 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1341 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1342 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1343 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1344 .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
1345 .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
1346 .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
1347 .vidioc_log_status = vidioc_log_status,
1348 .vidioc_queryctrl = vidioc_queryctrl,
1349 .vidioc_g_chip_ident = saa7164_g_chip_ident,
1350#ifdef CONFIG_VIDEO_ADV_DEBUG
1351 .vidioc_g_register = saa7164_g_register,
1352 .vidioc_s_register = saa7164_s_register,
1353#endif
1354};
1355
1356static struct video_device saa7164_mpeg_template = {
1357 .name = "saa7164",
1358 .fops = &mpeg_fops,
1359 .ioctl_ops = &mpeg_ioctl_ops,
1360 .minor = -1,
1361 .tvnorms = SAA7164_NORMS,
1362 .current_norm = V4L2_STD_NTSC_M,
1363};
1364
1365static struct video_device *saa7164_encoder_alloc(
1366 struct saa7164_port *port,
1367 struct pci_dev *pci,
1368 struct video_device *template,
1369 char *type)
1370{
1371 struct video_device *vfd;
1372 struct saa7164_dev *dev = port->dev;
1373
1374 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1375
1376 vfd = video_device_alloc();
1377 if (NULL == vfd)
1378 return NULL;
1379
1380 *vfd = *template;
1381 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
1382 type, saa7164_boards[dev->board].name);
1383
1384 vfd->parent = &pci->dev;
1385 vfd->release = video_device_release;
1386 return vfd;
1387}
1388
1389int saa7164_encoder_register(struct saa7164_port *port)
1390{
1391 struct saa7164_dev *dev = port->dev;
1392 int result = -ENODEV;
1393
1394 dprintk(DBGLVL_ENC, "%s()\n", __func__);
1395
1396 if (port->type != SAA7164_MPEG_ENCODER)
1397 BUG();
1398
1399 /* Sanity check that the PCI configuration space is active */
1400 if (port->hwcfg.BARLocation == 0) {
1401 printk(KERN_ERR "%s() failed "
1402 "(errno = %d), NO PCI configuration\n",
1403 __func__, result);
1404 result = -ENOMEM;
1405 goto failed;
1406 }
1407
1408 /* Establish encoder defaults here */
1409 /* Set default TV standard */
1410 port->encodernorm = saa7164_tvnorms[0];
1411 port->width = 720;
1412 port->mux_input = 1; /* Composite */
1413 port->video_format = EU_VIDEO_FORMAT_MPEG_2;
1414 port->audio_format = 0;
1415 port->video_resolution = 0;
1416 port->ctl_brightness = 127;
1417 port->ctl_contrast = 66;
1418 port->ctl_hue = 128;
1419 port->ctl_saturation = 62;
1420 port->ctl_sharpness = 8;
1421 port->encoder_params.bitrate = ENCODER_DEF_BITRATE;
1422 port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE;
1423 port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
1424 port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
1425 port->encoder_params.ctl_mute = 0;
1426 port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
1427 port->encoder_params.refdist = 1;
1428 port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE;
1429
1430 if (port->encodernorm.id & V4L2_STD_525_60)
1431 port->height = 480;
1432 else
1433 port->height = 576;
1434
1435 /* Allocate and register the video device node */
1436 port->v4l_device = saa7164_encoder_alloc(port,
1437 dev->pci, &saa7164_mpeg_template, "mpeg");
1438
1439 if (port->v4l_device == NULL) {
1440 printk(KERN_INFO "%s: can't allocate mpeg device\n",
1441 dev->name);
1442 result = -ENOMEM;
1443 goto failed;
1444 }
1445
1446 video_set_drvdata(port->v4l_device, port);
1447 result = video_register_device(port->v4l_device,
1448 VFL_TYPE_GRABBER, -1);
1449 if (result < 0) {
1450 printk(KERN_INFO "%s: can't register mpeg device\n",
1451 dev->name);
1452 /* TODO: We're going to leak here if we don't dealloc
1453 The buffers above. The unreg function can't deal wit it.
1454 */
1455 goto failed;
1456 }
1457
1458 printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
1459 dev->name, port->v4l_device->num);
1460
1461 /* Configure the hardware defaults */
1462 saa7164_api_set_videomux(port);
1463 saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
1464 saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
1465 saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
1466 saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
1467 saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
1468 saa7164_api_audio_mute(port, 0);
1469 saa7164_api_set_audio_volume(port, 20);
1470 saa7164_api_set_aspect_ratio(port);
1471
1472 /* Disable audio standard detection, it's buggy */
1473 saa7164_api_set_audio_detection(port, 0);
1474
1475 saa7164_api_set_encoder(port);
1476 saa7164_api_get_encoder(port);
1477
1478 result = 0;
1479failed:
1480 return result;
1481}
1482
1483void saa7164_encoder_unregister(struct saa7164_port *port)
1484{
1485 struct saa7164_dev *dev = port->dev;
1486
1487 dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
1488
1489 if (port->type != SAA7164_MPEG_ENCODER)
1490 BUG();
1491
1492 if (port->v4l_device) {
1493 if (port->v4l_device->minor != -1)
1494 video_unregister_device(port->v4l_device);
1495 else
1496 video_device_release(port->v4l_device);
1497
1498 port->v4l_device = NULL;
1499 }
1500
1501 dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
1502}
1503
diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c
index 270245d275ab..484533c32bb1 100644
--- a/drivers/media/video/saa7164/saa7164-fw.c
+++ b/drivers/media/video/saa7164/saa7164-fw.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -24,11 +24,11 @@
24 24
25#include "saa7164.h" 25#include "saa7164.h"
26 26
27#define SAA7164_REV2_FIRMWARE "v4l-saa7164-1.0.2.fw" 27#define SAA7164_REV2_FIRMWARE "NXP7164-2010-03-10.1.fw"
28#define SAA7164_REV2_FIRMWARE_SIZE 3978608 28#define SAA7164_REV2_FIRMWARE_SIZE 4019072
29 29
30#define SAA7164_REV3_FIRMWARE "v4l-saa7164-1.0.3.fw" 30#define SAA7164_REV3_FIRMWARE "NXP7164-2010-03-10.1.fw"
31#define SAA7164_REV3_FIRMWARE_SIZE 3978608 31#define SAA7164_REV3_FIRMWARE_SIZE 4019072
32 32
33struct fw_header { 33struct fw_header {
34 u32 firmwaresize; 34 u32 firmwaresize;
@@ -604,6 +604,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev)
604 } 604 }
605 } 605 }
606 606
607 dev->firmwareloaded = 1;
607 ret = 0; 608 ret = 0;
608 609
609out: 610out:
diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c
index e1ae9b01bf0f..b5167d33650a 100644
--- a/drivers/media/video/saa7164/saa7164-i2c.c
+++ b/drivers/media/video/saa7164/saa7164-i2c.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/saa7164/saa7164-reg.h b/drivers/media/video/saa7164/saa7164-reg.h
index 06be4c13d5b1..2bbf81583d33 100644
--- a/drivers/media/video/saa7164/saa7164-reg.h
+++ b/drivers/media/video/saa7164/saa7164-reg.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -60,6 +60,7 @@
60#define GET_STRING_CONTROL 0x03 60#define GET_STRING_CONTROL 0x03
61#define GET_LANGUAGE_CONTROL 0x05 61#define GET_LANGUAGE_CONTROL 0x05
62#define SET_POWER_CONTROL 0x07 62#define SET_POWER_CONTROL 0x07
63#define GET_FW_STATUS_CONTROL 0x08
63#define GET_FW_VERSION_CONTROL 0x09 64#define GET_FW_VERSION_CONTROL 0x09
64#define SET_DEBUG_LEVEL_CONTROL 0x0B 65#define SET_DEBUG_LEVEL_CONTROL 0x0B
65#define GET_DEBUG_DATA_CONTROL 0x0C 66#define GET_DEBUG_DATA_CONTROL 0x0C
@@ -156,11 +157,63 @@
156#define EXU_INTERRUPT_CONTROL 0x03 157#define EXU_INTERRUPT_CONTROL 0x03
157 158
158/* State Transition and args */ 159/* State Transition and args */
160#define SAA_PROBE_CONTROL 0x01
161#define SAA_COMMIT_CONTROL 0x02
159#define SAA_STATE_CONTROL 0x03 162#define SAA_STATE_CONTROL 0x03
160#define SAA_DMASTATE_STOP 0x00 163#define SAA_DMASTATE_STOP 0x00
161#define SAA_DMASTATE_ACQUIRE 0x01 164#define SAA_DMASTATE_ACQUIRE 0x01
162#define SAA_DMASTATE_PAUSE 0x02 165#define SAA_DMASTATE_PAUSE 0x02
163#define SAA_DMASTATE_RUN 0x03 166#define SAA_DMASTATE_RUN 0x03
164 167
165/* Hardware registers */ 168/* A/V Mux Input Selector */
166 169#define SU_INPUT_SELECT_CONTROL 0x01
170
171/* Encoder Profiles */
172#define EU_PROFILE_PS_DVD 0x06
173#define EU_PROFILE_TS_HQ 0x09
174#define EU_VIDEO_FORMAT_MPEG_2 0x02
175
176/* Tuner */
177#define TU_AUDIO_MODE_CONTROL 0x17
178
179/* Video Formats */
180#define TU_STANDARD_CONTROL 0x00
181#define TU_STANDARD_AUTO_CONTROL 0x01
182#define TU_STANDARD_NONE 0x00
183#define TU_STANDARD_NTSC_M 0x01
184#define TU_STANDARD_PAL_I 0x08
185#define TU_STANDARD_MANUAL 0x00
186#define TU_STANDARD_AUTO 0x01
187
188/* Video Controls */
189#define PU_BRIGHTNESS_CONTROL 0x02
190#define PU_CONTRAST_CONTROL 0x03
191#define PU_HUE_CONTROL 0x06
192#define PU_SATURATION_CONTROL 0x07
193#define PU_SHARPNESS_CONTROL 0x08
194
195/* Audio Controls */
196#define MUTE_CONTROL 0x01
197#define VOLUME_CONTROL 0x02
198#define AUDIO_DEFAULT_CONTROL 0x0D
199
200/* Default Volume Levels */
201#define TMHW_LEV_ADJ_DECLEV_DEFAULT 0x00
202#define TMHW_LEV_ADJ_MONOLEV_DEFAULT 0x00
203#define TMHW_LEV_ADJ_NICLEV_DEFAULT 0x00
204#define TMHW_LEV_ADJ_SAPLEV_DEFAULT 0x00
205#define TMHW_LEV_ADJ_ADCLEV_DEFAULT 0x00
206
207/* Encoder Related Commands */
208#define EU_PROFILE_CONTROL 0x00
209#define EU_VIDEO_FORMAT_CONTROL 0x01
210#define EU_VIDEO_BIT_RATE_CONTROL 0x02
211#define EU_VIDEO_RESOLUTION_CONTROL 0x03
212#define EU_VIDEO_GOP_STRUCTURE_CONTROL 0x04
213#define EU_VIDEO_INPUT_ASPECT_CONTROL 0x0A
214#define EU_AUDIO_FORMAT_CONTROL 0x0C
215#define EU_AUDIO_BIT_RATE_CONTROL 0x0D
216
217/* Firmware Debugging */
218#define SET_DEBUG_LEVEL_CONTROL 0x0B
219#define GET_DEBUG_DATA_CONTROL 0x0C
diff --git a/drivers/media/video/saa7164/saa7164-types.h b/drivers/media/video/saa7164/saa7164-types.h
index 99093f23aae5..df1d2997fa6c 100644
--- a/drivers/media/video/saa7164/saa7164-types.h
+++ b/drivers/media/video/saa7164/saa7164-types.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
24/* Some structues are passed directly to/from the firmware and 24/* Some structues are passed directly to/from the firmware and
25 * have strict alignment requirements. This is one of them. 25 * have strict alignment requirements. This is one of them.
26 */ 26 */
27typedef struct { 27struct tmComResHWDescr {
28 u8 bLength; 28 u8 bLength;
29 u8 bDescriptorType; 29 u8 bDescriptorType;
30 u8 bDescriptorSubtype; 30 u8 bDescriptorSubtype;
@@ -37,14 +37,14 @@ typedef struct {
37 u32 dwHostMemoryRegionSize; 37 u32 dwHostMemoryRegionSize;
38 u32 dwHostHibernatMemRegion; 38 u32 dwHostHibernatMemRegion;
39 u32 dwHostHibernatMemRegionSize; 39 u32 dwHostHibernatMemRegionSize;
40} __attribute__((packed)) tmComResHWDescr_t; 40} __attribute__((packed));
41 41
42/* This is DWORD aligned on windows but I can't find the right 42/* This is DWORD aligned on windows but I can't find the right
43 * gcc syntax to match the binary data from the device. 43 * gcc syntax to match the binary data from the device.
44 * I've manually padded with Reserved[3] bytes to match the hardware, 44 * I've manually padded with Reserved[3] bytes to match the hardware,
45 * but this could break if GCC decies to pack in a different way. 45 * but this could break if GCC decies to pack in a different way.
46 */ 46 */
47typedef struct { 47struct tmComResInterfaceDescr {
48 u8 bLength; 48 u8 bLength;
49 u8 bDescriptorType; 49 u8 bDescriptorType;
50 u8 bDescriptorSubtype; 50 u8 bDescriptorSubtype;
@@ -56,52 +56,52 @@ typedef struct {
56 u8 bDebugInterruptId; 56 u8 bDebugInterruptId;
57 u8 BARLocation; 57 u8 BARLocation;
58 u8 Reserved[3]; 58 u8 Reserved[3];
59} tmComResInterfaceDescr_t; 59};
60 60
61typedef struct { 61struct tmComResBusDescr {
62 u64 CommandRing; 62 u64 CommandRing;
63 u64 ResponseRing; 63 u64 ResponseRing;
64 u32 CommandWrite; 64 u32 CommandWrite;
65 u32 CommandRead; 65 u32 CommandRead;
66 u32 ResponseWrite; 66 u32 ResponseWrite;
67 u32 ResponseRead; 67 u32 ResponseRead;
68} tmComResBusDescr_t; 68};
69 69
70typedef enum { 70enum tmBusType {
71 NONE = 0, 71 NONE = 0,
72 TYPE_BUS_PCI = 1, 72 TYPE_BUS_PCI = 1,
73 TYPE_BUS_PCIe = 2, 73 TYPE_BUS_PCIe = 2,
74 TYPE_BUS_USB = 3, 74 TYPE_BUS_USB = 3,
75 TYPE_BUS_I2C = 4 75 TYPE_BUS_I2C = 4
76} tmBusType_t; 76};
77 77
78typedef struct { 78struct tmComResBusInfo {
79 tmBusType_t Type; 79 enum tmBusType Type;
80 u16 m_wMaxReqSize; 80 u16 m_wMaxReqSize;
81 u8 *m_pdwSetRing; 81 u8 *m_pdwSetRing;
82 u32 m_dwSizeSetRing; 82 u32 m_dwSizeSetRing;
83 u8 *m_pdwGetRing; 83 u8 *m_pdwGetRing;
84 u32 m_dwSizeGetRing; 84 u32 m_dwSizeGetRing;
85 u32 *m_pdwSetWritePos; 85 u32 m_dwSetWritePos;
86 u32 *m_pdwSetReadPos; 86 u32 m_dwSetReadPos;
87 u32 *m_pdwGetWritePos; 87 u32 m_dwGetWritePos;
88 u32 *m_pdwGetReadPos; 88 u32 m_dwGetReadPos;
89 89
90 /* All access is protected */ 90 /* All access is protected */
91 struct mutex lock; 91 struct mutex lock;
92 92
93} tmComResBusInfo_t; 93};
94 94
95typedef struct { 95struct tmComResInfo {
96 u8 id; 96 u8 id;
97 u8 flags; 97 u8 flags;
98 u16 size; 98 u16 size;
99 u32 command; 99 u32 command;
100 u16 controlselector; 100 u16 controlselector;
101 u8 seqno; 101 u8 seqno;
102} __attribute__((packed)) tmComResInfo_t; 102} __attribute__((packed));
103 103
104typedef enum { 104enum tmComResCmd {
105 SET_CUR = 0x01, 105 SET_CUR = 0x01,
106 GET_CUR = 0x81, 106 GET_CUR = 0x81,
107 GET_MIN = 0x82, 107 GET_MIN = 0x82,
@@ -110,7 +110,7 @@ typedef enum {
110 GET_LEN = 0x85, 110 GET_LEN = 0x85,
111 GET_INFO = 0x86, 111 GET_INFO = 0x86,
112 GET_DEF = 0x87 112 GET_DEF = 0x87
113} tmComResCmd_t; 113};
114 114
115struct cmd { 115struct cmd {
116 u8 seqno; 116 u8 seqno;
@@ -121,20 +121,20 @@ struct cmd {
121 wait_queue_head_t wait; 121 wait_queue_head_t wait;
122}; 122};
123 123
124typedef struct { 124struct tmDescriptor {
125 u32 pathid; 125 u32 pathid;
126 u32 size; 126 u32 size;
127 void *descriptor; 127 void *descriptor;
128} tmDescriptor_t; 128};
129 129
130typedef struct { 130struct tmComResDescrHeader {
131 u8 len; 131 u8 len;
132 u8 type; 132 u8 type;
133 u8 subtype; 133 u8 subtype;
134 u8 unitid; 134 u8 unitid;
135} __attribute__((packed)) tmComResDescrHeader_t; 135} __attribute__((packed));
136 136
137typedef struct { 137struct tmComResExtDevDescrHeader {
138 u8 len; 138 u8 len;
139 u8 type; 139 u8 type;
140 u8 subtype; 140 u8 subtype;
@@ -144,22 +144,22 @@ typedef struct {
144 u32 numgpiopins; 144 u32 numgpiopins;
145 u8 numgpiogroups; 145 u8 numgpiogroups;
146 u8 controlsize; 146 u8 controlsize;
147} __attribute__((packed)) tmComResExtDevDescrHeader_t; 147} __attribute__((packed));
148 148
149typedef struct { 149struct tmComResGPIO {
150 u32 pin; 150 u32 pin;
151 u8 state; 151 u8 state;
152} __attribute__((packed)) tmComResGPIO_t; 152} __attribute__((packed));
153 153
154typedef struct { 154struct tmComResPathDescrHeader {
155 u8 len; 155 u8 len;
156 u8 type; 156 u8 type;
157 u8 subtype; 157 u8 subtype;
158 u8 pathid; 158 u8 pathid;
159} __attribute__((packed)) tmComResPathDescrHeader_t; 159} __attribute__((packed));
160 160
161/* terminaltype */ 161/* terminaltype */
162typedef enum { 162enum tmComResTermType {
163 ITT_ANTENNA = 0x0203, 163 ITT_ANTENNA = 0x0203,
164 LINE_CONNECTOR = 0x0603, 164 LINE_CONNECTOR = 0x0603,
165 SPDIF_CONNECTOR = 0x0605, 165 SPDIF_CONNECTOR = 0x0605,
@@ -167,9 +167,9 @@ typedef enum {
167 SVIDEO_CONNECTOR = 0x0402, 167 SVIDEO_CONNECTOR = 0x0402,
168 COMPONENT_CONNECTOR = 0x0403, 168 COMPONENT_CONNECTOR = 0x0403,
169 STANDARD_DMA = 0xF101 169 STANDARD_DMA = 0xF101
170} tmComResTermType_t; 170};
171 171
172typedef struct { 172struct tmComResAntTermDescrHeader {
173 u8 len; 173 u8 len;
174 u8 type; 174 u8 type;
175 u8 subtype; 175 u8 subtype;
@@ -178,9 +178,9 @@ typedef struct {
178 u8 assocterminal; 178 u8 assocterminal;
179 u8 iterminal; 179 u8 iterminal;
180 u8 controlsize; 180 u8 controlsize;
181} __attribute__((packed)) tmComResAntTermDescrHeader_t; 181} __attribute__((packed));
182 182
183typedef struct { 183struct tmComResTunerDescrHeader {
184 u8 len; 184 u8 len;
185 u8 type; 185 u8 type;
186 u8 subtype; 186 u8 subtype;
@@ -190,9 +190,9 @@ typedef struct {
190 u32 tuningstandards; 190 u32 tuningstandards;
191 u8 controlsize; 191 u8 controlsize;
192 u32 controls; 192 u32 controls;
193} __attribute__((packed)) tmComResTunerDescrHeader_t; 193} __attribute__((packed));
194 194
195typedef enum { 195enum tmBufferFlag {
196 /* the buffer does not contain any valid data */ 196 /* the buffer does not contain any valid data */
197 TM_BUFFER_FLAG_EMPTY, 197 TM_BUFFER_FLAG_EMPTY,
198 198
@@ -201,23 +201,23 @@ typedef enum {
201 201
202 /* the buffer is the dummy buffer - TODO??? */ 202 /* the buffer is the dummy buffer - TODO??? */
203 TM_BUFFER_FLAG_DUMMY_BUFFER 203 TM_BUFFER_FLAG_DUMMY_BUFFER
204} tmBufferFlag_t; 204};
205 205
206typedef struct { 206struct tmBuffer {
207 u64 *pagetablevirt; 207 u64 *pagetablevirt;
208 u64 pagetablephys; 208 u64 pagetablephys;
209 u16 offset; 209 u16 offset;
210 u8 *context; 210 u8 *context;
211 u64 timestamp; 211 u64 timestamp;
212 tmBufferFlag_t BufferFlag_t; 212 enum tmBufferFlag BufferFlag;
213 u32 lostbuffers; 213 u32 lostbuffers;
214 u32 validbuffers; 214 u32 validbuffers;
215 u64 *dummypagevirt; 215 u64 *dummypagevirt;
216 u64 dummypagephys; 216 u64 dummypagephys;
217 u64 *addressvirt; 217 u64 *addressvirt;
218} tmBuffer_t; 218};
219 219
220typedef struct { 220struct tmHWStreamParameters {
221 u32 bitspersample; 221 u32 bitspersample;
222 u32 samplesperline; 222 u32 samplesperline;
223 u32 numberoflines; 223 u32 numberoflines;
@@ -227,15 +227,15 @@ typedef struct {
227 u64 *pagetablelistphys; 227 u64 *pagetablelistphys;
228 u32 numpagetables; 228 u32 numpagetables;
229 u32 numpagetableentries; 229 u32 numpagetableentries;
230} tmHWStreamParameters_t; 230};
231 231
232typedef struct { 232struct tmStreamParameters {
233 tmHWStreamParameters_t HWStreamParameters_t; 233 struct tmHWStreamParameters HWStreamParameters;
234 u64 qwDummyPageTablePhys; 234 u64 qwDummyPageTablePhys;
235 u64 *pDummyPageTableVirt; 235 u64 *pDummyPageTableVirt;
236} tmStreamParameters_t; 236};
237 237
238typedef struct { 238struct tmComResDMATermDescrHeader {
239 u8 len; 239 u8 len;
240 u8 type; 240 u8 type;
241 u8 subtyle; 241 u8 subtyle;
@@ -251,7 +251,7 @@ typedef struct {
251 u8 metadatasize; 251 u8 metadatasize;
252 u8 numformats; 252 u8 numformats;
253 u8 controlsize; 253 u8 controlsize;
254} __attribute__((packed)) tmComResDMATermDescrHeader_t; 254} __attribute__((packed));
255 255
256/* 256/*
257 * 257 *
@@ -274,7 +274,7 @@ typedef struct {
274 * Data is to be ignored by the application. 274 * Data is to be ignored by the application.
275 * 275 *
276 */ 276 */
277typedef struct { 277struct tmComResTSFormatDescrHeader {
278 u8 len; 278 u8 len;
279 u8 type; 279 u8 type;
280 u8 subtype; 280 u8 subtype;
@@ -283,5 +283,160 @@ typedef struct {
283 u8 bPacketLength; 283 u8 bPacketLength;
284 u8 bStrideLength; 284 u8 bStrideLength;
285 u8 guidStrideFormat[16]; 285 u8 guidStrideFormat[16];
286} __attribute__((packed)) tmComResTSFormatDescrHeader_t; 286} __attribute__((packed));
287
288/* Encoder related structures */
289
290/* A/V Mux Selector */
291struct tmComResSelDescrHeader {
292 u8 len;
293 u8 type;
294 u8 subtype;
295 u8 unitid;
296 u8 nrinpins;
297 u8 sourceid;
298} __attribute__((packed));
299
300/* A/V Audio processor definitions */
301struct tmComResProcDescrHeader {
302 u8 len;
303 u8 type;
304 u8 subtype;
305 u8 unitid;
306 u8 sourceid;
307 u16 wreserved;
308 u8 controlsize;
309} __attribute__((packed));
310
311/* Video bitrate control message */
312#define EU_VIDEO_BIT_RATE_MODE_CONSTANT (0)
313#define EU_VIDEO_BIT_RATE_MODE_VARIABLE_AVERAGE (1)
314#define EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK (2)
315struct tmComResEncVideoBitRate {
316 u8 ucVideoBitRateMode;
317 u32 dwVideoBitRate;
318 u32 dwVideoBitRatePeak;
319} __attribute__((packed));
320
321/* Video Encoder Aspect Ratio message */
322struct tmComResEncVideoInputAspectRatio {
323 u8 width;
324 u8 height;
325} __attribute__((packed));
326
327/* Video Encoder GOP IBP message */
328/* 1. IPPPPPPPPPPPPPP */
329/* 2. IBPBPBPBPBPBPBP */
330/* 3. IBBPBBPBBPBBP */
331#define SAA7164_ENCODER_DEFAULT_GOP_DIST (1)
332#define SAA7164_ENCODER_DEFAULT_GOP_SIZE (15)
333struct tmComResEncVideoGopStructure {
334 u8 ucGOPSize; /* GOP Size 12, 15 */
335 u8 ucRefFrameDist; /* Reference Frame Distance */
336} __attribute__((packed));
337
338/* Encoder processor definition */
339struct tmComResEncoderDescrHeader {
340 u8 len;
341 u8 type;
342 u8 subtype;
343 u8 unitid;
344 u8 vsourceid;
345 u8 asourceid;
346 u8 iunit;
347 u32 dwmControlCap;
348 u32 dwmProfileCap;
349 u32 dwmVidFormatCap;
350 u8 bmVidBitrateCap;
351 u16 wmVidResolutionsCap;
352 u16 wmVidFrmRateCap;
353 u32 dwmAudFormatCap;
354 u8 bmAudBitrateCap;
355} __attribute__((packed));
356
357/* Audio processor definition */
358struct tmComResAFeatureDescrHeader {
359 u8 len;
360 u8 type;
361 u8 subtype;
362 u8 unitid;
363 u8 sourceid;
364 u8 controlsize;
365} __attribute__((packed));
366
367/* Audio control messages */
368struct tmComResAudioDefaults {
369 u8 ucDecoderLevel;
370 u8 ucDecoderFM_Level;
371 u8 ucMonoLevel;
372 u8 ucNICAM_Level;
373 u8 ucSAP_Level;
374 u8 ucADC_Level;
375} __attribute__((packed));
376
377/* Audio bitrate control message */
378struct tmComResEncAudioBitRate {
379 u8 ucAudioBitRateMode;
380 u32 dwAudioBitRate;
381 u32 dwAudioBitRatePeak;
382} __attribute__((packed));
383
384/* Tuner / AV Decoder messages */
385struct tmComResTunerStandard {
386 u8 std;
387 u32 country;
388} __attribute__((packed));
389
390struct tmComResTunerStandardAuto {
391 u8 mode;
392} __attribute__((packed));
393
394/* EEPROM definition for PS stream types */
395struct tmComResPSFormatDescrHeader {
396 u8 len;
397 u8 type;
398 u8 subtype;
399 u8 bFormatIndex;
400 u16 wPacketLength;
401 u16 wPackLength;
402 u8 bPackDataType;
403} __attribute__((packed));
404
405/* VBI control structure */
406struct tmComResVBIFormatDescrHeader {
407 u8 len;
408 u8 type;
409 u8 subtype; /* VS_FORMAT_VBI */
410 u8 bFormatIndex;
411 u32 VideoStandard; /* See KS_AnalogVideoStandard, NTSC = 1 */
412 u8 StartLine; /* NTSC Start = 10 */
413 u8 EndLine; /* NTSC = 21 */
414 u8 FieldRate; /* 60 for NTSC */
415 u8 bNumLines; /* Unsed - scheduled for removal */
416} __attribute__((packed));
417
418struct tmComResProbeCommit {
419 u16 bmHint;
420 u8 bFormatIndex;
421 u8 bFrameIndex;
422} __attribute__((packed));
423
424struct tmComResDebugSetLevel {
425 u32 dwDebugLevel;
426} __attribute__((packed));
427
428struct tmComResDebugGetData {
429 u32 dwResult;
430 u8 ucDebugData[256];
431} __attribute__((packed));
287 432
433struct tmFwInfoStruct {
434 u32 status;
435 u32 mode;
436 u32 devicespec;
437 u32 deviceinst;
438 u32 CPULoad;
439 u32 RemainHeap;
440 u32 CPUClock;
441 u32 RAMSpeed;
442} __attribute__((packed));
diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/video/saa7164/saa7164-vbi.c
new file mode 100644
index 000000000000..323c7cdca37b
--- /dev/null
+++ b/drivers/media/video/saa7164/saa7164-vbi.c
@@ -0,0 +1,1375 @@
1/*
2 * Driver for the NXP SAA7164 PCIe bridge
3 *
4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
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 "saa7164.h"
23
24static struct saa7164_tvnorm saa7164_tvnorms[] = {
25 {
26 .name = "NTSC-M",
27 .id = V4L2_STD_NTSC_M,
28 }, {
29 .name = "NTSC-JP",
30 .id = V4L2_STD_NTSC_M_JP,
31 }
32};
33
34static const u32 saa7164_v4l2_ctrls[] = {
35 0
36};
37
38/* Take the encoder configuration from the port struct and
39 * flush it to the hardware.
40 */
41static void saa7164_vbi_configure(struct saa7164_port *port)
42{
43 struct saa7164_dev *dev = port->dev;
44 dprintk(DBGLVL_VBI, "%s()\n", __func__);
45
46 port->vbi_params.width = port->width;
47 port->vbi_params.height = port->height;
48 port->vbi_params.is_50hz =
49 (port->encodernorm.id & V4L2_STD_625_50) != 0;
50
51 /* Set up the DIF (enable it) for analog mode by default */
52 saa7164_api_initialize_dif(port);
53
54// /* Configure the correct video standard */
55// saa7164_api_configure_dif(port, port->encodernorm.id);
56
57// /* Ensure the audio decoder is correct configured */
58// saa7164_api_set_audio_std(port);
59 dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
60}
61
62static int saa7164_vbi_buffers_dealloc(struct saa7164_port *port)
63{
64 struct list_head *c, *n, *p, *q, *l, *v;
65 struct saa7164_dev *dev = port->dev;
66 struct saa7164_buffer *buf;
67 struct saa7164_user_buffer *ubuf;
68
69 /* Remove any allocated buffers */
70 mutex_lock(&port->dmaqueue_lock);
71
72 dprintk(DBGLVL_VBI, "%s(port=%d) dmaqueue\n", __func__, port->nr);
73 list_for_each_safe(c, n, &port->dmaqueue.list) {
74 buf = list_entry(c, struct saa7164_buffer, list);
75 list_del(c);
76 saa7164_buffer_dealloc(buf);
77 }
78
79 dprintk(DBGLVL_VBI, "%s(port=%d) used\n", __func__, port->nr);
80 list_for_each_safe(p, q, &port->list_buf_used.list) {
81 ubuf = list_entry(p, struct saa7164_user_buffer, list);
82 list_del(p);
83 saa7164_buffer_dealloc_user(ubuf);
84 }
85
86 dprintk(DBGLVL_VBI, "%s(port=%d) free\n", __func__, port->nr);
87 list_for_each_safe(l, v, &port->list_buf_free.list) {
88 ubuf = list_entry(l, struct saa7164_user_buffer, list);
89 list_del(l);
90 saa7164_buffer_dealloc_user(ubuf);
91 }
92
93 mutex_unlock(&port->dmaqueue_lock);
94 dprintk(DBGLVL_VBI, "%s(port=%d) done\n", __func__, port->nr);
95
96 return 0;
97}
98
99/* Dynamic buffer switch at vbi start time */
100static int saa7164_vbi_buffers_alloc(struct saa7164_port *port)
101{
102 struct saa7164_dev *dev = port->dev;
103 struct saa7164_buffer *buf;
104 struct saa7164_user_buffer *ubuf;
105 struct tmHWStreamParameters *params = &port->hw_streamingparams;
106 int result = -ENODEV, i;
107 int len = 0;
108
109 dprintk(DBGLVL_VBI, "%s()\n", __func__);
110
111 /* TODO: NTSC SPECIFIC */
112 /* Init and establish defaults */
113 params->samplesperline = 1440;
114 params->numberoflines = 12;
115 params->numberoflines = 18;
116 params->pitch = 1600;
117 params->pitch = 1440;
118 params->numpagetables = 2 +
119 ((params->numberoflines * params->pitch) / PAGE_SIZE);
120 params->bitspersample = 8;
121 params->linethreshold = 0;
122 params->pagetablelistvirt = 0;
123 params->pagetablelistphys = 0;
124 params->numpagetableentries = port->hwcfg.buffercount;
125
126 /* Allocate the PCI resources, buffers (hard) */
127 for (i = 0; i < port->hwcfg.buffercount; i++) {
128 buf = saa7164_buffer_alloc(port,
129 params->numberoflines *
130 params->pitch);
131
132 if (!buf) {
133 printk(KERN_ERR "%s() failed "
134 "(errno = %d), unable to allocate buffer\n",
135 __func__, result);
136 result = -ENOMEM;
137 goto failed;
138 } else {
139
140 mutex_lock(&port->dmaqueue_lock);
141 list_add_tail(&buf->list, &port->dmaqueue.list);
142 mutex_unlock(&port->dmaqueue_lock);
143
144 }
145 }
146
147 /* Allocate some kenrel kernel buffers for copying
148 * to userpsace.
149 */
150 len = params->numberoflines * params->pitch;
151
152 if (vbi_buffers < 16)
153 vbi_buffers = 16;
154 if (vbi_buffers > 512)
155 vbi_buffers = 512;
156
157 for (i = 0; i < vbi_buffers; i++) {
158
159 ubuf = saa7164_buffer_alloc_user(dev, len);
160 if (ubuf) {
161 mutex_lock(&port->dmaqueue_lock);
162 list_add_tail(&ubuf->list, &port->list_buf_free.list);
163 mutex_unlock(&port->dmaqueue_lock);
164 }
165
166 }
167
168 result = 0;
169
170failed:
171 return result;
172}
173
174
175static int saa7164_vbi_initialize(struct saa7164_port *port)
176{
177 saa7164_vbi_configure(port);
178 return 0;
179}
180
181/* -- V4L2 --------------------------------------------------------- */
182static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
183{
184 struct saa7164_vbi_fh *fh = file->private_data;
185 struct saa7164_port *port = fh->port;
186 struct saa7164_dev *dev = port->dev;
187 unsigned int i;
188
189 dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)*id);
190
191 for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
192 if (*id & saa7164_tvnorms[i].id)
193 break;
194 }
195 if (i == ARRAY_SIZE(saa7164_tvnorms))
196 return -EINVAL;
197
198 port->encodernorm = saa7164_tvnorms[i];
199
200 /* Update the audio decoder while is not running in
201 * auto detect mode.
202 */
203 saa7164_api_set_audio_std(port);
204
205 dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)*id);
206
207 return 0;
208}
209
210static int vidioc_enum_input(struct file *file, void *priv,
211 struct v4l2_input *i)
212{
213 int n;
214
215 char *inputs[] = { "tuner", "composite", "svideo", "aux",
216 "composite 2", "svideo 2", "aux 2" };
217
218 if (i->index >= 7)
219 return -EINVAL;
220
221 strcpy(i->name, inputs[i->index]);
222
223 if (i->index == 0)
224 i->type = V4L2_INPUT_TYPE_TUNER;
225 else
226 i->type = V4L2_INPUT_TYPE_CAMERA;
227
228 for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
229 i->std |= saa7164_tvnorms[n].id;
230
231 return 0;
232}
233
234static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
235{
236 struct saa7164_vbi_fh *fh = file->private_data;
237 struct saa7164_port *port = fh->port;
238 struct saa7164_dev *dev = port->dev;
239
240 if (saa7164_api_get_videomux(port) != SAA_OK)
241 return -EIO;
242
243 *i = (port->mux_input - 1);
244
245 dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, *i);
246
247 return 0;
248}
249
250static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
251{
252 struct saa7164_vbi_fh *fh = file->private_data;
253 struct saa7164_port *port = fh->port;
254 struct saa7164_dev *dev = port->dev;
255
256 dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, i);
257
258 if (i >= 7)
259 return -EINVAL;
260
261 port->mux_input = i + 1;
262
263 if (saa7164_api_set_videomux(port) != SAA_OK)
264 return -EIO;
265
266 return 0;
267}
268
269static int vidioc_g_tuner(struct file *file, void *priv,
270 struct v4l2_tuner *t)
271{
272 struct saa7164_vbi_fh *fh = file->private_data;
273 struct saa7164_port *port = fh->port;
274 struct saa7164_dev *dev = port->dev;
275
276 if (0 != t->index)
277 return -EINVAL;
278
279 strcpy(t->name, "tuner");
280 t->type = V4L2_TUNER_ANALOG_TV;
281 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
282
283 dprintk(DBGLVL_VBI, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
284
285 return 0;
286}
287
288static int vidioc_s_tuner(struct file *file, void *priv,
289 struct v4l2_tuner *t)
290{
291 /* Update the A/V core */
292 return 0;
293}
294
295static int vidioc_g_frequency(struct file *file, void *priv,
296 struct v4l2_frequency *f)
297{
298 struct saa7164_vbi_fh *fh = file->private_data;
299 struct saa7164_port *port = fh->port;
300
301 f->type = V4L2_TUNER_ANALOG_TV;
302 f->frequency = port->freq;
303
304 return 0;
305}
306
307static int vidioc_s_frequency(struct file *file, void *priv,
308 struct v4l2_frequency *f)
309{
310 struct saa7164_vbi_fh *fh = file->private_data;
311 struct saa7164_port *port = fh->port;
312 struct saa7164_dev *dev = port->dev;
313 struct saa7164_port *tsport;
314 struct dvb_frontend *fe;
315
316 /* TODO: Pull this for the std */
317 struct analog_parameters params = {
318 .mode = V4L2_TUNER_ANALOG_TV,
319 .audmode = V4L2_TUNER_MODE_STEREO,
320 .std = port->encodernorm.id,
321 .frequency = f->frequency
322 };
323
324 /* Stop the encoder */
325 dprintk(DBGLVL_VBI, "%s() frequency=%d tuner=%d\n", __func__,
326 f->frequency, f->tuner);
327
328 if (f->tuner != 0)
329 return -EINVAL;
330
331 if (f->type != V4L2_TUNER_ANALOG_TV)
332 return -EINVAL;
333
334 port->freq = f->frequency;
335
336 /* Update the hardware */
337 if (port->nr == SAA7164_PORT_VBI1)
338 tsport = &dev->ports[SAA7164_PORT_TS1];
339 else
340 if (port->nr == SAA7164_PORT_VBI2)
341 tsport = &dev->ports[SAA7164_PORT_TS2];
342 else
343 BUG();
344
345 fe = tsport->dvb.frontend;
346
347 if (fe && fe->ops.tuner_ops.set_analog_params)
348 fe->ops.tuner_ops.set_analog_params(fe, &params);
349 else
350 printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
351
352 saa7164_vbi_initialize(port);
353
354 return 0;
355}
356
357static int vidioc_g_ctrl(struct file *file, void *priv,
358 struct v4l2_control *ctl)
359{
360 struct saa7164_vbi_fh *fh = file->private_data;
361 struct saa7164_port *port = fh->port;
362 struct saa7164_dev *dev = port->dev;
363
364 dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
365 ctl->id, ctl->value);
366
367 switch (ctl->id) {
368 case V4L2_CID_BRIGHTNESS:
369 ctl->value = port->ctl_brightness;
370 break;
371 case V4L2_CID_CONTRAST:
372 ctl->value = port->ctl_contrast;
373 break;
374 case V4L2_CID_SATURATION:
375 ctl->value = port->ctl_saturation;
376 break;
377 case V4L2_CID_HUE:
378 ctl->value = port->ctl_hue;
379 break;
380 case V4L2_CID_SHARPNESS:
381 ctl->value = port->ctl_sharpness;
382 break;
383 case V4L2_CID_AUDIO_VOLUME:
384 ctl->value = port->ctl_volume;
385 break;
386 default:
387 return -EINVAL;
388 }
389
390 return 0;
391}
392
393static int vidioc_s_ctrl(struct file *file, void *priv,
394 struct v4l2_control *ctl)
395{
396 struct saa7164_vbi_fh *fh = file->private_data;
397 struct saa7164_port *port = fh->port;
398 struct saa7164_dev *dev = port->dev;
399 int ret = 0;
400
401 dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
402 ctl->id, ctl->value);
403
404 switch (ctl->id) {
405 case V4L2_CID_BRIGHTNESS:
406 if ((ctl->value >= 0) && (ctl->value <= 255)) {
407 port->ctl_brightness = ctl->value;
408 saa7164_api_set_usercontrol(port,
409 PU_BRIGHTNESS_CONTROL);
410 } else
411 ret = -EINVAL;
412 break;
413 case V4L2_CID_CONTRAST:
414 if ((ctl->value >= 0) && (ctl->value <= 255)) {
415 port->ctl_contrast = ctl->value;
416 saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
417 } else
418 ret = -EINVAL;
419 break;
420 case V4L2_CID_SATURATION:
421 if ((ctl->value >= 0) && (ctl->value <= 255)) {
422 port->ctl_saturation = ctl->value;
423 saa7164_api_set_usercontrol(port,
424 PU_SATURATION_CONTROL);
425 } else
426 ret = -EINVAL;
427 break;
428 case V4L2_CID_HUE:
429 if ((ctl->value >= 0) && (ctl->value <= 255)) {
430 port->ctl_hue = ctl->value;
431 saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
432 } else
433 ret = -EINVAL;
434 break;
435 case V4L2_CID_SHARPNESS:
436 if ((ctl->value >= 0) && (ctl->value <= 255)) {
437 port->ctl_sharpness = ctl->value;
438 saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
439 } else
440 ret = -EINVAL;
441 break;
442 case V4L2_CID_AUDIO_VOLUME:
443 if ((ctl->value >= -83) && (ctl->value <= 24)) {
444 port->ctl_volume = ctl->value;
445 saa7164_api_set_audio_volume(port, port->ctl_volume);
446 } else
447 ret = -EINVAL;
448 break;
449 default:
450 ret = -EINVAL;
451 }
452
453 return ret;
454}
455
456static int saa7164_get_ctrl(struct saa7164_port *port,
457 struct v4l2_ext_control *ctrl)
458{
459 struct saa7164_vbi_params *params = &port->vbi_params;
460
461 switch (ctrl->id) {
462 case V4L2_CID_MPEG_STREAM_TYPE:
463 ctrl->value = params->stream_type;
464 break;
465 case V4L2_CID_MPEG_AUDIO_MUTE:
466 ctrl->value = params->ctl_mute;
467 break;
468 case V4L2_CID_MPEG_VIDEO_ASPECT:
469 ctrl->value = params->ctl_aspect;
470 break;
471 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
472 ctrl->value = params->refdist;
473 break;
474 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
475 ctrl->value = params->gop_size;
476 break;
477 default:
478 return -EINVAL;
479 }
480 return 0;
481}
482
483static int vidioc_g_ext_ctrls(struct file *file, void *priv,
484 struct v4l2_ext_controls *ctrls)
485{
486 struct saa7164_vbi_fh *fh = file->private_data;
487 struct saa7164_port *port = fh->port;
488 int i, err = 0;
489
490 if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
491 for (i = 0; i < ctrls->count; i++) {
492 struct v4l2_ext_control *ctrl = ctrls->controls + i;
493
494 err = saa7164_get_ctrl(port, ctrl);
495 if (err) {
496 ctrls->error_idx = i;
497 break;
498 }
499 }
500 return err;
501
502 }
503
504 return -EINVAL;
505}
506
507static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
508{
509 int ret = -EINVAL;
510
511 switch (ctrl->id) {
512 case V4L2_CID_MPEG_STREAM_TYPE:
513 if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
514 (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
515 ret = 0;
516 break;
517 case V4L2_CID_MPEG_AUDIO_MUTE:
518 if ((ctrl->value >= 0) &&
519 (ctrl->value <= 1))
520 ret = 0;
521 break;
522 case V4L2_CID_MPEG_VIDEO_ASPECT:
523 if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
524 (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
525 ret = 0;
526 break;
527 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
528 if ((ctrl->value >= 0) &&
529 (ctrl->value <= 255))
530 ret = 0;
531 break;
532 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
533 if ((ctrl->value >= 1) &&
534 (ctrl->value <= 3))
535 ret = 0;
536 break;
537 default:
538 ret = -EINVAL;
539 }
540
541 return ret;
542}
543
544static int vidioc_try_ext_ctrls(struct file *file, void *priv,
545 struct v4l2_ext_controls *ctrls)
546{
547 int i, err = 0;
548
549 if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
550 for (i = 0; i < ctrls->count; i++) {
551 struct v4l2_ext_control *ctrl = ctrls->controls + i;
552
553 err = saa7164_try_ctrl(ctrl, 0);
554 if (err) {
555 ctrls->error_idx = i;
556 break;
557 }
558 }
559 return err;
560 }
561
562 return -EINVAL;
563}
564
565static int saa7164_set_ctrl(struct saa7164_port *port,
566 struct v4l2_ext_control *ctrl)
567{
568 struct saa7164_vbi_params *params = &port->vbi_params;
569 int ret = 0;
570
571 switch (ctrl->id) {
572 case V4L2_CID_MPEG_STREAM_TYPE:
573 params->stream_type = ctrl->value;
574 break;
575 case V4L2_CID_MPEG_AUDIO_MUTE:
576 params->ctl_mute = ctrl->value;
577 ret = saa7164_api_audio_mute(port, params->ctl_mute);
578 if (ret != SAA_OK) {
579 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
580 ret);
581 ret = -EIO;
582 }
583 break;
584 case V4L2_CID_MPEG_VIDEO_ASPECT:
585 params->ctl_aspect = ctrl->value;
586 ret = saa7164_api_set_aspect_ratio(port);
587 if (ret != SAA_OK) {
588 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
589 ret);
590 ret = -EIO;
591 }
592 break;
593 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
594 params->refdist = ctrl->value;
595 break;
596 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
597 params->gop_size = ctrl->value;
598 break;
599 default:
600 return -EINVAL;
601 }
602
603 /* TODO: Update the hardware */
604
605 return ret;
606}
607
608static int vidioc_s_ext_ctrls(struct file *file, void *priv,
609 struct v4l2_ext_controls *ctrls)
610{
611 struct saa7164_vbi_fh *fh = file->private_data;
612 struct saa7164_port *port = fh->port;
613 int i, err = 0;
614
615 if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
616 for (i = 0; i < ctrls->count; i++) {
617 struct v4l2_ext_control *ctrl = ctrls->controls + i;
618
619 err = saa7164_try_ctrl(ctrl, 0);
620 if (err) {
621 ctrls->error_idx = i;
622 break;
623 }
624 err = saa7164_set_ctrl(port, ctrl);
625 if (err) {
626 ctrls->error_idx = i;
627 break;
628 }
629 }
630 return err;
631
632 }
633
634 return -EINVAL;
635}
636
637static int vidioc_querycap(struct file *file, void *priv,
638 struct v4l2_capability *cap)
639{
640 struct saa7164_vbi_fh *fh = file->private_data;
641 struct saa7164_port *port = fh->port;
642 struct saa7164_dev *dev = port->dev;
643
644 strcpy(cap->driver, dev->name);
645 strlcpy(cap->card, saa7164_boards[dev->board].name,
646 sizeof(cap->card));
647 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
648
649 cap->capabilities =
650 V4L2_CAP_VBI_CAPTURE |
651 V4L2_CAP_READWRITE |
652 0;
653
654 cap->capabilities |= V4L2_CAP_TUNER;
655 cap->version = 0;
656
657 return 0;
658}
659
660static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
661 struct v4l2_fmtdesc *f)
662{
663 if (f->index != 0)
664 return -EINVAL;
665
666 strlcpy(f->description, "VBI", sizeof(f->description));
667 f->pixelformat = V4L2_PIX_FMT_MPEG;
668
669 return 0;
670}
671
672static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
673 struct v4l2_format *f)
674{
675 struct saa7164_vbi_fh *fh = file->private_data;
676 struct saa7164_port *port = fh->port;
677 struct saa7164_dev *dev = port->dev;
678
679 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
680 f->fmt.pix.bytesperline = 0;
681 f->fmt.pix.sizeimage =
682 port->ts_packet_size * port->ts_packet_count;
683 f->fmt.pix.colorspace = 0;
684 f->fmt.pix.width = port->width;
685 f->fmt.pix.height = port->height;
686
687 dprintk(DBGLVL_VBI, "VIDIOC_G_FMT: w: %d, h: %d\n",
688 port->width, port->height);
689
690 return 0;
691}
692
693static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
694 struct v4l2_format *f)
695{
696 struct saa7164_vbi_fh *fh = file->private_data;
697 struct saa7164_port *port = fh->port;
698 struct saa7164_dev *dev = port->dev;
699
700 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
701 f->fmt.pix.bytesperline = 0;
702 f->fmt.pix.sizeimage =
703 port->ts_packet_size * port->ts_packet_count;
704 f->fmt.pix.colorspace = 0;
705 dprintk(DBGLVL_VBI, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
706 port->width, port->height);
707 return 0;
708}
709
710static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
711 struct v4l2_format *f)
712{
713 struct saa7164_vbi_fh *fh = file->private_data;
714 struct saa7164_port *port = fh->port;
715 struct saa7164_dev *dev = port->dev;
716
717 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
718 f->fmt.pix.bytesperline = 0;
719 f->fmt.pix.sizeimage =
720 port->ts_packet_size * port->ts_packet_count;
721 f->fmt.pix.colorspace = 0;
722
723 dprintk(DBGLVL_VBI, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
724 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
725
726 return 0;
727}
728
729static int vidioc_log_status(struct file *file, void *priv)
730{
731 return 0;
732}
733
734static int fill_queryctrl(struct saa7164_vbi_params *params,
735 struct v4l2_queryctrl *c)
736{
737 switch (c->id) {
738 case V4L2_CID_BRIGHTNESS:
739 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
740 case V4L2_CID_CONTRAST:
741 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
742 case V4L2_CID_SATURATION:
743 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
744 case V4L2_CID_HUE:
745 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
746 case V4L2_CID_SHARPNESS:
747 return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
748 case V4L2_CID_MPEG_AUDIO_MUTE:
749 return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
750 case V4L2_CID_AUDIO_VOLUME:
751 return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
752 case V4L2_CID_MPEG_STREAM_TYPE:
753 return v4l2_ctrl_query_fill(c,
754 V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
755 V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
756 1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
757 case V4L2_CID_MPEG_VIDEO_ASPECT:
758 return v4l2_ctrl_query_fill(c,
759 V4L2_MPEG_VIDEO_ASPECT_1x1,
760 V4L2_MPEG_VIDEO_ASPECT_221x100,
761 1, V4L2_MPEG_VIDEO_ASPECT_4x3);
762 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
763 return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
764 case V4L2_CID_MPEG_VIDEO_B_FRAMES:
765 return v4l2_ctrl_query_fill(c,
766 1, 3, 1, 1);
767 default:
768 return -EINVAL;
769 }
770}
771
772static int vidioc_queryctrl(struct file *file, void *priv,
773 struct v4l2_queryctrl *c)
774{
775 struct saa7164_vbi_fh *fh = priv;
776 struct saa7164_port *port = fh->port;
777 int i, next;
778 u32 id = c->id;
779
780 memset(c, 0, sizeof(*c));
781
782 next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
783 c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
784
785 for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
786 if (next) {
787 if (c->id < saa7164_v4l2_ctrls[i])
788 c->id = saa7164_v4l2_ctrls[i];
789 else
790 continue;
791 }
792
793 if (c->id == saa7164_v4l2_ctrls[i])
794 return fill_queryctrl(&port->vbi_params, c);
795
796 if (c->id < saa7164_v4l2_ctrls[i])
797 break;
798 }
799
800 return -EINVAL;
801}
802
803static int saa7164_vbi_stop_port(struct saa7164_port *port)
804{
805 struct saa7164_dev *dev = port->dev;
806 int ret;
807
808 ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
809 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
810 printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
811 __func__, ret);
812 ret = -EIO;
813 } else {
814 dprintk(DBGLVL_VBI, "%s() Stopped\n", __func__);
815 ret = 0;
816 }
817
818 return ret;
819}
820
821static int saa7164_vbi_acquire_port(struct saa7164_port *port)
822{
823 struct saa7164_dev *dev = port->dev;
824 int ret;
825
826 ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
827 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
828 printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
829 __func__, ret);
830 ret = -EIO;
831 } else {
832 dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
833 ret = 0;
834 }
835
836 return ret;
837}
838
839static int saa7164_vbi_pause_port(struct saa7164_port *port)
840{
841 struct saa7164_dev *dev = port->dev;
842 int ret;
843
844 ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
845 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
846 printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
847 __func__, ret);
848 ret = -EIO;
849 } else {
850 dprintk(DBGLVL_VBI, "%s() Paused\n", __func__);
851 ret = 0;
852 }
853
854 return ret;
855}
856
857/* Firmware is very windows centric, meaning you have to transition
858 * the part through AVStream / KS Windows stages, forwards or backwards.
859 * States are: stopped, acquired (h/w), paused, started.
860 * We have to leave here will all of the soft buffers on the free list,
861 * else the cfg_post() func won't have soft buffers to correctly configure.
862 */
863static int saa7164_vbi_stop_streaming(struct saa7164_port *port)
864{
865 struct saa7164_dev *dev = port->dev;
866 struct saa7164_buffer *buf;
867 struct saa7164_user_buffer *ubuf;
868 struct list_head *c, *n;
869 int ret;
870
871 dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
872
873 ret = saa7164_vbi_pause_port(port);
874 ret = saa7164_vbi_acquire_port(port);
875 ret = saa7164_vbi_stop_port(port);
876
877 dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__,
878 port->nr);
879
880 /* Reset the state of any allocated buffer resources */
881 mutex_lock(&port->dmaqueue_lock);
882
883 /* Reset the hard and soft buffer state */
884 list_for_each_safe(c, n, &port->dmaqueue.list) {
885 buf = list_entry(c, struct saa7164_buffer, list);
886 buf->flags = SAA7164_BUFFER_FREE;
887 buf->pos = 0;
888 }
889
890 list_for_each_safe(c, n, &port->list_buf_used.list) {
891 ubuf = list_entry(c, struct saa7164_user_buffer, list);
892 ubuf->pos = 0;
893 list_move_tail(&ubuf->list, &port->list_buf_free.list);
894 }
895
896 mutex_unlock(&port->dmaqueue_lock);
897
898 /* Free any allocated resources */
899 saa7164_vbi_buffers_dealloc(port);
900
901 dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr);
902
903 return ret;
904}
905
906static int saa7164_vbi_start_streaming(struct saa7164_port *port)
907{
908 struct saa7164_dev *dev = port->dev;
909 int result, ret = 0;
910
911 dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
912
913 port->done_first_interrupt = 0;
914
915 /* allocate all of the PCIe DMA buffer resources on the fly,
916 * allowing switching between TS and PS payloads without
917 * requiring a complete driver reload.
918 */
919 saa7164_vbi_buffers_alloc(port);
920
921 /* Configure the encoder with any cache values */
922// saa7164_api_set_encoder(port);
923// saa7164_api_get_encoder(port);
924
925 /* Place the empty buffers on the hardware */
926 saa7164_buffer_cfg_port(port);
927
928 /* Negotiate format */
929 if (saa7164_api_set_vbi_format(port) != SAA_OK) {
930 printk(KERN_ERR "%s() No supported VBI format\n", __func__);
931 ret = -EIO;
932 goto out;
933 }
934
935 /* Acquire the hardware */
936 result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
937 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
938 printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
939 __func__, result);
940
941 ret = -EIO;
942 goto out;
943 } else
944 dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
945
946 /* Pause the hardware */
947 result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
948 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
949 printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
950 __func__, result);
951
952 /* Stop the hardware, regardless */
953 result = saa7164_vbi_stop_port(port);
954 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
955 printk(KERN_ERR "%s() pause/forced stop transition "
956 "failed, res = 0x%x\n", __func__, result);
957 }
958
959 ret = -EIO;
960 goto out;
961 } else
962 dprintk(DBGLVL_VBI, "%s() Paused\n", __func__);
963
964 /* Start the hardware */
965 result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
966 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
967 printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
968 __func__, result);
969
970 /* Stop the hardware, regardless */
971 result = saa7164_vbi_acquire_port(port);
972 result = saa7164_vbi_stop_port(port);
973 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
974 printk(KERN_ERR "%s() run/forced stop transition "
975 "failed, res = 0x%x\n", __func__, result);
976 }
977
978 ret = -EIO;
979 } else
980 dprintk(DBGLVL_VBI, "%s() Running\n", __func__);
981
982out:
983 return ret;
984}
985
986int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f)
987{
988 /* ntsc */
989 f->fmt.vbi.samples_per_line = 1600;
990 f->fmt.vbi.samples_per_line = 1440;
991 f->fmt.vbi.sampling_rate = 27000000;
992 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
993 f->fmt.vbi.offset = 0;
994 f->fmt.vbi.flags = 0;
995 f->fmt.vbi.start[0] = 10;
996 f->fmt.vbi.count[0] = 18;
997 f->fmt.vbi.start[1] = 263 + 10 + 1;
998 f->fmt.vbi.count[1] = 18;
999 return 0;
1000}
1001
1002static int fops_open(struct file *file)
1003{
1004 struct saa7164_dev *dev;
1005 struct saa7164_port *port;
1006 struct saa7164_vbi_fh *fh;
1007
1008 port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
1009 if (!port)
1010 return -ENODEV;
1011
1012 dev = port->dev;
1013
1014 dprintk(DBGLVL_VBI, "%s()\n", __func__);
1015
1016 /* allocate + initialize per filehandle data */
1017 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1018 if (NULL == fh)
1019 return -ENOMEM;
1020
1021 file->private_data = fh;
1022 fh->port = port;
1023
1024 return 0;
1025}
1026
1027static int fops_release(struct file *file)
1028{
1029 struct saa7164_vbi_fh *fh = file->private_data;
1030 struct saa7164_port *port = fh->port;
1031 struct saa7164_dev *dev = port->dev;
1032
1033 dprintk(DBGLVL_VBI, "%s()\n", __func__);
1034
1035 /* Shut device down on last close */
1036 if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
1037 if (atomic_dec_return(&port->v4l_reader_count) == 0) {
1038 /* stop vbi capture then cancel buffers */
1039 saa7164_vbi_stop_streaming(port);
1040 }
1041 }
1042
1043 file->private_data = NULL;
1044 kfree(fh);
1045
1046 return 0;
1047}
1048
1049struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
1050{
1051 struct saa7164_user_buffer *ubuf = 0;
1052 struct saa7164_dev *dev = port->dev;
1053 u32 crc;
1054
1055 mutex_lock(&port->dmaqueue_lock);
1056 if (!list_empty(&port->list_buf_used.list)) {
1057 ubuf = list_first_entry(&port->list_buf_used.list,
1058 struct saa7164_user_buffer, list);
1059
1060 if (crc_checking) {
1061 crc = crc32(0, ubuf->data, ubuf->actual_size);
1062 if (crc != ubuf->crc) {
1063 printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__,
1064 ubuf, ubuf->crc, crc);
1065 }
1066 }
1067
1068 }
1069 mutex_unlock(&port->dmaqueue_lock);
1070
1071 dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf);
1072
1073 return ubuf;
1074}
1075
1076static ssize_t fops_read(struct file *file, char __user *buffer,
1077 size_t count, loff_t *pos)
1078{
1079 struct saa7164_vbi_fh *fh = file->private_data;
1080 struct saa7164_port *port = fh->port;
1081 struct saa7164_user_buffer *ubuf = NULL;
1082 struct saa7164_dev *dev = port->dev;
1083 int ret = 0;
1084 int rem, cnt;
1085 u8 *p;
1086
1087 port->last_read_msecs_diff = port->last_read_msecs;
1088 port->last_read_msecs = jiffies_to_msecs(jiffies);
1089 port->last_read_msecs_diff = port->last_read_msecs -
1090 port->last_read_msecs_diff;
1091
1092 saa7164_histogram_update(&port->read_interval,
1093 port->last_read_msecs_diff);
1094
1095 if (*pos) {
1096 printk(KERN_ERR "%s() ESPIPE\n", __func__);
1097 return -ESPIPE;
1098 }
1099
1100 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1101 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1102
1103 if (saa7164_vbi_initialize(port) < 0) {
1104 printk(KERN_ERR "%s() EINVAL\n", __func__);
1105 return -EINVAL;
1106 }
1107
1108 saa7164_vbi_start_streaming(port);
1109 msleep(200);
1110 }
1111 }
1112
1113 /* blocking wait for buffer */
1114 if ((file->f_flags & O_NONBLOCK) == 0) {
1115 if (wait_event_interruptible(port->wait_read,
1116 saa7164_vbi_next_buf(port))) {
1117 printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
1118 return -ERESTARTSYS;
1119 }
1120 }
1121
1122 /* Pull the first buffer from the used list */
1123 ubuf = saa7164_vbi_next_buf(port);
1124
1125 while ((count > 0) && ubuf) {
1126
1127 /* set remaining bytes to copy */
1128 rem = ubuf->actual_size - ubuf->pos;
1129 cnt = rem > count ? count : rem;
1130
1131 p = ubuf->data + ubuf->pos;
1132
1133 dprintk(DBGLVL_VBI,
1134 "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
1135 __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
1136
1137 if (copy_to_user(buffer, p, cnt)) {
1138 printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
1139 if (!ret) {
1140 printk(KERN_ERR "%s() EFAULT\n", __func__);
1141 ret = -EFAULT;
1142 }
1143 goto err;
1144 }
1145
1146 ubuf->pos += cnt;
1147 count -= cnt;
1148 buffer += cnt;
1149 ret += cnt;
1150
1151 if (ubuf->pos > ubuf->actual_size) {
1152 printk(KERN_ERR "read() pos > actual, huh?\n");
1153 }
1154
1155 if (ubuf->pos == ubuf->actual_size) {
1156
1157 /* finished with current buffer, take next buffer */
1158
1159 /* Requeue the buffer on the free list */
1160 ubuf->pos = 0;
1161
1162 mutex_lock(&port->dmaqueue_lock);
1163 list_move_tail(&ubuf->list, &port->list_buf_free.list);
1164 mutex_unlock(&port->dmaqueue_lock);
1165
1166 /* Dequeue next */
1167 if ((file->f_flags & O_NONBLOCK) == 0) {
1168 if (wait_event_interruptible(port->wait_read,
1169 saa7164_vbi_next_buf(port))) {
1170 break;
1171 }
1172 }
1173 ubuf = saa7164_vbi_next_buf(port);
1174 }
1175 }
1176err:
1177 if (!ret && !ubuf) {
1178 printk(KERN_ERR "%s() EAGAIN\n", __func__);
1179 ret = -EAGAIN;
1180 }
1181
1182 return ret;
1183}
1184
1185static unsigned int fops_poll(struct file *file, poll_table *wait)
1186{
1187 struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
1188 struct saa7164_port *port = fh->port;
1189 struct saa7164_user_buffer *ubuf;
1190 unsigned int mask = 0;
1191
1192 port->last_poll_msecs_diff = port->last_poll_msecs;
1193 port->last_poll_msecs = jiffies_to_msecs(jiffies);
1194 port->last_poll_msecs_diff = port->last_poll_msecs -
1195 port->last_poll_msecs_diff;
1196
1197 saa7164_histogram_update(&port->poll_interval,
1198 port->last_poll_msecs_diff);
1199
1200 if (!video_is_registered(port->v4l_device)) {
1201 return -EIO;
1202 }
1203
1204 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1205 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1206 if (saa7164_vbi_initialize(port) < 0)
1207 return -EINVAL;
1208 saa7164_vbi_start_streaming(port);
1209 msleep(200);
1210 }
1211 }
1212
1213 /* blocking wait for buffer */
1214 if ((file->f_flags & O_NONBLOCK) == 0) {
1215 if (wait_event_interruptible(port->wait_read,
1216 saa7164_vbi_next_buf(port))) {
1217 return -ERESTARTSYS;
1218 }
1219 }
1220
1221 /* Pull the first buffer from the used list */
1222 ubuf = list_first_entry(&port->list_buf_used.list,
1223 struct saa7164_user_buffer, list);
1224
1225 if (ubuf)
1226 mask |= POLLIN | POLLRDNORM;
1227
1228 return mask;
1229}
1230static const struct v4l2_file_operations vbi_fops = {
1231 .owner = THIS_MODULE,
1232 .open = fops_open,
1233 .release = fops_release,
1234 .read = fops_read,
1235 .poll = fops_poll,
1236 .unlocked_ioctl = video_ioctl2,
1237};
1238
1239static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
1240 .vidioc_s_std = vidioc_s_std,
1241 .vidioc_enum_input = vidioc_enum_input,
1242 .vidioc_g_input = vidioc_g_input,
1243 .vidioc_s_input = vidioc_s_input,
1244 .vidioc_g_tuner = vidioc_g_tuner,
1245 .vidioc_s_tuner = vidioc_s_tuner,
1246 .vidioc_g_frequency = vidioc_g_frequency,
1247 .vidioc_s_frequency = vidioc_s_frequency,
1248 .vidioc_s_ctrl = vidioc_s_ctrl,
1249 .vidioc_g_ctrl = vidioc_g_ctrl,
1250 .vidioc_querycap = vidioc_querycap,
1251 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1252 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1253 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1254 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1255 .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
1256 .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
1257 .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
1258 .vidioc_log_status = vidioc_log_status,
1259 .vidioc_queryctrl = vidioc_queryctrl,
1260// .vidioc_g_chip_ident = saa7164_g_chip_ident,
1261#ifdef CONFIG_VIDEO_ADV_DEBUG
1262// .vidioc_g_register = saa7164_g_register,
1263// .vidioc_s_register = saa7164_s_register,
1264#endif
1265 .vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt,
1266 .vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt,
1267 .vidioc_s_fmt_vbi_cap = saa7164_vbi_fmt,
1268};
1269
1270static struct video_device saa7164_vbi_template = {
1271 .name = "saa7164",
1272 .fops = &vbi_fops,
1273 .ioctl_ops = &vbi_ioctl_ops,
1274 .minor = -1,
1275 .tvnorms = SAA7164_NORMS,
1276 .current_norm = V4L2_STD_NTSC_M,
1277};
1278
1279static struct video_device *saa7164_vbi_alloc(
1280 struct saa7164_port *port,
1281 struct pci_dev *pci,
1282 struct video_device *template,
1283 char *type)
1284{
1285 struct video_device *vfd;
1286 struct saa7164_dev *dev = port->dev;
1287
1288 dprintk(DBGLVL_VBI, "%s()\n", __func__);
1289
1290 vfd = video_device_alloc();
1291 if (NULL == vfd)
1292 return NULL;
1293
1294 *vfd = *template;
1295 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
1296 type, saa7164_boards[dev->board].name);
1297
1298 vfd->parent = &pci->dev;
1299 vfd->release = video_device_release;
1300 return vfd;
1301}
1302
1303int saa7164_vbi_register(struct saa7164_port *port)
1304{
1305 struct saa7164_dev *dev = port->dev;
1306 int result = -ENODEV;
1307
1308 dprintk(DBGLVL_VBI, "%s()\n", __func__);
1309
1310 if (port->type != SAA7164_MPEG_VBI)
1311 BUG();
1312
1313 /* Sanity check that the PCI configuration space is active */
1314 if (port->hwcfg.BARLocation == 0) {
1315 printk(KERN_ERR "%s() failed "
1316 "(errno = %d), NO PCI configuration\n",
1317 __func__, result);
1318 result = -ENOMEM;
1319 goto failed;
1320 }
1321
1322 /* Establish VBI defaults here */
1323
1324 /* Allocate and register the video device node */
1325 port->v4l_device = saa7164_vbi_alloc(port,
1326 dev->pci, &saa7164_vbi_template, "vbi");
1327
1328 if (port->v4l_device == NULL) {
1329 printk(KERN_INFO "%s: can't allocate vbi device\n",
1330 dev->name);
1331 result = -ENOMEM;
1332 goto failed;
1333 }
1334
1335 video_set_drvdata(port->v4l_device, port);
1336 result = video_register_device(port->v4l_device,
1337 VFL_TYPE_VBI, -1);
1338 if (result < 0) {
1339 printk(KERN_INFO "%s: can't register vbi device\n",
1340 dev->name);
1341 /* TODO: We're going to leak here if we don't dealloc
1342 The buffers above. The unreg function can't deal wit it.
1343 */
1344 goto failed;
1345 }
1346
1347 printk(KERN_INFO "%s: registered device vbi%d [vbi]\n",
1348 dev->name, port->v4l_device->num);
1349
1350 /* Configure the hardware defaults */
1351
1352 result = 0;
1353failed:
1354 return result;
1355}
1356
1357void saa7164_vbi_unregister(struct saa7164_port *port)
1358{
1359 struct saa7164_dev *dev = port->dev;
1360
1361 dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
1362
1363 if (port->type != SAA7164_MPEG_VBI)
1364 BUG();
1365
1366 if (port->v4l_device) {
1367 if (port->v4l_device->minor != -1)
1368 video_unregister_device(port->v4l_device);
1369 else
1370 video_device_release(port->v4l_device);
1371
1372 port->v4l_device = NULL;
1373 }
1374
1375}
diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h
index 42660b546f0e..1d9c5cbbbc52 100644
--- a/drivers/media/video/saa7164/saa7164.h
+++ b/drivers/media/video/saa7164/saa7164.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Driver for the NXP SAA7164 PCIe bridge 2 * Driver for the NXP SAA7164 PCIe bridge
3 * 3 *
4 * Copyright (c) 2009 Steven Toth <stoth@kernellabs.com> 4 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 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 7 * it under the terms of the GNU General Public License as published by
@@ -48,18 +48,29 @@
48#include <linux/i2c.h> 48#include <linux/i2c.h>
49#include <linux/i2c-algo-bit.h> 49#include <linux/i2c-algo-bit.h>
50#include <linux/kdev_t.h> 50#include <linux/kdev_t.h>
51#include <linux/version.h>
52#include <linux/mutex.h>
53#include <linux/crc32.h>
54#include <linux/kthread.h>
55#include <linux/freezer.h>
51 56
52#include <media/tuner.h> 57#include <media/tuner.h>
53#include <media/tveeprom.h> 58#include <media/tveeprom.h>
54#include <media/videobuf-dma-sg.h> 59#include <media/videobuf-dma-sg.h>
55#include <media/videobuf-dvb.h> 60#include <media/videobuf-dvb.h>
61#include <linux/smp_lock.h>
62#include <dvb_demux.h>
63#include <dvb_frontend.h>
64#include <dvb_net.h>
65#include <dvbdev.h>
66#include <dmxdev.h>
67#include <media/v4l2-common.h>
68#include <media/v4l2-ioctl.h>
69#include <media/v4l2-chip-ident.h>
56 70
57#include "saa7164-reg.h" 71#include "saa7164-reg.h"
58#include "saa7164-types.h" 72#include "saa7164-types.h"
59 73
60#include <linux/version.h>
61#include <linux/mutex.h>
62
63#define SAA7164_MAXBOARDS 8 74#define SAA7164_MAXBOARDS 8
64 75
65#define UNSET (-1U) 76#define UNSET (-1U)
@@ -76,7 +87,19 @@
76 87
77#define SAA7164_MAX_UNITS 8 88#define SAA7164_MAX_UNITS 8
78#define SAA7164_TS_NUMBER_OF_LINES 312 89#define SAA7164_TS_NUMBER_OF_LINES 312
90#define SAA7164_PS_NUMBER_OF_LINES 256
79#define SAA7164_PT_ENTRIES 16 /* (312 * 188) / 4096 */ 91#define SAA7164_PT_ENTRIES 16 /* (312 * 188) / 4096 */
92#define SAA7164_MAX_ENCODER_BUFFERS 64 /* max 5secs of latency at 6Mbps */
93#define SAA7164_MAX_VBI_BUFFERS 64
94
95/* Port related defines */
96#define SAA7164_PORT_TS1 (0)
97#define SAA7164_PORT_TS2 (SAA7164_PORT_TS1 + 1)
98#define SAA7164_PORT_ENC1 (SAA7164_PORT_TS2 + 1)
99#define SAA7164_PORT_ENC2 (SAA7164_PORT_ENC1 + 1)
100#define SAA7164_PORT_VBI1 (SAA7164_PORT_ENC2 + 1)
101#define SAA7164_PORT_VBI2 (SAA7164_PORT_VBI1 + 1)
102#define SAA7164_MAX_PORTS (SAA7164_PORT_VBI2 + 1)
80 103
81#define DBGLVL_FW 4 104#define DBGLVL_FW 4
82#define DBGLVL_DVB 8 105#define DBGLVL_DVB 8
@@ -86,10 +109,18 @@
86#define DBGLVL_BUS 128 109#define DBGLVL_BUS 128
87#define DBGLVL_IRQ 256 110#define DBGLVL_IRQ 256
88#define DBGLVL_BUF 512 111#define DBGLVL_BUF 512
112#define DBGLVL_ENC 1024
113#define DBGLVL_VBI 2048
114#define DBGLVL_THR 4096
115#define DBGLVL_CPU 8192
116
117#define SAA7164_NORMS (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443)
89 118
90enum port_t { 119enum port_t {
91 SAA7164_MPEG_UNDEFINED = 0, 120 SAA7164_MPEG_UNDEFINED = 0,
92 SAA7164_MPEG_DVB, 121 SAA7164_MPEG_DVB,
122 SAA7164_MPEG_ENCODER,
123 SAA7164_MPEG_VBI,
93}; 124};
94 125
95enum saa7164_i2c_bus_nr { 126enum saa7164_i2c_bus_nr {
@@ -134,7 +165,8 @@ struct saa7164_unit {
134 165
135struct saa7164_board { 166struct saa7164_board {
136 char *name; 167 char *name;
137 enum port_t porta, portb; 168 enum port_t porta, portb, portc,
169 portd, porte, portf;
138 enum { 170 enum {
139 SAA7164_CHIP_UNDEFINED = 0, 171 SAA7164_CHIP_UNDEFINED = 0,
140 SAA7164_CHIP_REV2, 172 SAA7164_CHIP_REV2,
@@ -149,6 +181,42 @@ struct saa7164_subid {
149 u32 card; 181 u32 card;
150}; 182};
151 183
184struct saa7164_encoder_fh {
185 struct saa7164_port *port;
186// u32 freq;
187// u32 tuner_type;
188 atomic_t v4l_reading;
189};
190
191struct saa7164_vbi_fh {
192 struct saa7164_port *port;
193// u32 freq;
194// u32 tuner_type;
195 atomic_t v4l_reading;
196};
197
198struct saa7164_histogram_bucket {
199 u32 val;
200 u32 count;
201 u64 update_time;
202};
203
204struct saa7164_histogram {
205 char name[32];
206 struct saa7164_histogram_bucket counter1[64];
207};
208
209struct saa7164_user_buffer {
210 struct list_head list;
211
212 /* Attributes */
213 u8 *data;
214 u32 pos;
215 u32 actual_size;
216
217 u32 crc;
218};
219
152struct saa7164_fw_status { 220struct saa7164_fw_status {
153 221
154 /* RISC Core details */ 222 /* RISC Core details */
@@ -191,14 +259,60 @@ struct saa7164_i2c {
191 u32 i2c_rc; 259 u32 i2c_rc;
192}; 260};
193 261
194struct saa7164_tsport; 262struct saa7164_ctrl {
263 struct v4l2_queryctrl v;
264};
265
266struct saa7164_tvnorm {
267 char *name;
268 v4l2_std_id id;
269// u32 cxiformat;
270// u32 cxoformat;
271};
272
273struct saa7164_encoder_params {
274 struct saa7164_tvnorm encodernorm;
275 u32 height;
276 u32 width;
277 u32 is_50hz;
278 u32 bitrate; /* bps */
279 u32 bitrate_peak; /* bps */
280 u32 bitrate_mode;
281 u32 stream_type; /* V4L2_MPEG_STREAM_TYPE_MPEG2_TS */
282
283 u32 audio_sampling_freq;
284 u32 ctl_mute;
285 u32 ctl_aspect;
286 u32 refdist;
287 u32 gop_size;
288};
289
290struct saa7164_vbi_params {
291 struct saa7164_tvnorm encodernorm;
292 u32 height;
293 u32 width;
294 u32 is_50hz;
295 u32 bitrate; /* bps */
296 u32 bitrate_peak; /* bps */
297 u32 bitrate_mode;
298 u32 stream_type; /* V4L2_MPEG_STREAM_TYPE_MPEG2_TS */
299
300 u32 audio_sampling_freq;
301 u32 ctl_mute;
302 u32 ctl_aspect;
303 u32 refdist;
304 u32 gop_size;
305};
306
307struct saa7164_port;
195 308
196struct saa7164_buffer { 309struct saa7164_buffer {
197 struct list_head list; 310 struct list_head list;
198 311
199 u32 nr; 312 /* Note of which h/w buffer list index position we occupy */
313 int idx;
200 314
201 struct saa7164_tsport *port; 315 struct saa7164_port *port;
202 316
203 /* Hardware Specific */ 317 /* Hardware Specific */
204 /* PCI Memory allocations */ 318 /* PCI Memory allocations */
@@ -206,28 +320,33 @@ struct saa7164_buffer {
206 320
207 /* A block of page align PCI memory */ 321 /* A block of page align PCI memory */
208 u32 pci_size; /* PCI allocation size in bytes */ 322 u32 pci_size; /* PCI allocation size in bytes */
209 u64 *cpu; /* Virtual address */ 323 u64 __iomem *cpu; /* Virtual address */
210 dma_addr_t dma; /* Physical address */ 324 dma_addr_t dma; /* Physical address */
325 u32 crc; /* Checksum for the entire buffer data */
211 326
212 /* A page table that splits the block into a number of entries */ 327 /* A page table that splits the block into a number of entries */
213 u32 pt_size; /* PCI allocation size in bytes */ 328 u32 pt_size; /* PCI allocation size in bytes */
214 u64 *pt_cpu; /* Virtual address */ 329 u64 __iomem *pt_cpu; /* Virtual address */
215 dma_addr_t pt_dma; /* Physical address */ 330 dma_addr_t pt_dma; /* Physical address */
331
332 /* Encoder fops */
333 u32 pos;
334 u32 actual_size;
216}; 335};
217 336
218struct saa7164_tsport { 337struct saa7164_port {
219 338
220 struct saa7164_dev *dev; 339 struct saa7164_dev *dev;
221 int nr;
222 enum port_t type; 340 enum port_t type;
341 int nr;
223 342
224 struct saa7164_dvb dvb; 343 /* --- Generic port attributes --- */
225 344
226 /* HW related stream parameters */ 345 /* HW stream parameters */
227 tmHWStreamParameters_t hw_streamingparams; 346 struct tmHWStreamParameters hw_streamingparams;
228 347
229 /* DMA configuration values, is seeded during initialization */ 348 /* DMA configuration values, is seeded during initialization */
230 tmComResDMATermDescrHeader_t hwcfg; 349 struct tmComResDMATermDescrHeader hwcfg;
231 350
232 /* hardware specific registers */ 351 /* hardware specific registers */
233 u32 bufcounter; 352 u32 bufcounter;
@@ -239,11 +358,76 @@ struct saa7164_tsport {
239 u64 bufptr64; 358 u64 bufptr64;
240 359
241 u32 numpte; /* Number of entries in array, only valid in head */ 360 u32 numpte; /* Number of entries in array, only valid in head */
361
242 struct mutex dmaqueue_lock; 362 struct mutex dmaqueue_lock;
243 struct mutex dummy_dmaqueue_lock;
244 struct saa7164_buffer dmaqueue; 363 struct saa7164_buffer dmaqueue;
245 struct saa7164_buffer dummy_dmaqueue;
246 364
365 u64 last_irq_msecs, last_svc_msecs;
366 u64 last_irq_msecs_diff, last_svc_msecs_diff;
367 u32 last_svc_wp;
368 u32 last_svc_rp;
369 u64 last_irq_svc_msecs_diff;
370 u64 last_read_msecs, last_read_msecs_diff;
371 u64 last_poll_msecs, last_poll_msecs_diff;
372
373 struct saa7164_histogram irq_interval;
374 struct saa7164_histogram svc_interval;
375 struct saa7164_histogram irq_svc_interval;
376 struct saa7164_histogram read_interval;
377 struct saa7164_histogram poll_interval;
378
379 /* --- DVB Transport Specific --- */
380 struct saa7164_dvb dvb;
381
382 /* --- Encoder/V4L related attributes --- */
383 /* Encoder */
384 /* Defaults established in saa7164-encoder.c */
385 struct saa7164_tvnorm encodernorm;
386 u32 height;
387 u32 width;
388 u32 freq;
389 u32 ts_packet_size;
390 u32 ts_packet_count;
391 u8 mux_input;
392 u8 encoder_profile;
393 u8 video_format;
394 u8 audio_format;
395 u8 video_resolution;
396 u16 ctl_brightness;
397 u16 ctl_contrast;
398 u16 ctl_hue;
399 u16 ctl_saturation;
400 u16 ctl_sharpness;
401 s8 ctl_volume;
402
403 struct tmComResAFeatureDescrHeader audfeat;
404 struct tmComResEncoderDescrHeader encunit;
405 struct tmComResProcDescrHeader vidproc;
406 struct tmComResExtDevDescrHeader ifunit;
407 struct tmComResTunerDescrHeader tunerunit;
408
409 struct work_struct workenc;
410
411 /* V4L Encoder Video */
412 struct saa7164_encoder_params encoder_params;
413 struct video_device *v4l_device;
414 atomic_t v4l_reader_count;
415
416 struct saa7164_buffer list_buf_used;
417 struct saa7164_buffer list_buf_free;
418 wait_queue_head_t wait_read;
419
420 /* V4L VBI */
421 struct tmComResVBIFormatDescrHeader vbi_fmt_ntsc;
422 struct saa7164_vbi_params vbi_params;
423
424 /* Debug */
425 u32 sync_errors;
426 u32 v_cc_errors;
427 u32 a_cc_errors;
428 u8 last_v_cc;
429 u8 last_a_cc;
430 u32 done_first_interrupt;
247}; 431};
248 432
249struct saa7164_dev { 433struct saa7164_dev {
@@ -268,12 +452,13 @@ struct saa7164_dev {
268 452
269 /* firmware status */ 453 /* firmware status */
270 struct saa7164_fw_status fw_status; 454 struct saa7164_fw_status fw_status;
455 u32 firmwareloaded;
271 456
272 tmComResHWDescr_t hwdesc; 457 struct tmComResHWDescr hwdesc;
273 tmComResInterfaceDescr_t intfdesc; 458 struct tmComResInterfaceDescr intfdesc;
274 tmComResBusDescr_t busdesc; 459 struct tmComResBusDescr busdesc;
275 460
276 tmComResBusInfo_t bus; 461 struct tmComResBusInfo bus;
277 462
278 /* Interrupt status and ack registers */ 463 /* Interrupt status and ack registers */
279 u32 int_status; 464 u32 int_status;
@@ -286,15 +471,22 @@ struct saa7164_dev {
286 struct saa7164_i2c i2c_bus[3]; 471 struct saa7164_i2c i2c_bus[3];
287 472
288 /* Transport related */ 473 /* Transport related */
289 struct saa7164_tsport ts1, ts2; 474 struct saa7164_port ports[SAA7164_MAX_PORTS];
290 475
291 /* Deferred command/api interrupts handling */ 476 /* Deferred command/api interrupts handling */
292 struct work_struct workcmd; 477 struct work_struct workcmd;
293 478
479 /* A kernel thread to monitor the firmware log, used
480 * only in debug mode.
481 */
482 struct task_struct *kthread;
483
294}; 484};
295 485
296extern struct list_head saa7164_devlist; 486extern struct list_head saa7164_devlist;
297extern unsigned int waitsecs; 487extern unsigned int waitsecs;
488extern unsigned int encoder_buffers;
489extern unsigned int vbi_buffers;
298 490
299/* ----------------------------------------------------------- */ 491/* ----------------------------------------------------------- */
300/* saa7164-core.c */ 492/* saa7164-core.c */
@@ -302,6 +494,7 @@ void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr);
302void saa7164_dumphex16(struct saa7164_dev *dev, u8 *buf, int len); 494void saa7164_dumphex16(struct saa7164_dev *dev, u8 *buf, int len);
303void saa7164_getfirmwarestatus(struct saa7164_dev *dev); 495void saa7164_getfirmwarestatus(struct saa7164_dev *dev);
304u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev); 496u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev);
497void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val);
305 498
306/* ----------------------------------------------------------- */ 499/* ----------------------------------------------------------- */
307/* saa7164-fw.c */ 500/* saa7164-fw.c */
@@ -318,14 +511,14 @@ extern void saa7164_call_i2c_clients(struct saa7164_i2c *bus,
318/* saa7164-bus.c */ 511/* saa7164-bus.c */
319int saa7164_bus_setup(struct saa7164_dev *dev); 512int saa7164_bus_setup(struct saa7164_dev *dev);
320void saa7164_bus_dump(struct saa7164_dev *dev); 513void saa7164_bus_dump(struct saa7164_dev *dev);
321int saa7164_bus_set(struct saa7164_dev *dev, tmComResInfo_t* msg, void *buf); 514int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf);
322int saa7164_bus_get(struct saa7164_dev *dev, tmComResInfo_t* msg, 515int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
323 void *buf, int peekonly); 516 void *buf, int peekonly);
324 517
325/* ----------------------------------------------------------- */ 518/* ----------------------------------------------------------- */
326/* saa7164-cmd.c */ 519/* saa7164-cmd.c */
327int saa7164_cmd_send(struct saa7164_dev *dev, 520int saa7164_cmd_send(struct saa7164_dev *dev,
328 u8 id, tmComResCmd_t command, u16 controlselector, 521 u8 id, enum tmComResCmd command, u16 controlselector,
329 u16 size, void *buf); 522 u16 size, void *buf);
330void saa7164_cmd_signal(struct saa7164_dev *dev, u8 seqno); 523void saa7164_cmd_signal(struct saa7164_dev *dev, u8 seqno);
331int saa7164_irq_dequeue(struct saa7164_dev *dev); 524int saa7164_irq_dequeue(struct saa7164_dev *dev);
@@ -343,7 +536,24 @@ int saa7164_api_dif_write(struct saa7164_i2c *bus, u8 addr,
343int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen); 536int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen);
344int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin); 537int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin);
345int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin); 538int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin);
346int saa7164_api_transition_port(struct saa7164_tsport *port, u8 mode); 539int saa7164_api_transition_port(struct saa7164_port *port, u8 mode);
540int saa7164_api_initialize_dif(struct saa7164_port *port);
541int saa7164_api_configure_dif(struct saa7164_port *port, u32 std);
542int saa7164_api_set_encoder(struct saa7164_port *port);
543int saa7164_api_get_encoder(struct saa7164_port *port);
544int saa7164_api_set_aspect_ratio(struct saa7164_port *port);
545int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl);
546int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl);
547int saa7164_api_set_videomux(struct saa7164_port *port);
548int saa7164_api_audio_mute(struct saa7164_port *port, int mute);
549int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level);
550int saa7164_api_set_audio_std(struct saa7164_port *port);
551int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect);
552int saa7164_api_get_videomux(struct saa7164_port *port);
553int saa7164_api_set_vbi_format(struct saa7164_port *port);
554int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level);
555int saa7164_api_collect_debug(struct saa7164_dev *dev);
556int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i);
347 557
348/* ----------------------------------------------------------- */ 558/* ----------------------------------------------------------- */
349/* saa7164-cards.c */ 559/* saa7164-cards.c */
@@ -363,18 +573,36 @@ extern char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid);
363 573
364/* ----------------------------------------------------------- */ 574/* ----------------------------------------------------------- */
365/* saa7164-dvb.c */ 575/* saa7164-dvb.c */
366extern int saa7164_dvb_register(struct saa7164_tsport *port); 576extern int saa7164_dvb_register(struct saa7164_port *port);
367extern int saa7164_dvb_unregister(struct saa7164_tsport *port); 577extern int saa7164_dvb_unregister(struct saa7164_port *port);
368 578
369/* ----------------------------------------------------------- */ 579/* ----------------------------------------------------------- */
370/* saa7164-buffer.c */ 580/* saa7164-buffer.c */
371extern struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_tsport *port, 581extern struct saa7164_buffer *saa7164_buffer_alloc(
372 u32 len); 582 struct saa7164_port *port, u32 len);
373extern int saa7164_buffer_dealloc(struct saa7164_tsport *port, 583extern int saa7164_buffer_dealloc(struct saa7164_buffer *buf);
374 struct saa7164_buffer *buf); 584extern void saa7164_buffer_display(struct saa7164_buffer *buf);
585extern int saa7164_buffer_activate(struct saa7164_buffer *buf, int i);
586extern int saa7164_buffer_cfg_port(struct saa7164_port *port);
587extern struct saa7164_user_buffer *saa7164_buffer_alloc_user(
588 struct saa7164_dev *dev, u32 len);
589extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf);
590extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
591
592/* ----------------------------------------------------------- */
593/* saa7164-encoder.c */
594int saa7164_encoder_register(struct saa7164_port *port);
595void saa7164_encoder_unregister(struct saa7164_port *port);
596
597/* ----------------------------------------------------------- */
598/* saa7164-vbi.c */
599int saa7164_vbi_register(struct saa7164_port *port);
600void saa7164_vbi_unregister(struct saa7164_port *port);
375 601
376/* ----------------------------------------------------------- */ 602/* ----------------------------------------------------------- */
377 603
604extern unsigned int crc_checking;
605
378extern unsigned int saa_debug; 606extern unsigned int saa_debug;
379#define dprintk(level, fmt, arg...)\ 607#define dprintk(level, fmt, arg...)\
380 do { if (saa_debug & level)\ 608 do { if (saa_debug & level)\
@@ -394,7 +622,6 @@ extern unsigned int saa_debug;
394#define saa7164_readl(reg) readl(dev->lmmio + ((reg) >> 2)) 622#define saa7164_readl(reg) readl(dev->lmmio + ((reg) >> 2))
395#define saa7164_writel(reg, value) writel((value), dev->lmmio + ((reg) >> 2)) 623#define saa7164_writel(reg, value) writel((value), dev->lmmio + ((reg) >> 2))
396 624
397
398#define saa7164_readb(reg) readl(dev->bmmio + (reg)) 625#define saa7164_readb(reg) readl(dev->bmmio + (reg))
399#define saa7164_writeb(reg, value) writel((value), dev->bmmio + (reg)) 626#define saa7164_writeb(reg, value) writel((value), dev->bmmio + (reg))
400 627