diff options
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-encoder.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-encoder.c | 269 |
1 files changed, 191 insertions, 78 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index c94f97b79392..5786faf9b3b8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "pvrusb2-encoder.h" | 26 | #include "pvrusb2-encoder.h" |
27 | #include "pvrusb2-hdw-internal.h" | 27 | #include "pvrusb2-hdw-internal.h" |
28 | #include "pvrusb2-debug.h" | 28 | #include "pvrusb2-debug.h" |
29 | #include "pvrusb2-fx2-cmd.h" | ||
29 | 30 | ||
30 | 31 | ||
31 | 32 | ||
@@ -34,34 +35,41 @@ | |||
34 | #define IVTV_MBOX_DRIVER_DONE 0x00000002 | 35 | #define IVTV_MBOX_DRIVER_DONE 0x00000002 |
35 | #define IVTV_MBOX_DRIVER_BUSY 0x00000001 | 36 | #define IVTV_MBOX_DRIVER_BUSY 0x00000001 |
36 | 37 | ||
38 | #define MBOX_BASE 0x44 | ||
39 | |||
37 | 40 | ||
38 | static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, | 41 | static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, |
42 | unsigned int offs, | ||
39 | const u32 *data, unsigned int dlen) | 43 | const u32 *data, unsigned int dlen) |
40 | { | 44 | { |
41 | unsigned int idx; | 45 | unsigned int idx,addr; |
46 | unsigned int bAddr; | ||
42 | int ret; | 47 | int ret; |
43 | unsigned int offs = 0; | ||
44 | unsigned int chunkCnt; | 48 | unsigned int chunkCnt; |
45 | 49 | ||
46 | /* | 50 | /* |
47 | 51 | ||
48 | Format: First byte must be 0x01. Remaining 32 bit words are | 52 | Format: First byte must be 0x01. Remaining 32 bit words are |
49 | 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 |
50 | offset at zero within each 2 blank bytes following and a | 54 | being the data word (little endian), and the next 3 bytes |
51 | 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 |
52 | request for additional words, with offset adjusted | 56 | endian). Repeat request for additional words, with offset |
53 | accordingly. | 57 | adjusted accordingly. |
54 | 58 | ||
55 | */ | 59 | */ |
56 | while (dlen) { | 60 | while (dlen) { |
57 | chunkCnt = 8; | 61 | chunkCnt = 8; |
58 | if (chunkCnt > dlen) chunkCnt = dlen; | 62 | if (chunkCnt > dlen) chunkCnt = dlen; |
59 | memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); | 63 | memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); |
60 | hdw->cmd_buffer[0] = 0x01; | 64 | bAddr = 0; |
65 | hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD; | ||
61 | for (idx = 0; idx < chunkCnt; idx++) { | 66 | for (idx = 0; idx < chunkCnt; idx++) { |
62 | hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs; | 67 | addr = idx + offs; |
63 | PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7), | 68 | hdw->cmd_buffer[bAddr+6] = (addr & 0xffu); |
64 | 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; | ||
65 | } | 73 | } |
66 | ret = pvr2_send_request(hdw, | 74 | ret = pvr2_send_request(hdw, |
67 | hdw->cmd_buffer,1+(chunkCnt*7), | 75 | hdw->cmd_buffer,1+(chunkCnt*7), |
@@ -76,33 +84,42 @@ static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, | |||
76 | } | 84 | } |
77 | 85 | ||
78 | 86 | ||
79 | static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl, | 87 | static int pvr2_encoder_read_words(struct pvr2_hdw *hdw, |
88 | unsigned int offs, | ||
80 | u32 *data, unsigned int dlen) | 89 | u32 *data, unsigned int dlen) |
81 | { | 90 | { |
82 | unsigned int idx; | 91 | unsigned int idx; |
83 | int ret; | 92 | int ret; |
84 | unsigned int offs = 0; | ||
85 | unsigned int chunkCnt; | 93 | unsigned int chunkCnt; |
86 | 94 | ||
87 | /* | 95 | /* |
88 | 96 | ||
89 | Format: First byte must be 0x02 (status check) or 0x28 (read | 97 | Format: First byte must be 0x02 (status check) or 0x28 (read |
90 | 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, |
91 | 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 |
92 | 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 |
93 | read. | 101 | were read. |
94 | 102 | ||
95 | */ | 103 | */ |
96 | 104 | ||
97 | while (dlen) { | 105 | while (dlen) { |
98 | chunkCnt = 16; | 106 | chunkCnt = 16; |
99 | if (chunkCnt > dlen) chunkCnt = dlen; | 107 | if (chunkCnt > dlen) chunkCnt = dlen; |
100 | memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); | 108 | if (chunkCnt < 16) chunkCnt = 1; |
101 | hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28; | 109 | hdw->cmd_buffer[0] = |
102 | hdw->cmd_buffer[7] = 0x44 + offs; | 110 | ((chunkCnt == 1) ? |
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); | ||
103 | ret = pvr2_send_request(hdw, | 119 | ret = pvr2_send_request(hdw, |
104 | hdw->cmd_buffer,8, | 120 | hdw->cmd_buffer,8, |
105 | hdw->cmd_buffer,chunkCnt * 4); | 121 | hdw->cmd_buffer, |
122 | (chunkCnt == 1 ? 4 : 16 * 4)); | ||
106 | if (ret) return ret; | 123 | if (ret) return ret; |
107 | 124 | ||
108 | for (idx = 0; idx < chunkCnt; idx++) { | 125 | for (idx = 0; idx < chunkCnt; idx++) { |
@@ -129,6 +146,8 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
129 | u32 *argp) | 146 | u32 *argp) |
130 | { | 147 | { |
131 | unsigned int poll_count; | 148 | unsigned int poll_count; |
149 | unsigned int try_count = 0; | ||
150 | int retry_flag; | ||
132 | int ret = 0; | 151 | int ret = 0; |
133 | unsigned int idx; | 152 | unsigned int idx; |
134 | /* These sizes look to be limited by the FX2 firmware implementation */ | 153 | /* These sizes look to be limited by the FX2 firmware implementation */ |
@@ -140,14 +159,15 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
140 | /* | 159 | /* |
141 | 160 | ||
142 | The encoder seems to speak entirely using blocks 32 bit words. | 161 | The encoder seems to speak entirely using blocks 32 bit words. |
143 | 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 |
144 | data and watch what the hardware does with it. The first word | 163 | populate with data and watch what the hardware does with it. |
145 | 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 |
146 | word is the command to execute, the third byte is zero (ivtv | 165 | transaction, the second word is the command to execute, the |
147 | driver suggests that this is some kind of return value), and | 166 | third byte is zero (ivtv driver suggests that this is some |
148 | the fourth byte is a specified timeout (windows driver always | 167 | kind of return value), and the fourth byte is a specified |
149 | uses 0x00060000 except for one case when it is zero). All | 168 | timeout (windows driver always uses 0x00060000 except for one |
150 | 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. | ||
151 | 171 | ||
152 | 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 |
153 | being zero. | 173 | being zero. |
@@ -156,44 +176,42 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
156 | IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which | 176 | IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which |
157 | probably means "go"). | 177 | probably means "go"). |
158 | 178 | ||
159 | Next, read back 16 words as status. Check the first word, | 179 | Next, read back the return count words. Check the first word, |
160 | which should have IVTV_MBOX_FIRMWARE_DONE set. If however | 180 | which should have IVTV_MBOX_FIRMWARE_DONE set. If however |
161 | 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 |
162 | read. | 182 | read until it is set. |
163 | |||
164 | Next, read back 32 words and compare with the original | ||
165 | arugments. Hopefully they will match. | ||
166 | 183 | ||
167 | 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 |
168 | 0x0 this time (which probably means "idle"). | 185 | 0x0 this time (which probably means "idle"). |
169 | 186 | ||
170 | */ | 187 | */ |
171 | 188 | ||
172 | if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) { | 189 | if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) { |
173 | pvr2_trace( | 190 | pvr2_trace( |
174 | PVR2_TRACE_ERROR_LEGS, | 191 | PVR2_TRACE_ERROR_LEGS, |
175 | "Failed to write cx23416 command" | 192 | "Failed to write cx23416 command" |
176 | " - too many input arguments" | 193 | " - too many input arguments" |
177 | " (was given %u limit %u)", | 194 | " (was given %u limit %lu)", |
178 | arg_cnt_send, | 195 | arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4); |
179 | (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4); | ||
180 | return -EINVAL; | 196 | return -EINVAL; |
181 | } | 197 | } |
182 | 198 | ||
183 | if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) { | 199 | if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) { |
184 | pvr2_trace( | 200 | pvr2_trace( |
185 | PVR2_TRACE_ERROR_LEGS, | 201 | PVR2_TRACE_ERROR_LEGS, |
186 | "Failed to write cx23416 command" | 202 | "Failed to write cx23416 command" |
187 | " - too many return arguments" | 203 | " - too many return arguments" |
188 | " (was given %u limit %u)", | 204 | " (was given %u limit %lu)", |
189 | arg_cnt_recv, | 205 | arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4); |
190 | (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4); | ||
191 | return -EINVAL; | 206 | return -EINVAL; |
192 | } | 207 | } |
193 | 208 | ||
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; |
@@ -201,59 +219,74 @@ static int pvr2_encoder_cmd(void *ctxt, | |||
201 | for (idx = 0; idx < arg_cnt_send; idx++) { | 219 | for (idx = 0; idx < arg_cnt_send; idx++) { |
202 | wrData[idx+4] = argp[idx]; | 220 | wrData[idx+4] = argp[idx]; |
203 | } | 221 | } |
204 | for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) { | 222 | for (; idx < ARRAY_SIZE(wrData) - 4; idx++) { |
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; | ||
222 | pvr2_trace( | 245 | pvr2_trace( |
223 | PVR2_TRACE_ERROR_LEGS, | 246 | PVR2_TRACE_ERROR_LEGS, |
224 | "***WARNING*** device's encoder" | 247 | "Encoder timed out waiting for us" |
225 | " appears to be stuck" | 248 | "; arranging to retry"); |
226 | " (status=0%08x)",rdData[0]); | 249 | } else { |
227 | pvr2_trace( | 250 | pvr2_trace( |
228 | PVR2_TRACE_ERROR_LEGS, | 251 | PVR2_TRACE_ERROR_LEGS, |
229 | "Encoder command: 0x%02x",cmd); | 252 | "***WARNING*** device's encoder" |
230 | for (idx = 4; idx < arg_cnt_send; idx++) { | 253 | " appears to be stuck" |
231 | pvr2_trace( | 254 | " (status=0x%08x)",rdData[0]); |
232 | PVR2_TRACE_ERROR_LEGS, | 255 | } |
233 | "Encoder arg%d: 0x%08x", | 256 | pvr2_trace( |
234 | idx-3,wrData[idx]); | 257 | PVR2_TRACE_ERROR_LEGS, |
235 | } | 258 | "Encoder command: 0x%02x",cmd); |
259 | for (idx = 4; idx < arg_cnt_send; idx++) { | ||
236 | pvr2_trace( | 260 | pvr2_trace( |
237 | PVR2_TRACE_ERROR_LEGS, | 261 | PVR2_TRACE_ERROR_LEGS, |
238 | "Giving up waiting." | 262 | "Encoder arg%d: 0x%08x", |
239 | " It is likely that" | 263 | idx-3,wrData[idx]); |
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, | ||
249 | sizeof(rdData)/sizeof(rdData[0])); | ||
250 | if (ret) break; | ||
251 | for (idx = 0; idx < arg_cnt_recv; idx++) { | 284 | for (idx = 0; idx < arg_cnt_recv; idx++) { |
252 | argp[idx] = rdData[idx+4]; | 285 | argp[idx] = rdData[idx+4]; |
253 | } | 286 | } |
254 | 287 | ||
255 | wrData[0] = 0x0; | 288 | wrData[0] = 0x0; |
256 | ret = pvr2_encoder_write_words(hdw,wrData,1); | 289 | ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1); |
257 | if (ret) break; | 290 | if (ret) break; |
258 | 291 | ||
259 | } while(0); LOCK_GIVE(hdw->ctl_lock); | 292 | } while(0); LOCK_GIVE(hdw->ctl_lock); |
@@ -269,13 +302,13 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, | |||
269 | unsigned int idx; | 302 | unsigned int idx; |
270 | u32 data[12]; | 303 | u32 data[12]; |
271 | 304 | ||
272 | if (args > sizeof(data)/sizeof(data[0])) { | 305 | if (args > ARRAY_SIZE(data)) { |
273 | pvr2_trace( | 306 | pvr2_trace( |
274 | PVR2_TRACE_ERROR_LEGS, | 307 | PVR2_TRACE_ERROR_LEGS, |
275 | "Failed to write cx23416 command" | 308 | "Failed to write cx23416 command" |
276 | " - too many arguments" | 309 | " - too many arguments" |
277 | " (was given %u limit %u)", | 310 | " (was given %u limit %lu)", |
278 | args,(unsigned int)(sizeof(data)/sizeof(data[0]))); | 311 | args, (long unsigned) ARRAY_SIZE(data)); |
279 | return -EINVAL; | 312 | return -EINVAL; |
280 | } | 313 | } |
281 | 314 | ||
@@ -288,6 +321,73 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, | |||
288 | return pvr2_encoder_cmd(hdw,cmd,args,0,data); | 321 | return pvr2_encoder_cmd(hdw,cmd,args,0,data); |
289 | } | 322 | } |
290 | 323 | ||
324 | |||
325 | /* This implements some extra setup for the encoder that seems to be | ||
326 | specific to the PVR USB2 hardware. */ | ||
327 | int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) | ||
328 | { | ||
329 | int ret = 0; | ||
330 | int encMisc3Arg = 0; | ||
331 | |||
332 | #if 0 | ||
333 | /* This inexplicable bit happens in the Hauppage windows | ||
334 | driver (for both 24xxx and 29xxx devices). However I | ||
335 | currently see no difference in behavior with or without | ||
336 | this stuff. Leave this here as a note of its existence, | ||
337 | but don't use it. */ | ||
338 | LOCK_TAKE(hdw->ctl_lock); do { | ||
339 | u32 dat[1]; | ||
340 | dat[0] = 0x80000640; | ||
341 | pvr2_encoder_write_words(hdw,0x01fe,dat,1); | ||
342 | pvr2_encoder_write_words(hdw,0x023e,dat,1); | ||
343 | } while(0); LOCK_GIVE(hdw->ctl_lock); | ||
344 | #endif | ||
345 | |||
346 | /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver | ||
347 | sends the following list of ENC_MISC commands (for both | ||
348 | 24xxx and 29xxx devices). Meanings are not entirely clear, | ||
349 | however without the ENC_MISC(3,1) command then we risk | ||
350 | random perpetual video corruption whenever the video input | ||
351 | breaks up for a moment (like when switching channels). */ | ||
352 | |||
353 | |||
354 | #if 0 | ||
355 | /* This ENC_MISC(5,0) command seems to hurt 29xxx sync | ||
356 | performance on channel changes, but is not a problem on | ||
357 | 24xxx devices. */ | ||
358 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0); | ||
359 | #endif | ||
360 | |||
361 | /* This ENC_MISC(3,encMisc3Arg) command is critical - without | ||
362 | it there will eventually be video corruption. Also, the | ||
363 | 29xxx case is strange - the Windows driver is passing 1 | ||
364 | regardless of device type but if we have 1 for 29xxx device | ||
365 | the video turns sluggish. */ | ||
366 | switch (hdw->hdw_type) { | ||
367 | case PVR2_HDW_TYPE_24XXX: encMisc3Arg = 1; break; | ||
368 | case PVR2_HDW_TYPE_29XXX: encMisc3Arg = 0; break; | ||
369 | default: break; | ||
370 | } | ||
371 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3, | ||
372 | encMisc3Arg,0,0); | ||
373 | |||
374 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0); | ||
375 | |||
376 | #if 0 | ||
377 | /* This ENC_MISC(4,1) command is poisonous, so it is commented | ||
378 | out. But I'm leaving it here anyway to document its | ||
379 | existence in the Windows driver. The effect of this | ||
380 | command is that apps displaying the stream become sluggish | ||
381 | with stuttering video. */ | ||
382 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0); | ||
383 | #endif | ||
384 | |||
385 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); | ||
386 | ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
291 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) | 391 | int pvr2_encoder_configure(struct pvr2_hdw *hdw) |
292 | { | 392 | { |
293 | int ret; | 393 | int ret; |
@@ -302,6 +402,8 @@ int pvr2_encoder_configure(struct pvr2_hdw *hdw) | |||
302 | 402 | ||
303 | ret = 0; | 403 | ret = 0; |
304 | 404 | ||
405 | ret |= pvr2_encoder_prep_config(hdw); | ||
406 | |||
305 | if (!ret) ret = pvr2_encoder_vcmd( | 407 | if (!ret) ret = pvr2_encoder_vcmd( |
306 | hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, | 408 | hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, |
307 | 0xf0, 0xf0); | 409 | 0xf0, 0xf0); |
@@ -360,15 +462,22 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw) | |||
360 | pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481); | 462 | pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481); |
361 | pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); | 463 | pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); |
362 | 464 | ||
363 | if (hdw->config == pvr2_config_vbi) { | 465 | pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, |
466 | hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); | ||
467 | |||
468 | switch (hdw->config) { | ||
469 | case pvr2_config_vbi: | ||
364 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, | 470 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, |
365 | 0x01,0x14); | 471 | 0x01,0x14); |
366 | } else if (hdw->config == pvr2_config_mpeg) { | 472 | break; |
473 | case pvr2_config_mpeg: | ||
367 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, | 474 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, |
368 | 0,0x13); | 475 | 0,0x13); |
369 | } else { | 476 | break; |
477 | default: /* Unhandled cases for now */ | ||
370 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, | 478 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, |
371 | 0,0x13); | 479 | 0,0x13); |
480 | break; | ||
372 | } | 481 | } |
373 | if (!status) { | 482 | if (!status) { |
374 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); | 483 | hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); |
@@ -383,15 +492,19 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw) | |||
383 | /* mask all interrupts */ | 492 | /* mask all interrupts */ |
384 | pvr2_write_register(hdw, 0x0048, 0xffffffff); | 493 | pvr2_write_register(hdw, 0x0048, 0xffffffff); |
385 | 494 | ||
386 | if (hdw->config == pvr2_config_vbi) { | 495 | switch (hdw->config) { |
496 | case pvr2_config_vbi: | ||
387 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, | 497 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, |
388 | 0x01,0x01,0x14); | 498 | 0x01,0x01,0x14); |
389 | } else if (hdw->config == pvr2_config_mpeg) { | 499 | break; |
500 | case pvr2_config_mpeg: | ||
390 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, | 501 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, |
391 | 0x01,0,0x13); | 502 | 0x01,0,0x13); |
392 | } else { | 503 | break; |
504 | default: /* Unhandled cases for now */ | ||
393 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, | 505 | status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, |
394 | 0x01,0,0x13); | 506 | 0x01,0,0x13); |
507 | break; | ||
395 | } | 508 | } |
396 | 509 | ||
397 | /* change some GPIO data */ | 510 | /* change some GPIO data */ |