saa7164-api.c 17 KB

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