/kern_oII/drivers/staging/go7007/saa7134-go7007.c

http://omnia2droid.googlecode.com/ · C · 532 lines · 408 code · 81 blank · 43 comment · 41 complexity · f1c445536c165977536f3e974a7fd137 MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2006 Micronas USA Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License (Version 2) as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software Foundation,
  15. * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/init.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/wait.h>
  22. #include <linux/list.h>
  23. #include <linux/slab.h>
  24. #include <linux/time.h>
  25. #include <linux/mm.h>
  26. #include <linux/usb.h>
  27. #include <linux/i2c.h>
  28. #include <asm/byteorder.h>
  29. #include <media/v4l2-common.h>
  30. #include "saa7134-reg.h"
  31. #include "saa7134.h"
  32. #include "go7007-priv.h"
  33. #define GO7007_HPI_DEBUG
  34. enum hpi_address {
  35. HPI_ADDR_VIDEO_BUFFER = 0xe4,
  36. HPI_ADDR_INIT_BUFFER = 0xea,
  37. HPI_ADDR_INTR_RET_VALUE = 0xee,
  38. HPI_ADDR_INTR_RET_DATA = 0xec,
  39. HPI_ADDR_INTR_STATUS = 0xf4,
  40. HPI_ADDR_INTR_WR_PARAM = 0xf6,
  41. HPI_ADDR_INTR_WR_INDEX = 0xf8,
  42. };
  43. enum gpio_command {
  44. GPIO_COMMAND_RESET = 0x00, /* 000b */
  45. GPIO_COMMAND_REQ1 = 0x04, /* 001b */
  46. GPIO_COMMAND_WRITE = 0x20, /* 010b */
  47. GPIO_COMMAND_REQ2 = 0x24, /* 011b */
  48. GPIO_COMMAND_READ = 0x80, /* 100b */
  49. GPIO_COMMAND_VIDEO = 0x84, /* 101b */
  50. GPIO_COMMAND_IDLE = 0xA0, /* 110b */
  51. GPIO_COMMAND_ADDR = 0xA4, /* 111b */
  52. };
  53. struct saa7134_go7007 {
  54. struct saa7134_dev *dev;
  55. u8 *top;
  56. u8 *bottom;
  57. dma_addr_t top_dma;
  58. dma_addr_t bottom_dma;
  59. };
  60. static struct go7007_board_info board_voyager = {
  61. .firmware = "go7007tv.bin",
  62. .flags = 0,
  63. .sensor_flags = GO7007_SENSOR_656 |
  64. GO7007_SENSOR_VALID_ENABLE |
  65. GO7007_SENSOR_TV |
  66. GO7007_SENSOR_VBI,
  67. .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
  68. GO7007_AUDIO_WORD_16,
  69. .audio_rate = 48000,
  70. .audio_bclk_div = 8,
  71. .audio_main_div = 2,
  72. .hpi_buffer_cap = 7,
  73. .num_inputs = 1,
  74. .inputs = {
  75. {
  76. .name = "SAA7134",
  77. },
  78. },
  79. };
  80. /********************* Driver for GPIO HPI interface *********************/
  81. static int gpio_write(struct saa7134_dev *dev, u8 addr, u16 data)
  82. {
  83. saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
  84. /* Write HPI address */
  85. saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
  86. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
  87. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  88. /* Write low byte */
  89. saa_writeb(SAA7134_GPIO_GPSTATUS0, data & 0xff);
  90. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
  91. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  92. /* Write high byte */
  93. saa_writeb(SAA7134_GPIO_GPSTATUS0, data >> 8);
  94. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
  95. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  96. return 0;
  97. }
  98. static int gpio_read(struct saa7134_dev *dev, u8 addr, u16 *data)
  99. {
  100. saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
  101. /* Write HPI address */
  102. saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
  103. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
  104. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  105. saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
  106. /* Read low byte */
  107. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
  108. saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  109. saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  110. *data = saa_readb(SAA7134_GPIO_GPSTATUS0);
  111. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  112. /* Read high byte */
  113. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
  114. saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  115. saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  116. *data |= saa_readb(SAA7134_GPIO_GPSTATUS0) << 8;
  117. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  118. return 0;
  119. }
  120. static int saa7134_go7007_interface_reset(struct go7007 *go)
  121. {
  122. struct saa7134_go7007 *saa = go->hpi_context;
  123. struct saa7134_dev *dev = saa->dev;
  124. u32 status;
  125. u16 intr_val, intr_data;
  126. int count = 20;
  127. saa_clearb(SAA7134_TS_PARALLEL, 0x80); /* Disable TS interface */
  128. saa_writeb(SAA7134_GPIO_GPMODE2, 0xa4);
  129. saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
  130. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
  131. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_RESET);
  132. msleep(1);
  133. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
  134. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
  135. msleep(10);
  136. saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  137. saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  138. status = saa_readb(SAA7134_GPIO_GPSTATUS2);
  139. /*printk(KERN_DEBUG "status is %s\n", status & 0x40 ? "OK" : "not OK"); */
  140. /* enter command mode...(?) */
  141. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
  142. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
  143. do {
  144. saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  145. saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
  146. status = saa_readb(SAA7134_GPIO_GPSTATUS2);
  147. /*printk(KERN_INFO "gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */
  148. } while (--count > 0);
  149. /* Wait for an interrupt to indicate successful hardware reset */
  150. if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
  151. (intr_val & ~0x1) != 0x55aa) {
  152. printk(KERN_ERR
  153. "saa7134-go7007: unable to reset the GO7007\n");
  154. return -1;
  155. }
  156. return 0;
  157. }
  158. static int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data)
  159. {
  160. struct saa7134_go7007 *saa = go->hpi_context;
  161. struct saa7134_dev *dev = saa->dev;
  162. int i;
  163. u16 status_reg;
  164. #ifdef GO7007_HPI_DEBUG
  165. printk(KERN_DEBUG
  166. "saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data);
  167. #endif
  168. for (i = 0; i < 100; ++i) {
  169. gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
  170. if (!(status_reg & 0x0010))
  171. break;
  172. msleep(10);
  173. }
  174. if (i == 100) {
  175. printk(KERN_ERR
  176. "saa7134-go7007: device is hung, status reg = 0x%04x\n",
  177. status_reg);
  178. return -1;
  179. }
  180. gpio_write(dev, HPI_ADDR_INTR_WR_PARAM, data);
  181. gpio_write(dev, HPI_ADDR_INTR_WR_INDEX, addr);
  182. return 0;
  183. }
  184. static int saa7134_go7007_read_interrupt(struct go7007 *go)
  185. {
  186. struct saa7134_go7007 *saa = go->hpi_context;
  187. struct saa7134_dev *dev = saa->dev;
  188. /* XXX we need to wait if there is no interrupt available */
  189. go->interrupt_available = 1;
  190. gpio_read(dev, HPI_ADDR_INTR_RET_VALUE, &go->interrupt_value);
  191. gpio_read(dev, HPI_ADDR_INTR_RET_DATA, &go->interrupt_data);
  192. #ifdef GO7007_HPI_DEBUG
  193. printk(KERN_DEBUG "saa7134-go7007: ReadInterrupt: %04x %04x\n",
  194. go->interrupt_value, go->interrupt_data);
  195. #endif
  196. return 0;
  197. }
  198. static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
  199. unsigned long status)
  200. {
  201. struct go7007 *go = video_get_drvdata(dev->empress_dev);
  202. struct saa7134_go7007 *saa = go->hpi_context;
  203. if (!go->streaming)
  204. return;
  205. if (0 != (status & 0x000f0000))
  206. printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
  207. (status >> 16) & 0x0f);
  208. if (status & 0x100000) {
  209. dma_sync_single(&dev->pci->dev,
  210. saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE);
  211. go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE);
  212. saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
  213. } else {
  214. dma_sync_single(&dev->pci->dev,
  215. saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE);
  216. go7007_parse_video_stream(go, saa->top, PAGE_SIZE);
  217. saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
  218. }
  219. }
  220. static int saa7134_go7007_stream_start(struct go7007 *go)
  221. {
  222. struct saa7134_go7007 *saa = go->hpi_context;
  223. struct saa7134_dev *dev = saa->dev;
  224. saa->top_dma = dma_map_page(&dev->pci->dev, virt_to_page(saa->top),
  225. 0, PAGE_SIZE, DMA_FROM_DEVICE);
  226. if (!saa->top_dma)
  227. return -ENOMEM;
  228. saa->bottom_dma = dma_map_page(&dev->pci->dev,
  229. virt_to_page(saa->bottom),
  230. 0, PAGE_SIZE, DMA_FROM_DEVICE);
  231. if (!saa->bottom_dma) {
  232. dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
  233. DMA_FROM_DEVICE);
  234. return -ENOMEM;
  235. }
  236. saa_writel(SAA7134_VIDEO_PORT_CTRL0 >> 2, 0xA300B000);
  237. saa_writel(SAA7134_VIDEO_PORT_CTRL4 >> 2, 0x40000200);
  238. /* Set HPI interface for video */
  239. saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
  240. saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_VIDEO_BUFFER);
  241. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
  242. saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
  243. /* Enable TS interface */
  244. saa_writeb(SAA7134_TS_PARALLEL, 0xe6);
  245. /* Reset TS interface */
  246. saa_setb(SAA7134_TS_SERIAL1, 0x01);
  247. saa_clearb(SAA7134_TS_SERIAL1, 0x01);
  248. /* Set up transfer block size */
  249. saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 128 - 1);
  250. saa_writeb(SAA7134_TS_DMA0, (PAGE_SIZE >> 7) - 1);
  251. saa_writeb(SAA7134_TS_DMA1, 0);
  252. saa_writeb(SAA7134_TS_DMA2, 0);
  253. /* Enable video streaming mode */
  254. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_VIDEO);
  255. saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
  256. saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
  257. saa_writel(SAA7134_RS_PITCH(5), 128);
  258. saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_MAX);
  259. /* Enable TS FIFO */
  260. saa_setl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
  261. /* Enable DMA IRQ */
  262. saa_setl(SAA7134_IRQ1,
  263. SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
  264. return 0;
  265. }
  266. static int saa7134_go7007_stream_stop(struct go7007 *go)
  267. {
  268. struct saa7134_go7007 *saa = go->hpi_context;
  269. struct saa7134_dev *dev;
  270. if (!saa)
  271. return -EINVAL;
  272. dev = saa->dev;
  273. if (!dev)
  274. return -EINVAL;
  275. /* Shut down TS FIFO */
  276. saa_clearl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
  277. /* Disable DMA IRQ */
  278. saa_clearl(SAA7134_IRQ1,
  279. SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
  280. /* Disable TS interface */
  281. saa_clearb(SAA7134_TS_PARALLEL, 0x80);
  282. dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
  283. DMA_FROM_DEVICE);
  284. dma_unmap_page(&dev->pci->dev, saa->bottom_dma, PAGE_SIZE,
  285. DMA_FROM_DEVICE);
  286. return 0;
  287. }
  288. static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
  289. {
  290. struct saa7134_go7007 *saa = go->hpi_context;
  291. struct saa7134_dev *dev = saa->dev;
  292. u16 status_reg;
  293. int i;
  294. #ifdef GO7007_HPI_DEBUG
  295. printk(KERN_DEBUG "saa7134-go7007: DownloadBuffer "
  296. "sending %d bytes\n", len);
  297. #endif
  298. while (len > 0) {
  299. i = len > 64 ? 64 : len;
  300. saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
  301. saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_INIT_BUFFER);
  302. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
  303. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  304. while (i-- > 0) {
  305. saa_writeb(SAA7134_GPIO_GPSTATUS0, *data);
  306. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
  307. saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
  308. ++data;
  309. --len;
  310. }
  311. for (i = 0; i < 100; ++i) {
  312. gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
  313. if (!(status_reg & 0x0002))
  314. break;
  315. }
  316. if (i == 100) {
  317. printk(KERN_ERR "saa7134-go7007: device is hung, "
  318. "status reg = 0x%04x\n", status_reg);
  319. return -1;
  320. }
  321. }
  322. return 0;
  323. }
  324. static int saa7134_go7007_send_command(struct go7007 *go, unsigned int cmd,
  325. void *arg)
  326. {
  327. struct saa7134_go7007 *saa = go->hpi_context;
  328. struct saa7134_dev *dev = saa->dev;
  329. switch (cmd) {
  330. case VIDIOC_S_STD:
  331. {
  332. v4l2_std_id *std = arg;
  333. return saa7134_s_std_internal(dev, NULL, std);
  334. }
  335. case VIDIOC_G_STD:
  336. {
  337. v4l2_std_id *std = arg;
  338. *std = dev->tvnorm->id;
  339. return 0;
  340. }
  341. case VIDIOC_QUERYCTRL:
  342. {
  343. struct v4l2_queryctrl *ctrl = arg;
  344. if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
  345. return saa7134_queryctrl(NULL, NULL, ctrl);
  346. }
  347. case VIDIOC_G_CTRL:
  348. {
  349. struct v4l2_control *ctrl = arg;
  350. if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
  351. return saa7134_g_ctrl_internal(dev, NULL, ctrl);
  352. }
  353. case VIDIOC_S_CTRL:
  354. {
  355. struct v4l2_control *ctrl = arg;
  356. if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
  357. return saa7134_s_ctrl_internal(dev, NULL, ctrl);
  358. }
  359. }
  360. return -EINVAL;
  361. }
  362. static struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
  363. .interface_reset = saa7134_go7007_interface_reset,
  364. .write_interrupt = saa7134_go7007_write_interrupt,
  365. .read_interrupt = saa7134_go7007_read_interrupt,
  366. .stream_start = saa7134_go7007_stream_start,
  367. .stream_stop = saa7134_go7007_stream_stop,
  368. .send_firmware = saa7134_go7007_send_firmware,
  369. .send_command = saa7134_go7007_send_command,
  370. };
  371. /********************* Add/remove functions *********************/
  372. static int saa7134_go7007_init(struct saa7134_dev *dev)
  373. {
  374. struct go7007 *go;
  375. struct saa7134_go7007 *saa;
  376. printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n");
  377. saa = kmalloc(sizeof(struct saa7134_go7007), GFP_KERNEL);
  378. if (saa == NULL)
  379. return -ENOMEM;
  380. memset(saa, 0, sizeof(struct saa7134_go7007));
  381. /* Allocate a couple pages for receiving the compressed stream */
  382. saa->top = (u8 *)get_zeroed_page(GFP_KERNEL);
  383. if (!saa->top)
  384. goto allocfail;
  385. saa->bottom = (u8 *)get_zeroed_page(GFP_KERNEL);
  386. if (!saa->bottom)
  387. goto allocfail;
  388. go = go7007_alloc(&board_voyager, &dev->pci->dev);
  389. if (go == NULL)
  390. goto allocfail;
  391. go->board_id = GO7007_BOARDID_PCI_VOYAGER;
  392. strncpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
  393. go->hpi_ops = &saa7134_go7007_hpi_ops;
  394. go->hpi_context = saa;
  395. saa->dev = dev;
  396. /* Boot the GO7007 */
  397. if (go7007_boot_encoder(go, go->board_info->flags &
  398. GO7007_BOARD_USE_ONBOARD_I2C) < 0)
  399. goto initfail;
  400. /* Do any final GO7007 initialization, then register the
  401. * V4L2 and ALSA interfaces */
  402. if (go7007_register_encoder(go) < 0)
  403. goto initfail;
  404. dev->empress_dev = go->video_dev;
  405. video_set_drvdata(dev->empress_dev, go);
  406. go->status = STATUS_ONLINE;
  407. return 0;
  408. initfail:
  409. go->status = STATUS_SHUTDOWN;
  410. return 0;
  411. allocfail:
  412. if (saa->top)
  413. free_page((unsigned long)saa->top);
  414. if (saa->bottom)
  415. free_page((unsigned long)saa->bottom);
  416. kfree(saa);
  417. return -ENOMEM;
  418. }
  419. static int saa7134_go7007_fini(struct saa7134_dev *dev)
  420. {
  421. struct go7007 *go;
  422. struct saa7134_go7007 *saa;
  423. if (NULL == dev->empress_dev)
  424. return 0;
  425. go = video_get_drvdata(dev->empress_dev);
  426. saa = go->hpi_context;
  427. go->status = STATUS_SHUTDOWN;
  428. free_page((unsigned long)saa->top);
  429. free_page((unsigned long)saa->bottom);
  430. kfree(saa);
  431. go7007_remove(go);
  432. dev->empress_dev = NULL;
  433. return 0;
  434. }
  435. static struct saa7134_mpeg_ops saa7134_go7007_ops = {
  436. .type = SAA7134_MPEG_GO7007,
  437. .init = saa7134_go7007_init,
  438. .fini = saa7134_go7007_fini,
  439. .irq_ts_done = saa7134_go7007_irq_ts_done,
  440. };
  441. static int __init saa7134_go7007_mod_init(void)
  442. {
  443. return saa7134_ts_register(&saa7134_go7007_ops);
  444. }
  445. static void __exit saa7134_go7007_mod_cleanup(void)
  446. {
  447. saa7134_ts_unregister(&saa7134_go7007_ops);
  448. }
  449. module_init(saa7134_go7007_mod_init);
  450. module_exit(saa7134_go7007_mod_cleanup);
  451. MODULE_LICENSE("GPL v2");