aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Isely <isely@pobox.com>2007-01-28 13:41:12 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-02-21 10:35:12 -0500
commitc43000ef0c9f21fff090ff3b5428ac31a41dbc99 (patch)
treef3744d934d4c887278ae3905da5c5219e456a72d
parent567d7115b9ce8145c166e3368bf31fe613451f77 (diff)
V4L/DVB (5173): Pvrusb2: encoder comm protocol cleanup
Update the implementation of the communication protocol for operating the encoder, using updated knowledge about the encoder. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-encoder.c150
1 files changed, 92 insertions, 58 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index ee5eb26ad56d..7cd95e9f914d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -35,34 +35,41 @@
35#define IVTV_MBOX_DRIVER_DONE 0x00000002 35#define IVTV_MBOX_DRIVER_DONE 0x00000002
36#define IVTV_MBOX_DRIVER_BUSY 0x00000001 36#define IVTV_MBOX_DRIVER_BUSY 0x00000001
37 37
38#define MBOX_BASE 0x44
39
38 40
39static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, 41static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
42 unsigned int offs,
40 const u32 *data, unsigned int dlen) 43 const u32 *data, unsigned int dlen)
41{ 44{
42 unsigned int idx; 45 unsigned int idx,addr;
46 unsigned int bAddr;
43 int ret; 47 int ret;
44 unsigned int offs = 0;
45 unsigned int chunkCnt; 48 unsigned int chunkCnt;
46 49
47 /* 50 /*
48 51
49 Format: First byte must be 0x01. Remaining 32 bit words are 52 Format: First byte must be 0x01. Remaining 32 bit words are
50 spread out into chunks of 7 bytes each, little-endian ordered, 53 spread out into chunks of 7 bytes each, with the first 4 bytes
51 offset at zero within each 2 blank bytes following and a 54 being the data word (little endian), and the next 3 bytes
52 single byte that is 0x44 plus the offset of the word. Repeat 55 being the address where that data word is to be written (big
53 request for additional words, with offset adjusted 56 endian). Repeat request for additional words, with offset
54 accordingly. 57 adjusted accordingly.
55 58
56 */ 59 */
57 while (dlen) { 60 while (dlen) {
58 chunkCnt = 8; 61 chunkCnt = 8;
59 if (chunkCnt > dlen) chunkCnt = dlen; 62 if (chunkCnt > dlen) chunkCnt = dlen;
60 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); 63 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
61 hdw->cmd_buffer[0] = FX2CMD_MEM_WRITE_DWORD; 64 bAddr = 0;
65 hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
62 for (idx = 0; idx < chunkCnt; idx++) { 66 for (idx = 0; idx < chunkCnt; idx++) {
63 hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs; 67 addr = idx + offs;
64 PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7), 68 hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
65 data[idx]); 69 hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
70 hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
71 PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
72 bAddr += 7;
66 } 73 }
67 ret = pvr2_send_request(hdw, 74 ret = pvr2_send_request(hdw,
68 hdw->cmd_buffer,1+(chunkCnt*7), 75 hdw->cmd_buffer,1+(chunkCnt*7),
@@ -77,34 +84,42 @@ static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
77} 84}
78 85
79 86
80static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl, 87static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
88 unsigned int offs,
81 u32 *data, unsigned int dlen) 89 u32 *data, unsigned int dlen)
82{ 90{
83 unsigned int idx; 91 unsigned int idx;
84 int ret; 92 int ret;
85 unsigned int offs = 0;
86 unsigned int chunkCnt; 93 unsigned int chunkCnt;
87 94
88 /* 95 /*
89 96
90 Format: First byte must be 0x02 (status check) or 0x28 (read 97 Format: First byte must be 0x02 (status check) or 0x28 (read
91 back block of 32 bit words). Next 6 bytes must be zero, 98 back block of 32 bit words). Next 6 bytes must be zero,
92 followed by a single byte of 0x44+offset for portion to be 99 followed by a single byte of MBOX_BASE+offset for portion to
93 read. Returned data is packed set of 32 bits words that were 100 be read. Returned data is packed set of 32 bits words that
94 read. 101 were read.
95 102
96 */ 103 */
97 104
98 while (dlen) { 105 while (dlen) {
99 chunkCnt = 16; 106 chunkCnt = 16;
100 if (chunkCnt > dlen) chunkCnt = dlen; 107 if (chunkCnt > dlen) chunkCnt = dlen;
101 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); 108 if (chunkCnt < 16) chunkCnt = 1;
102 hdw->cmd_buffer[0] = 109 hdw->cmd_buffer[0] =
103 (statusFl ? FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES); 110 ((chunkCnt == 1) ?
104 hdw->cmd_buffer[7] = 0x44 + offs; 111 FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
112 hdw->cmd_buffer[1] = 0;
113 hdw->cmd_buffer[2] = 0;
114 hdw->cmd_buffer[3] = 0;
115 hdw->cmd_buffer[4] = 0;
116 hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
117 hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
118 hdw->cmd_buffer[7] = (offs & 0xffu);
105 ret = pvr2_send_request(hdw, 119 ret = pvr2_send_request(hdw,
106 hdw->cmd_buffer,8, 120 hdw->cmd_buffer,8,
107 hdw->cmd_buffer,chunkCnt * 4); 121 hdw->cmd_buffer,
122 (chunkCnt == 1 ? 4 : 16 * 4));
108 if (ret) return ret; 123 if (ret) return ret;
109 124
110 for (idx = 0; idx < chunkCnt; idx++) { 125 for (idx = 0; idx < chunkCnt; idx++) {
@@ -131,6 +146,8 @@ static int pvr2_encoder_cmd(void *ctxt,
131 u32 *argp) 146 u32 *argp)
132{ 147{
133 unsigned int poll_count; 148 unsigned int poll_count;
149 unsigned int try_count = 0;
150 int retry_flag;
134 int ret = 0; 151 int ret = 0;
135 unsigned int idx; 152 unsigned int idx;
136 /* These sizes look to be limited by the FX2 firmware implementation */ 153 /* These sizes look to be limited by the FX2 firmware implementation */
@@ -142,14 +159,15 @@ static int pvr2_encoder_cmd(void *ctxt,
142 /* 159 /*
143 160
144 The encoder seems to speak entirely using blocks 32 bit words. 161 The encoder seems to speak entirely using blocks 32 bit words.
145 In ivtv driver terms, this is a mailbox which we populate with 162 In ivtv driver terms, this is a mailbox at MBOX_BASE which we
146 data and watch what the hardware does with it. The first word 163 populate with data and watch what the hardware does with it.
147 is a set of flags used to control the transaction, the second 164 The first word is a set of flags used to control the
148 word is the command to execute, the third byte is zero (ivtv 165 transaction, the second word is the command to execute, the
149 driver suggests that this is some kind of return value), and 166 third byte is zero (ivtv driver suggests that this is some
150 the fourth byte is a specified timeout (windows driver always 167 kind of return value), and the fourth byte is a specified
151 uses 0x00060000 except for one case when it is zero). All 168 timeout (windows driver always uses 0x00060000 except for one
152 successive words are the argument words for the command. 169 case when it is zero). All successive words are the argument
170 words for the command.
153 171
154 First, write out the entire set of words, with the first word 172 First, write out the entire set of words, with the first word
155 being zero. 173 being zero.
@@ -158,13 +176,10 @@ static int pvr2_encoder_cmd(void *ctxt,
158 IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which 176 IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
159 probably means "go"). 177 probably means "go").
160 178
161 Next, read back 16 words as status. Check the first word, 179 Next, read back the return count words. Check the first word,
162 which should have IVTV_MBOX_FIRMWARE_DONE set. If however 180 which should have IVTV_MBOX_FIRMWARE_DONE set. If however
163 that bit is not set, then the command isn't done so repeat the 181 that bit is not set, then the command isn't done so repeat the
164 read. 182 read until it is set.
165
166 Next, read back 32 words and compare with the original
167 arugments. Hopefully they will match.
168 183
169 Finally, write out just the first word again, but set it to 184 Finally, write out just the first word again, but set it to
170 0x0 this time (which probably means "idle"). 185 0x0 this time (which probably means "idle").
@@ -194,6 +209,9 @@ static int pvr2_encoder_cmd(void *ctxt,
194 209
195 LOCK_TAKE(hdw->ctl_lock); do { 210 LOCK_TAKE(hdw->ctl_lock); do {
196 211
212 retry_flag = 0;
213 try_count++;
214 ret = 0;
197 wrData[0] = 0; 215 wrData[0] = 0;
198 wrData[1] = cmd; 216 wrData[1] = cmd;
199 wrData[2] = 0; 217 wrData[2] = 0;
@@ -205,54 +223,70 @@ static int pvr2_encoder_cmd(void *ctxt,
205 wrData[idx+4] = 0; 223 wrData[idx+4] = 0;
206 } 224 }
207 225
208 ret = pvr2_encoder_write_words(hdw,wrData,idx); 226 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
209 if (ret) break; 227 if (ret) break;
210 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY; 228 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
211 ret = pvr2_encoder_write_words(hdw,wrData,1); 229 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
212 if (ret) break; 230 if (ret) break;
213 poll_count = 0; 231 poll_count = 0;
214 while (1) { 232 while (1) {
215 if (poll_count < 10000000) poll_count++; 233 poll_count++;
216 ret = pvr2_encoder_read_words(hdw,!0,rdData,1); 234 ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
217 if (ret) break; 235 arg_cnt_recv+4);
236 if (ret) {
237 break;
238 }
218 if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) { 239 if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
219 break; 240 break;
220 } 241 }
221 if (poll_count == 100) { 242 if (rdData[0] && (poll_count < 1000)) continue;
243 if (!rdData[0]) {
244 retry_flag = !0;
245 pvr2_trace(
246 PVR2_TRACE_ERROR_LEGS,
247 "Encoder timed out waiting for us"
248 "; arranging to retry");
249 } else {
222 pvr2_trace( 250 pvr2_trace(
223 PVR2_TRACE_ERROR_LEGS, 251 PVR2_TRACE_ERROR_LEGS,
224 "***WARNING*** device's encoder" 252 "***WARNING*** device's encoder"
225 " appears to be stuck" 253 " appears to be stuck"
226 " (status=0%08x)",rdData[0]); 254 " (status=0%08x)",rdData[0]);
255 }
256 pvr2_trace(
257 PVR2_TRACE_ERROR_LEGS,
258 "Encoder command: 0x%02x",cmd);
259 for (idx = 4; idx < arg_cnt_send; idx++) {
227 pvr2_trace( 260 pvr2_trace(
228 PVR2_TRACE_ERROR_LEGS, 261 PVR2_TRACE_ERROR_LEGS,
229 "Encoder command: 0x%02x",cmd); 262 "Encoder arg%d: 0x%08x",
230 for (idx = 4; idx < arg_cnt_send; idx++) { 263 idx-3,wrData[idx]);
231 pvr2_trace(
232 PVR2_TRACE_ERROR_LEGS,
233 "Encoder arg%d: 0x%08x",
234 idx-3,wrData[idx]);
235 }
236 pvr2_trace(
237 PVR2_TRACE_ERROR_LEGS,
238 "Giving up waiting."
239 " It is likely that"
240 " this is a bad idea...");
241 ret = -EBUSY;
242 break;
243 } 264 }
265 ret = -EBUSY;
266 break;
267 }
268 if (retry_flag) {
269 if (try_count < 20) continue;
270 pvr2_trace(
271 PVR2_TRACE_ERROR_LEGS,
272 "Too many retries...");
273 ret = -EBUSY;
274 }
275 if (ret) {
276 pvr2_trace(
277 PVR2_TRACE_ERROR_LEGS,
278 "Giving up on command."
279 " It is likely that"
280 " this is a bad idea...");
281 break;
244 } 282 }
245 if (ret) break;
246 wrData[0] = 0x7; 283 wrData[0] = 0x7;
247 ret = pvr2_encoder_read_words(
248 hdw,0,rdData, ARRAY_SIZE(rdData));
249 if (ret) break;
250 for (idx = 0; idx < arg_cnt_recv; idx++) { 284 for (idx = 0; idx < arg_cnt_recv; idx++) {
251 argp[idx] = rdData[idx+4]; 285 argp[idx] = rdData[idx+4];
252 } 286 }
253 287
254 wrData[0] = 0x0; 288 wrData[0] = 0x0;
255 ret = pvr2_encoder_write_words(hdw,wrData,1); 289 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
256 if (ret) break; 290 if (ret) break;
257 291
258 } while(0); LOCK_GIVE(hdw->ctl_lock); 292 } while(0); LOCK_GIVE(hdw->ctl_lock);