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