blob: 9fd39326b85ab528f5909b35e8e8692f47151dfb [file] [log] [blame]
Steven Toth443c12282009-05-09 21:17:28 -03001/*
2 * Driver for the NXP SAA7164 PCIe bridge
3 *
Steven Toth9b8b0192010-07-31 14:39:44 -03004 * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
Steven Toth443c12282009-05-09 21:17:28 -03005 *
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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Steven Toth443c12282009-05-09 21:17:28 -030024
25#include "saa7164.h"
26
Steven Totheafea212010-07-31 14:48:45 -030027int saa7164_api_set_gop_size(struct saa7164_port *port)
28{
29 struct saa7164_dev *dev = port->dev;
30 tmComResEncVideoGopStructure_t gs;
31 int ret;
32
33 dprintk(DBGLVL_ENC, "%s()\n", __func__);
34
Steven Toth3ed43cf2010-07-31 14:58:35 -030035 gs.ucRefFrameDist = port->encoder_params.refdist;
Steven Toth5fa56cc2010-07-31 15:05:35 -030036 gs.ucGOPSize = port->encoder_params.gop_size;
Steven Totheafea212010-07-31 14:48:45 -030037 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
38 EU_VIDEO_GOP_STRUCTURE_CONTROL,
39 sizeof(gs), &gs);
40 if (ret != SAA_OK)
41 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
42
43 return ret;
44}
45
Steven Toth7615e432010-07-31 14:44:53 -030046int saa7164_api_set_encoder(struct saa7164_port *port)
47{
48 struct saa7164_dev *dev = port->dev;
49 tmComResEncVideoBitRate_t vb;
50 tmComResEncAudioBitRate_t ab;
51 int ret;
52
Steven Totheafea212010-07-31 14:48:45 -030053 dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,
54 port->hwcfg.sourceid);
Steven Toth7615e432010-07-31 14:44:53 -030055
Steven Tothf91d0952010-07-31 15:03:31 -030056 if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
57 port->encoder_profile = EU_PROFILE_PS_DVD;
58 else
59 port->encoder_profile = EU_PROFILE_TS_HQ;
60
Steven Toth7615e432010-07-31 14:44:53 -030061 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
62 EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
63 if (ret != SAA_OK)
64 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
65
Steven Tothf6eeece2010-07-31 15:28:18 -030066 /* Resolution */
67 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
68 EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
69 if (ret != SAA_OK)
70 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
71
Steven Toth7615e432010-07-31 14:44:53 -030072 /* Establish video bitrates */
Steven Toth2600d712010-07-31 14:51:30 -030073 if (port->encoder_params.bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
74 vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT;
75 else
76 vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK;
Steven Toth7615e432010-07-31 14:44:53 -030077 vb.dwVideoBitRate = port->encoder_params.bitrate;
Steven Toth968b11b2010-07-31 14:59:38 -030078 vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak;
Steven Toth7615e432010-07-31 14:44:53 -030079 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
80 EU_VIDEO_BIT_RATE_CONTROL, sizeof(tmComResEncVideoBitRate_t), &vb);
81 if (ret != SAA_OK)
82 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
83
84 /* Establish audio bitrates */
85 ab.ucAudioBitRateMode = 0;
86 ab.dwAudioBitRate = 384000;
87 ab.dwAudioBitRatePeak = ab.dwAudioBitRate;
88 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
89 EU_AUDIO_BIT_RATE_CONTROL, sizeof(tmComResEncAudioBitRate_t), &ab);
90 if (ret != SAA_OK)
91 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
92
93 saa7164_api_set_aspect_ratio(port);
Steven Totheafea212010-07-31 14:48:45 -030094 saa7164_api_set_gop_size(port);
Steven Toth7615e432010-07-31 14:44:53 -030095
96 return ret;
97}
98
99int saa7164_api_get_encoder(struct saa7164_port *port)
100{
101 struct saa7164_dev *dev = port->dev;
102 tmComResEncVideoBitRate_t v;
103 tmComResEncAudioBitRate_t a;
104 tmComResEncVideoInputAspectRatio_t ar;
105 int ret;
106
107 dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, port->hwcfg.sourceid);
108
109 port->encoder_profile = 0;
110 port->video_format = 0;
111 port->video_resolution = 0;
112 port->audio_format = 0;
113
114 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
115 EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
116 if (ret != SAA_OK)
117 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
118
119 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
Steven Tothf6eeece2010-07-31 15:28:18 -0300120 EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), &port->video_resolution);
121 if (ret != SAA_OK)
122 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
123
124 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
Steven Toth7615e432010-07-31 14:44:53 -0300125 EU_VIDEO_FORMAT_CONTROL, sizeof(u8), &port->video_format);
126 if (ret != SAA_OK)
127 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
128
129 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
130 EU_VIDEO_BIT_RATE_CONTROL, sizeof(v), &v);
131 if (ret != SAA_OK)
132 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
133
134 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
135 EU_AUDIO_FORMAT_CONTROL, sizeof(u8), &port->audio_format);
136 if (ret != SAA_OK)
137 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
138
139 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
140 EU_AUDIO_BIT_RATE_CONTROL, sizeof(a), &a);
141 if (ret != SAA_OK)
142 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
143
144 /* Aspect Ratio */
145 ar.width = 0;
146 ar.height = 0;
147 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
148 EU_VIDEO_INPUT_ASPECT_CONTROL,
149 sizeof(tmComResEncVideoInputAspectRatio_t), &ar);
150 if (ret != SAA_OK)
151 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
152
153 dprintk(DBGLVL_ENC, "encoder_profile = %d\n", port->encoder_profile);
154 dprintk(DBGLVL_ENC, "video_format = %d\n", port->video_format);
155 dprintk(DBGLVL_ENC, "audio_format = %d\n", port->audio_format);
156 dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution);
157 dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", v.ucVideoBitRateMode);
158 dprintk(DBGLVL_ENC, "v.dwVideoBitRate = %d\n", v.dwVideoBitRate);
159 dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", v.dwVideoBitRatePeak);
160 dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", a.ucAudioBitRateMode);
161 dprintk(DBGLVL_ENC, "a.dwVideoBitRate = %d\n", a.dwAudioBitRate);
162 dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", a.dwAudioBitRatePeak);
163 dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", ar.width, ar.height);
164
165 return ret;
166}
167
168int saa7164_api_set_aspect_ratio(struct saa7164_port *port)
169{
170 struct saa7164_dev *dev = port->dev;
171 tmComResEncVideoInputAspectRatio_t ar;
172 int ret;
173
174 dprintk(DBGLVL_ENC, "%s(%d)\n", __func__,
175 port->encoder_params.ctl_aspect);
176
177 switch (port->encoder_params.ctl_aspect) {
178 case V4L2_MPEG_VIDEO_ASPECT_1x1:
179 ar.width = 1;
180 ar.height = 1;
181 break;
182 case V4L2_MPEG_VIDEO_ASPECT_4x3:
183 ar.width = 4;
184 ar.height = 3;
185 break;
186 case V4L2_MPEG_VIDEO_ASPECT_16x9:
187 ar.width = 16;
188 ar.height = 9;
189 break;
190 case V4L2_MPEG_VIDEO_ASPECT_221x100:
191 ar.width = 221;
192 ar.height = 100;
193 break;
194 default:
195 BUG();
196 }
197
198 dprintk(DBGLVL_ENC, "%s(%d) now %d:%d\n", __func__,
199 port->encoder_params.ctl_aspect,
200 ar.width, ar.height);
201
202 /* Aspect Ratio */
203 ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
204 EU_VIDEO_INPUT_ASPECT_CONTROL,
205 sizeof(tmComResEncVideoInputAspectRatio_t), &ar);
206 if (ret != SAA_OK)
207 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
208
209 return ret;
210}
211
212int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl)
213{
214 struct saa7164_dev *dev = port->dev;
215 int ret;
216 u16 val;
217
218 if (ctl == PU_BRIGHTNESS_CONTROL)
219 val = port->ctl_brightness;
220 else
221 if (ctl == PU_CONTRAST_CONTROL)
222 val = port->ctl_contrast;
223 else
224 if (ctl == PU_HUE_CONTROL)
225 val = port->ctl_hue;
226 else
227 if (ctl == PU_SATURATION_CONTROL)
228 val = port->ctl_saturation;
229 else
230 if (ctl == PU_SHARPNESS_CONTROL)
231 val = port->ctl_sharpness;
232 else
233 return -EINVAL;
234
235 dprintk(DBGLVL_ENC, "%s() unitid=0x%x ctl=%d, val=%d\n",
236 __func__, port->encunit.vsourceid, ctl, val);
237
238 ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, SET_CUR,
239 ctl, sizeof(u16), &val);
240 if (ret != SAA_OK)
241 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
242
243 return ret;
244}
245
246int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl)
247{
248 struct saa7164_dev *dev = port->dev;
249 int ret;
250 u16 val;
251
252 ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, GET_CUR,
253 ctl, sizeof(u16), &val);
254 if (ret != SAA_OK) {
255 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
256 return ret;
257 }
258
259 dprintk(DBGLVL_ENC, "%s() ctl=%d, val=%d\n",
260 __func__, ctl, val);
261
262 if (ctl == PU_BRIGHTNESS_CONTROL)
263 port->ctl_brightness = val;
264 else
265 if (ctl == PU_CONTRAST_CONTROL)
266 port->ctl_contrast = val;
267 else
268 if (ctl == PU_HUE_CONTROL)
269 port->ctl_hue = val;
270 else
271 if (ctl == PU_SATURATION_CONTROL)
272 port->ctl_saturation = val;
273 else
274 if (ctl == PU_SHARPNESS_CONTROL)
275 port->ctl_sharpness = val;
276
277 return ret;
278}
279
280int saa7164_api_set_videomux(struct saa7164_port *port)
281{
282 struct saa7164_dev *dev = port->dev;
283 u8 inputs[] = { 1, 2, 2, 2, 5, 5, 5 };
284 int ret;
285
286 dprintk(DBGLVL_ENC, "%s() v_mux=%d a_mux=%d\n",
287 __func__, port->mux_input, inputs[ port->mux_input - 1 ]);
288
289 /* Audio Mute */
290 ret = saa7164_api_audio_mute(port, 1);
291 if (ret != SAA_OK)
292 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
293
294 /* Video Mux */
295 ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, SET_CUR,
296 SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
297 if (ret != SAA_OK)
298 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
299 /* Audio Mux */
300 ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR,
301 SU_INPUT_SELECT_CONTROL, sizeof(u8), &inputs[ port->mux_input - 1 ]);
302 if (ret != SAA_OK)
303 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
304 /* Audio UnMute */
305 ret = saa7164_api_audio_mute(port, 0);
306 if (ret != SAA_OK)
307 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
308
309 return ret;
310}
311
312int saa7164_api_audio_mute(struct saa7164_port *port, int mute)
313{
314 struct saa7164_dev *dev = port->dev;
315 u8 v = mute;
316 int ret;
317
318 dprintk(DBGLVL_API, "%s(%d)\n", __func__, mute);
319
320 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
321 MUTE_CONTROL, sizeof(u8), &v);
322 if (ret != SAA_OK)
323 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
324
325 return ret;
326}
327
328/* 0 = silence, 0xff = full */
329int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level)
330{
331 struct saa7164_dev *dev = port->dev;
332 s16 v, min, max;
333 int ret;
334
335 dprintk(DBGLVL_API, "%s(%d)\n", __func__, level);
336
337 /* Obtain the min/max ranges */
338 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MIN,
339 VOLUME_CONTROL, sizeof(u16), &min);
340 if (ret != SAA_OK)
341 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
342
343 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MAX,
344 VOLUME_CONTROL, sizeof(u16), &max);
345 if (ret != SAA_OK)
346 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
347
348 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
349 ( 0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
350 if (ret != SAA_OK)
351 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
352
353 dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v);
354
355 v = level;
356 if (v < min)
357 v = min;
358 if (v > max)
359 v = max;
360
361 /* Left */
362 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
363 ( 0x01 << 8 ) | VOLUME_CONTROL, sizeof(s16), &v);
364 if (ret != SAA_OK)
365 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
366
367 /* Right */
368 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
369 ( 0x02 << 8 ) | VOLUME_CONTROL, sizeof(s16), &v);
370 if (ret != SAA_OK)
371 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
372
373 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
374 ( 0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
375 if (ret != SAA_OK)
376 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
377
378 dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v);
379
380 return ret;
381}
382
383int saa7164_api_set_audio_std(struct saa7164_port *port)
384{
385 struct saa7164_dev *dev = port->dev;
386 tmComResAudioDefaults_t lvl;
387 tmComResTunerStandard_t tvaudio;
388 int ret;
389
390 dprintk(DBGLVL_API, "%s()\n", __func__);
391
392 /* Establish default levels */
393 lvl.ucDecoderLevel = TMHW_LEV_ADJ_DECLEV_DEFAULT;
394 lvl.ucDecoderFM_Level = TMHW_LEV_ADJ_DECLEV_DEFAULT;
395 lvl.ucMonoLevel = TMHW_LEV_ADJ_MONOLEV_DEFAULT;
396 lvl.ucNICAM_Level = TMHW_LEV_ADJ_NICLEV_DEFAULT;
397 lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT;
398 lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT;
399 ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
400 AUDIO_DEFAULT_CONTROL, sizeof(tmComResAudioDefaults_t), &lvl);
401 if (ret != SAA_OK)
402 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
403
404 /* Manually select the appropriate TV audio standard */
405 if (port->encodernorm.id & V4L2_STD_NTSC) {
406 tvaudio.std = TU_STANDARD_NTSC_M;
407 tvaudio.country = 1;
408 } else {
409 tvaudio.std = TU_STANDARD_PAL_I;
410 tvaudio.country = 44;
411 }
412
413 ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
414 TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio);
415 if (ret != SAA_OK)
416 printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", __func__, ret);
417 return ret;
418}
419
420int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect)
421{
422 struct saa7164_dev *dev = port->dev;
423 tmComResTunerStandardAuto_t p;
424 int ret;
425
426 dprintk(DBGLVL_API, "%s(%d)\n", __func__, autodetect);
427
428 /* Disable TV Audio autodetect if not already set (buggy) */
429 if (autodetect)
430 p.mode = TU_STANDARD_AUTO;
431 else
432 p.mode = TU_STANDARD_MANUAL;
433 ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
434 TU_STANDARD_AUTO_CONTROL, sizeof(p), &p);
435 if (ret != SAA_OK)
436 printk(KERN_ERR "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", __func__, ret);
437
438 return ret;
439}
440
441int saa7164_api_get_videomux(struct saa7164_port *port)
442{
443 struct saa7164_dev *dev = port->dev;
444 int ret;
445
446 ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, GET_CUR,
447 SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
448 if (ret != SAA_OK)
449 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
450
451 dprintk(DBGLVL_ENC, "%s() v_mux=%d\n",
452 __func__, port->mux_input);
453
454 return ret;
455}
456
457int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
458{
459 struct saa7164_dev *dev = port->dev;
460
461 u16 len = 0;
462 u8 buf[256];
463 int ret;
464 u8 mas;
465
466 dprintk(DBGLVL_API, "%s()\n", __func__);
467
468 if (port->nr == 0)
469 mas = 0xd0;
470 else
471 mas = 0xe0;
472
473 memset(buf, 0, sizeof(buf));
474
475 buf[0x00] = 0x04;
476 buf[0x01] = 0x00;
477 buf[0x02] = 0x00;
478 buf[0x03] = 0x00;
479
480 buf[0x04] = 0x04;
481 buf[0x05] = 0x00;
482 buf[0x06] = 0x00;
483 buf[0x07] = 0x00;
484
485 buf[0x08] = reg;
486 buf[0x09] = 0x26;
487 buf[0x0a] = mas;
488 buf[0x0b] = 0xb0;
489
490 buf[0x0c] = val;
491 buf[0x0d] = 0x00;
492 buf[0x0e] = 0x00;
493 buf[0x0f] = 0x00;
494
495 ret = saa7164_cmd_send(dev, port->ifunit.unitid, GET_LEN,
496 EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
497 if (ret != SAA_OK) {
498 printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
499 return -EIO;
500 }
501
502 ret = saa7164_cmd_send(dev, port->ifunit.unitid, SET_CUR,
503 EXU_REGISTER_ACCESS_CONTROL, len, &buf);
504 if (ret != SAA_OK)
505 printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
506
507 //saa7164_dumphex16(dev, buf, 16);
508
509 return ret == SAA_OK ? 0 : -EIO;
510}
511
512/* Disable the IF block AGC controls */
513int saa7164_api_configure_dif(struct saa7164_port *port, u32 std)
514{
515 struct saa7164_dev *dev = port->dev;
516 int ret = 0;
517 u8 agc_disable;
518
519 dprintk(DBGLVL_API, "%s(%p, 0x%x)\n", __func__, port, std);
520
521 if (std & V4L2_STD_NTSC) {
522 dprintk(DBGLVL_API, " NTSC\n");
523 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
524 agc_disable = 0;
525 } else if (std & V4L2_STD_PAL_I) {
526 dprintk(DBGLVL_API, " PAL-I\n");
527 saa7164_api_set_dif(port, 0x00, 0x08); /* Video Standard */
528 agc_disable = 0;
529 } else if (std & V4L2_STD_PAL_M) {
530 dprintk(DBGLVL_API, " PAL-M\n");
531 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
532 agc_disable = 0;
533 } else if (std & V4L2_STD_PAL_N) {
534 dprintk(DBGLVL_API, " PAL-N\n");
535 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
536 agc_disable = 0;
537 } else if (std & V4L2_STD_PAL_Nc) {
538 dprintk(DBGLVL_API, " PAL-Nc\n");
539 saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
540 agc_disable = 0;
541 } else if (std & V4L2_STD_PAL_B) {
542 dprintk(DBGLVL_API, " PAL-B\n");
543 saa7164_api_set_dif(port, 0x00, 0x02); /* Video Standard */
544 agc_disable = 0;
545 } else if (std & V4L2_STD_PAL_DK) {
546 dprintk(DBGLVL_API, " PAL-DK\n");
547 saa7164_api_set_dif(port, 0x00, 0x10); /* Video Standard */
548 agc_disable = 0;
549 } else if (std & V4L2_STD_SECAM_L) {
550 dprintk(DBGLVL_API, " SECAM-L\n");
551 saa7164_api_set_dif(port, 0x00, 0x20); /* Video Standard */
552 agc_disable = 0;
553 } else {
554 /* Unknown standard, assume DTV */
555 dprintk(DBGLVL_API, " Unknown (assuming DTV)\n");
556 saa7164_api_set_dif(port, 0x00, 0x80); /* Undefined Video Standard */
557 agc_disable = 1;
558 }
559
560 saa7164_api_set_dif(port, 0x48, 0xa0); /* AGC Functions 1 */
561 saa7164_api_set_dif(port, 0xc0, agc_disable); /* AGC Output Disable */
562 saa7164_api_set_dif(port, 0x7c, 0x04); /* CVBS EQ */
563 saa7164_api_set_dif(port, 0x04, 0x01); /* Active */
564 msleep(100);
565 saa7164_api_set_dif(port, 0x04, 0x00); /* Active (again) */
566 msleep(100);
567
568 return ret;
569}
570
571/* Ensure the dif is in the correct state for the operating mode
572 * (analog / dtv). We only configure the diff through the analog encoder
573 * so when we're in digital mode we need to find the appropriate encoder
574 * and use it to configure the DIF.
575 */
576int saa7164_api_initialize_dif(struct saa7164_port *port)
577{
578 struct saa7164_dev *dev = port->dev;
579 struct saa7164_port *p = 0;
580 int ret = -EINVAL;
581 u32 std = 0;
582
583 if (port->type == SAA7164_MPEG_ENCODER) {
584 /* Pick any analog standard to init the diff.
585 * we'll come back during encoder_init'
586 * and set the correct standard if requried.
587 */
588 std = V4L2_STD_NTSC;
589 } else
590 if (port->type == SAA7164_MPEG_DVB) {
591 if (port->nr == SAA7164_PORT_TS1)
592 p = &dev->ports[ SAA7164_PORT_ENC1 ];
593 else
594 p = &dev->ports[ SAA7164_PORT_ENC2 ];
595 } else
596 BUG();
597
598 if (p)
599 ret = saa7164_api_configure_dif(p, std);
600
601 return ret;
602}
603
Steven Tothadd3f582010-07-31 14:43:07 -0300604int saa7164_api_transition_port(struct saa7164_port *port, u8 mode)
Steven Toth443c12282009-05-09 21:17:28 -0300605{
606 int ret;
607
608 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR,
609 SAA_STATE_CONTROL, sizeof(mode), &mode);
610 if (ret != SAA_OK)
611 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
612
613 return ret;
614}
615
616int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version)
617{
618 int ret;
619
620 ret = saa7164_cmd_send(dev, 0, GET_CUR,
621 GET_FW_VERSION_CONTROL, sizeof(u32), version);
622 if (ret != SAA_OK)
623 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
624
625 return ret;
626}
627
628int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)
629{
630 u8 reg[] = { 0x0f, 0x00 };
631
632 if (buflen < 128)
633 return -ENOMEM;
634
635 /* Assumption: Hauppauge eeprom is at 0xa0 on on bus 0 */
636 /* TODO: Pull the details from the boards struct */
637 return saa7164_api_i2c_read(&dev->i2c_bus[0], 0xa0 >> 1, sizeof(reg),
638 &reg[0], 128, buf);
639}
640
Steven Toth443c12282009-05-09 21:17:28 -0300641
642int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
Steven Tothadd3f582010-07-31 14:43:07 -0300643 struct saa7164_port *port,
Steven Toth443c12282009-05-09 21:17:28 -0300644 tmComResTSFormatDescrHeader_t *tsfmt)
645{
646 dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);
647 dprintk(DBGLVL_API, " bDataOffset = 0x%x\n", tsfmt->bDataOffset);
648 dprintk(DBGLVL_API, " bPacketLength= 0x%x\n", tsfmt->bPacketLength);
649 dprintk(DBGLVL_API, " bStrideLength= 0x%x\n", tsfmt->bStrideLength);
650 dprintk(DBGLVL_API, " bguid = (....)\n");
651
652 /* Cache the hardware configuration in the port */
653
654 port->bufcounter = port->hwcfg.BARLocation;
655 port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
656 port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
657 port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
658 port->bufptr32l = port->hwcfg.BARLocation +
659 (4 * sizeof(u32)) +
660 (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
661 port->bufptr32h = port->hwcfg.BARLocation +
662 (4 * sizeof(u32)) +
663 (sizeof(u32) * port->hwcfg.buffercount);
664 port->bufptr64 = port->hwcfg.BARLocation +
665 (4 * sizeof(u32)) +
666 (sizeof(u32) * port->hwcfg.buffercount);
667 dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n",
668 port->hwcfg.BARLocation);
669
670 dprintk(DBGLVL_API, " = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n",
671 port->nr);
672
673 return 0;
674}
675
Steven Toth7615e432010-07-31 14:44:53 -0300676int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
677 struct saa7164_port *port,
678 tmComResPSFormatDescrHeader_t *fmt)
679{
680 dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", fmt->bFormatIndex);
681 dprintk(DBGLVL_API, " wPacketLength= 0x%x\n", fmt->wPacketLength);
682 dprintk(DBGLVL_API, " wPackLength= 0x%x\n", fmt->wPackLength);
683 dprintk(DBGLVL_API, " bPackDataType= 0x%x\n", fmt->bPackDataType);
684
685 /* Cache the hardware configuration in the port */
686 /* TODO: CHECK THIS in the port config */
687 port->bufcounter = port->hwcfg.BARLocation;
688 port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
689 port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
690 port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
691 port->bufptr32l = port->hwcfg.BARLocation +
692 (4 * sizeof(u32)) +
693 (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
694 port->bufptr32h = port->hwcfg.BARLocation +
695 (4 * sizeof(u32)) +
696 (sizeof(u32) * port->hwcfg.buffercount);
697 port->bufptr64 = port->hwcfg.BARLocation +
698 (4 * sizeof(u32)) +
699 (sizeof(u32) * port->hwcfg.buffercount);
700 dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n",
701 port->hwcfg.BARLocation);
702
703 dprintk(DBGLVL_API, " = VS_FORMAT_MPEGPS (becomes dev->enc[%d])\n",
704 port->nr);
705
706 return 0;
707}
708
Steven Toth443c12282009-05-09 21:17:28 -0300709int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
710{
Steven Toth7615e432010-07-31 14:44:53 -0300711 struct saa7164_port *tsport = 0;
712 struct saa7164_port *encport = 0;
Steven Toth443c12282009-05-09 21:17:28 -0300713 u32 idx, next_offset;
714 int i;
715 tmComResDescrHeader_t *hdr, *t;
716 tmComResExtDevDescrHeader_t *exthdr;
717 tmComResPathDescrHeader_t *pathhdr;
718 tmComResAntTermDescrHeader_t *anttermhdr;
719 tmComResTunerDescrHeader_t *tunerunithdr;
720 tmComResDMATermDescrHeader_t *vcoutputtermhdr;
721 tmComResTSFormatDescrHeader_t *tsfmt;
Steven Toth7615e432010-07-31 14:44:53 -0300722 tmComResPSFormatDescrHeader_t *psfmt;
723 tmComResSelDescrHeader_t *psel;
724 tmComResProcDescrHeader_t *pdh;
725 tmComResAFeatureDescrHeader_t *afd;
726 tmComResEncoderDescrHeader_t *edh;
Steven Toth443c12282009-05-09 21:17:28 -0300727 u32 currpath = 0;
728
729 dprintk(DBGLVL_API,
Steven Toth207b42c2009-05-09 21:30:05 -0300730 "%s(?,?,%d) sizeof(tmComResDescrHeader_t) = %d bytes\n",
731 __func__, len, (u32)sizeof(tmComResDescrHeader_t));
Steven Toth443c12282009-05-09 21:17:28 -0300732
733 for (idx = 0; idx < (len - sizeof(tmComResDescrHeader_t)); ) {
734
735 hdr = (tmComResDescrHeader_t *)(buf + idx);
736
737 if (hdr->type != CS_INTERFACE)
738 return SAA_ERR_NOT_SUPPORTED;
739
740 dprintk(DBGLVL_API, "@ 0x%x = \n", idx);
741 switch (hdr->subtype) {
742 case GENERAL_REQUEST:
743 dprintk(DBGLVL_API, " GENERAL_REQUEST\n");
744 break;
745 case VC_TUNER_PATH:
746 dprintk(DBGLVL_API, " VC_TUNER_PATH\n");
747 pathhdr = (tmComResPathDescrHeader_t *)(buf + idx);
748 dprintk(DBGLVL_API, " pathid = 0x%x\n",
749 pathhdr->pathid);
750 currpath = pathhdr->pathid;
751 break;
752 case VC_INPUT_TERMINAL:
753 dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n");
754 anttermhdr =
755 (tmComResAntTermDescrHeader_t *)(buf + idx);
756 dprintk(DBGLVL_API, " terminalid = 0x%x\n",
757 anttermhdr->terminalid);
758 dprintk(DBGLVL_API, " terminaltype = 0x%x\n",
759 anttermhdr->terminaltype);
760 switch (anttermhdr->terminaltype) {
761 case ITT_ANTENNA:
762 dprintk(DBGLVL_API, " = ITT_ANTENNA\n");
763 break;
764 case LINE_CONNECTOR:
765 dprintk(DBGLVL_API, " = LINE_CONNECTOR\n");
766 break;
767 case SPDIF_CONNECTOR:
768 dprintk(DBGLVL_API, " = SPDIF_CONNECTOR\n");
769 break;
770 case COMPOSITE_CONNECTOR:
771 dprintk(DBGLVL_API,
772 " = COMPOSITE_CONNECTOR\n");
773 break;
774 case SVIDEO_CONNECTOR:
775 dprintk(DBGLVL_API, " = SVIDEO_CONNECTOR\n");
776 break;
777 case COMPONENT_CONNECTOR:
778 dprintk(DBGLVL_API,
779 " = COMPONENT_CONNECTOR\n");
780 break;
781 case STANDARD_DMA:
782 dprintk(DBGLVL_API, " = STANDARD_DMA\n");
783 break;
784 default:
785 dprintk(DBGLVL_API, " = undefined (0x%x)\n",
786 anttermhdr->terminaltype);
787 }
788 dprintk(DBGLVL_API, " assocterminal= 0x%x\n",
789 anttermhdr->assocterminal);
790 dprintk(DBGLVL_API, " iterminal = 0x%x\n",
791 anttermhdr->iterminal);
792 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
793 anttermhdr->controlsize);
794 break;
795 case VC_OUTPUT_TERMINAL:
796 dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n");
797 vcoutputtermhdr =
798 (tmComResDMATermDescrHeader_t *)(buf + idx);
799 dprintk(DBGLVL_API, " unitid = 0x%x\n",
800 vcoutputtermhdr->unitid);
801 dprintk(DBGLVL_API, " terminaltype = 0x%x\n",
802 vcoutputtermhdr->terminaltype);
803 switch (vcoutputtermhdr->terminaltype) {
804 case ITT_ANTENNA:
805 dprintk(DBGLVL_API, " = ITT_ANTENNA\n");
806 break;
807 case LINE_CONNECTOR:
808 dprintk(DBGLVL_API, " = LINE_CONNECTOR\n");
809 break;
810 case SPDIF_CONNECTOR:
811 dprintk(DBGLVL_API, " = SPDIF_CONNECTOR\n");
812 break;
813 case COMPOSITE_CONNECTOR:
814 dprintk(DBGLVL_API,
815 " = COMPOSITE_CONNECTOR\n");
816 break;
817 case SVIDEO_CONNECTOR:
818 dprintk(DBGLVL_API, " = SVIDEO_CONNECTOR\n");
819 break;
820 case COMPONENT_CONNECTOR:
821 dprintk(DBGLVL_API,
822 " = COMPONENT_CONNECTOR\n");
823 break;
824 case STANDARD_DMA:
825 dprintk(DBGLVL_API, " = STANDARD_DMA\n");
826 break;
827 default:
828 dprintk(DBGLVL_API, " = undefined (0x%x)\n",
829 vcoutputtermhdr->terminaltype);
830 }
831 dprintk(DBGLVL_API, " assocterminal= 0x%x\n",
832 vcoutputtermhdr->assocterminal);
833 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
834 vcoutputtermhdr->sourceid);
835 dprintk(DBGLVL_API, " iterminal = 0x%x\n",
836 vcoutputtermhdr->iterminal);
837 dprintk(DBGLVL_API, " BARLocation = 0x%x\n",
838 vcoutputtermhdr->BARLocation);
839 dprintk(DBGLVL_API, " flags = 0x%x\n",
840 vcoutputtermhdr->flags);
841 dprintk(DBGLVL_API, " interruptid = 0x%x\n",
842 vcoutputtermhdr->interruptid);
843 dprintk(DBGLVL_API, " buffercount = 0x%x\n",
844 vcoutputtermhdr->buffercount);
845 dprintk(DBGLVL_API, " metadatasize = 0x%x\n",
846 vcoutputtermhdr->metadatasize);
847 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
848 vcoutputtermhdr->controlsize);
849 dprintk(DBGLVL_API, " numformats = 0x%x\n",
850 vcoutputtermhdr->numformats);
851
852 t = (tmComResDescrHeader_t *)
853 ((tmComResDMATermDescrHeader_t *)(buf + idx));
854 next_offset = idx + (vcoutputtermhdr->len);
855 for (i = 0; i < vcoutputtermhdr->numformats; i++) {
856 t = (tmComResDescrHeader_t *)
857 (buf + next_offset);
858 switch (t->subtype) {
859 case VS_FORMAT_MPEG2TS:
860 tsfmt =
861 (tmComResTSFormatDescrHeader_t *)t;
862 if (currpath == 1)
Steven Toth7615e432010-07-31 14:44:53 -0300863 tsport = &dev->ports[ SAA7164_PORT_TS1 ];
Steven Toth443c12282009-05-09 21:17:28 -0300864 else
Steven Toth7615e432010-07-31 14:44:53 -0300865 tsport = &dev->ports[ SAA7164_PORT_TS2 ];
866 memcpy(&tsport->hwcfg, vcoutputtermhdr,
Steven Toth443c12282009-05-09 21:17:28 -0300867 sizeof(*vcoutputtermhdr));
868 saa7164_api_configure_port_mpeg2ts(dev,
Steven Toth7615e432010-07-31 14:44:53 -0300869 tsport, tsfmt);
Steven Toth443c12282009-05-09 21:17:28 -0300870 break;
871 case VS_FORMAT_MPEG2PS:
Steven Toth7615e432010-07-31 14:44:53 -0300872 psfmt =
873 (tmComResPSFormatDescrHeader_t *)t;
874 if (currpath == 1)
875 encport = &dev->ports[ SAA7164_PORT_ENC1 ];
876 else
877 encport = &dev->ports[ SAA7164_PORT_ENC2 ];
878 memcpy(&encport->hwcfg, vcoutputtermhdr,
879 sizeof(*vcoutputtermhdr));
880 saa7164_api_configure_port_mpeg2ps(dev,
881 encport, psfmt);
Steven Toth443c12282009-05-09 21:17:28 -0300882 break;
883 case VS_FORMAT_VBI:
884 dprintk(DBGLVL_API,
885 " = VS_FORMAT_VBI\n");
886 break;
887 case VS_FORMAT_RDS:
888 dprintk(DBGLVL_API,
889 " = VS_FORMAT_RDS\n");
890 break;
891 case VS_FORMAT_UNCOMPRESSED:
892 dprintk(DBGLVL_API,
893 " = VS_FORMAT_UNCOMPRESSED\n");
894 break;
895 case VS_FORMAT_TYPE:
896 dprintk(DBGLVL_API,
897 " = VS_FORMAT_TYPE\n");
898 break;
899 default:
900 dprintk(DBGLVL_API,
901 " = undefined (0x%x)\n",
902 t->subtype);
903 }
904 next_offset += t->len;
905 }
906
907 break;
908 case TUNER_UNIT:
909 dprintk(DBGLVL_API, " TUNER_UNIT\n");
910 tunerunithdr =
911 (tmComResTunerDescrHeader_t *)(buf + idx);
912 dprintk(DBGLVL_API, " unitid = 0x%x\n",
913 tunerunithdr->unitid);
914 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
915 tunerunithdr->sourceid);
916 dprintk(DBGLVL_API, " iunit = 0x%x\n",
917 tunerunithdr->iunit);
918 dprintk(DBGLVL_API, " tuningstandards = 0x%x\n",
919 tunerunithdr->tuningstandards);
920 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
921 tunerunithdr->controlsize);
922 dprintk(DBGLVL_API, " controls = 0x%x\n",
923 tunerunithdr->controls);
Steven Toth7615e432010-07-31 14:44:53 -0300924
925 if (tunerunithdr->unitid == tunerunithdr->iunit) {
926 if (currpath == 1)
927 encport = &dev->ports[ SAA7164_PORT_ENC1 ];
928 else
929 encport = &dev->ports[ SAA7164_PORT_ENC2 ];
930 memcpy(&encport->tunerunit, tunerunithdr,
931 sizeof(tmComResTunerDescrHeader_t));
932 dprintk(DBGLVL_API, " (becomes dev->enc[%d] tuner)\n", encport->nr);
933 }
Steven Toth443c12282009-05-09 21:17:28 -0300934 break;
935 case VC_SELECTOR_UNIT:
Steven Toth7615e432010-07-31 14:44:53 -0300936 psel = (tmComResSelDescrHeader_t *)(buf + idx);
Steven Toth443c12282009-05-09 21:17:28 -0300937 dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n");
Steven Toth7615e432010-07-31 14:44:53 -0300938 dprintk(DBGLVL_API, " unitid = 0x%x\n",
939 psel->unitid);
940 dprintk(DBGLVL_API, " nrinpins = 0x%x\n",
941 psel->nrinpins);
942 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
943 psel->sourceid);
Steven Toth443c12282009-05-09 21:17:28 -0300944 break;
945 case VC_PROCESSING_UNIT:
Steven Toth7615e432010-07-31 14:44:53 -0300946 pdh = (tmComResProcDescrHeader_t *)(buf + idx);
Steven Toth443c12282009-05-09 21:17:28 -0300947 dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n");
Steven Toth7615e432010-07-31 14:44:53 -0300948 dprintk(DBGLVL_API, " unitid = 0x%x\n",
949 pdh->unitid);
950 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
951 pdh->sourceid);
952 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
953 pdh->controlsize);
954 if (pdh->controlsize == 0x04) {
955 if (currpath == 1)
956 encport = &dev->ports[ SAA7164_PORT_ENC1 ];
957 else
958 encport = &dev->ports[ SAA7164_PORT_ENC2 ];
959 memcpy(&encport->vidproc, pdh,
960 sizeof(tmComResProcDescrHeader_t));
961 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
962 }
Steven Toth443c12282009-05-09 21:17:28 -0300963 break;
964 case FEATURE_UNIT:
Steven Toth7615e432010-07-31 14:44:53 -0300965 afd = (tmComResAFeatureDescrHeader_t *)(buf + idx);
Steven Toth443c12282009-05-09 21:17:28 -0300966 dprintk(DBGLVL_API, " FEATURE_UNIT\n");
Steven Toth7615e432010-07-31 14:44:53 -0300967 dprintk(DBGLVL_API, " unitid = 0x%x\n",
968 afd->unitid);
969 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
970 afd->sourceid);
971 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
972 afd->controlsize);
973 if (currpath == 1)
974 encport = &dev->ports[ SAA7164_PORT_ENC1 ];
975 else
976 encport = &dev->ports[ SAA7164_PORT_ENC2 ];
977 memcpy(&encport->audfeat, afd,
978 sizeof(tmComResAFeatureDescrHeader_t));
979 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
Steven Toth443c12282009-05-09 21:17:28 -0300980 break;
981 case ENCODER_UNIT:
Steven Toth7615e432010-07-31 14:44:53 -0300982 edh = (tmComResEncoderDescrHeader_t *)(buf + idx);
Steven Toth443c12282009-05-09 21:17:28 -0300983 dprintk(DBGLVL_API, " ENCODER_UNIT\n");
Steven Toth7615e432010-07-31 14:44:53 -0300984 dprintk(DBGLVL_API, " subtype = 0x%x\n", edh->subtype);
985 dprintk(DBGLVL_API, " unitid = 0x%x\n", edh->unitid);
986 dprintk(DBGLVL_API, " vsourceid = 0x%x\n", edh->vsourceid);
987 dprintk(DBGLVL_API, " asourceid = 0x%x\n", edh->asourceid);
988 dprintk(DBGLVL_API, " iunit = 0x%x\n", edh->iunit);
989 if (edh->iunit == edh->unitid) {
990 if (currpath == 1)
991 encport = &dev->ports[ SAA7164_PORT_ENC1 ];
992 else
993 encport = &dev->ports[ SAA7164_PORT_ENC2 ];
994 memcpy(&encport->encunit, edh,
995 sizeof(tmComResEncoderDescrHeader_t));
996 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
997 }
Steven Toth443c12282009-05-09 21:17:28 -0300998 break;
999 case EXTENSION_UNIT:
1000 dprintk(DBGLVL_API, " EXTENSION_UNIT\n");
1001 exthdr = (tmComResExtDevDescrHeader_t *)(buf + idx);
1002 dprintk(DBGLVL_API, " unitid = 0x%x\n",
1003 exthdr->unitid);
1004 dprintk(DBGLVL_API, " deviceid = 0x%x\n",
1005 exthdr->deviceid);
1006 dprintk(DBGLVL_API, " devicetype = 0x%x\n",
1007 exthdr->devicetype);
1008 if (exthdr->devicetype & 0x1)
1009 dprintk(DBGLVL_API, " = Decoder Device\n");
1010 if (exthdr->devicetype & 0x2)
1011 dprintk(DBGLVL_API, " = GPIO Source\n");
1012 if (exthdr->devicetype & 0x4)
1013 dprintk(DBGLVL_API, " = Video Decoder\n");
1014 if (exthdr->devicetype & 0x8)
1015 dprintk(DBGLVL_API, " = Audio Decoder\n");
1016 if (exthdr->devicetype & 0x20)
1017 dprintk(DBGLVL_API, " = Crossbar\n");
1018 if (exthdr->devicetype & 0x40)
1019 dprintk(DBGLVL_API, " = Tuner\n");
1020 if (exthdr->devicetype & 0x80)
1021 dprintk(DBGLVL_API, " = IF PLL\n");
1022 if (exthdr->devicetype & 0x100)
1023 dprintk(DBGLVL_API, " = Demodulator\n");
1024 if (exthdr->devicetype & 0x200)
1025 dprintk(DBGLVL_API, " = RDS Decoder\n");
1026 if (exthdr->devicetype & 0x400)
1027 dprintk(DBGLVL_API, " = Encoder\n");
1028 if (exthdr->devicetype & 0x800)
1029 dprintk(DBGLVL_API, " = IR Decoder\n");
1030 if (exthdr->devicetype & 0x1000)
1031 dprintk(DBGLVL_API, " = EEPROM\n");
1032 if (exthdr->devicetype & 0x2000)
1033 dprintk(DBGLVL_API,
1034 " = VBI Decoder\n");
1035 if (exthdr->devicetype & 0x10000)
1036 dprintk(DBGLVL_API,
1037 " = Streaming Device\n");
1038 if (exthdr->devicetype & 0x20000)
1039 dprintk(DBGLVL_API,
1040 " = DRM Device\n");
1041 if (exthdr->devicetype & 0x40000000)
1042 dprintk(DBGLVL_API,
1043 " = Generic Device\n");
1044 if (exthdr->devicetype & 0x80000000)
1045 dprintk(DBGLVL_API,
1046 " = Config Space Device\n");
1047 dprintk(DBGLVL_API, " numgpiopins = 0x%x\n",
1048 exthdr->numgpiopins);
1049 dprintk(DBGLVL_API, " numgpiogroups = 0x%x\n",
1050 exthdr->numgpiogroups);
1051 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
1052 exthdr->controlsize);
Steven Toth7615e432010-07-31 14:44:53 -03001053 if (exthdr->devicetype & 0x80) {
1054 if (currpath == 1)
1055 encport = &dev->ports[ SAA7164_PORT_ENC1 ];
1056 else
1057 encport = &dev->ports[ SAA7164_PORT_ENC2 ];
1058 memcpy(&encport->ifunit, exthdr,
1059 sizeof(tmComResExtDevDescrHeader_t));
1060 dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr);
1061 }
Steven Toth443c12282009-05-09 21:17:28 -03001062 break;
1063 case PVC_INFRARED_UNIT:
1064 dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n");
1065 break;
1066 case DRM_UNIT:
1067 dprintk(DBGLVL_API, " DRM_UNIT\n");
1068 break;
1069 default:
1070 dprintk(DBGLVL_API, "default %d\n", hdr->subtype);
1071 }
1072
1073 dprintk(DBGLVL_API, " 1.%x\n", hdr->len);
1074 dprintk(DBGLVL_API, " 2.%x\n", hdr->type);
1075 dprintk(DBGLVL_API, " 3.%x\n", hdr->subtype);
1076 dprintk(DBGLVL_API, " 4.%x\n", hdr->unitid);
1077
1078 idx += hdr->len;
1079 }
1080
1081 return 0;
1082}
1083
1084int saa7164_api_enum_subdevs(struct saa7164_dev *dev)
1085{
1086 int ret;
1087 u32 buflen = 0;
1088 u8 *buf;
1089
1090 dprintk(DBGLVL_API, "%s()\n", __func__);
1091
1092 /* Get the total descriptor length */
1093 ret = saa7164_cmd_send(dev, 0, GET_LEN,
1094 GET_DESCRIPTORS_CONTROL, sizeof(buflen), &buflen);
1095 if (ret != SAA_OK)
1096 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
1097
1098 dprintk(DBGLVL_API, "%s() total descriptor size = %d bytes.\n",
1099 __func__, buflen);
1100
1101 /* Allocate enough storage for all of the descs */
1102 buf = kzalloc(buflen, GFP_KERNEL);
1103 if (buf == NULL)
1104 return SAA_ERR_NO_RESOURCES;
1105
1106 /* Retrieve them */
1107 ret = saa7164_cmd_send(dev, 0, GET_CUR,
1108 GET_DESCRIPTORS_CONTROL, buflen, buf);
1109 if (ret != SAA_OK) {
1110 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
1111 goto out;
1112 }
1113
Ingo Molnarb1912a852009-09-21 15:23:45 -03001114 if (saa_debug & DBGLVL_API)
Steven Toth443c12282009-05-09 21:17:28 -03001115 saa7164_dumphex16(dev, buf, (buflen/16)*16);
1116
1117 saa7164_api_dump_subdevs(dev, buf, buflen);
1118
1119out:
1120 kfree(buf);
1121 return ret;
1122}
1123
1124int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
1125 u32 datalen, u8 *data)
1126{
1127 struct saa7164_dev *dev = bus->dev;
1128 u16 len = 0;
1129 int unitid;
1130 u32 regval;
1131 u8 buf[256];
1132 int ret;
1133
1134 dprintk(DBGLVL_API, "%s()\n", __func__);
1135
1136 if (reglen > 4)
1137 return -EIO;
1138
1139 if (reglen == 1)
1140 regval = *(reg);
1141 else
1142 if (reglen == 2)
1143 regval = ((*(reg) << 8) || *(reg+1));
1144 else
1145 if (reglen == 3)
1146 regval = ((*(reg) << 16) | (*(reg+1) << 8) | *(reg+2));
1147 else
1148 if (reglen == 4)
1149 regval = ((*(reg) << 24) | (*(reg+1) << 16) |
1150 (*(reg+2) << 8) | *(reg+3));
1151
1152 /* Prepare the send buffer */
1153 /* Bytes 00-03 source register length
1154 * 04-07 source bytes to read
1155 * 08... register address
1156 */
1157 memset(buf, 0, sizeof(buf));
1158 memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen);
1159 *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
1160 *((u32 *)(buf + 1 * sizeof(u32))) = datalen;
1161
1162 unitid = saa7164_i2caddr_to_unitid(bus, addr);
1163 if (unitid < 0) {
1164 printk(KERN_ERR
1165 "%s() error, cannot translate regaddr 0x%x to unitid\n",
1166 __func__, addr);
1167 return -EIO;
1168 }
1169
1170 ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
1171 EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
1172 if (ret != SAA_OK) {
1173 printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
1174 return -EIO;
1175 }
1176
1177 dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
1178
Ingo Molnarb1912a852009-09-21 15:23:45 -03001179 if (saa_debug & DBGLVL_I2C)
Steven Toth443c12282009-05-09 21:17:28 -03001180 saa7164_dumphex16(dev, buf, 2 * 16);
1181
1182 ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR,
1183 EXU_REGISTER_ACCESS_CONTROL, len, &buf);
1184 if (ret != SAA_OK)
1185 printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
1186 else {
Ingo Molnarb1912a852009-09-21 15:23:45 -03001187 if (saa_debug & DBGLVL_I2C)
Steven Toth443c12282009-05-09 21:17:28 -03001188 saa7164_dumphex16(dev, buf, sizeof(buf));
1189 memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen);
1190 }
1191
1192 return ret == SAA_OK ? 0 : -EIO;
1193}
1194
1195/* For a given 8 bit i2c address device, write the buffer */
1196int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
1197 u8 *data)
1198{
1199 struct saa7164_dev *dev = bus->dev;
1200 u16 len = 0;
1201 int unitid;
1202 int reglen;
1203 u8 buf[256];
1204 int ret;
1205
1206 dprintk(DBGLVL_API, "%s()\n", __func__);
1207
1208 if ((datalen == 0) || (datalen > 232))
1209 return -EIO;
1210
1211 memset(buf, 0, sizeof(buf));
1212
1213 unitid = saa7164_i2caddr_to_unitid(bus, addr);
1214 if (unitid < 0) {
1215 printk(KERN_ERR
1216 "%s() error, cannot translate regaddr 0x%x to unitid\n",
1217 __func__, addr);
1218 return -EIO;
1219 }
1220
1221 reglen = saa7164_i2caddr_to_reglen(bus, addr);
Roel Kluinad695512010-01-03 14:04:42 -03001222 if (reglen < 0) {
Steven Toth443c12282009-05-09 21:17:28 -03001223 printk(KERN_ERR
1224 "%s() error, cannot translate regaddr to reglen\n",
1225 __func__);
1226 return -EIO;
1227 }
1228
1229 ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
1230 EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
1231 if (ret != SAA_OK) {
1232 printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
1233 return -EIO;
1234 }
1235
1236 dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
1237
1238 /* Prepare the send buffer */
1239 /* Bytes 00-03 dest register length
1240 * 04-07 dest bytes to write
1241 * 08... register address
1242 */
1243 *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
1244 *((u32 *)(buf + 1 * sizeof(u32))) = datalen - reglen;
1245 memcpy((buf + 2 * sizeof(u32)), data, datalen);
1246
Ingo Molnarb1912a852009-09-21 15:23:45 -03001247 if (saa_debug & DBGLVL_I2C)
Steven Toth443c12282009-05-09 21:17:28 -03001248 saa7164_dumphex16(dev, buf, sizeof(buf));
1249
1250 ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR,
1251 EXU_REGISTER_ACCESS_CONTROL, len, &buf);
1252 if (ret != SAA_OK)
1253 printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
1254
1255 return ret == SAA_OK ? 0 : -EIO;
1256}
1257
1258
1259int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
1260 u8 pin, u8 state)
1261{
1262 int ret;
1263 tmComResGPIO_t t;
1264
1265 dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n",
1266 __func__, unitid, pin, state);
1267
1268 if ((pin > 7) || (state > 2))
1269 return SAA_ERR_BAD_PARAMETER;
1270
1271 t.pin = pin;
1272 t.state = state;
1273
1274 ret = saa7164_cmd_send(dev, unitid, SET_CUR,
1275 EXU_GPIO_CONTROL, sizeof(t), &t);
1276 if (ret != SAA_OK)
1277 printk(KERN_ERR "%s() error, ret = 0x%x\n",
1278 __func__, ret);
1279
1280 return ret;
1281}
1282
1283int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid,
1284 u8 pin)
1285{
1286 return saa7164_api_modify_gpio(dev, unitid, pin, 1);
1287}
1288
1289int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid,
1290 u8 pin)
1291{
1292 return saa7164_api_modify_gpio(dev, unitid, pin, 0);
1293}
1294
1295
1296