This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / media / dvb / b2c2 / flexcop-dma.c
1 /*
2  * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
3  *
4  * flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop.
5  *
6  * see flexcop.c for copyright information.
7  */
8 #include "flexcop.h"
9
10 int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size)
11 {
12         u8 *tcpu;
13         dma_addr_t tdma;
14
15         if (size % 2) {
16                 err("dma buffersize has to be even.");
17                 return -EINVAL;
18         }
19
20         if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) {
21                 dma->pdev = pdev;
22                 dma->cpu_addr0 = tcpu;
23                 dma->dma_addr0 = tdma;
24                 dma->cpu_addr1 = tcpu + size/2;
25                 dma->dma_addr1 = tdma + size/2;
26                 dma->size = size/2;
27                 return 0;
28         }
29         return -ENOMEM;
30 }
31 EXPORT_SYMBOL(flexcop_dma_allocate);
32
33 void flexcop_dma_free(struct flexcop_dma *dma)
34 {
35         pci_free_consistent(dma->pdev, dma->size*2,dma->cpu_addr0, dma->dma_addr0);
36         memset(dma,0,sizeof(struct flexcop_dma));
37 }
38 EXPORT_SYMBOL(flexcop_dma_free);
39
40 int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
41 {
42         flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
43
44         if (no & FC_DMA_1)
45                 v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
46
47         if (no & FC_DMA_2)
48                 v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
49
50         fc->write_ibi_reg(fc,ctrl_208,v);
51         return 0;
52 }
53 EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
54
55 int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
56 {
57         flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
58
59         if (no & FC_DMA_1)
60                 v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
61
62         if (no & FC_DMA_2)
63                 v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
64
65         fc->write_ibi_reg(fc,ctrl_208,v);
66         return 0;
67 }
68 EXPORT_SYMBOL(flexcop_dma_control_size_irq);
69
70 int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
71 {
72         flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
73
74         if (no & FC_DMA_1)
75                 v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
76
77         if (no & FC_DMA_2)
78                 v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
79
80         fc->write_ibi_reg(fc,ctrl_208,v);
81         return 0;
82 }
83 EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
84
85 int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index)
86 {
87
88         flexcop_ibi_value v0x0,v0x4,v0xc;
89         v0x0.raw = v0x4.raw = v0xc.raw = 0;
90
91         v0x0.dma_0x0.dma_address0        = dma->dma_addr0 >> 2;
92         v0xc.dma_0xc.dma_address1        = dma->dma_addr1 >> 2;
93         v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
94
95         if (index & FC_DMA_SUBADDR_0)
96                 v0x0.dma_0x0.dma_0start = 1;
97
98         if (index & FC_DMA_SUBADDR_1)
99                 v0xc.dma_0xc.dma_1start = 1;
100
101         if (dma_idx & FC_DMA_1) {
102                 fc->write_ibi_reg(fc,dma1_000,v0x0);
103                 fc->write_ibi_reg(fc,dma1_004,v0x4);
104                 fc->write_ibi_reg(fc,dma1_00c,v0xc);
105         } else { /* (dma_idx & FC_DMA_2) */
106                 fc->write_ibi_reg(fc,dma2_010,v0x0);
107                 fc->write_ibi_reg(fc,dma2_014,v0x4);
108                 fc->write_ibi_reg(fc,dma2_01c,v0xc);
109         }
110
111         return 0;
112 }
113 EXPORT_SYMBOL(flexcop_dma_config);
114
115 static int flexcop_dma_remap(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, 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         v.dma_0xc.remap_enable = onoff;
120         fc->write_ibi_reg(fc,r,v);
121         return 0;
122 }
123
124 /* 1 cycles = 1.97 msec */
125 int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles)
126 {
127         flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
128         flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
129
130         flexcop_dma_remap(fc,dma_idx,0);
131
132         v.dma_0x4_write.dmatimer = cycles >> 1;
133         fc->write_ibi_reg(fc,r,v);
134         return 0;
135 }
136 EXPORT_SYMBOL(flexcop_dma_config_timer);
137
138 int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets)
139 {
140         flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
141         flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
142
143         flexcop_dma_remap(fc,dma_idx,1);
144
145         v.dma_0x4_remap.DMA_maxpackets = packets;
146         fc->write_ibi_reg(fc,r,v);
147         return 0;
148 }
149 EXPORT_SYMBOL(flexcop_dma_config_packet_count);