diff options
Diffstat (limited to 'drivers/media/pci/saa7164/saa7164-api.c')
-rw-r--r-- | drivers/media/pci/saa7164/saa7164-api.c | 1524 |
1 files changed, 1524 insertions, 0 deletions
diff --git a/drivers/media/pci/saa7164/saa7164-api.c b/drivers/media/pci/saa7164/saa7164-api.c new file mode 100644 index 000000000000..eff7135cf0e8 --- /dev/null +++ b/drivers/media/pci/saa7164/saa7164-api.c | |||
@@ -0,0 +1,1524 @@ | |||
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 <linux/wait.h> | ||
23 | #include <linux/slab.h> | ||
24 | |||
25 | #include "saa7164.h" | ||
26 | |||
27 | int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i) | ||
28 | { | ||
29 | int ret; | ||
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 | printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad); | ||
47 | |||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | int saa7164_api_collect_debug(struct saa7164_dev *dev) | ||
52 | { | ||
53 | struct tmComResDebugGetData d; | ||
54 | u8 more = 255; | ||
55 | int ret; | ||
56 | |||
57 | dprintk(DBGLVL_API, "%s()\n", __func__); | ||
58 | |||
59 | while (more--) { | ||
60 | |||
61 | memset(&d, 0, sizeof(d)); | ||
62 | |||
63 | ret = saa7164_cmd_send(dev, 0, GET_CUR, | ||
64 | GET_DEBUG_DATA_CONTROL, sizeof(d), &d); | ||
65 | if (ret != SAA_OK) | ||
66 | printk(KERN_ERR "%s() error, ret = 0x%x\n", | ||
67 | __func__, ret); | ||
68 | |||
69 | if (d.dwResult != SAA_OK) | ||
70 | break; | ||
71 | |||
72 | printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr, | ||
73 | d.ucDebugData); | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | int 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 | return ret; | ||
103 | } | ||
104 | |||
105 | int saa7164_api_set_vbi_format(struct saa7164_port *port) | ||
106 | { | ||
107 | struct saa7164_dev *dev = port->dev; | ||
108 | struct tmComResProbeCommit fmt, rsp; | ||
109 | int ret; | ||
110 | |||
111 | dprintk(DBGLVL_API, "%s(nr=%d, unitid=0x%x)\n", __func__, | ||
112 | port->nr, port->hwcfg.unitid); | ||
113 | |||
114 | fmt.bmHint = 0; | ||
115 | fmt.bFormatIndex = 1; | ||
116 | fmt.bFrameIndex = 1; | ||
117 | |||
118 | /* Probe, see if it can support this format */ | ||
119 | ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, | ||
120 | SET_CUR, SAA_PROBE_CONTROL, sizeof(fmt), &fmt); | ||
121 | if (ret != SAA_OK) | ||
122 | printk(KERN_ERR "%s() set error, ret = 0x%x\n", __func__, ret); | ||
123 | |||
124 | /* See of the format change was successful */ | ||
125 | ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, | ||
126 | GET_CUR, SAA_PROBE_CONTROL, sizeof(rsp), &rsp); | ||
127 | if (ret != SAA_OK) { | ||
128 | printk(KERN_ERR "%s() get error, ret = 0x%x\n", __func__, ret); | ||
129 | } else { | ||
130 | /* Compare requested vs received, should be same */ | ||
131 | if (memcmp(&fmt, &rsp, sizeof(rsp)) == 0) { | ||
132 | dprintk(DBGLVL_API, "SET/PROBE Verified\n"); | ||
133 | |||
134 | /* Ask the device to select the negotiated format */ | ||
135 | ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, | ||
136 | SET_CUR, SAA_COMMIT_CONTROL, sizeof(fmt), &fmt); | ||
137 | if (ret != SAA_OK) | ||
138 | printk(KERN_ERR "%s() commit error, ret = 0x%x\n", | ||
139 | __func__, ret); | ||
140 | |||
141 | ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, | ||
142 | GET_CUR, SAA_COMMIT_CONTROL, sizeof(rsp), &rsp); | ||
143 | if (ret != SAA_OK) | ||
144 | printk(KERN_ERR "%s() GET commit error, ret = 0x%x\n", | ||
145 | __func__, ret); | ||
146 | |||
147 | if (memcmp(&fmt, &rsp, sizeof(rsp)) != 0) { | ||
148 | printk(KERN_ERR "%s() memcmp error, ret = 0x%x\n", | ||
149 | __func__, ret); | ||
150 | } else | ||
151 | dprintk(DBGLVL_API, "SET/COMMIT Verified\n"); | ||
152 | |||
153 | dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint); | ||
154 | dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n", | ||
155 | rsp.bFormatIndex); | ||
156 | dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n", | ||
157 | rsp.bFrameIndex); | ||
158 | } else | ||
159 | printk(KERN_ERR "%s() compare failed\n", __func__); | ||
160 | } | ||
161 | |||
162 | if (ret == SAA_OK) | ||
163 | dprintk(DBGLVL_API, "%s(nr=%d) Success\n", __func__, port->nr); | ||
164 | |||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | int saa7164_api_set_gop_size(struct saa7164_port *port) | ||
169 | { | ||
170 | struct saa7164_dev *dev = port->dev; | ||
171 | struct tmComResEncVideoGopStructure gs; | ||
172 | int ret; | ||
173 | |||
174 | dprintk(DBGLVL_ENC, "%s()\n", __func__); | ||
175 | |||
176 | gs.ucRefFrameDist = port->encoder_params.refdist; | ||
177 | gs.ucGOPSize = port->encoder_params.gop_size; | ||
178 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, | ||
179 | EU_VIDEO_GOP_STRUCTURE_CONTROL, | ||
180 | sizeof(gs), &gs); | ||
181 | if (ret != SAA_OK) | ||
182 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | int saa7164_api_set_encoder(struct saa7164_port *port) | ||
188 | { | ||
189 | struct saa7164_dev *dev = port->dev; | ||
190 | struct tmComResEncVideoBitRate vb; | ||
191 | struct tmComResEncAudioBitRate ab; | ||
192 | int ret; | ||
193 | |||
194 | dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, | ||
195 | port->hwcfg.sourceid); | ||
196 | |||
197 | if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) | ||
198 | port->encoder_profile = EU_PROFILE_PS_DVD; | ||
199 | else | ||
200 | port->encoder_profile = EU_PROFILE_TS_HQ; | ||
201 | |||
202 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, | ||
203 | EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile); | ||
204 | if (ret != SAA_OK) | ||
205 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
206 | |||
207 | /* Resolution */ | ||
208 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, | ||
209 | EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile); | ||
210 | if (ret != SAA_OK) | ||
211 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
212 | |||
213 | /* Establish video bitrates */ | ||
214 | if (port->encoder_params.bitrate_mode == | ||
215 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) | ||
216 | vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT; | ||
217 | else | ||
218 | vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK; | ||
219 | vb.dwVideoBitRate = port->encoder_params.bitrate; | ||
220 | vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak; | ||
221 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, | ||
222 | EU_VIDEO_BIT_RATE_CONTROL, | ||
223 | sizeof(struct tmComResEncVideoBitRate), | ||
224 | &vb); | ||
225 | if (ret != SAA_OK) | ||
226 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
227 | |||
228 | /* Establish audio bitrates */ | ||
229 | ab.ucAudioBitRateMode = 0; | ||
230 | ab.dwAudioBitRate = 384000; | ||
231 | ab.dwAudioBitRatePeak = ab.dwAudioBitRate; | ||
232 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, | ||
233 | EU_AUDIO_BIT_RATE_CONTROL, | ||
234 | sizeof(struct tmComResEncAudioBitRate), | ||
235 | &ab); | ||
236 | if (ret != SAA_OK) | ||
237 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, | ||
238 | ret); | ||
239 | |||
240 | saa7164_api_set_aspect_ratio(port); | ||
241 | saa7164_api_set_gop_size(port); | ||
242 | |||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | int saa7164_api_get_encoder(struct saa7164_port *port) | ||
247 | { | ||
248 | struct saa7164_dev *dev = port->dev; | ||
249 | struct tmComResEncVideoBitRate v; | ||
250 | struct tmComResEncAudioBitRate a; | ||
251 | struct tmComResEncVideoInputAspectRatio ar; | ||
252 | int ret; | ||
253 | |||
254 | dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, | ||
255 | port->hwcfg.sourceid); | ||
256 | |||
257 | port->encoder_profile = 0; | ||
258 | port->video_format = 0; | ||
259 | port->video_resolution = 0; | ||
260 | port->audio_format = 0; | ||
261 | |||
262 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, | ||
263 | EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile); | ||
264 | if (ret != SAA_OK) | ||
265 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
266 | |||
267 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, | ||
268 | EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), | ||
269 | &port->video_resolution); | ||
270 | if (ret != SAA_OK) | ||
271 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
272 | |||
273 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, | ||
274 | EU_VIDEO_FORMAT_CONTROL, sizeof(u8), &port->video_format); | ||
275 | if (ret != SAA_OK) | ||
276 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
277 | |||
278 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, | ||
279 | EU_VIDEO_BIT_RATE_CONTROL, sizeof(v), &v); | ||
280 | if (ret != SAA_OK) | ||
281 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
282 | |||
283 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, | ||
284 | EU_AUDIO_FORMAT_CONTROL, sizeof(u8), &port->audio_format); | ||
285 | if (ret != SAA_OK) | ||
286 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
287 | |||
288 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, | ||
289 | EU_AUDIO_BIT_RATE_CONTROL, sizeof(a), &a); | ||
290 | if (ret != SAA_OK) | ||
291 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
292 | |||
293 | /* Aspect Ratio */ | ||
294 | ar.width = 0; | ||
295 | ar.height = 0; | ||
296 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, | ||
297 | EU_VIDEO_INPUT_ASPECT_CONTROL, | ||
298 | sizeof(struct tmComResEncVideoInputAspectRatio), &ar); | ||
299 | if (ret != SAA_OK) | ||
300 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
301 | |||
302 | dprintk(DBGLVL_ENC, "encoder_profile = %d\n", port->encoder_profile); | ||
303 | dprintk(DBGLVL_ENC, "video_format = %d\n", port->video_format); | ||
304 | dprintk(DBGLVL_ENC, "audio_format = %d\n", port->audio_format); | ||
305 | dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution); | ||
306 | dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", | ||
307 | v.ucVideoBitRateMode); | ||
308 | dprintk(DBGLVL_ENC, "v.dwVideoBitRate = %d\n", | ||
309 | v.dwVideoBitRate); | ||
310 | dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", | ||
311 | v.dwVideoBitRatePeak); | ||
312 | dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", | ||
313 | a.ucAudioBitRateMode); | ||
314 | dprintk(DBGLVL_ENC, "a.dwVideoBitRate = %d\n", | ||
315 | a.dwAudioBitRate); | ||
316 | dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", | ||
317 | a.dwAudioBitRatePeak); | ||
318 | dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", | ||
319 | ar.width, ar.height); | ||
320 | |||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | int saa7164_api_set_aspect_ratio(struct saa7164_port *port) | ||
325 | { | ||
326 | struct saa7164_dev *dev = port->dev; | ||
327 | struct tmComResEncVideoInputAspectRatio ar; | ||
328 | int ret; | ||
329 | |||
330 | dprintk(DBGLVL_ENC, "%s(%d)\n", __func__, | ||
331 | port->encoder_params.ctl_aspect); | ||
332 | |||
333 | switch (port->encoder_params.ctl_aspect) { | ||
334 | case V4L2_MPEG_VIDEO_ASPECT_1x1: | ||
335 | ar.width = 1; | ||
336 | ar.height = 1; | ||
337 | break; | ||
338 | case V4L2_MPEG_VIDEO_ASPECT_4x3: | ||
339 | ar.width = 4; | ||
340 | ar.height = 3; | ||
341 | break; | ||
342 | case V4L2_MPEG_VIDEO_ASPECT_16x9: | ||
343 | ar.width = 16; | ||
344 | ar.height = 9; | ||
345 | break; | ||
346 | case V4L2_MPEG_VIDEO_ASPECT_221x100: | ||
347 | ar.width = 221; | ||
348 | ar.height = 100; | ||
349 | break; | ||
350 | default: | ||
351 | BUG(); | ||
352 | } | ||
353 | |||
354 | dprintk(DBGLVL_ENC, "%s(%d) now %d:%d\n", __func__, | ||
355 | port->encoder_params.ctl_aspect, | ||
356 | ar.width, ar.height); | ||
357 | |||
358 | /* Aspect Ratio */ | ||
359 | ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, | ||
360 | EU_VIDEO_INPUT_ASPECT_CONTROL, | ||
361 | sizeof(struct tmComResEncVideoInputAspectRatio), &ar); | ||
362 | if (ret != SAA_OK) | ||
363 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
364 | |||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl) | ||
369 | { | ||
370 | struct saa7164_dev *dev = port->dev; | ||
371 | int ret; | ||
372 | u16 val; | ||
373 | |||
374 | if (ctl == PU_BRIGHTNESS_CONTROL) | ||
375 | val = port->ctl_brightness; | ||
376 | else | ||
377 | if (ctl == PU_CONTRAST_CONTROL) | ||
378 | val = port->ctl_contrast; | ||
379 | else | ||
380 | if (ctl == PU_HUE_CONTROL) | ||
381 | val = port->ctl_hue; | ||
382 | else | ||
383 | if (ctl == PU_SATURATION_CONTROL) | ||
384 | val = port->ctl_saturation; | ||
385 | else | ||
386 | if (ctl == PU_SHARPNESS_CONTROL) | ||
387 | val = port->ctl_sharpness; | ||
388 | else | ||
389 | return -EINVAL; | ||
390 | |||
391 | dprintk(DBGLVL_ENC, "%s() unitid=0x%x ctl=%d, val=%d\n", | ||
392 | __func__, port->encunit.vsourceid, ctl, val); | ||
393 | |||
394 | ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, SET_CUR, | ||
395 | ctl, sizeof(u16), &val); | ||
396 | if (ret != SAA_OK) | ||
397 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
398 | |||
399 | return ret; | ||
400 | } | ||
401 | |||
402 | int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl) | ||
403 | { | ||
404 | struct saa7164_dev *dev = port->dev; | ||
405 | int ret; | ||
406 | u16 val; | ||
407 | |||
408 | ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, GET_CUR, | ||
409 | ctl, sizeof(u16), &val); | ||
410 | if (ret != SAA_OK) { | ||
411 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | dprintk(DBGLVL_ENC, "%s() ctl=%d, val=%d\n", | ||
416 | __func__, ctl, val); | ||
417 | |||
418 | if (ctl == PU_BRIGHTNESS_CONTROL) | ||
419 | port->ctl_brightness = val; | ||
420 | else | ||
421 | if (ctl == PU_CONTRAST_CONTROL) | ||
422 | port->ctl_contrast = val; | ||
423 | else | ||
424 | if (ctl == PU_HUE_CONTROL) | ||
425 | port->ctl_hue = val; | ||
426 | else | ||
427 | if (ctl == PU_SATURATION_CONTROL) | ||
428 | port->ctl_saturation = val; | ||
429 | else | ||
430 | if (ctl == PU_SHARPNESS_CONTROL) | ||
431 | port->ctl_sharpness = val; | ||
432 | |||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | int saa7164_api_set_videomux(struct saa7164_port *port) | ||
437 | { | ||
438 | struct saa7164_dev *dev = port->dev; | ||
439 | u8 inputs[] = { 1, 2, 2, 2, 5, 5, 5 }; | ||
440 | int ret; | ||
441 | |||
442 | dprintk(DBGLVL_ENC, "%s() v_mux=%d a_mux=%d\n", | ||
443 | __func__, port->mux_input, inputs[port->mux_input - 1]); | ||
444 | |||
445 | /* Audio Mute */ | ||
446 | ret = saa7164_api_audio_mute(port, 1); | ||
447 | if (ret != SAA_OK) | ||
448 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
449 | |||
450 | /* Video Mux */ | ||
451 | ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, SET_CUR, | ||
452 | SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input); | ||
453 | if (ret != SAA_OK) | ||
454 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
455 | |||
456 | /* Audio Mux */ | ||
457 | ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR, | ||
458 | SU_INPUT_SELECT_CONTROL, sizeof(u8), | ||
459 | &inputs[port->mux_input - 1]); | ||
460 | if (ret != SAA_OK) | ||
461 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
462 | |||
463 | /* Audio UnMute */ | ||
464 | ret = saa7164_api_audio_mute(port, 0); | ||
465 | if (ret != SAA_OK) | ||
466 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
467 | |||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | int saa7164_api_audio_mute(struct saa7164_port *port, int mute) | ||
472 | { | ||
473 | struct saa7164_dev *dev = port->dev; | ||
474 | u8 v = mute; | ||
475 | int ret; | ||
476 | |||
477 | dprintk(DBGLVL_API, "%s(%d)\n", __func__, mute); | ||
478 | |||
479 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR, | ||
480 | MUTE_CONTROL, sizeof(u8), &v); | ||
481 | if (ret != SAA_OK) | ||
482 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
483 | |||
484 | return ret; | ||
485 | } | ||
486 | |||
487 | /* 0 = silence, 0xff = full */ | ||
488 | int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level) | ||
489 | { | ||
490 | struct saa7164_dev *dev = port->dev; | ||
491 | s16 v, min, max; | ||
492 | int ret; | ||
493 | |||
494 | dprintk(DBGLVL_API, "%s(%d)\n", __func__, level); | ||
495 | |||
496 | /* Obtain the min/max ranges */ | ||
497 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MIN, | ||
498 | VOLUME_CONTROL, sizeof(u16), &min); | ||
499 | if (ret != SAA_OK) | ||
500 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
501 | |||
502 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MAX, | ||
503 | VOLUME_CONTROL, sizeof(u16), &max); | ||
504 | if (ret != SAA_OK) | ||
505 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
506 | |||
507 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR, | ||
508 | (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v); | ||
509 | if (ret != SAA_OK) | ||
510 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
511 | |||
512 | dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, | ||
513 | level, min, max, v); | ||
514 | |||
515 | v = level; | ||
516 | if (v < min) | ||
517 | v = min; | ||
518 | if (v > max) | ||
519 | v = max; | ||
520 | |||
521 | /* Left */ | ||
522 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR, | ||
523 | (0x01 << 8) | VOLUME_CONTROL, sizeof(s16), &v); | ||
524 | if (ret != SAA_OK) | ||
525 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
526 | |||
527 | /* Right */ | ||
528 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR, | ||
529 | (0x02 << 8) | VOLUME_CONTROL, sizeof(s16), &v); | ||
530 | if (ret != SAA_OK) | ||
531 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
532 | |||
533 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR, | ||
534 | (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v); | ||
535 | if (ret != SAA_OK) | ||
536 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
537 | |||
538 | dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, | ||
539 | level, min, max, v); | ||
540 | |||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | int saa7164_api_set_audio_std(struct saa7164_port *port) | ||
545 | { | ||
546 | struct saa7164_dev *dev = port->dev; | ||
547 | struct tmComResAudioDefaults lvl; | ||
548 | struct tmComResTunerStandard tvaudio; | ||
549 | int ret; | ||
550 | |||
551 | dprintk(DBGLVL_API, "%s()\n", __func__); | ||
552 | |||
553 | /* Establish default levels */ | ||
554 | lvl.ucDecoderLevel = TMHW_LEV_ADJ_DECLEV_DEFAULT; | ||
555 | lvl.ucDecoderFM_Level = TMHW_LEV_ADJ_DECLEV_DEFAULT; | ||
556 | lvl.ucMonoLevel = TMHW_LEV_ADJ_MONOLEV_DEFAULT; | ||
557 | lvl.ucNICAM_Level = TMHW_LEV_ADJ_NICLEV_DEFAULT; | ||
558 | lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT; | ||
559 | lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT; | ||
560 | ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR, | ||
561 | AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults), | ||
562 | &lvl); | ||
563 | if (ret != SAA_OK) | ||
564 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
565 | |||
566 | /* Manually select the appropriate TV audio standard */ | ||
567 | if (port->encodernorm.id & V4L2_STD_NTSC) { | ||
568 | tvaudio.std = TU_STANDARD_NTSC_M; | ||
569 | tvaudio.country = 1; | ||
570 | } else { | ||
571 | tvaudio.std = TU_STANDARD_PAL_I; | ||
572 | tvaudio.country = 44; | ||
573 | } | ||
574 | |||
575 | ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR, | ||
576 | TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio); | ||
577 | if (ret != SAA_OK) | ||
578 | printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", | ||
579 | __func__, ret); | ||
580 | return ret; | ||
581 | } | ||
582 | |||
583 | int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect) | ||
584 | { | ||
585 | struct saa7164_dev *dev = port->dev; | ||
586 | struct tmComResTunerStandardAuto p; | ||
587 | int ret; | ||
588 | |||
589 | dprintk(DBGLVL_API, "%s(%d)\n", __func__, autodetect); | ||
590 | |||
591 | /* Disable TV Audio autodetect if not already set (buggy) */ | ||
592 | if (autodetect) | ||
593 | p.mode = TU_STANDARD_AUTO; | ||
594 | else | ||
595 | p.mode = TU_STANDARD_MANUAL; | ||
596 | ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR, | ||
597 | TU_STANDARD_AUTO_CONTROL, sizeof(p), &p); | ||
598 | if (ret != SAA_OK) | ||
599 | printk(KERN_ERR | ||
600 | "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", | ||
601 | __func__, ret); | ||
602 | |||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | int saa7164_api_get_videomux(struct saa7164_port *port) | ||
607 | { | ||
608 | struct saa7164_dev *dev = port->dev; | ||
609 | int ret; | ||
610 | |||
611 | ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, GET_CUR, | ||
612 | SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input); | ||
613 | if (ret != SAA_OK) | ||
614 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
615 | |||
616 | dprintk(DBGLVL_ENC, "%s() v_mux=%d\n", | ||
617 | __func__, port->mux_input); | ||
618 | |||
619 | return ret; | ||
620 | } | ||
621 | |||
622 | int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val) | ||
623 | { | ||
624 | struct saa7164_dev *dev = port->dev; | ||
625 | |||
626 | u16 len = 0; | ||
627 | u8 buf[256]; | ||
628 | int ret; | ||
629 | u8 mas; | ||
630 | |||
631 | dprintk(DBGLVL_API, "%s(nr=%d type=%d val=%x)\n", __func__, | ||
632 | port->nr, port->type, val); | ||
633 | |||
634 | if (port->nr == 0) | ||
635 | mas = 0xd0; | ||
636 | else | ||
637 | mas = 0xe0; | ||
638 | |||
639 | memset(buf, 0, sizeof(buf)); | ||
640 | |||
641 | buf[0x00] = 0x04; | ||
642 | buf[0x01] = 0x00; | ||
643 | buf[0x02] = 0x00; | ||
644 | buf[0x03] = 0x00; | ||
645 | |||
646 | buf[0x04] = 0x04; | ||
647 | buf[0x05] = 0x00; | ||
648 | buf[0x06] = 0x00; | ||
649 | buf[0x07] = 0x00; | ||
650 | |||
651 | buf[0x08] = reg; | ||
652 | buf[0x09] = 0x26; | ||
653 | buf[0x0a] = mas; | ||
654 | buf[0x0b] = 0xb0; | ||
655 | |||
656 | buf[0x0c] = val; | ||
657 | buf[0x0d] = 0x00; | ||
658 | buf[0x0e] = 0x00; | ||
659 | buf[0x0f] = 0x00; | ||
660 | |||
661 | ret = saa7164_cmd_send(dev, port->ifunit.unitid, GET_LEN, | ||
662 | EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len); | ||
663 | if (ret != SAA_OK) { | ||
664 | printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret); | ||
665 | return -EIO; | ||
666 | } | ||
667 | |||
668 | ret = saa7164_cmd_send(dev, port->ifunit.unitid, SET_CUR, | ||
669 | EXU_REGISTER_ACCESS_CONTROL, len, &buf); | ||
670 | if (ret != SAA_OK) | ||
671 | printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret); | ||
672 | #if 0 | ||
673 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, 16, | ||
674 | false); | ||
675 | #endif | ||
676 | return ret == SAA_OK ? 0 : -EIO; | ||
677 | } | ||
678 | |||
679 | /* Disable the IF block AGC controls */ | ||
680 | int saa7164_api_configure_dif(struct saa7164_port *port, u32 std) | ||
681 | { | ||
682 | struct saa7164_dev *dev = port->dev; | ||
683 | int ret = 0; | ||
684 | u8 agc_disable; | ||
685 | |||
686 | dprintk(DBGLVL_API, "%s(nr=%d, 0x%x)\n", __func__, port->nr, std); | ||
687 | |||
688 | if (std & V4L2_STD_NTSC) { | ||
689 | dprintk(DBGLVL_API, " NTSC\n"); | ||
690 | saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */ | ||
691 | agc_disable = 0; | ||
692 | } else if (std & V4L2_STD_PAL_I) { | ||
693 | dprintk(DBGLVL_API, " PAL-I\n"); | ||
694 | saa7164_api_set_dif(port, 0x00, 0x08); /* Video Standard */ | ||
695 | agc_disable = 0; | ||
696 | } else if (std & V4L2_STD_PAL_M) { | ||
697 | dprintk(DBGLVL_API, " PAL-M\n"); | ||
698 | saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */ | ||
699 | agc_disable = 0; | ||
700 | } else if (std & V4L2_STD_PAL_N) { | ||
701 | dprintk(DBGLVL_API, " PAL-N\n"); | ||
702 | saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */ | ||
703 | agc_disable = 0; | ||
704 | } else if (std & V4L2_STD_PAL_Nc) { | ||
705 | dprintk(DBGLVL_API, " PAL-Nc\n"); | ||
706 | saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */ | ||
707 | agc_disable = 0; | ||
708 | } else if (std & V4L2_STD_PAL_B) { | ||
709 | dprintk(DBGLVL_API, " PAL-B\n"); | ||
710 | saa7164_api_set_dif(port, 0x00, 0x02); /* Video Standard */ | ||
711 | agc_disable = 0; | ||
712 | } else if (std & V4L2_STD_PAL_DK) { | ||
713 | dprintk(DBGLVL_API, " PAL-DK\n"); | ||
714 | saa7164_api_set_dif(port, 0x00, 0x10); /* Video Standard */ | ||
715 | agc_disable = 0; | ||
716 | } else if (std & V4L2_STD_SECAM_L) { | ||
717 | dprintk(DBGLVL_API, " SECAM-L\n"); | ||
718 | saa7164_api_set_dif(port, 0x00, 0x20); /* Video Standard */ | ||
719 | agc_disable = 0; | ||
720 | } else { | ||
721 | /* Unknown standard, assume DTV */ | ||
722 | dprintk(DBGLVL_API, " Unknown (assuming DTV)\n"); | ||
723 | /* Undefinded Video Standard */ | ||
724 | saa7164_api_set_dif(port, 0x00, 0x80); | ||
725 | agc_disable = 1; | ||
726 | } | ||
727 | |||
728 | saa7164_api_set_dif(port, 0x48, 0xa0); /* AGC Functions 1 */ | ||
729 | saa7164_api_set_dif(port, 0xc0, agc_disable); /* AGC Output Disable */ | ||
730 | saa7164_api_set_dif(port, 0x7c, 0x04); /* CVBS EQ */ | ||
731 | saa7164_api_set_dif(port, 0x04, 0x01); /* Active */ | ||
732 | msleep(100); | ||
733 | saa7164_api_set_dif(port, 0x04, 0x00); /* Active (again) */ | ||
734 | msleep(100); | ||
735 | |||
736 | return ret; | ||
737 | } | ||
738 | |||
739 | /* Ensure the dif is in the correct state for the operating mode | ||
740 | * (analog / dtv). We only configure the diff through the analog encoder | ||
741 | * so when we're in digital mode we need to find the appropriate encoder | ||
742 | * and use it to configure the DIF. | ||
743 | */ | ||
744 | int saa7164_api_initialize_dif(struct saa7164_port *port) | ||
745 | { | ||
746 | struct saa7164_dev *dev = port->dev; | ||
747 | struct saa7164_port *p = NULL; | ||
748 | int ret = -EINVAL; | ||
749 | u32 std = 0; | ||
750 | |||
751 | dprintk(DBGLVL_API, "%s(nr=%d type=%d)\n", __func__, | ||
752 | port->nr, port->type); | ||
753 | |||
754 | if (port->type == SAA7164_MPEG_ENCODER) { | ||
755 | /* Pick any analog standard to init the diff. | ||
756 | * we'll come back during encoder_init' | ||
757 | * and set the correct standard if requried. | ||
758 | */ | ||
759 | std = V4L2_STD_NTSC; | ||
760 | } else | ||
761 | if (port->type == SAA7164_MPEG_DVB) { | ||
762 | if (port->nr == SAA7164_PORT_TS1) | ||
763 | p = &dev->ports[SAA7164_PORT_ENC1]; | ||
764 | else | ||
765 | p = &dev->ports[SAA7164_PORT_ENC2]; | ||
766 | } else | ||
767 | if (port->type == SAA7164_MPEG_VBI) { | ||
768 | std = V4L2_STD_NTSC; | ||
769 | if (port->nr == SAA7164_PORT_VBI1) | ||
770 | p = &dev->ports[SAA7164_PORT_ENC1]; | ||
771 | else | ||
772 | p = &dev->ports[SAA7164_PORT_ENC2]; | ||
773 | } else | ||
774 | BUG(); | ||
775 | |||
776 | if (p) | ||
777 | ret = saa7164_api_configure_dif(p, std); | ||
778 | |||
779 | return ret; | ||
780 | } | ||
781 | |||
782 | int saa7164_api_transition_port(struct saa7164_port *port, u8 mode) | ||
783 | { | ||
784 | struct saa7164_dev *dev = port->dev; | ||
785 | |||
786 | int ret; | ||
787 | |||
788 | dprintk(DBGLVL_API, "%s(nr=%d unitid=0x%x,%d)\n", | ||
789 | __func__, port->nr, port->hwcfg.unitid, mode); | ||
790 | |||
791 | ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR, | ||
792 | SAA_STATE_CONTROL, sizeof(mode), &mode); | ||
793 | if (ret != SAA_OK) | ||
794 | printk(KERN_ERR "%s(portnr %d unitid 0x%x) error, ret = 0x%x\n", | ||
795 | __func__, port->nr, port->hwcfg.unitid, ret); | ||
796 | |||
797 | return ret; | ||
798 | } | ||
799 | |||
800 | int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version) | ||
801 | { | ||
802 | int ret; | ||
803 | |||
804 | ret = saa7164_cmd_send(dev, 0, GET_CUR, | ||
805 | GET_FW_VERSION_CONTROL, sizeof(u32), version); | ||
806 | if (ret != SAA_OK) | ||
807 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
808 | |||
809 | return ret; | ||
810 | } | ||
811 | |||
812 | int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen) | ||
813 | { | ||
814 | u8 reg[] = { 0x0f, 0x00 }; | ||
815 | |||
816 | if (buflen < 128) | ||
817 | return -ENOMEM; | ||
818 | |||
819 | /* Assumption: Hauppauge eeprom is at 0xa0 on on bus 0 */ | ||
820 | /* TODO: Pull the details from the boards struct */ | ||
821 | return saa7164_api_i2c_read(&dev->i2c_bus[0], 0xa0 >> 1, sizeof(reg), | ||
822 | ®[0], 128, buf); | ||
823 | } | ||
824 | |||
825 | int saa7164_api_configure_port_vbi(struct saa7164_dev *dev, | ||
826 | struct saa7164_port *port) | ||
827 | { | ||
828 | struct tmComResVBIFormatDescrHeader *fmt = &port->vbi_fmt_ntsc; | ||
829 | |||
830 | dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", fmt->bFormatIndex); | ||
831 | dprintk(DBGLVL_API, " VideoStandard = 0x%x\n", fmt->VideoStandard); | ||
832 | dprintk(DBGLVL_API, " StartLine = %d\n", fmt->StartLine); | ||
833 | dprintk(DBGLVL_API, " EndLine = %d\n", fmt->EndLine); | ||
834 | dprintk(DBGLVL_API, " FieldRate = %d\n", fmt->FieldRate); | ||
835 | dprintk(DBGLVL_API, " bNumLines = %d\n", fmt->bNumLines); | ||
836 | |||
837 | /* Cache the hardware configuration in the port */ | ||
838 | |||
839 | port->bufcounter = port->hwcfg.BARLocation; | ||
840 | port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32)); | ||
841 | port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32)); | ||
842 | port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32)); | ||
843 | port->bufptr32l = port->hwcfg.BARLocation + | ||
844 | (4 * sizeof(u32)) + | ||
845 | (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32); | ||
846 | port->bufptr32h = port->hwcfg.BARLocation + | ||
847 | (4 * sizeof(u32)) + | ||
848 | (sizeof(u32) * port->hwcfg.buffercount); | ||
849 | port->bufptr64 = port->hwcfg.BARLocation + | ||
850 | (4 * sizeof(u32)) + | ||
851 | (sizeof(u32) * port->hwcfg.buffercount); | ||
852 | dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n", | ||
853 | port->hwcfg.BARLocation); | ||
854 | |||
855 | dprintk(DBGLVL_API, " = VS_FORMAT_VBI (becomes dev->en[%d])\n", | ||
856 | port->nr); | ||
857 | |||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev, | ||
862 | struct saa7164_port *port, | ||
863 | struct tmComResTSFormatDescrHeader *tsfmt) | ||
864 | { | ||
865 | dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", tsfmt->bFormatIndex); | ||
866 | dprintk(DBGLVL_API, " bDataOffset = 0x%x\n", tsfmt->bDataOffset); | ||
867 | dprintk(DBGLVL_API, " bPacketLength= 0x%x\n", tsfmt->bPacketLength); | ||
868 | dprintk(DBGLVL_API, " bStrideLength= 0x%x\n", tsfmt->bStrideLength); | ||
869 | dprintk(DBGLVL_API, " bguid = (....)\n"); | ||
870 | |||
871 | /* Cache the hardware configuration in the port */ | ||
872 | |||
873 | port->bufcounter = port->hwcfg.BARLocation; | ||
874 | port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32)); | ||
875 | port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32)); | ||
876 | port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32)); | ||
877 | port->bufptr32l = port->hwcfg.BARLocation + | ||
878 | (4 * sizeof(u32)) + | ||
879 | (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32); | ||
880 | port->bufptr32h = port->hwcfg.BARLocation + | ||
881 | (4 * sizeof(u32)) + | ||
882 | (sizeof(u32) * port->hwcfg.buffercount); | ||
883 | port->bufptr64 = port->hwcfg.BARLocation + | ||
884 | (4 * sizeof(u32)) + | ||
885 | (sizeof(u32) * port->hwcfg.buffercount); | ||
886 | dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n", | ||
887 | port->hwcfg.BARLocation); | ||
888 | |||
889 | dprintk(DBGLVL_API, " = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n", | ||
890 | port->nr); | ||
891 | |||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev, | ||
896 | struct saa7164_port *port, | ||
897 | struct tmComResPSFormatDescrHeader *fmt) | ||
898 | { | ||
899 | dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", fmt->bFormatIndex); | ||
900 | dprintk(DBGLVL_API, " wPacketLength= 0x%x\n", fmt->wPacketLength); | ||
901 | dprintk(DBGLVL_API, " wPackLength= 0x%x\n", fmt->wPackLength); | ||
902 | dprintk(DBGLVL_API, " bPackDataType= 0x%x\n", fmt->bPackDataType); | ||
903 | |||
904 | /* Cache the hardware configuration in the port */ | ||
905 | /* TODO: CHECK THIS in the port config */ | ||
906 | port->bufcounter = port->hwcfg.BARLocation; | ||
907 | port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32)); | ||
908 | port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32)); | ||
909 | port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32)); | ||
910 | port->bufptr32l = port->hwcfg.BARLocation + | ||
911 | (4 * sizeof(u32)) + | ||
912 | (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32); | ||
913 | port->bufptr32h = port->hwcfg.BARLocation + | ||
914 | (4 * sizeof(u32)) + | ||
915 | (sizeof(u32) * port->hwcfg.buffercount); | ||
916 | port->bufptr64 = port->hwcfg.BARLocation + | ||
917 | (4 * sizeof(u32)) + | ||
918 | (sizeof(u32) * port->hwcfg.buffercount); | ||
919 | dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n", | ||
920 | port->hwcfg.BARLocation); | ||
921 | |||
922 | dprintk(DBGLVL_API, " = VS_FORMAT_MPEGPS (becomes dev->enc[%d])\n", | ||
923 | port->nr); | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) | ||
929 | { | ||
930 | struct saa7164_port *tsport = NULL; | ||
931 | struct saa7164_port *encport = NULL; | ||
932 | struct saa7164_port *vbiport = NULL; | ||
933 | u32 idx, next_offset; | ||
934 | int i; | ||
935 | struct tmComResDescrHeader *hdr, *t; | ||
936 | struct tmComResExtDevDescrHeader *exthdr; | ||
937 | struct tmComResPathDescrHeader *pathhdr; | ||
938 | struct tmComResAntTermDescrHeader *anttermhdr; | ||
939 | struct tmComResTunerDescrHeader *tunerunithdr; | ||
940 | struct tmComResDMATermDescrHeader *vcoutputtermhdr; | ||
941 | struct tmComResTSFormatDescrHeader *tsfmt; | ||
942 | struct tmComResPSFormatDescrHeader *psfmt; | ||
943 | struct tmComResSelDescrHeader *psel; | ||
944 | struct tmComResProcDescrHeader *pdh; | ||
945 | struct tmComResAFeatureDescrHeader *afd; | ||
946 | struct tmComResEncoderDescrHeader *edh; | ||
947 | struct tmComResVBIFormatDescrHeader *vbifmt; | ||
948 | u32 currpath = 0; | ||
949 | |||
950 | dprintk(DBGLVL_API, | ||
951 | "%s(?,?,%d) sizeof(struct tmComResDescrHeader) = %d bytes\n", | ||
952 | __func__, len, (u32)sizeof(struct tmComResDescrHeader)); | ||
953 | |||
954 | for (idx = 0; idx < (len - sizeof(struct tmComResDescrHeader));) { | ||
955 | |||
956 | hdr = (struct tmComResDescrHeader *)(buf + idx); | ||
957 | |||
958 | if (hdr->type != CS_INTERFACE) | ||
959 | return SAA_ERR_NOT_SUPPORTED; | ||
960 | |||
961 | dprintk(DBGLVL_API, "@ 0x%x =\n", idx); | ||
962 | switch (hdr->subtype) { | ||
963 | case GENERAL_REQUEST: | ||
964 | dprintk(DBGLVL_API, " GENERAL_REQUEST\n"); | ||
965 | break; | ||
966 | case VC_TUNER_PATH: | ||
967 | dprintk(DBGLVL_API, " VC_TUNER_PATH\n"); | ||
968 | pathhdr = (struct tmComResPathDescrHeader *)(buf + idx); | ||
969 | dprintk(DBGLVL_API, " pathid = 0x%x\n", | ||
970 | pathhdr->pathid); | ||
971 | currpath = pathhdr->pathid; | ||
972 | break; | ||
973 | case VC_INPUT_TERMINAL: | ||
974 | dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n"); | ||
975 | anttermhdr = | ||
976 | (struct tmComResAntTermDescrHeader *)(buf + idx); | ||
977 | dprintk(DBGLVL_API, " terminalid = 0x%x\n", | ||
978 | anttermhdr->terminalid); | ||
979 | dprintk(DBGLVL_API, " terminaltype = 0x%x\n", | ||
980 | anttermhdr->terminaltype); | ||
981 | switch (anttermhdr->terminaltype) { | ||
982 | case ITT_ANTENNA: | ||
983 | dprintk(DBGLVL_API, " = ITT_ANTENNA\n"); | ||
984 | break; | ||
985 | case LINE_CONNECTOR: | ||
986 | dprintk(DBGLVL_API, " = LINE_CONNECTOR\n"); | ||
987 | break; | ||
988 | case SPDIF_CONNECTOR: | ||
989 | dprintk(DBGLVL_API, " = SPDIF_CONNECTOR\n"); | ||
990 | break; | ||
991 | case COMPOSITE_CONNECTOR: | ||
992 | dprintk(DBGLVL_API, | ||
993 | " = COMPOSITE_CONNECTOR\n"); | ||
994 | break; | ||
995 | case SVIDEO_CONNECTOR: | ||
996 | dprintk(DBGLVL_API, " = SVIDEO_CONNECTOR\n"); | ||
997 | break; | ||
998 | case COMPONENT_CONNECTOR: | ||
999 | dprintk(DBGLVL_API, | ||
1000 | " = COMPONENT_CONNECTOR\n"); | ||
1001 | break; | ||
1002 | case STANDARD_DMA: | ||
1003 | dprintk(DBGLVL_API, " = STANDARD_DMA\n"); | ||
1004 | break; | ||
1005 | default: | ||
1006 | dprintk(DBGLVL_API, " = undefined (0x%x)\n", | ||
1007 | anttermhdr->terminaltype); | ||
1008 | } | ||
1009 | dprintk(DBGLVL_API, " assocterminal= 0x%x\n", | ||
1010 | anttermhdr->assocterminal); | ||
1011 | dprintk(DBGLVL_API, " iterminal = 0x%x\n", | ||
1012 | anttermhdr->iterminal); | ||
1013 | dprintk(DBGLVL_API, " controlsize = 0x%x\n", | ||
1014 | anttermhdr->controlsize); | ||
1015 | break; | ||
1016 | case VC_OUTPUT_TERMINAL: | ||
1017 | dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n"); | ||
1018 | vcoutputtermhdr = | ||
1019 | (struct tmComResDMATermDescrHeader *)(buf + idx); | ||
1020 | dprintk(DBGLVL_API, " unitid = 0x%x\n", | ||
1021 | vcoutputtermhdr->unitid); | ||
1022 | dprintk(DBGLVL_API, " terminaltype = 0x%x\n", | ||
1023 | vcoutputtermhdr->terminaltype); | ||
1024 | switch (vcoutputtermhdr->terminaltype) { | ||
1025 | case ITT_ANTENNA: | ||
1026 | dprintk(DBGLVL_API, " = ITT_ANTENNA\n"); | ||
1027 | break; | ||
1028 | case LINE_CONNECTOR: | ||
1029 | dprintk(DBGLVL_API, " = LINE_CONNECTOR\n"); | ||
1030 | break; | ||
1031 | case SPDIF_CONNECTOR: | ||
1032 | dprintk(DBGLVL_API, " = SPDIF_CONNECTOR\n"); | ||
1033 | break; | ||
1034 | case COMPOSITE_CONNECTOR: | ||
1035 | dprintk(DBGLVL_API, | ||
1036 | " = COMPOSITE_CONNECTOR\n"); | ||
1037 | break; | ||
1038 | case SVIDEO_CONNECTOR: | ||
1039 | dprintk(DBGLVL_API, " = SVIDEO_CONNECTOR\n"); | ||
1040 | break; | ||
1041 | case COMPONENT_CONNECTOR: | ||
1042 | dprintk(DBGLVL_API, | ||
1043 | " = COMPONENT_CONNECTOR\n"); | ||
1044 | break; | ||
1045 | case STANDARD_DMA: | ||
1046 | dprintk(DBGLVL_API, " = STANDARD_DMA\n"); | ||
1047 | break; | ||
1048 | default: | ||
1049 | dprintk(DBGLVL_API, " = undefined (0x%x)\n", | ||
1050 | vcoutputtermhdr->terminaltype); | ||
1051 | } | ||
1052 | dprintk(DBGLVL_API, " assocterminal= 0x%x\n", | ||
1053 | vcoutputtermhdr->assocterminal); | ||
1054 | dprintk(DBGLVL_API, " sourceid = 0x%x\n", | ||
1055 | vcoutputtermhdr->sourceid); | ||
1056 | dprintk(DBGLVL_API, " iterminal = 0x%x\n", | ||
1057 | vcoutputtermhdr->iterminal); | ||
1058 | dprintk(DBGLVL_API, " BARLocation = 0x%x\n", | ||
1059 | vcoutputtermhdr->BARLocation); | ||
1060 | dprintk(DBGLVL_API, " flags = 0x%x\n", | ||
1061 | vcoutputtermhdr->flags); | ||
1062 | dprintk(DBGLVL_API, " interruptid = 0x%x\n", | ||
1063 | vcoutputtermhdr->interruptid); | ||
1064 | dprintk(DBGLVL_API, " buffercount = 0x%x\n", | ||
1065 | vcoutputtermhdr->buffercount); | ||
1066 | dprintk(DBGLVL_API, " metadatasize = 0x%x\n", | ||
1067 | vcoutputtermhdr->metadatasize); | ||
1068 | dprintk(DBGLVL_API, " controlsize = 0x%x\n", | ||
1069 | vcoutputtermhdr->controlsize); | ||
1070 | dprintk(DBGLVL_API, " numformats = 0x%x\n", | ||
1071 | vcoutputtermhdr->numformats); | ||
1072 | |||
1073 | t = (struct tmComResDescrHeader *) | ||
1074 | ((struct tmComResDMATermDescrHeader *)(buf + idx)); | ||
1075 | next_offset = idx + (vcoutputtermhdr->len); | ||
1076 | for (i = 0; i < vcoutputtermhdr->numformats; i++) { | ||
1077 | t = (struct tmComResDescrHeader *) | ||
1078 | (buf + next_offset); | ||
1079 | switch (t->subtype) { | ||
1080 | case VS_FORMAT_MPEG2TS: | ||
1081 | tsfmt = | ||
1082 | (struct tmComResTSFormatDescrHeader *)t; | ||
1083 | if (currpath == 1) | ||
1084 | tsport = &dev->ports[SAA7164_PORT_TS1]; | ||
1085 | else | ||
1086 | tsport = &dev->ports[SAA7164_PORT_TS2]; | ||
1087 | memcpy(&tsport->hwcfg, vcoutputtermhdr, | ||
1088 | sizeof(*vcoutputtermhdr)); | ||
1089 | saa7164_api_configure_port_mpeg2ts(dev, | ||
1090 | tsport, tsfmt); | ||
1091 | break; | ||
1092 | case VS_FORMAT_MPEG2PS: | ||
1093 | psfmt = | ||
1094 | (struct tmComResPSFormatDescrHeader *)t; | ||
1095 | if (currpath == 1) | ||
1096 | encport = &dev->ports[SAA7164_PORT_ENC1]; | ||
1097 | else | ||
1098 | encport = &dev->ports[SAA7164_PORT_ENC2]; | ||
1099 | memcpy(&encport->hwcfg, vcoutputtermhdr, | ||
1100 | sizeof(*vcoutputtermhdr)); | ||
1101 | saa7164_api_configure_port_mpeg2ps(dev, | ||
1102 | encport, psfmt); | ||
1103 | break; | ||
1104 | case VS_FORMAT_VBI: | ||
1105 | vbifmt = | ||
1106 | (struct tmComResVBIFormatDescrHeader *)t; | ||
1107 | if (currpath == 1) | ||
1108 | vbiport = &dev->ports[SAA7164_PORT_VBI1]; | ||
1109 | else | ||
1110 | vbiport = &dev->ports[SAA7164_PORT_VBI2]; | ||
1111 | memcpy(&vbiport->hwcfg, vcoutputtermhdr, | ||
1112 | sizeof(*vcoutputtermhdr)); | ||
1113 | memcpy(&vbiport->vbi_fmt_ntsc, vbifmt, | ||
1114 | sizeof(*vbifmt)); | ||
1115 | saa7164_api_configure_port_vbi(dev, | ||
1116 | vbiport); | ||
1117 | break; | ||
1118 | case VS_FORMAT_RDS: | ||
1119 | dprintk(DBGLVL_API, | ||
1120 | " = VS_FORMAT_RDS\n"); | ||
1121 | break; | ||
1122 | case VS_FORMAT_UNCOMPRESSED: | ||
1123 | dprintk(DBGLVL_API, | ||
1124 | " = VS_FORMAT_UNCOMPRESSED\n"); | ||
1125 | break; | ||
1126 | case VS_FORMAT_TYPE: | ||
1127 | dprintk(DBGLVL_API, | ||
1128 | " = VS_FORMAT_TYPE\n"); | ||
1129 | break; | ||
1130 | default: | ||
1131 | dprintk(DBGLVL_API, | ||
1132 | " = undefined (0x%x)\n", | ||
1133 | t->subtype); | ||
1134 | } | ||
1135 | next_offset += t->len; | ||
1136 | } | ||
1137 | |||
1138 | break; | ||
1139 | case TUNER_UNIT: | ||
1140 | dprintk(DBGLVL_API, " TUNER_UNIT\n"); | ||
1141 | tunerunithdr = | ||
1142 | (struct tmComResTunerDescrHeader *)(buf + idx); | ||
1143 | dprintk(DBGLVL_API, " unitid = 0x%x\n", | ||
1144 | tunerunithdr->unitid); | ||
1145 | dprintk(DBGLVL_API, " sourceid = 0x%x\n", | ||
1146 | tunerunithdr->sourceid); | ||
1147 | dprintk(DBGLVL_API, " iunit = 0x%x\n", | ||
1148 | tunerunithdr->iunit); | ||
1149 | dprintk(DBGLVL_API, " tuningstandards = 0x%x\n", | ||
1150 | tunerunithdr->tuningstandards); | ||
1151 | dprintk(DBGLVL_API, " controlsize = 0x%x\n", | ||
1152 | tunerunithdr->controlsize); | ||
1153 | dprintk(DBGLVL_API, " controls = 0x%x\n", | ||
1154 | tunerunithdr->controls); | ||
1155 | |||
1156 | if (tunerunithdr->unitid == tunerunithdr->iunit) { | ||
1157 | if (currpath == 1) | ||
1158 | encport = &dev->ports[SAA7164_PORT_ENC1]; | ||
1159 | else | ||
1160 | encport = &dev->ports[SAA7164_PORT_ENC2]; | ||
1161 | memcpy(&encport->tunerunit, tunerunithdr, | ||
1162 | sizeof(struct tmComResTunerDescrHeader)); | ||
1163 | dprintk(DBGLVL_API, | ||
1164 | " (becomes dev->enc[%d] tuner)\n", | ||
1165 | encport->nr); | ||
1166 | } | ||
1167 | break; | ||
1168 | case VC_SELECTOR_UNIT: | ||
1169 | psel = (struct tmComResSelDescrHeader *)(buf + idx); | ||
1170 | dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n"); | ||
1171 | dprintk(DBGLVL_API, " unitid = 0x%x\n", | ||
1172 | psel->unitid); | ||
1173 | dprintk(DBGLVL_API, " nrinpins = 0x%x\n", | ||
1174 | psel->nrinpins); | ||
1175 | dprintk(DBGLVL_API, " sourceid = 0x%x\n", | ||
1176 | psel->sourceid); | ||
1177 | break; | ||
1178 | case VC_PROCESSING_UNIT: | ||
1179 | pdh = (struct tmComResProcDescrHeader *)(buf + idx); | ||
1180 | dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n"); | ||
1181 | dprintk(DBGLVL_API, " unitid = 0x%x\n", | ||
1182 | pdh->unitid); | ||
1183 | dprintk(DBGLVL_API, " sourceid = 0x%x\n", | ||
1184 | pdh->sourceid); | ||
1185 | dprintk(DBGLVL_API, " controlsize = 0x%x\n", | ||
1186 | pdh->controlsize); | ||
1187 | if (pdh->controlsize == 0x04) { | ||
1188 | if (currpath == 1) | ||
1189 | encport = &dev->ports[SAA7164_PORT_ENC1]; | ||
1190 | else | ||
1191 | encport = &dev->ports[SAA7164_PORT_ENC2]; | ||
1192 | memcpy(&encport->vidproc, pdh, | ||
1193 | sizeof(struct tmComResProcDescrHeader)); | ||
1194 | dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", | ||
1195 | encport->nr); | ||
1196 | } | ||
1197 | break; | ||
1198 | case FEATURE_UNIT: | ||
1199 | afd = (struct tmComResAFeatureDescrHeader *)(buf + idx); | ||
1200 | dprintk(DBGLVL_API, " FEATURE_UNIT\n"); | ||
1201 | dprintk(DBGLVL_API, " unitid = 0x%x\n", | ||
1202 | afd->unitid); | ||
1203 | dprintk(DBGLVL_API, " sourceid = 0x%x\n", | ||
1204 | afd->sourceid); | ||
1205 | dprintk(DBGLVL_API, " controlsize = 0x%x\n", | ||
1206 | afd->controlsize); | ||
1207 | if (currpath == 1) | ||
1208 | encport = &dev->ports[SAA7164_PORT_ENC1]; | ||
1209 | else | ||
1210 | encport = &dev->ports[SAA7164_PORT_ENC2]; | ||
1211 | memcpy(&encport->audfeat, afd, | ||
1212 | sizeof(struct tmComResAFeatureDescrHeader)); | ||
1213 | dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", | ||
1214 | encport->nr); | ||
1215 | break; | ||
1216 | case ENCODER_UNIT: | ||
1217 | edh = (struct tmComResEncoderDescrHeader *)(buf + idx); | ||
1218 | dprintk(DBGLVL_API, " ENCODER_UNIT\n"); | ||
1219 | dprintk(DBGLVL_API, " subtype = 0x%x\n", edh->subtype); | ||
1220 | dprintk(DBGLVL_API, " unitid = 0x%x\n", edh->unitid); | ||
1221 | dprintk(DBGLVL_API, " vsourceid = 0x%x\n", | ||
1222 | edh->vsourceid); | ||
1223 | dprintk(DBGLVL_API, " asourceid = 0x%x\n", | ||
1224 | edh->asourceid); | ||
1225 | dprintk(DBGLVL_API, " iunit = 0x%x\n", edh->iunit); | ||
1226 | if (edh->iunit == edh->unitid) { | ||
1227 | if (currpath == 1) | ||
1228 | encport = &dev->ports[SAA7164_PORT_ENC1]; | ||
1229 | else | ||
1230 | encport = &dev->ports[SAA7164_PORT_ENC2]; | ||
1231 | memcpy(&encport->encunit, edh, | ||
1232 | sizeof(struct tmComResEncoderDescrHeader)); | ||
1233 | dprintk(DBGLVL_API, | ||
1234 | " (becomes dev->enc[%d])\n", | ||
1235 | encport->nr); | ||
1236 | } | ||
1237 | break; | ||
1238 | case EXTENSION_UNIT: | ||
1239 | dprintk(DBGLVL_API, " EXTENSION_UNIT\n"); | ||
1240 | exthdr = (struct tmComResExtDevDescrHeader *)(buf + idx); | ||
1241 | dprintk(DBGLVL_API, " unitid = 0x%x\n", | ||
1242 | exthdr->unitid); | ||
1243 | dprintk(DBGLVL_API, " deviceid = 0x%x\n", | ||
1244 | exthdr->deviceid); | ||
1245 | dprintk(DBGLVL_API, " devicetype = 0x%x\n", | ||
1246 | exthdr->devicetype); | ||
1247 | if (exthdr->devicetype & 0x1) | ||
1248 | dprintk(DBGLVL_API, " = Decoder Device\n"); | ||
1249 | if (exthdr->devicetype & 0x2) | ||
1250 | dprintk(DBGLVL_API, " = GPIO Source\n"); | ||
1251 | if (exthdr->devicetype & 0x4) | ||
1252 | dprintk(DBGLVL_API, " = Video Decoder\n"); | ||
1253 | if (exthdr->devicetype & 0x8) | ||
1254 | dprintk(DBGLVL_API, " = Audio Decoder\n"); | ||
1255 | if (exthdr->devicetype & 0x20) | ||
1256 | dprintk(DBGLVL_API, " = Crossbar\n"); | ||
1257 | if (exthdr->devicetype & 0x40) | ||
1258 | dprintk(DBGLVL_API, " = Tuner\n"); | ||
1259 | if (exthdr->devicetype & 0x80) | ||
1260 | dprintk(DBGLVL_API, " = IF PLL\n"); | ||
1261 | if (exthdr->devicetype & 0x100) | ||
1262 | dprintk(DBGLVL_API, " = Demodulator\n"); | ||
1263 | if (exthdr->devicetype & 0x200) | ||
1264 | dprintk(DBGLVL_API, " = RDS Decoder\n"); | ||
1265 | if (exthdr->devicetype & 0x400) | ||
1266 | dprintk(DBGLVL_API, " = Encoder\n"); | ||
1267 | if (exthdr->devicetype & 0x800) | ||
1268 | dprintk(DBGLVL_API, " = IR Decoder\n"); | ||
1269 | if (exthdr->devicetype & 0x1000) | ||
1270 | dprintk(DBGLVL_API, " = EEPROM\n"); | ||
1271 | if (exthdr->devicetype & 0x2000) | ||
1272 | dprintk(DBGLVL_API, | ||
1273 | " = VBI Decoder\n"); | ||
1274 | if (exthdr->devicetype & 0x10000) | ||
1275 | dprintk(DBGLVL_API, | ||
1276 | " = Streaming Device\n"); | ||
1277 | if (exthdr->devicetype & 0x20000) | ||
1278 | dprintk(DBGLVL_API, | ||
1279 | " = DRM Device\n"); | ||
1280 | if (exthdr->devicetype & 0x40000000) | ||
1281 | dprintk(DBGLVL_API, | ||
1282 | " = Generic Device\n"); | ||
1283 | if (exthdr->devicetype & 0x80000000) | ||
1284 | dprintk(DBGLVL_API, | ||
1285 | " = Config Space Device\n"); | ||
1286 | dprintk(DBGLVL_API, " numgpiopins = 0x%x\n", | ||
1287 | exthdr->numgpiopins); | ||
1288 | dprintk(DBGLVL_API, " numgpiogroups = 0x%x\n", | ||
1289 | exthdr->numgpiogroups); | ||
1290 | dprintk(DBGLVL_API, " controlsize = 0x%x\n", | ||
1291 | exthdr->controlsize); | ||
1292 | if (exthdr->devicetype & 0x80) { | ||
1293 | if (currpath == 1) | ||
1294 | encport = &dev->ports[SAA7164_PORT_ENC1]; | ||
1295 | else | ||
1296 | encport = &dev->ports[SAA7164_PORT_ENC2]; | ||
1297 | memcpy(&encport->ifunit, exthdr, | ||
1298 | sizeof(struct tmComResExtDevDescrHeader)); | ||
1299 | dprintk(DBGLVL_API, | ||
1300 | " (becomes dev->enc[%d])\n", | ||
1301 | encport->nr); | ||
1302 | } | ||
1303 | break; | ||
1304 | case PVC_INFRARED_UNIT: | ||
1305 | dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n"); | ||
1306 | break; | ||
1307 | case DRM_UNIT: | ||
1308 | dprintk(DBGLVL_API, " DRM_UNIT\n"); | ||
1309 | break; | ||
1310 | default: | ||
1311 | dprintk(DBGLVL_API, "default %d\n", hdr->subtype); | ||
1312 | } | ||
1313 | |||
1314 | dprintk(DBGLVL_API, " 1.%x\n", hdr->len); | ||
1315 | dprintk(DBGLVL_API, " 2.%x\n", hdr->type); | ||
1316 | dprintk(DBGLVL_API, " 3.%x\n", hdr->subtype); | ||
1317 | dprintk(DBGLVL_API, " 4.%x\n", hdr->unitid); | ||
1318 | |||
1319 | idx += hdr->len; | ||
1320 | } | ||
1321 | |||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | int saa7164_api_enum_subdevs(struct saa7164_dev *dev) | ||
1326 | { | ||
1327 | int ret; | ||
1328 | u32 buflen = 0; | ||
1329 | u8 *buf; | ||
1330 | |||
1331 | dprintk(DBGLVL_API, "%s()\n", __func__); | ||
1332 | |||
1333 | /* Get the total descriptor length */ | ||
1334 | ret = saa7164_cmd_send(dev, 0, GET_LEN, | ||
1335 | GET_DESCRIPTORS_CONTROL, sizeof(buflen), &buflen); | ||
1336 | if (ret != SAA_OK) | ||
1337 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
1338 | |||
1339 | dprintk(DBGLVL_API, "%s() total descriptor size = %d bytes.\n", | ||
1340 | __func__, buflen); | ||
1341 | |||
1342 | /* Allocate enough storage for all of the descs */ | ||
1343 | buf = kzalloc(buflen, GFP_KERNEL); | ||
1344 | if (!buf) | ||
1345 | return SAA_ERR_NO_RESOURCES; | ||
1346 | |||
1347 | /* Retrieve them */ | ||
1348 | ret = saa7164_cmd_send(dev, 0, GET_CUR, | ||
1349 | GET_DESCRIPTORS_CONTROL, buflen, buf); | ||
1350 | if (ret != SAA_OK) { | ||
1351 | printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); | ||
1352 | goto out; | ||
1353 | } | ||
1354 | |||
1355 | if (saa_debug & DBGLVL_API) | ||
1356 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, | ||
1357 | buflen & ~15, false); | ||
1358 | |||
1359 | saa7164_api_dump_subdevs(dev, buf, buflen); | ||
1360 | |||
1361 | out: | ||
1362 | kfree(buf); | ||
1363 | return ret; | ||
1364 | } | ||
1365 | |||
1366 | int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg, | ||
1367 | u32 datalen, u8 *data) | ||
1368 | { | ||
1369 | struct saa7164_dev *dev = bus->dev; | ||
1370 | u16 len = 0; | ||
1371 | int unitid; | ||
1372 | u8 buf[256]; | ||
1373 | int ret; | ||
1374 | |||
1375 | dprintk(DBGLVL_API, "%s()\n", __func__); | ||
1376 | |||
1377 | if (reglen > 4) | ||
1378 | return -EIO; | ||
1379 | |||
1380 | /* Prepare the send buffer */ | ||
1381 | /* Bytes 00-03 source register length | ||
1382 | * 04-07 source bytes to read | ||
1383 | * 08... register address | ||
1384 | */ | ||
1385 | memset(buf, 0, sizeof(buf)); | ||
1386 | memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen); | ||
1387 | *((u32 *)(buf + 0 * sizeof(u32))) = reglen; | ||
1388 | *((u32 *)(buf + 1 * sizeof(u32))) = datalen; | ||
1389 | |||
1390 | unitid = saa7164_i2caddr_to_unitid(bus, addr); | ||
1391 | if (unitid < 0) { | ||
1392 | printk(KERN_ERR | ||
1393 | "%s() error, cannot translate regaddr 0x%x to unitid\n", | ||
1394 | __func__, addr); | ||
1395 | return -EIO; | ||
1396 | } | ||
1397 | |||
1398 | ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN, | ||
1399 | EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len); | ||
1400 | if (ret != SAA_OK) { | ||
1401 | printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret); | ||
1402 | return -EIO; | ||
1403 | } | ||
1404 | |||
1405 | dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len); | ||
1406 | |||
1407 | if (saa_debug & DBGLVL_I2C) | ||
1408 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, | ||
1409 | 32, false); | ||
1410 | |||
1411 | ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR, | ||
1412 | EXU_REGISTER_ACCESS_CONTROL, len, &buf); | ||
1413 | if (ret != SAA_OK) | ||
1414 | printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret); | ||
1415 | else { | ||
1416 | if (saa_debug & DBGLVL_I2C) | ||
1417 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, | ||
1418 | buf, sizeof(buf), false); | ||
1419 | memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen); | ||
1420 | } | ||
1421 | |||
1422 | return ret == SAA_OK ? 0 : -EIO; | ||
1423 | } | ||
1424 | |||
1425 | /* For a given 8 bit i2c address device, write the buffer */ | ||
1426 | int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen, | ||
1427 | u8 *data) | ||
1428 | { | ||
1429 | struct saa7164_dev *dev = bus->dev; | ||
1430 | u16 len = 0; | ||
1431 | int unitid; | ||
1432 | int reglen; | ||
1433 | u8 buf[256]; | ||
1434 | int ret; | ||
1435 | |||
1436 | dprintk(DBGLVL_API, "%s()\n", __func__); | ||
1437 | |||
1438 | if ((datalen == 0) || (datalen > 232)) | ||
1439 | return -EIO; | ||
1440 | |||
1441 | memset(buf, 0, sizeof(buf)); | ||
1442 | |||
1443 | unitid = saa7164_i2caddr_to_unitid(bus, addr); | ||
1444 | if (unitid < 0) { | ||
1445 | printk(KERN_ERR | ||
1446 | "%s() error, cannot translate regaddr 0x%x to unitid\n", | ||
1447 | __func__, addr); | ||
1448 | return -EIO; | ||
1449 | } | ||
1450 | |||
1451 | reglen = saa7164_i2caddr_to_reglen(bus, addr); | ||
1452 | if (reglen < 0) { | ||
1453 | printk(KERN_ERR | ||
1454 | "%s() error, cannot translate regaddr to reglen\n", | ||
1455 | __func__); | ||
1456 | return -EIO; | ||
1457 | } | ||
1458 | |||
1459 | ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN, | ||
1460 | EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len); | ||
1461 | if (ret != SAA_OK) { | ||
1462 | printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret); | ||
1463 | return -EIO; | ||
1464 | } | ||
1465 | |||
1466 | dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len); | ||
1467 | |||
1468 | /* Prepare the send buffer */ | ||
1469 | /* Bytes 00-03 dest register length | ||
1470 | * 04-07 dest bytes to write | ||
1471 | * 08... register address | ||
1472 | */ | ||
1473 | *((u32 *)(buf + 0 * sizeof(u32))) = reglen; | ||
1474 | *((u32 *)(buf + 1 * sizeof(u32))) = datalen - reglen; | ||
1475 | memcpy((buf + 2 * sizeof(u32)), data, datalen); | ||
1476 | |||
1477 | if (saa_debug & DBGLVL_I2C) | ||
1478 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, | ||
1479 | buf, sizeof(buf), false); | ||
1480 | |||
1481 | ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR, | ||
1482 | EXU_REGISTER_ACCESS_CONTROL, len, &buf); | ||
1483 | if (ret != SAA_OK) | ||
1484 | printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret); | ||
1485 | |||
1486 | return ret == SAA_OK ? 0 : -EIO; | ||
1487 | } | ||
1488 | |||
1489 | int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid, | ||
1490 | u8 pin, u8 state) | ||
1491 | { | ||
1492 | int ret; | ||
1493 | struct tmComResGPIO t; | ||
1494 | |||
1495 | dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n", | ||
1496 | __func__, unitid, pin, state); | ||
1497 | |||
1498 | if ((pin > 7) || (state > 2)) | ||
1499 | return SAA_ERR_BAD_PARAMETER; | ||
1500 | |||
1501 | t.pin = pin; | ||
1502 | t.state = state; | ||
1503 | |||
1504 | ret = saa7164_cmd_send(dev, unitid, SET_CUR, | ||
1505 | EXU_GPIO_CONTROL, sizeof(t), &t); | ||
1506 | if (ret != SAA_OK) | ||
1507 | printk(KERN_ERR "%s() error, ret = 0x%x\n", | ||
1508 | __func__, ret); | ||
1509 | |||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid, | ||
1514 | u8 pin) | ||
1515 | { | ||
1516 | return saa7164_api_modify_gpio(dev, unitid, pin, 1); | ||
1517 | } | ||
1518 | |||
1519 | int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid, | ||
1520 | u8 pin) | ||
1521 | { | ||
1522 | return saa7164_api_modify_gpio(dev, unitid, pin, 0); | ||
1523 | } | ||
1524 | |||