0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h> // for linux/firmware.h
0009 #include <linux/firmware.h>
0010 #include "pvrusb2-util.h"
0011 #include "pvrusb2-encoder.h"
0012 #include "pvrusb2-hdw-internal.h"
0013 #include "pvrusb2-debug.h"
0014 #include "pvrusb2-fx2-cmd.h"
0015
0016
0017
0018
0019 #define IVTV_MBOX_FIRMWARE_DONE 0x00000004
0020 #define IVTV_MBOX_DRIVER_DONE 0x00000002
0021 #define IVTV_MBOX_DRIVER_BUSY 0x00000001
0022
0023 #define MBOX_BASE 0x44
0024
0025
0026 static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
0027 unsigned int offs,
0028 const u32 *data, unsigned int dlen)
0029 {
0030 unsigned int idx,addr;
0031 unsigned int bAddr;
0032 int ret;
0033 unsigned int chunkCnt;
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 while (dlen) {
0046 chunkCnt = 8;
0047 if (chunkCnt > dlen) chunkCnt = dlen;
0048 memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
0049 bAddr = 0;
0050 hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
0051 for (idx = 0; idx < chunkCnt; idx++) {
0052 addr = idx + offs;
0053 hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
0054 hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
0055 hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
0056 PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
0057 bAddr += 7;
0058 }
0059 ret = pvr2_send_request(hdw,
0060 hdw->cmd_buffer,1+(chunkCnt*7),
0061 NULL,0);
0062 if (ret) return ret;
0063 data += chunkCnt;
0064 dlen -= chunkCnt;
0065 offs += chunkCnt;
0066 }
0067
0068 return 0;
0069 }
0070
0071
0072 static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
0073 unsigned int offs,
0074 u32 *data, unsigned int dlen)
0075 {
0076 unsigned int idx;
0077 int ret;
0078 unsigned int chunkCnt;
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 while (dlen) {
0091 chunkCnt = 16;
0092 if (chunkCnt > dlen) chunkCnt = dlen;
0093 if (chunkCnt < 16) chunkCnt = 1;
0094 hdw->cmd_buffer[0] =
0095 ((chunkCnt == 1) ?
0096 FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
0097 hdw->cmd_buffer[1] = 0;
0098 hdw->cmd_buffer[2] = 0;
0099 hdw->cmd_buffer[3] = 0;
0100 hdw->cmd_buffer[4] = 0;
0101 hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
0102 hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
0103 hdw->cmd_buffer[7] = (offs & 0xffu);
0104 ret = pvr2_send_request(hdw,
0105 hdw->cmd_buffer,8,
0106 hdw->cmd_buffer,
0107 (chunkCnt == 1 ? 4 : 16 * 4));
0108 if (ret) return ret;
0109
0110 for (idx = 0; idx < chunkCnt; idx++) {
0111 data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
0112 }
0113 data += chunkCnt;
0114 dlen -= chunkCnt;
0115 offs += chunkCnt;
0116 }
0117
0118 return 0;
0119 }
0120
0121
0122
0123
0124
0125
0126
0127 static int pvr2_encoder_cmd(void *ctxt,
0128 u32 cmd,
0129 int arg_cnt_send,
0130 int arg_cnt_recv,
0131 u32 *argp)
0132 {
0133 unsigned int poll_count;
0134 unsigned int try_count = 0;
0135 int retry_flag;
0136 int ret = 0;
0137 unsigned int idx;
0138
0139 u32 wrData[16];
0140 u32 rdData[16];
0141 struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
0175 pvr2_trace(
0176 PVR2_TRACE_ERROR_LEGS,
0177 "Failed to write cx23416 command - too many input arguments (was given %u limit %lu)",
0178 arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
0179 return -EINVAL;
0180 }
0181
0182 if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
0183 pvr2_trace(
0184 PVR2_TRACE_ERROR_LEGS,
0185 "Failed to write cx23416 command - too many return arguments (was given %u limit %lu)",
0186 arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
0187 return -EINVAL;
0188 }
0189
0190
0191 LOCK_TAKE(hdw->ctl_lock);
0192 while (1) {
0193 if (!hdw->state_encoder_ok) {
0194 ret = -EIO;
0195 break;
0196 }
0197
0198 retry_flag = 0;
0199 try_count++;
0200 ret = 0;
0201 wrData[0] = 0;
0202 wrData[1] = cmd;
0203 wrData[2] = 0;
0204 wrData[3] = 0x00060000;
0205 for (idx = 0; idx < arg_cnt_send; idx++) {
0206 wrData[idx+4] = argp[idx];
0207 }
0208 for (; idx < ARRAY_SIZE(wrData) - 4; idx++) {
0209 wrData[idx+4] = 0;
0210 }
0211
0212 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
0213 if (ret) break;
0214 wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
0215 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
0216 if (ret) break;
0217 poll_count = 0;
0218 while (1) {
0219 poll_count++;
0220 ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
0221 arg_cnt_recv+4);
0222 if (ret) {
0223 break;
0224 }
0225 if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
0226 break;
0227 }
0228 if (rdData[0] && (poll_count < 1000)) continue;
0229 if (!rdData[0]) {
0230 retry_flag = !0;
0231 pvr2_trace(
0232 PVR2_TRACE_ERROR_LEGS,
0233 "Encoder timed out waiting for us; arranging to retry");
0234 } else {
0235 pvr2_trace(
0236 PVR2_TRACE_ERROR_LEGS,
0237 "***WARNING*** device's encoder appears to be stuck (status=0x%08x)",
0238 rdData[0]);
0239 }
0240 pvr2_trace(
0241 PVR2_TRACE_ERROR_LEGS,
0242 "Encoder command: 0x%02x",cmd);
0243 for (idx = 4; idx < arg_cnt_send; idx++) {
0244 pvr2_trace(
0245 PVR2_TRACE_ERROR_LEGS,
0246 "Encoder arg%d: 0x%08x",
0247 idx-3,wrData[idx]);
0248 }
0249 ret = -EBUSY;
0250 break;
0251 }
0252 if (retry_flag) {
0253 if (try_count < 20) continue;
0254 pvr2_trace(
0255 PVR2_TRACE_ERROR_LEGS,
0256 "Too many retries...");
0257 ret = -EBUSY;
0258 }
0259 if (ret) {
0260 del_timer_sync(&hdw->encoder_run_timer);
0261 hdw->state_encoder_ok = 0;
0262 pvr2_trace(PVR2_TRACE_STBITS,
0263 "State bit %s <-- %s",
0264 "state_encoder_ok",
0265 (hdw->state_encoder_ok ? "true" : "false"));
0266 if (hdw->state_encoder_runok) {
0267 hdw->state_encoder_runok = 0;
0268 pvr2_trace(PVR2_TRACE_STBITS,
0269 "State bit %s <-- %s",
0270 "state_encoder_runok",
0271 (hdw->state_encoder_runok ?
0272 "true" : "false"));
0273 }
0274 pvr2_trace(
0275 PVR2_TRACE_ERROR_LEGS,
0276 "Giving up on command. This is normally recovered via a firmware reload and re-initialization; concern is only warranted if this happens repeatedly and rapidly.");
0277 break;
0278 }
0279 wrData[0] = 0x7;
0280 for (idx = 0; idx < arg_cnt_recv; idx++) {
0281 argp[idx] = rdData[idx+4];
0282 }
0283
0284 wrData[0] = 0x0;
0285 ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
0286 break;
0287 }
0288 LOCK_GIVE(hdw->ctl_lock);
0289
0290 return ret;
0291 }
0292
0293
0294 static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
0295 int args, ...)
0296 {
0297 va_list vl;
0298 unsigned int idx;
0299 u32 data[12];
0300
0301 if (args > ARRAY_SIZE(data)) {
0302 pvr2_trace(
0303 PVR2_TRACE_ERROR_LEGS,
0304 "Failed to write cx23416 command - too many arguments (was given %u limit %lu)",
0305 args, (long unsigned) ARRAY_SIZE(data));
0306 return -EINVAL;
0307 }
0308
0309 va_start(vl, args);
0310 for (idx = 0; idx < args; idx++) {
0311 data[idx] = va_arg(vl, u32);
0312 }
0313 va_end(vl);
0314
0315 return pvr2_encoder_cmd(hdw,cmd,args,0,data);
0316 }
0317
0318
0319
0320
0321 static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
0322 {
0323 int ret = 0;
0324 int encMisc3Arg = 0;
0325
0326 #if 0
0327
0328
0329
0330
0331
0332 LOCK_TAKE(hdw->ctl_lock); do {
0333 u32 dat[1];
0334 dat[0] = 0x80000640;
0335 pvr2_encoder_write_words(hdw,0x01fe,dat,1);
0336 pvr2_encoder_write_words(hdw,0x023e,dat,1);
0337 } while(0); LOCK_GIVE(hdw->ctl_lock);
0338 #endif
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348 #if 0
0349
0350
0351
0352 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
0353 #endif
0354
0355
0356
0357
0358
0359
0360 if (hdw->hdw_desc->flag_has_cx25840) {
0361 encMisc3Arg = 1;
0362 } else {
0363 encMisc3Arg = 0;
0364 }
0365 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
0366 encMisc3Arg,0,0);
0367
0368 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
0369
0370 #if 0
0371
0372
0373
0374
0375
0376 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
0377 #endif
0378
0379 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
0380 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
0381
0382
0383
0384 ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
0385
0386 return ret;
0387 }
0388
0389 int pvr2_encoder_adjust(struct pvr2_hdw *hdw)
0390 {
0391 int ret;
0392 ret = cx2341x_update(hdw,pvr2_encoder_cmd,
0393 (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
0394 &hdw->enc_ctl_state);
0395 if (ret) {
0396 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0397 "Error from cx2341x module code=%d",ret);
0398 } else {
0399 hdw->enc_cur_state = hdw->enc_ctl_state;
0400 hdw->enc_cur_valid = !0;
0401 }
0402 return ret;
0403 }
0404
0405
0406 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
0407 {
0408 int ret;
0409 int val;
0410 pvr2_trace(PVR2_TRACE_ENCODER, "pvr2_encoder_configure (cx2341x module)");
0411 hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
0412 hdw->enc_ctl_state.width = hdw->res_hor_val;
0413 hdw->enc_ctl_state.height = hdw->res_ver_val;
0414 hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
0415 0 : 1);
0416
0417 ret = 0;
0418
0419 ret |= pvr2_encoder_prep_config(hdw);
0420
0421
0422 val = 0xf0;
0423 if (hdw->hdw_desc->flag_has_cx25840) {
0424
0425 val = 0x140;
0426 }
0427
0428 if (!ret) ret = pvr2_encoder_vcmd(
0429 hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
0430 val, val);
0431
0432
0433 if (!ret) ret = pvr2_encoder_vcmd(
0434 hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
0435 0, 0, 0x10000000, 0xffffffff);
0436
0437 if (!ret) ret = pvr2_encoder_vcmd(
0438 hdw,CX2341X_ENC_SET_VBI_LINE, 5,
0439 0xffffffff,0,0,0,0);
0440
0441 if (ret) {
0442 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0443 "Failed to configure cx23416");
0444 return ret;
0445 }
0446
0447 ret = pvr2_encoder_adjust(hdw);
0448 if (ret) return ret;
0449
0450 ret = pvr2_encoder_vcmd(
0451 hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
0452
0453 if (ret) {
0454 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
0455 "Failed to initialize cx23416 video input");
0456 return ret;
0457 }
0458
0459 return 0;
0460 }
0461
0462
0463 int pvr2_encoder_start(struct pvr2_hdw *hdw)
0464 {
0465 int status;
0466
0467
0468 pvr2_write_register(hdw, 0x0048, 0xbfffffff);
0469
0470 pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
0471 hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
0472
0473 switch (hdw->active_stream_type) {
0474 case pvr2_config_vbi:
0475 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
0476 0x01,0x14);
0477 break;
0478 case pvr2_config_mpeg:
0479 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
0480 0,0x13);
0481 break;
0482 default:
0483 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
0484 0,0x13);
0485 break;
0486 }
0487 return status;
0488 }
0489
0490 int pvr2_encoder_stop(struct pvr2_hdw *hdw)
0491 {
0492 int status;
0493
0494
0495 pvr2_write_register(hdw, 0x0048, 0xffffffff);
0496
0497 switch (hdw->active_stream_type) {
0498 case pvr2_config_vbi:
0499 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
0500 0x01,0x01,0x14);
0501 break;
0502 case pvr2_config_mpeg:
0503 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
0504 0x01,0,0x13);
0505 break;
0506 default:
0507 status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
0508 0x01,0,0x13);
0509 break;
0510 }
0511
0512 return status;
0513 }