include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / 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 #include <linux/slab.h>
24
25 #include "saa7164.h"
26
27 int 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
39 int 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
51 int 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
65 int 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
99 int 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
389 int 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
424 out:
425         kfree(buf);
426         return ret;
427 }
428
429 int 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 */
501 int 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
564 int 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
588 int 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
594 int 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
600
601