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 9 int flexcop_dma_allocate(struct pci_dev *pdev, 10 struct flexcop_dma *dma, u32 size) 11 { 12 u8 *tcpu; 13 dma_addr_t tdma = 0; 14 15 if (size % 2) { 16 err("dma buffersize has to be even."); 17 return -EINVAL; 18 } 19 20 tcpu = dma_alloc_coherent(&pdev->dev, size, &tdma, GFP_KERNEL); 21 if (tcpu != NULL) { 22 dma->pdev = pdev; 23 dma->cpu_addr0 = tcpu; 24 dma->dma_addr0 = tdma; 25 dma->cpu_addr1 = tcpu + size/2; 26 dma->dma_addr1 = tdma + size/2; 27 dma->size = size/2; 28 return 0; 29 } 30 return -ENOMEM; 31 } 32 EXPORT_SYMBOL(flexcop_dma_allocate); 33 34 void flexcop_dma_free(struct flexcop_dma *dma) 35 { 36 dma_free_coherent(&dma->pdev->dev, dma->size * 2, dma->cpu_addr0, 37 dma->dma_addr0); 38 memset(dma, 0, sizeof(struct flexcop_dma)); 39 } 40 EXPORT_SYMBOL(flexcop_dma_free); 41 42 int flexcop_dma_config(struct flexcop_device *fc, 43 struct flexcop_dma *dma, 44 flexcop_dma_index_t dma_idx) 45 { 46 flexcop_ibi_value v0x0, v0x4, v0xc; 47 48 v0x0.raw = v0x4.raw = v0xc.raw = 0; 49 v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; 50 v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; 51 v0x4.dma_0x4_write.dma_addr_size = dma->size / 4; 52 53 if ((dma_idx & FC_DMA_1) == dma_idx) { 54 fc->write_ibi_reg(fc, dma1_000, v0x0); 55 fc->write_ibi_reg(fc, dma1_004, v0x4); 56 fc->write_ibi_reg(fc, dma1_00c, v0xc); 57 } else if ((dma_idx & FC_DMA_2) == dma_idx) { 58 fc->write_ibi_reg(fc, dma2_010, v0x0); 59 fc->write_ibi_reg(fc, dma2_014, v0x4); 60 fc->write_ibi_reg(fc, dma2_01c, v0xc); 61 } else { 62 err("either DMA1 or DMA2 can be configured within one %s call.", 63 __func__); 64 return -EINVAL; 65 } 66 67 return 0; 68 } 69 EXPORT_SYMBOL(flexcop_dma_config); 70 71 /* start the DMA transfers, but not the DMA IRQs */ 72 int flexcop_dma_xfer_control(struct flexcop_device *fc, 73 flexcop_dma_index_t dma_idx, 74 flexcop_dma_addr_index_t index, 75 int onoff) 76 { 77 flexcop_ibi_value v0x0, v0xc; 78 flexcop_ibi_register r0x0, r0xc; 79 80 if ((dma_idx & FC_DMA_1) == dma_idx) { 81 r0x0 = dma1_000; 82 r0xc = dma1_00c; 83 } else if ((dma_idx & FC_DMA_2) == dma_idx) { 84 r0x0 = dma2_010; 85 r0xc = dma2_01c; 86 } else { 87 err("transfer DMA1 or DMA2 can be started within one %s call.", 88 __func__); 89 return -EINVAL; 90 } 91 92 v0x0 = fc->read_ibi_reg(fc, r0x0); 93 v0xc = fc->read_ibi_reg(fc, r0xc); 94 95 deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw); 96 deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw); 97 98 if (index & FC_DMA_SUBADDR_0) 99 v0x0.dma_0x0.dma_0start = onoff; 100 101 if (index & FC_DMA_SUBADDR_1) 102 v0xc.dma_0xc.dma_1start = onoff; 103 104 fc->write_ibi_reg(fc, r0x0, v0x0); 105 fc->write_ibi_reg(fc, r0xc, v0xc); 106 107 deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw); 108 deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw); 109 return 0; 110 } 111 EXPORT_SYMBOL(flexcop_dma_xfer_control); 112 113 static int flexcop_dma_remap(struct flexcop_device *fc, 114 flexcop_dma_index_t dma_idx, 115 int onoff) 116 { 117 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c; 118 flexcop_ibi_value v = fc->read_ibi_reg(fc, r); 119 120 deb_info("%s\n", __func__); 121 v.dma_0xc.remap_enable = onoff; 122 fc->write_ibi_reg(fc, r, v); 123 return 0; 124 } 125 126 int flexcop_dma_control_size_irq(struct flexcop_device *fc, 127 flexcop_dma_index_t no, 128 int onoff) 129 { 130 flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208); 131 132 if (no & FC_DMA_1) 133 v.ctrl_208.DMA1_IRQ_Enable_sig = onoff; 134 135 if (no & FC_DMA_2) 136 v.ctrl_208.DMA2_IRQ_Enable_sig = onoff; 137 138 fc->write_ibi_reg(fc, ctrl_208, v); 139 return 0; 140 } 141 EXPORT_SYMBOL(flexcop_dma_control_size_irq); 142 143 int flexcop_dma_control_timer_irq(struct flexcop_device *fc, 144 flexcop_dma_index_t no, 145 int onoff) 146 { 147 flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208); 148 149 if (no & FC_DMA_1) 150 v.ctrl_208.DMA1_Timer_Enable_sig = onoff; 151 152 if (no & FC_DMA_2) 153 v.ctrl_208.DMA2_Timer_Enable_sig = onoff; 154 155 fc->write_ibi_reg(fc, ctrl_208, v); 156 return 0; 157 } 158 EXPORT_SYMBOL(flexcop_dma_control_timer_irq); 159 160 /* 1 cycles = 1.97 msec */ 161 int flexcop_dma_config_timer(struct flexcop_device *fc, 162 flexcop_dma_index_t dma_idx, u8 cycles) 163 { 164 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 165 flexcop_ibi_value v = fc->read_ibi_reg(fc, r); 166 167 flexcop_dma_remap(fc, dma_idx, 0); 168 169 deb_info("%s\n", __func__); 170 v.dma_0x4_write.dmatimer = cycles; 171 fc->write_ibi_reg(fc, r, v); 172 return 0; 173 } 174 EXPORT_SYMBOL(flexcop_dma_config_timer); 175 176