saa7164-api.c 17 KB

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