aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/b2c2/flexcop-dma.c
diff options
context:
space:
mode:
authorPatrick Boettcher <pb@linuxtv.org>2005-07-07 20:57:49 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-07 21:23:56 -0400
commit64221be7b9006338e4a45228f013e467ee4bf045 (patch)
treeacf137799c31c966f6d8083aee39c27f331905ab /drivers/media/dvb/b2c2/flexcop-dma.c
parent2819639b5630cd26d399ee0481be9a752280cf4d (diff)
[PATCH] dvb: flexcop: woraround irq stop problem
The flexcop chip often stops generating interrupts after some hours of operation. Apparently this can be fixed by resetting register block 0x300 at each channel change (this is not detailed in the flexcop data books). This patch also restructures DMA handling and adds a bit of debug code for the irq problem in case it still happens for someone. Signed-off-by: Patrick Boettcher <pb@linuxtv.org> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media/dvb/b2c2/flexcop-dma.c')
-rw-r--r--drivers/media/dvb/b2c2/flexcop-dma.c165
1 files changed, 111 insertions, 54 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
index 8d2706075360..cf4ed1df6086 100644
--- a/drivers/media/dvb/b2c2/flexcop-dma.c
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -37,22 +37,90 @@ void flexcop_dma_free(struct flexcop_dma *dma)
37} 37}
38EXPORT_SYMBOL(flexcop_dma_free); 38EXPORT_SYMBOL(flexcop_dma_free);
39 39
40int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 40int flexcop_dma_config(struct flexcop_device *fc,
41 struct flexcop_dma *dma,
42 flexcop_dma_index_t dma_idx)
41{ 43{
42 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 44 flexcop_ibi_value v0x0,v0x4,v0xc;
45 v0x0.raw = v0x4.raw = v0xc.raw = 0;
43 46
44 if (no & FC_DMA_1) 47 v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
45 v.ctrl_208.DMA1_Timer_Enable_sig = onoff; 48 v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
49 v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
46 50
47 if (no & FC_DMA_2) 51 if ((dma_idx & FC_DMA_1) == dma_idx) {
48 v.ctrl_208.DMA2_Timer_Enable_sig = onoff; 52 fc->write_ibi_reg(fc,dma1_000,v0x0);
53 fc->write_ibi_reg(fc,dma1_004,v0x4);
54 fc->write_ibi_reg(fc,dma1_00c,v0xc);
55 } else if ((dma_idx & FC_DMA_2) == dma_idx) {
56 fc->write_ibi_reg(fc,dma2_010,v0x0);
57 fc->write_ibi_reg(fc,dma2_014,v0x4);
58 fc->write_ibi_reg(fc,dma2_01c,v0xc);
59 } else {
60 err("either DMA1 or DMA2 can be configured at the within one flexcop_dma_config call.");
61 return -EINVAL;
62 }
49 63
50 fc->write_ibi_reg(fc,ctrl_208,v);
51 return 0; 64 return 0;
52} 65}
53EXPORT_SYMBOL(flexcop_dma_control_timer_irq); 66EXPORT_SYMBOL(flexcop_dma_config);
67
68/* start the DMA transfers, but not the DMA IRQs */
69int flexcop_dma_xfer_control(struct flexcop_device *fc,
70 flexcop_dma_index_t dma_idx,
71 flexcop_dma_addr_index_t index,
72 int onoff)
73{
74 flexcop_ibi_value v0x0,v0xc;
75 flexcop_ibi_register r0x0,r0xc;
76
77 if ((dma_idx & FC_DMA_1) == dma_idx) {
78 r0x0 = dma1_000;
79 r0xc = dma1_00c;
80 } else if ((dma_idx & FC_DMA_2) == dma_idx) {
81 r0x0 = dma2_010;
82 r0xc = dma2_01c;
83 } else {
84 err("either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call.");
85 return -EINVAL;
86 }
87
88 v0x0 = fc->read_ibi_reg(fc,r0x0);
89 v0xc = fc->read_ibi_reg(fc,r0xc);
90
91 deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
92 deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
93
94 if (index & FC_DMA_SUBADDR_0)
95 v0x0.dma_0x0.dma_0start = onoff;
96
97 if (index & FC_DMA_SUBADDR_1)
98 v0xc.dma_0xc.dma_1start = onoff;
99
100 fc->write_ibi_reg(fc,r0x0,v0x0);
101 fc->write_ibi_reg(fc,r0xc,v0xc);
102
103 deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
104 deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
105 return 0;
106}
107EXPORT_SYMBOL(flexcop_dma_xfer_control);
108
109static int flexcop_dma_remap(struct flexcop_device *fc,
110 flexcop_dma_index_t dma_idx,
111 int onoff)
112{
113 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
114 flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
115 deb_info("%s\n",__FUNCTION__);
116 v.dma_0xc.remap_enable = onoff;
117 fc->write_ibi_reg(fc,r,v);
118 return 0;
119}
54 120
55int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 121int flexcop_dma_control_size_irq(struct flexcop_device *fc,
122 flexcop_dma_index_t no,
123 int onoff)
56{ 124{
57 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 125 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
58 126
@@ -67,75 +135,64 @@ int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t
67} 135}
68EXPORT_SYMBOL(flexcop_dma_control_size_irq); 136EXPORT_SYMBOL(flexcop_dma_control_size_irq);
69 137
70int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 138int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
139 flexcop_dma_index_t no,
140 int onoff)
71{ 141{
72 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 142 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
73 143
74 if (no & FC_DMA_1) 144 if (no & FC_DMA_1)
75 v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff; 145 v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
76 146
77 if (no & FC_DMA_2) 147 if (no & FC_DMA_2)
78 v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff; 148 v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
79 149
80 fc->write_ibi_reg(fc,ctrl_208,v); 150 fc->write_ibi_reg(fc,ctrl_208,v);
81 return 0; 151 return 0;
82} 152}
83EXPORT_SYMBOL(flexcop_dma_control_packet_irq); 153EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
84 154
85int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index) 155/* 1 cycles = 1.97 msec */
156int flexcop_dma_config_timer(struct flexcop_device *fc,
157 flexcop_dma_index_t dma_idx,
158 u8 cycles)
86{ 159{
160 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
161 flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
87 162
88 flexcop_ibi_value v0x0,v0x4,v0xc; 163 flexcop_dma_remap(fc,dma_idx,0);
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}
113EXPORT_SYMBOL(flexcop_dma_config);
114 164
115static int flexcop_dma_remap(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, int onoff) 165 deb_info("%s\n",__FUNCTION__);
116{ 166 v.dma_0x4_write.dmatimer = cycles;
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); 167 fc->write_ibi_reg(fc,r,v);
121 return 0; 168 return 0;
122} 169}
170EXPORT_SYMBOL(flexcop_dma_config_timer);
123 171
124/* 1 cycles = 1.97 msec */ 172/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */
125int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles) 173int flexcop_dma_control_packet_irq(struct flexcop_device *fc,
174 flexcop_dma_index_t no,
175 int onoff)
126{ 176{
127 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 177 flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
128 flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
129 178
130 flexcop_dma_remap(fc,dma_idx,0); 179 deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
180 if (no & FC_DMA_1)
181 v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
182
183 if (no & FC_DMA_2)
184 v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
185
186 fc->write_ibi_reg(fc,ctrl_208,v);
187 deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
131 188
132 v.dma_0x4_write.dmatimer = cycles >> 1;
133 fc->write_ibi_reg(fc,r,v);
134 return 0; 189 return 0;
135} 190}
136EXPORT_SYMBOL(flexcop_dma_config_timer); 191EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
137 192
138int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets) 193int flexcop_dma_config_packet_count(struct flexcop_device *fc,
194 flexcop_dma_index_t dma_idx,
195 u8 packets)
139{ 196{
140 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 197 flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
141 flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 198 flexcop_ibi_value v = fc->read_ibi_reg(fc,r);