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