flexcop-dma.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
  4. * flexcop-dma.c - configuring and controlling the DMA of the FlexCop
  5. * see flexcop.c for copyright information
  6. */
  7. #include "flexcop.h"
  8. int flexcop_dma_allocate(struct pci_dev *pdev,
  9. struct flexcop_dma *dma, u32 size)
  10. {
  11. u8 *tcpu;
  12. dma_addr_t tdma = 0;
  13. if (size % 2) {
  14. err("dma buffersize has to be even.");
  15. return -EINVAL;
  16. }
  17. tcpu = dma_alloc_coherent(&pdev->dev, size, &tdma, GFP_KERNEL);
  18. if (tcpu != NULL) {
  19. dma->pdev = pdev;
  20. dma->cpu_addr0 = tcpu;
  21. dma->dma_addr0 = tdma;
  22. dma->cpu_addr1 = tcpu + size/2;
  23. dma->dma_addr1 = tdma + size/2;
  24. dma->size = size/2;
  25. return 0;
  26. }
  27. return -ENOMEM;
  28. }
  29. EXPORT_SYMBOL(flexcop_dma_allocate);
  30. void flexcop_dma_free(struct flexcop_dma *dma)
  31. {
  32. dma_free_coherent(&dma->pdev->dev, dma->size * 2, dma->cpu_addr0,
  33. dma->dma_addr0);
  34. memset(dma, 0, sizeof(struct flexcop_dma));
  35. }
  36. EXPORT_SYMBOL(flexcop_dma_free);
  37. int flexcop_dma_config(struct flexcop_device *fc,
  38. struct flexcop_dma *dma,
  39. flexcop_dma_index_t dma_idx)
  40. {
  41. flexcop_ibi_value v0x0, v0x4, v0xc;
  42. v0x0.raw = v0x4.raw = v0xc.raw = 0;
  43. v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
  44. v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
  45. v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
  46. if ((dma_idx & FC_DMA_1) == dma_idx) {
  47. fc->write_ibi_reg(fc, dma1_000, v0x0);
  48. fc->write_ibi_reg(fc, dma1_004, v0x4);
  49. fc->write_ibi_reg(fc, dma1_00c, v0xc);
  50. } else if ((dma_idx & FC_DMA_2) == dma_idx) {
  51. fc->write_ibi_reg(fc, dma2_010, v0x0);
  52. fc->write_ibi_reg(fc, dma2_014, v0x4);
  53. fc->write_ibi_reg(fc, dma2_01c, v0xc);
  54. } else {
  55. err("either DMA1 or DMA2 can be configured within one %s call.",
  56. __func__);
  57. return -EINVAL;
  58. }
  59. return 0;
  60. }
  61. EXPORT_SYMBOL(flexcop_dma_config);
  62. /* start the DMA transfers, but not the DMA IRQs */
  63. int flexcop_dma_xfer_control(struct flexcop_device *fc,
  64. flexcop_dma_index_t dma_idx,
  65. flexcop_dma_addr_index_t index,
  66. int onoff)
  67. {
  68. flexcop_ibi_value v0x0, v0xc;
  69. flexcop_ibi_register r0x0, r0xc;
  70. if ((dma_idx & FC_DMA_1) == dma_idx) {
  71. r0x0 = dma1_000;
  72. r0xc = dma1_00c;
  73. } else if ((dma_idx & FC_DMA_2) == dma_idx) {
  74. r0x0 = dma2_010;
  75. r0xc = dma2_01c;
  76. } else {
  77. err("transfer DMA1 or DMA2 can be started within one %s call.",
  78. __func__);
  79. return -EINVAL;
  80. }
  81. v0x0 = fc->read_ibi_reg(fc, r0x0);
  82. v0xc = fc->read_ibi_reg(fc, r0xc);
  83. deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw);
  84. deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw);
  85. if (index & FC_DMA_SUBADDR_0)
  86. v0x0.dma_0x0.dma_0start = onoff;
  87. if (index & FC_DMA_SUBADDR_1)
  88. v0xc.dma_0xc.dma_1start = onoff;
  89. fc->write_ibi_reg(fc, r0x0, v0x0);
  90. fc->write_ibi_reg(fc, r0xc, v0xc);
  91. deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw);
  92. deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw);
  93. return 0;
  94. }
  95. EXPORT_SYMBOL(flexcop_dma_xfer_control);
  96. static int flexcop_dma_remap(struct flexcop_device *fc,
  97. flexcop_dma_index_t dma_idx,
  98. int onoff)
  99. {
  100. flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
  101. flexcop_ibi_value v = fc->read_ibi_reg(fc, r);
  102. deb_info("%s\n", __func__);
  103. v.dma_0xc.remap_enable = onoff;
  104. fc->write_ibi_reg(fc, r, v);
  105. return 0;
  106. }
  107. int flexcop_dma_control_size_irq(struct flexcop_device *fc,
  108. flexcop_dma_index_t no,
  109. int onoff)
  110. {
  111. flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208);
  112. if (no & FC_DMA_1)
  113. v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
  114. if (no & FC_DMA_2)
  115. v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
  116. fc->write_ibi_reg(fc, ctrl_208, v);
  117. return 0;
  118. }
  119. EXPORT_SYMBOL(flexcop_dma_control_size_irq);
  120. int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
  121. flexcop_dma_index_t no,
  122. int onoff)
  123. {
  124. flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208);
  125. if (no & FC_DMA_1)
  126. v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
  127. if (no & FC_DMA_2)
  128. v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
  129. fc->write_ibi_reg(fc, ctrl_208, v);
  130. return 0;
  131. }
  132. EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
  133. /* 1 cycles = 1.97 msec */
  134. int flexcop_dma_config_timer(struct flexcop_device *fc,
  135. flexcop_dma_index_t dma_idx, u8 cycles)
  136. {
  137. flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
  138. flexcop_ibi_value v = fc->read_ibi_reg(fc, r);
  139. flexcop_dma_remap(fc, dma_idx, 0);
  140. deb_info("%s\n", __func__);
  141. v.dma_0x4_write.dmatimer = cycles;
  142. fc->write_ibi_reg(fc, r, v);
  143. return 0;
  144. }
  145. EXPORT_SYMBOL(flexcop_dma_config_timer);