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