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