Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
0004  * flexcop-dma.c - configuring and controlling the DMA of the FlexCop
0005  * see flexcop.c for copyright information
0006  */
0007 #include "flexcop.h"
0008 
0009 int flexcop_dma_allocate(struct pci_dev *pdev,
0010         struct flexcop_dma *dma, u32 size)
0011 {
0012     u8 *tcpu;
0013     dma_addr_t tdma = 0;
0014 
0015     if (size % 2) {
0016         err("dma buffersize has to be even.");
0017         return -EINVAL;
0018     }
0019 
0020     tcpu = dma_alloc_coherent(&pdev->dev, size, &tdma, GFP_KERNEL);
0021     if (tcpu != NULL) {
0022         dma->pdev = pdev;
0023         dma->cpu_addr0 = tcpu;
0024         dma->dma_addr0 = tdma;
0025         dma->cpu_addr1 = tcpu + size/2;
0026         dma->dma_addr1 = tdma + size/2;
0027         dma->size = size/2;
0028         return 0;
0029     }
0030     return -ENOMEM;
0031 }
0032 EXPORT_SYMBOL(flexcop_dma_allocate);
0033 
0034 void flexcop_dma_free(struct flexcop_dma *dma)
0035 {
0036     dma_free_coherent(&dma->pdev->dev, dma->size * 2, dma->cpu_addr0,
0037               dma->dma_addr0);
0038     memset(dma, 0, sizeof(struct flexcop_dma));
0039 }
0040 EXPORT_SYMBOL(flexcop_dma_free);
0041 
0042 int flexcop_dma_config(struct flexcop_device *fc,
0043         struct flexcop_dma *dma,
0044         flexcop_dma_index_t dma_idx)
0045 {
0046     flexcop_ibi_value v0x0, v0x4, v0xc;
0047 
0048     v0x0.raw = v0x4.raw = v0xc.raw = 0;
0049     v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
0050     v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
0051     v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
0052 
0053     if ((dma_idx & FC_DMA_1) == dma_idx) {
0054         fc->write_ibi_reg(fc, dma1_000, v0x0);
0055         fc->write_ibi_reg(fc, dma1_004, v0x4);
0056         fc->write_ibi_reg(fc, dma1_00c, v0xc);
0057     } else if ((dma_idx & FC_DMA_2) == dma_idx) {
0058         fc->write_ibi_reg(fc, dma2_010, v0x0);
0059         fc->write_ibi_reg(fc, dma2_014, v0x4);
0060         fc->write_ibi_reg(fc, dma2_01c, v0xc);
0061     } else {
0062         err("either DMA1 or DMA2 can be configured within one %s call.",
0063             __func__);
0064         return -EINVAL;
0065     }
0066 
0067     return 0;
0068 }
0069 EXPORT_SYMBOL(flexcop_dma_config);
0070 
0071 /* start the DMA transfers, but not the DMA IRQs */
0072 int flexcop_dma_xfer_control(struct flexcop_device *fc,
0073         flexcop_dma_index_t dma_idx,
0074         flexcop_dma_addr_index_t index,
0075         int onoff)
0076 {
0077     flexcop_ibi_value v0x0, v0xc;
0078     flexcop_ibi_register r0x0, r0xc;
0079 
0080     if ((dma_idx & FC_DMA_1) == dma_idx) {
0081         r0x0 = dma1_000;
0082         r0xc = dma1_00c;
0083     } else if ((dma_idx & FC_DMA_2) == dma_idx) {
0084         r0x0 = dma2_010;
0085         r0xc = dma2_01c;
0086     } else {
0087         err("transfer DMA1 or DMA2 can be started within one %s call.",
0088             __func__);
0089         return -EINVAL;
0090     }
0091 
0092     v0x0 = fc->read_ibi_reg(fc, r0x0);
0093     v0xc = fc->read_ibi_reg(fc, r0xc);
0094 
0095     deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw);
0096     deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw);
0097 
0098     if (index & FC_DMA_SUBADDR_0)
0099         v0x0.dma_0x0.dma_0start = onoff;
0100 
0101     if (index & FC_DMA_SUBADDR_1)
0102         v0xc.dma_0xc.dma_1start = onoff;
0103 
0104     fc->write_ibi_reg(fc, r0x0, v0x0);
0105     fc->write_ibi_reg(fc, r0xc, v0xc);
0106 
0107     deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw);
0108     deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw);
0109     return 0;
0110 }
0111 EXPORT_SYMBOL(flexcop_dma_xfer_control);
0112 
0113 static int flexcop_dma_remap(struct flexcop_device *fc,
0114         flexcop_dma_index_t dma_idx,
0115         int onoff)
0116 {
0117     flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
0118     flexcop_ibi_value v = fc->read_ibi_reg(fc, r);
0119 
0120     deb_info("%s\n", __func__);
0121     v.dma_0xc.remap_enable = onoff;
0122     fc->write_ibi_reg(fc, r, v);
0123     return 0;
0124 }
0125 
0126 int flexcop_dma_control_size_irq(struct flexcop_device *fc,
0127         flexcop_dma_index_t no,
0128         int onoff)
0129 {
0130     flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208);
0131 
0132     if (no & FC_DMA_1)
0133         v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
0134 
0135     if (no & FC_DMA_2)
0136         v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
0137 
0138     fc->write_ibi_reg(fc, ctrl_208, v);
0139     return 0;
0140 }
0141 EXPORT_SYMBOL(flexcop_dma_control_size_irq);
0142 
0143 int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
0144         flexcop_dma_index_t no,
0145         int onoff)
0146 {
0147     flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208);
0148 
0149     if (no & FC_DMA_1)
0150         v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
0151 
0152     if (no & FC_DMA_2)
0153         v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
0154 
0155     fc->write_ibi_reg(fc, ctrl_208, v);
0156     return 0;
0157 }
0158 EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
0159 
0160 /* 1 cycles = 1.97 msec */
0161 int flexcop_dma_config_timer(struct flexcop_device *fc,
0162         flexcop_dma_index_t dma_idx, u8 cycles)
0163 {
0164     flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
0165     flexcop_ibi_value v = fc->read_ibi_reg(fc, r);
0166 
0167     flexcop_dma_remap(fc, dma_idx, 0);
0168 
0169     deb_info("%s\n", __func__);
0170     v.dma_0x4_write.dmatimer = cycles;
0171     fc->write_ibi_reg(fc, r, v);
0172     return 0;
0173 }
0174 EXPORT_SYMBOL(flexcop_dma_config_timer);
0175