aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7164/saa7164-api.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7164/saa7164-api.c')
-rw-r--r--drivers/media/video/saa7164/saa7164-api.c600
1 files changed, 600 insertions, 0 deletions
diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c
new file mode 100644
index 000000000000..bb6df1b276be
--- /dev/null
+++ b/drivers/media/video/saa7164/saa7164-api.c
@@ -0,0 +1,600 @@
1/*
2 * Driver for the NXP SAA7164 PCIe bridge
3 *
4 * Copyright (c) 2009 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
24#include "saa7164.h"
25
26int saa7164_api_transition_port(struct saa7164_tsport *port, u8 mode)
27{
28 int ret;
29
30 ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR,
31 SAA_STATE_CONTROL, sizeof(mode), &mode);
32 if (ret != SAA_OK)
33 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
34
35 return ret;
36}
37
38int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version)
39{
40 int ret;
41
42 ret = saa7164_cmd_send(dev, 0, GET_CUR,
43 GET_FW_VERSION_CONTROL, sizeof(u32), version);
44 if (ret != SAA_OK)
45 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
46
47 return ret;
48}
49
50int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)
51{
52 u8 reg[] = { 0x0f, 0x00 };
53
54 if (buflen < 128)
55 return -ENOMEM;
56
57 /* Assumption: Hauppauge eeprom is at 0xa0 on on bus 0 */
58 /* TODO: Pull the details from the boards struct */
59 return saa7164_api_i2c_read(&dev->i2c_bus[0], 0xa0 >> 1, sizeof(reg),
60 &reg[0], 128, buf);
61}
62
63
64int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
65 struct saa7164_tsport *port,
66 tmComResTSFormatDescrHeader_t *tsfmt)
67{
68 dprintk(DBGLVL_API, " bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);
69 dprintk(DBGLVL_API, " bDataOffset = 0x%x\n", tsfmt->bDataOffset);
70 dprintk(DBGLVL_API, " bPacketLength= 0x%x\n", tsfmt->bPacketLength);
71 dprintk(DBGLVL_API, " bStrideLength= 0x%x\n", tsfmt->bStrideLength);
72 dprintk(DBGLVL_API, " bguid = (....)\n");
73
74 /* Cache the hardware configuration in the port */
75
76 port->bufcounter = port->hwcfg.BARLocation;
77 port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
78 port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
79 port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
80 port->bufptr32l = port->hwcfg.BARLocation +
81 (4 * sizeof(u32)) +
82 (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
83 port->bufptr32h = port->hwcfg.BARLocation +
84 (4 * sizeof(u32)) +
85 (sizeof(u32) * port->hwcfg.buffercount);
86 port->bufptr64 = port->hwcfg.BARLocation +
87 (4 * sizeof(u32)) +
88 (sizeof(u32) * port->hwcfg.buffercount);
89 dprintk(DBGLVL_API, " = port->hwcfg.BARLocation = 0x%x\n",
90 port->hwcfg.BARLocation);
91
92 dprintk(DBGLVL_API, " = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n",
93 port->nr);
94
95 return 0;
96}
97
98int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
99{
100 struct saa7164_tsport *port = 0;
101 u32 idx, next_offset;
102 int i;
103 tmComResDescrHeader_t *hdr, *t;
104 tmComResExtDevDescrHeader_t *exthdr;
105 tmComResPathDescrHeader_t *pathhdr;
106 tmComResAntTermDescrHeader_t *anttermhdr;
107 tmComResTunerDescrHeader_t *tunerunithdr;
108 tmComResDMATermDescrHeader_t *vcoutputtermhdr;
109 tmComResTSFormatDescrHeader_t *tsfmt;
110 u32 currpath = 0;
111
112 dprintk(DBGLVL_API,
113 "%s(?,?,%d) sizeof(tmComResDescrHeader_t) = %d bytes\n",
114 __func__, len, (u32)sizeof(tmComResDescrHeader_t));
115
116 for (idx = 0; idx < (len - sizeof(tmComResDescrHeader_t)); ) {
117
118 hdr = (tmComResDescrHeader_t *)(buf + idx);
119
120 if (hdr->type != CS_INTERFACE)
121 return SAA_ERR_NOT_SUPPORTED;
122
123 dprintk(DBGLVL_API, "@ 0x%x = \n", idx);
124 switch (hdr->subtype) {
125 case GENERAL_REQUEST:
126 dprintk(DBGLVL_API, " GENERAL_REQUEST\n");
127 break;
128 case VC_TUNER_PATH:
129 dprintk(DBGLVL_API, " VC_TUNER_PATH\n");
130 pathhdr = (tmComResPathDescrHeader_t *)(buf + idx);
131 dprintk(DBGLVL_API, " pathid = 0x%x\n",
132 pathhdr->pathid);
133 currpath = pathhdr->pathid;
134 break;
135 case VC_INPUT_TERMINAL:
136 dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n");
137 anttermhdr =
138 (tmComResAntTermDescrHeader_t *)(buf + idx);
139 dprintk(DBGLVL_API, " terminalid = 0x%x\n",
140 anttermhdr->terminalid);
141 dprintk(DBGLVL_API, " terminaltype = 0x%x\n",
142 anttermhdr->terminaltype);
143 switch (anttermhdr->terminaltype) {
144 case ITT_ANTENNA:
145 dprintk(DBGLVL_API, " = ITT_ANTENNA\n");
146 break;
147 case LINE_CONNECTOR:
148 dprintk(DBGLVL_API, " = LINE_CONNECTOR\n");
149 break;
150 case SPDIF_CONNECTOR:
151 dprintk(DBGLVL_API, " = SPDIF_CONNECTOR\n");
152 break;
153 case COMPOSITE_CONNECTOR:
154 dprintk(DBGLVL_API,
155 " = COMPOSITE_CONNECTOR\n");
156 break;
157 case SVIDEO_CONNECTOR:
158 dprintk(DBGLVL_API, " = SVIDEO_CONNECTOR\n");
159 break;
160 case COMPONENT_CONNECTOR:
161 dprintk(DBGLVL_API,
162 " = COMPONENT_CONNECTOR\n");
163 break;
164 case STANDARD_DMA:
165 dprintk(DBGLVL_API, " = STANDARD_DMA\n");
166 break;
167 default:
168 dprintk(DBGLVL_API, " = undefined (0x%x)\n",
169 anttermhdr->terminaltype);
170 }
171 dprintk(DBGLVL_API, " assocterminal= 0x%x\n",
172 anttermhdr->assocterminal);
173 dprintk(DBGLVL_API, " iterminal = 0x%x\n",
174 anttermhdr->iterminal);
175 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
176 anttermhdr->controlsize);
177 break;
178 case VC_OUTPUT_TERMINAL:
179 dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n");
180 vcoutputtermhdr =
181 (tmComResDMATermDescrHeader_t *)(buf + idx);
182 dprintk(DBGLVL_API, " unitid = 0x%x\n",
183 vcoutputtermhdr->unitid);
184 dprintk(DBGLVL_API, " terminaltype = 0x%x\n",
185 vcoutputtermhdr->terminaltype);
186 switch (vcoutputtermhdr->terminaltype) {
187 case ITT_ANTENNA:
188 dprintk(DBGLVL_API, " = ITT_ANTENNA\n");
189 break;
190 case LINE_CONNECTOR:
191 dprintk(DBGLVL_API, " = LINE_CONNECTOR\n");
192 break;
193 case SPDIF_CONNECTOR:
194 dprintk(DBGLVL_API, " = SPDIF_CONNECTOR\n");
195 break;
196 case COMPOSITE_CONNECTOR:
197 dprintk(DBGLVL_API,
198 " = COMPOSITE_CONNECTOR\n");
199 break;
200 case SVIDEO_CONNECTOR:
201 dprintk(DBGLVL_API, " = SVIDEO_CONNECTOR\n");
202 break;
203 case COMPONENT_CONNECTOR:
204 dprintk(DBGLVL_API,
205 " = COMPONENT_CONNECTOR\n");
206 break;
207 case STANDARD_DMA:
208 dprintk(DBGLVL_API, " = STANDARD_DMA\n");
209 break;
210 default:
211 dprintk(DBGLVL_API, " = undefined (0x%x)\n",
212 vcoutputtermhdr->terminaltype);
213 }
214 dprintk(DBGLVL_API, " assocterminal= 0x%x\n",
215 vcoutputtermhdr->assocterminal);
216 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
217 vcoutputtermhdr->sourceid);
218 dprintk(DBGLVL_API, " iterminal = 0x%x\n",
219 vcoutputtermhdr->iterminal);
220 dprintk(DBGLVL_API, " BARLocation = 0x%x\n",
221 vcoutputtermhdr->BARLocation);
222 dprintk(DBGLVL_API, " flags = 0x%x\n",
223 vcoutputtermhdr->flags);
224 dprintk(DBGLVL_API, " interruptid = 0x%x\n",
225 vcoutputtermhdr->interruptid);
226 dprintk(DBGLVL_API, " buffercount = 0x%x\n",
227 vcoutputtermhdr->buffercount);
228 dprintk(DBGLVL_API, " metadatasize = 0x%x\n",
229 vcoutputtermhdr->metadatasize);
230 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
231 vcoutputtermhdr->controlsize);
232 dprintk(DBGLVL_API, " numformats = 0x%x\n",
233 vcoutputtermhdr->numformats);
234
235 t = (tmComResDescrHeader_t *)
236 ((tmComResDMATermDescrHeader_t *)(buf + idx));
237 next_offset = idx + (vcoutputtermhdr->len);
238 for (i = 0; i < vcoutputtermhdr->numformats; i++) {
239 t = (tmComResDescrHeader_t *)
240 (buf + next_offset);
241 switch (t->subtype) {
242 case VS_FORMAT_MPEG2TS:
243 tsfmt =
244 (tmComResTSFormatDescrHeader_t *)t;
245 if (currpath == 1)
246 port = &dev->ts1;
247 else
248 port = &dev->ts2;
249 memcpy(&port->hwcfg, vcoutputtermhdr,
250 sizeof(*vcoutputtermhdr));
251 saa7164_api_configure_port_mpeg2ts(dev,
252 port, tsfmt);
253 break;
254 case VS_FORMAT_MPEG2PS:
255 dprintk(DBGLVL_API,
256 " = VS_FORMAT_MPEG2PS\n");
257 break;
258 case VS_FORMAT_VBI:
259 dprintk(DBGLVL_API,
260 " = VS_FORMAT_VBI\n");
261 break;
262 case VS_FORMAT_RDS:
263 dprintk(DBGLVL_API,
264 " = VS_FORMAT_RDS\n");
265 break;
266 case VS_FORMAT_UNCOMPRESSED:
267 dprintk(DBGLVL_API,
268 " = VS_FORMAT_UNCOMPRESSED\n");
269 break;
270 case VS_FORMAT_TYPE:
271 dprintk(DBGLVL_API,
272 " = VS_FORMAT_TYPE\n");
273 break;
274 default:
275 dprintk(DBGLVL_API,
276 " = undefined (0x%x)\n",
277 t->subtype);
278 }
279 next_offset += t->len;
280 }
281
282 break;
283 case TUNER_UNIT:
284 dprintk(DBGLVL_API, " TUNER_UNIT\n");
285 tunerunithdr =
286 (tmComResTunerDescrHeader_t *)(buf + idx);
287 dprintk(DBGLVL_API, " unitid = 0x%x\n",
288 tunerunithdr->unitid);
289 dprintk(DBGLVL_API, " sourceid = 0x%x\n",
290 tunerunithdr->sourceid);
291 dprintk(DBGLVL_API, " iunit = 0x%x\n",
292 tunerunithdr->iunit);
293 dprintk(DBGLVL_API, " tuningstandards = 0x%x\n",
294 tunerunithdr->tuningstandards);
295 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
296 tunerunithdr->controlsize);
297 dprintk(DBGLVL_API, " controls = 0x%x\n",
298 tunerunithdr->controls);
299 break;
300 case VC_SELECTOR_UNIT:
301 dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n");
302 break;
303 case VC_PROCESSING_UNIT:
304 dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n");
305 break;
306 case FEATURE_UNIT:
307 dprintk(DBGLVL_API, " FEATURE_UNIT\n");
308 break;
309 case ENCODER_UNIT:
310 dprintk(DBGLVL_API, " ENCODER_UNIT\n");
311 break;
312 case EXTENSION_UNIT:
313 dprintk(DBGLVL_API, " EXTENSION_UNIT\n");
314 exthdr = (tmComResExtDevDescrHeader_t *)(buf + idx);
315 dprintk(DBGLVL_API, " unitid = 0x%x\n",
316 exthdr->unitid);
317 dprintk(DBGLVL_API, " deviceid = 0x%x\n",
318 exthdr->deviceid);
319 dprintk(DBGLVL_API, " devicetype = 0x%x\n",
320 exthdr->devicetype);
321 if (exthdr->devicetype & 0x1)
322 dprintk(DBGLVL_API, " = Decoder Device\n");
323 if (exthdr->devicetype & 0x2)
324 dprintk(DBGLVL_API, " = GPIO Source\n");
325 if (exthdr->devicetype & 0x4)
326 dprintk(DBGLVL_API, " = Video Decoder\n");
327 if (exthdr->devicetype & 0x8)
328 dprintk(DBGLVL_API, " = Audio Decoder\n");
329 if (exthdr->devicetype & 0x20)
330 dprintk(DBGLVL_API, " = Crossbar\n");
331 if (exthdr->devicetype & 0x40)
332 dprintk(DBGLVL_API, " = Tuner\n");
333 if (exthdr->devicetype & 0x80)
334 dprintk(DBGLVL_API, " = IF PLL\n");
335 if (exthdr->devicetype & 0x100)
336 dprintk(DBGLVL_API, " = Demodulator\n");
337 if (exthdr->devicetype & 0x200)
338 dprintk(DBGLVL_API, " = RDS Decoder\n");
339 if (exthdr->devicetype & 0x400)
340 dprintk(DBGLVL_API, " = Encoder\n");
341 if (exthdr->devicetype & 0x800)
342 dprintk(DBGLVL_API, " = IR Decoder\n");
343 if (exthdr->devicetype & 0x1000)
344 dprintk(DBGLVL_API, " = EEPROM\n");
345 if (exthdr->devicetype & 0x2000)
346 dprintk(DBGLVL_API,
347 " = VBI Decoder\n");
348 if (exthdr->devicetype & 0x10000)
349 dprintk(DBGLVL_API,
350 " = Streaming Device\n");
351 if (exthdr->devicetype & 0x20000)
352 dprintk(DBGLVL_API,
353 " = DRM Device\n");
354 if (exthdr->devicetype & 0x40000000)
355 dprintk(DBGLVL_API,
356 " = Generic Device\n");
357 if (exthdr->devicetype & 0x80000000)
358 dprintk(DBGLVL_API,
359 " = Config Space Device\n");
360 dprintk(DBGLVL_API, " numgpiopins = 0x%x\n",
361 exthdr->numgpiopins);
362 dprintk(DBGLVL_API, " numgpiogroups = 0x%x\n",
363 exthdr->numgpiogroups);
364 dprintk(DBGLVL_API, " controlsize = 0x%x\n",
365 exthdr->controlsize);
366 break;
367 case PVC_INFRARED_UNIT:
368 dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n");
369 break;
370 case DRM_UNIT:
371 dprintk(DBGLVL_API, " DRM_UNIT\n");
372 break;
373 default:
374 dprintk(DBGLVL_API, "default %d\n", hdr->subtype);
375 }
376
377 dprintk(DBGLVL_API, " 1.%x\n", hdr->len);
378 dprintk(DBGLVL_API, " 2.%x\n", hdr->type);
379 dprintk(DBGLVL_API, " 3.%x\n", hdr->subtype);
380 dprintk(DBGLVL_API, " 4.%x\n", hdr->unitid);
381
382 idx += hdr->len;
383 }
384
385 return 0;
386}
387
388int saa7164_api_enum_subdevs(struct saa7164_dev *dev)
389{
390 int ret;
391 u32 buflen = 0;
392 u8 *buf;
393
394 dprintk(DBGLVL_API, "%s()\n", __func__);
395
396 /* Get the total descriptor length */
397 ret = saa7164_cmd_send(dev, 0, GET_LEN,
398 GET_DESCRIPTORS_CONTROL, sizeof(buflen), &buflen);
399 if (ret != SAA_OK)
400 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
401
402 dprintk(DBGLVL_API, "%s() total descriptor size = %d bytes.\n",
403 __func__, buflen);
404
405 /* Allocate enough storage for all of the descs */
406 buf = kzalloc(buflen, GFP_KERNEL);
407 if (buf == NULL)
408 return SAA_ERR_NO_RESOURCES;
409
410 /* Retrieve them */
411 ret = saa7164_cmd_send(dev, 0, GET_CUR,
412 GET_DESCRIPTORS_CONTROL, buflen, buf);
413 if (ret != SAA_OK) {
414 printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
415 goto out;
416 }
417
418 if (debug & DBGLVL_API)
419 saa7164_dumphex16(dev, buf, (buflen/16)*16);
420
421 saa7164_api_dump_subdevs(dev, buf, buflen);
422
423out:
424 kfree(buf);
425 return ret;
426}
427
428int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
429 u32 datalen, u8 *data)
430{
431 struct saa7164_dev *dev = bus->dev;
432 u16 len = 0;
433 int unitid;
434 u32 regval;
435 u8 buf[256];
436 int ret;
437
438 dprintk(DBGLVL_API, "%s()\n", __func__);
439
440 if (reglen > 4)
441 return -EIO;
442
443 if (reglen == 1)
444 regval = *(reg);
445 else
446 if (reglen == 2)
447 regval = ((*(reg) << 8) || *(reg+1));
448 else
449 if (reglen == 3)
450 regval = ((*(reg) << 16) | (*(reg+1) << 8) | *(reg+2));
451 else
452 if (reglen == 4)
453 regval = ((*(reg) << 24) | (*(reg+1) << 16) |
454 (*(reg+2) << 8) | *(reg+3));
455
456 /* Prepare the send buffer */
457 /* Bytes 00-03 source register length
458 * 04-07 source bytes to read
459 * 08... register address
460 */
461 memset(buf, 0, sizeof(buf));
462 memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen);
463 *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
464 *((u32 *)(buf + 1 * sizeof(u32))) = datalen;
465
466 unitid = saa7164_i2caddr_to_unitid(bus, addr);
467 if (unitid < 0) {
468 printk(KERN_ERR
469 "%s() error, cannot translate regaddr 0x%x to unitid\n",
470 __func__, addr);
471 return -EIO;
472 }
473
474 ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
475 EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
476 if (ret != SAA_OK) {
477 printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
478 return -EIO;
479 }
480
481 dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
482
483 if (debug & DBGLVL_I2C)
484 saa7164_dumphex16(dev, buf, 2 * 16);
485
486 ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR,
487 EXU_REGISTER_ACCESS_CONTROL, len, &buf);
488 if (ret != SAA_OK)
489 printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
490 else {
491 if (debug & DBGLVL_I2C)
492 saa7164_dumphex16(dev, buf, sizeof(buf));
493 memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen);
494 }
495
496 return ret == SAA_OK ? 0 : -EIO;
497}
498
499/* For a given 8 bit i2c address device, write the buffer */
500int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
501 u8 *data)
502{
503 struct saa7164_dev *dev = bus->dev;
504 u16 len = 0;
505 int unitid;
506 int reglen;
507 u8 buf[256];
508 int ret;
509
510 dprintk(DBGLVL_API, "%s()\n", __func__);
511
512 if ((datalen == 0) || (datalen > 232))
513 return -EIO;
514
515 memset(buf, 0, sizeof(buf));
516
517 unitid = saa7164_i2caddr_to_unitid(bus, addr);
518 if (unitid < 0) {
519 printk(KERN_ERR
520 "%s() error, cannot translate regaddr 0x%x to unitid\n",
521 __func__, addr);
522 return -EIO;
523 }
524
525 reglen = saa7164_i2caddr_to_reglen(bus, addr);
526 if (unitid < 0) {
527 printk(KERN_ERR
528 "%s() error, cannot translate regaddr to reglen\n",
529 __func__);
530 return -EIO;
531 }
532
533 ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
534 EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
535 if (ret != SAA_OK) {
536 printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
537 return -EIO;
538 }
539
540 dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
541
542 /* Prepare the send buffer */
543 /* Bytes 00-03 dest register length
544 * 04-07 dest bytes to write
545 * 08... register address
546 */
547 *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
548 *((u32 *)(buf + 1 * sizeof(u32))) = datalen - reglen;
549 memcpy((buf + 2 * sizeof(u32)), data, datalen);
550
551 if (debug & DBGLVL_I2C)
552 saa7164_dumphex16(dev, buf, sizeof(buf));
553
554 ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR,
555 EXU_REGISTER_ACCESS_CONTROL, len, &buf);
556 if (ret != SAA_OK)
557 printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
558
559 return ret == SAA_OK ? 0 : -EIO;
560}
561
562
563int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
564 u8 pin, u8 state)
565{
566 int ret;
567 tmComResGPIO_t t;
568
569 dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n",
570 __func__, unitid, pin, state);
571
572 if ((pin > 7) || (state > 2))
573 return SAA_ERR_BAD_PARAMETER;
574
575 t.pin = pin;
576 t.state = state;
577
578 ret = saa7164_cmd_send(dev, unitid, SET_CUR,
579 EXU_GPIO_CONTROL, sizeof(t), &t);
580 if (ret != SAA_OK)
581 printk(KERN_ERR "%s() error, ret = 0x%x\n",
582 __func__, ret);
583
584 return ret;
585}
586
587int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid,
588 u8 pin)
589{
590 return saa7164_api_modify_gpio(dev, unitid, pin, 1);
591}
592
593int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid,
594 u8 pin)
595{
596 return saa7164_api_modify_gpio(dev, unitid, pin, 0);
597}
598
599
600