Merge branch 'writeback' of git://git.kernel.dk/linux-2.6-block
[pandora-kernel.git] / drivers / media / video / saa7164 / saa7164-api.c
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
26 int 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
38 int 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
50 int 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
64 int 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
98 int 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
388 int 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 (saa_debug & DBGLVL_API)
419                 saa7164_dumphex16(dev, buf, (buflen/16)*16);
420
421         saa7164_api_dump_subdevs(dev, buf, buflen);
422
423 out:
424         kfree(buf);
425         return ret;
426 }
427
428 int 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 (saa_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 (saa_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 */
500 int 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 (saa_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
563 int 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
587 int 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
593 int 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