diff -ur ivtv.vanilla/driver/ivtv-api.c ivtv/driver/ivtv-api.c --- ivtv.vanilla/driver/ivtv-api.c 2003-10-24 08:16:14.000000000 +0200 +++ ivtv/driver/ivtv-api.c 2003-10-28 15:33:57.000000000 +0100 @@ -468,7 +468,7 @@ /* 3 stream types: mpeg, yuv, passthru */ struct ivtv_v4l2_stream tmk_mpg_stream = { /*MPEG*/ - .capturing = 0, + .s_flags = 0, .id = -1, .v4l_reg_type = VFL_TYPE_GRABBER, .format = { @@ -488,7 +488,7 @@ struct ivtv_v4l2_stream tmk_yuv_stream = { /*YUV*/ - .capturing = 0, + .s_flags = 0, .id = -1, .v4l_reg_type = VFL_TYPE_GRABBER, .format = { @@ -508,7 +508,7 @@ //FIXME these settings are way wrong struct ivtv_v4l2_stream tmk_vbi_stream = { - .capturing = 0, + .s_flags = 0, .id = -1, .v4l_reg_type = VFL_TYPE_VBI, .format = { @@ -528,7 +528,7 @@ struct ivtv_v4l2_stream dec_mpg_stream = { /*Decoder MPG*/ - .capturing = 0, + .s_flags = 0, .id = -1, .v4l_reg_type = VFL_TYPE_GRABBER, .format = { @@ -548,7 +548,7 @@ struct ivtv_v4l2_stream dec_yuv_stream = { /*Decoder YUV*/ - .capturing = 0, + .s_flags = 0, .id = -1, .v4l_reg_type = VFL_TYPE_GRABBER, .format = { @@ -566,7 +566,6 @@ .controls = NULL }; - /* Initialize v4l2 variables and register v4l2 device */ int ivtv_v4l2_setup(struct ivtv *itv) { int x, cont, retval; @@ -632,14 +631,6 @@ itv->dec_options.fr_mask = 2; itv->dec_options.fr_field = 1; - if (itv->v4l2.standard.active == 0) { - itv->v4l2.codec.framespergop = 15; // NTSC - itv->v4l2.codec.framerate = 0; // NTSC 30fps - } else { - itv->v4l2.codec.framespergop = 12; // PAL - itv->v4l2.codec.framerate = 1; // PAL 25fps - } - /* Allocate streams */ itv->v4l2.streams = (struct ivtv_v4l2_stream *) kmalloc((itv->v4l2.streamcount * @@ -651,6 +642,13 @@ goto ivtv_stream_fail; } + /* pre-init */ + retval = ivtv_v4l2_pre_init(itv); + if (retval < 0) { + IVTV_DEBUG(IVTV_DEBUG_ERR, "Error in pre-init\n"); + goto ivtv_pre_init_fail; + } + /* Fill in streams with some defaults */ memcpy(&itv->v4l2.streams[IVTV_ENC_STREAM_TYPE_MPG], &tmk_mpg_stream, sizeof(struct ivtv_v4l2_stream)); @@ -750,7 +748,8 @@ /* Set poll for decoder parts */ itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG].v4l2dev.fops->poll = ivtv_dec_poll; - itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].v4l2dev.fops->poll = ivtv_dec_poll; + if (itv->options.dec_yuv_buffers) + itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].v4l2dev.fops->poll = ivtv_dec_poll; break; case IVTV_250_V2: @@ -760,16 +759,6 @@ break; } - /* setup semaphore */ - sema_init(&itv->v4l2.v4l2_lock, 1); - - /* pre-init */ - retval = ivtv_v4l2_pre_init(itv); - if (retval < 0) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "Error in pre-init\n"); - goto ivtv_pre_init_fail; - } - /* allocate minor, register, loop until works or out of range */ for (x=0;x < itv->v4l2.streamcount; x++) { cont = 0; @@ -800,6 +789,7 @@ return 0; ivtv_pre_init_fail: + /* needs lots of queue cleanup here -axboe */ ivtv_initq_fail: kfree(itv->v4l2.streams); ivtv_stream_fail: @@ -841,14 +831,34 @@ data[0] = 0; /* 0 = pause, 1 = unpause */ if (cmd) data[0] = 1; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_PAUSE_ENCODER, + x = ivtv_api(itv->enc_mbox, &itv->sem_lock, IVTV_API_PAUSE_ENCODER, &result,1, &data[0]); return result; } -/* Called if v4l2 registration is successful */ +/* Called if v4l2 registration is successful. Set video mode here, at least + * that is required on PAL cards */ int ivtv_v4l2_init(struct video_device *v) { - /* just a placeholder for now */ + struct ivtv *ivtv = v->priv; + u32 data[IVTV_MBOX_MAX_DATA], result; + int x; + + /* + * only set it on minor 0 + */ + if (v->minor != 0) + return 0; + + memset(data, 0, sizeof(data)); + /* set display standard */ + if (ivtv_pal) + data[0] = 1; + else + data[0] = 0; + + x = ivtv_api(ivtv->dec_mbox, &ivtv->sem_lock,IVTV_API_DEC_DISP_STANDARD, + &result, 1, &data[0]); + return 0; } @@ -879,10 +889,28 @@ itv->v4l2.output.table.output = NULL; //standards (NTSC, PAL, SECAM) - itv->v4l2.standard.active = 0; + if (ivtv_pal) + itv->v4l2.standard.active = 1; + else + itv->v4l2.standard.active = 0; itv->v4l2.standard.count = 3; itv->v4l2.standard.table.std = tmk_standards; + if (itv->v4l2.standard.active == 0) { + itv->v4l2.codec.framespergop = 15; // NTSC + itv->v4l2.codec.framerate = 0; // NTSC 30fps + } else { + itv->v4l2.codec.framespergop = 12; // PAL + itv->v4l2.codec.framerate = 1; // PAL 25fps + + /* set pal height in stream defaults */ + tmk_mpg_stream.format.fmt.pix.height = 576; + tmk_yuv_stream.format.fmt.pix.height = 576; + tmk_vbi_stream.format.fmt.pix.height = 576; + dec_mpg_stream.format.fmt.pix.height = 576; + dec_yuv_stream.format.fmt.pix.height = 576; + } + //tuner itv->v4l2.tuner.active = 0; if (itv->card_type == IVTV_350_V1) { @@ -905,9 +933,6 @@ memcpy(itv->v4l2.tuner.table.tuner, &tmk_tuners[0], (itv->v4l2.tuner.count * sizeof(struct v4l2_tuner))); - /* Some initial setup */ - itv->v4l2.standard.active = 0; - /* Setup audio */ /* V4L2_CID_IVTV_FREQ */ itv->v4l2.audio_meta[0].ctrl = &ivtv_ctrl_menu_freq; @@ -1000,6 +1025,9 @@ int type,subtype; unsigned int dig; + /* sem_lock must be held */ + IVTV_ASSERT(sem_getcount(&itv->sem_lock) >= 1); + IVTV_DEBUG(IVTV_DEBUG_INFO,"ivtv start v4l2 stream\n"); /* NTSC/PAL switching */ @@ -1020,9 +1048,6 @@ break; } - /* FIXME i'm wrapping the whole start-cap in a semaphore */ - down_interruptible(&itv->enc_sem_adm); - /* clear queues */ ivtv_move_queue(&itv->v4l2.streams[id->type].full_q, &itv->v4l2.streams[id->type].free_q); @@ -1040,46 +1065,45 @@ /* FIXME this needs a flag */ data[0] = 1; /* num bytes in block*/ data[1] = 1; /* use info from sg instead */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_DMA_BLOCKLEN, - &result, 2, &data[0]); + x = __ivtv_api(itv->enc_mbox,IVTV_API_ASSIGN_DMA_BLOCKLEN, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 1. Code %d\n",x); /*assign program index info */ /* FIXME need more info on this call */ data[0] = 0; /*Mask 0:Disable */ data[1] = 0; /*Num_req 0:??/ */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_PGM_INDEX_INFO, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_PGM_INDEX_INFO, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 2. Code %d\n",x); /*assign stream type */ data[0] = itv->v4l2.codec.stream_type; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_STREAM_TYPE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_STREAM_TYPE, &result,1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 3. Code %d\n",x); /*assign output port */ data[0] = 0; /*0:Memory */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_OUTPUT_PORT, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_OUTPUT_PORT, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 4. Code %d\n",x); /*assign framerate */ data[0] = itv->v4l2.codec.framerate; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_FRAMERATE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_FRAMERATE, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 5. Code %d\n",x); /*assign frame size */ data[0] = vsize; /* height*/ data[1] = hsize; /* width */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_FRAME_SIZE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_FRAME_SIZE, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 6. Code %d\n",x); /*assign aspect ratio */ data[0] = itv->v4l2.codec.aspect; /*mpeg spec sez 2 */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_ASPECT_RATIO, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_ASPECT_RATIO, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 7. Code %d\n",x); @@ -1090,46 +1114,46 @@ data[2] = itv->v4l2.codec.bitrate_peak / 400; /* peak/400 */ data[3] = 0; /*??? */ data[4] = 0x70; /*??? */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_BITRATES, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_BITRATES, &result, 5, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 8. Code %d\n",x); /*assign gop properties */ data[0] = itv->v4l2.codec.framespergop; data[1] = itv->v4l2.codec.bframes; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_GOP_PROPERTIES, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_GOP_PROPERTIES, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 9. Code %d\n",x); /*assign 3 2 pulldown */ data[0] = itv->v4l2.codec.pulldown; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_3_2_PULLDOWN, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_3_2_PULLDOWN, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 10. Code %d\n",x); /*assign gop closure */ data[0] = itv->v4l2.codec.gop_closure; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_GOP_CLOSURE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_GOP_CLOSURE, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 11. Code %d\n",x); /*assign audio properties */ data[0] = itv->v4l2.codec.audio_bitmap; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_AUDIO_PROPERTIES, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_AUDIO_PROPERTIES, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 12. Code %d\n",x); /*assign dnr filter mode */ data[0] = itv->v4l2.codec.dnr_mode; data[1] = itv->v4l2.codec.dnr_type; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_DNR_FILTER_MODE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_DNR_FILTER_MODE, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 13. Code %d\n",x); /*assign dnr filter props*/ data[0] = itv->v4l2.codec.dnr_spatial; data[1] = itv->v4l2.codec.dnr_temporal; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_DNR_FILTER_PROPS, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_DNR_FILTER_PROPS, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 14. Code %d\n",x); @@ -1138,20 +1162,20 @@ data[1] = 255; /*luma_l */ data[2] = 0; /*chroma_h */ data[3] = 255; /*chroma_l */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_CORING_LEVELS, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_CORING_LEVELS, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 15. Code %d\n",x); /*assign spatial filter type */ data[0] = 1; /*luma_t: 1 = horiz_only */ data[1] = 1; /*chroma_t: 1 = horiz_only */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 16. Code %d\n",x); /*assign frame drop rate */ data[0] = 0; - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_FRAME_DROP_RATE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_FRAME_DROP_RATE, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 17. Code %d\n",x); @@ -1168,14 +1192,14 @@ data[9] = 0; /*arg6 */ data[10] = 0; /*arg7 */ data[11] = 0; /*arg8 */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_PLACEHOLDER, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_PLACEHOLDER, &result, 12, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 18. Code %d\n\n",x); /* assign num vsync lines */ data[0] = vsync; /*??? */ data[1] = vsync; /* ??? */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_ASSIGN_NUM_VSYNC_LINES, + x = __ivtv_api(itv->enc_mbox, IVTV_API_ASSIGN_NUM_VSYNC_LINES, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 20. Code %d\n",x); @@ -1194,7 +1218,7 @@ data[1] = 1; /*on/off: 1 = on */ data[2] = 0x10000000; /*intr_bit: 0x10000000 = digitizer */ data[3] = -1; /*mbox_id: -1: none */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, + x = __ivtv_api(itv->enc_mbox, IVTV_API_EVENT_NOTIFICATION, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "startcap error 2. Code %d\n",x); @@ -1205,7 +1229,7 @@ DECODER_ENABLE_OUTPUT,&dig); /*initialize input (no args) */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, + x = __ivtv_api(itv->enc_mbox, IVTV_API_INITIALIZE_INPUT, &result, 0, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "init error 19. Code %d\n\n",x); @@ -1217,7 +1241,7 @@ IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 100ms\n"); set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(.1*HZ); + schedule_timeout(HZ/10); } itv->graceful_eos = 0; @@ -1225,7 +1249,7 @@ /* begin_capture */ data[0] = type; /*type: 0 = mpeg */ data[1] = subtype; /*subtype: 3 = video+audio */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_BEGIN_CAPTURE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_BEGIN_CAPTURE, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "startcap error 1. Code %d\n",x); @@ -1238,7 +1262,6 @@ /*you're live! sit back and await interrupts :)*/ atomic_inc(&itv->capturing); - up(&itv->enc_sem_adm); return 0; } @@ -1251,7 +1274,7 @@ data[4] = mute_audio; data[5] = display_fields; - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, IVTV_API_DEC_PLAYBACK_SPEED, &result, 6, &data[0]); + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_PLAYBACK_SPEED, &result, 6, &data[0]); return result; } @@ -1263,12 +1286,11 @@ int type; int standard=0; + /* sem_lock must be held */ + IVTV_ASSERT(sem_getcount(&itv->sem_lock) >= 1); type = id->type; - /* FIXME wrong semaphore */ - down_interruptible(&itv->dec_sem_adm); - if (itv->v4l2.standard.active != 0) { /* if not NTSC */ standard = 1; /* PAL */ } @@ -1297,23 +1319,26 @@ /* set display standard */ data[0] = standard; /* 0 = NTSC, 1 = PAL */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_DISP_STANDARD, + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_DISP_STANDARD, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN'T SET DISPLAY STD %d\n",x); /* set audio mode */ data[0] = 0; /* Dual mono-mode action: ??? */ data[1] = 0; /* stereo mode action: 0=stereo, 1=left, 2=right, 3=mono */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_SELECT_AUDIO, + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_SELECT_AUDIO, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN'T SET AUDIO MODE %d\n",x); /* set decoder source settings */ data[0] = id->type; /* Data type: 0 = mpeg from host, 1 = yuv from encoder, 2 = yuv_from_host */ data[1] = 720; /* YUV source width*/ - data[2] = 480; /* YUV source height*/ + if (itv->v4l2.standard.active == 1) + data[2] = 576; /* YUV source height*/ + else + data[2] = 480; /* YUV source height*/ data[3] = itv->v4l2.codec.audio_bitmap; /* Audio settings to use, bitmap. see docs.*/ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_DECODE_SOURCE, + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_DECODE_SOURCE, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN't INITIALIZE DECODER SOURCE %d\n",x); @@ -1323,40 +1348,36 @@ data[1] = 1; /* Enable/Disable: 0 = disabled, 1 = enabled */ data[2] = 0x00010000; /* Bit: interrupt bit to fire */ data[3] = -1; /* Mailbox to use: -1 = no mailbox needed */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_EVENT_NOTIFICATION, + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_EVENT_NOTIFICATION, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN'T INITIALIZE EVENT NOTIFICATION %d\n",x); #endif /* set number of internal decoder buffers */ data[0] = 1; /* 0 = 6 buffers, 1 = 9 buffers */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_DISPLAY_BUFFERS, + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_DISPLAY_BUFFERS, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN'T INITIALIZE # OF DISPLAY BUFFERS %d\n",x); /* prebufferring*/ data[0] = 1; /* 0 = no prebuffering, 1 = enabled, see docs */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_BUFFER, - &result, 1, &data[0]); + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_BUFFER, &result, 1,&data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN't INITIALIZE BUFFER %d\n",x); #if 0 /* set stream input port */ data[0] = 0; /* 0 = memory, 1 = streaming */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_STREAM_INPUT, - &result, 1, &data[0]); + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_STREAM_INPUT, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN'T INITIALIZE STREAM INPUT %d\n",x); /* A/V sync delay */ data[0] = 0; /* Delay in 90khz ticks. 0 = synced, negative = audio lags, positive = video lags */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_SET_AV_DELAY, - &result, 1, &data[0]); + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_SET_AV_DELAY, &result, 1, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN't INITIALIZE Audio/Vid sync delay %d\n",x); #endif /* start playback */ data[0] = itv->dec_options.gop_offset; /* frame to start from (in GOP) */ data[1] = itv->dec_options.mute_frames; /* # of audio frames to mute */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_START_PLAYBACK, - &result, 2, &data[0]); + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_START_PLAYBACK, &result, 2, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "COULDN'T START PLAYBACK %d\n",x); if (atomic_read(&itv->decoding) == 0) @@ -1369,14 +1390,7 @@ /*you're live! sit back and await interrupts :)*/ atomic_inc(&itv->decoding); - - /* FIXME wrong semaphore still */ - up(&itv->dec_sem_adm); - - /* start thread */ - ivtv_start_decode(itv); - - return 0; + return 0; } void ivtv_v4l2_cleanup(struct ivtv *itv) { @@ -1409,6 +1423,7 @@ IVTV_DEBUG(IVTV_DEBUG_INFO,"v4l2 open on minor %d\n", minor); /* Find which card this open was on */ + spin_lock_irq(&ivtv_lock); for (x=0;xlist); - if (down_interruptible(&item->itv->enc_sem_adm)) { - kfree(item); - return -ERESTARTSYS; - } + down(&itv->sem_lock); + item->open_id = item->itv->open_id++; - up(&item->itv->enc_sem_adm); list_add_tail (&item->list, &item->itv->client_list); + + up(&itv->sem_lock); filp->private_data = item; @@ -1471,16 +1486,16 @@ IVTV_DEBUG(IVTV_DEBUG_INFO,"v4l2 read\n"); - if (down_interruptible(&id->itv->v4l2.v4l2_lock)) + if (down_interruptible(&id->itv->sem_lock)) return -ERESTARTSYS; //FIXME need to handle non-blocking io //FIXME needs locking //FIXME this can be collapsed into 1 var i think - if ((id->itv->v4l2.streams[id->type].capturing == 0) && + if (!test_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags) && (id->itv->v4l2.streams[id->type].id == -1)) { - id->itv->v4l2.streams[id->type].capturing = 1; + set_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags); id->itv->v4l2.streams[id->type].id = id->open_id; ret = ivtv_start_v4l2_stream(id); @@ -1489,13 +1504,12 @@ "Error in v4l2 stream init\n"); id->itv->v4l2.streams[id->type].seq = 0; id->itv->v4l2.streams[id->type].ubytes= 0; - up(&id->itv->v4l2.v4l2_lock); } else { if (id->open_id != id->itv->v4l2.streams[id->type].id) ret = -EBUSY; } - up(&id->itv->v4l2.v4l2_lock); + up(&id->itv->sem_lock); if (ret) return ret; @@ -1521,15 +1535,14 @@ (id->type != IVTV_DEC_STREAM_TYPE_YUV)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Write on read-only interface\n"); return -EINVAL; - } + } - if (down_interruptible(&id->itv->v4l2.v4l2_lock)) + if (down_interruptible(&id->itv->sem_lock)) return -ERESTARTSYS; // Initialize Decoder /* FIXME we'll need to make this its own stream type */ - if(id->itv->v4l2.streams[id->type].capturing == 0) { - id->itv->v4l2.streams[id->type].capturing = 1; + if (!test_and_set_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags)) { id->itv->v4l2.streams[id->type].id = id->open_id; ret = ivtv_start_v4l2_decode(id); } else { @@ -1537,7 +1550,7 @@ ret = -EBUSY; } - up(&id->itv->v4l2.v4l2_lock); + up(&id->itv->sem_lock); if (ret) return ret; @@ -1556,19 +1569,20 @@ return -ENODEV; } + if (down_interruptible(&id->itv->sem_lock)) + return -ERESTARTSYS; + if (id->open_id == id->itv->v4l2.streams[id->type].id) { ivtv_close(id); - if (down_interruptible(&id->itv->v4l2.v4l2_lock)) - return -ERESTARTSYS; - - id->itv->v4l2.streams[id->type].capturing = 0; + clear_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags); id->itv->v4l2.streams[id->type].id = -1; - up(&id->itv->v4l2.v4l2_lock); } list_del(&id->list); + up(&id->itv->sem_lock); + kfree(id); return 0; @@ -1636,11 +1650,10 @@ break; } case IVTV_IOC_GET_FB: { - if (itv->fb_id >= 0) { - copy_to_user((int*)arg, &itv->fb_id, sizeof(itv->fb_id)); - } else { + if (itv->fb_id < 0) return -EINVAL; - } + if (copy_to_user((int*)arg, &itv->fb_id, sizeof(itv->fb_id))) + return -EFAULT; break; } @@ -1650,22 +1663,24 @@ IVTV_DEBUG(IVTV_DEBUG_INFO,"ivtv ioctl: FWAPI\n"); - memcpy(&fwapi, (struct ivtv_ioctl_fwapi *)arg, - sizeof(struct ivtv_ioctl_fwapi)); + if (copy_from_user(&fwapi, (struct ivtv_ioctl_fwapi *) arg, + sizeof(struct ivtv_ioctl_fwapi))) + return -EFAULT; /* Encoder - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, fwapi.cmd, + x = ivtv_api(itv->enc_mbox, &itv->sem_lock, fwapi.cmd, &fwapi.result, fwapi.args, &fwapi.data[0]); */ /* Decoder */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, fwapi.cmd, + x = ivtv_api(itv->dec_mbox, &itv->sem_lock, fwapi.cmd, &fwapi.result, fwapi.args, &fwapi.data[0]); - memcpy((struct ivtv_ioctl_fwapi *) arg, &fwapi, - sizeof(struct ivtv_ioctl_fwapi)); + + if (copy_to_user((struct ivtv_ioctl_fwapi *) arg, &fwapi, + sizeof(struct ivtv_ioctl_fwapi))) + return -EFAULT; return x; - break; } case IVTV_IOC_FRAMESYNC: { interruptible_sleep_on(&itv->vsync_w); @@ -1684,7 +1699,7 @@ u32 data[IVTV_MBOX_MAX_DATA], result; data[0] = 0; /* 0-based frame # to start from (in GOP) */ data[1] = 0; /* # of audio frames to mute */ - if (ivtv_api(itv->dec_mbox, &itv->dec_sem_w, + if (ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_START_PLAYBACK, &result, 2, &data[0])) IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: error starting playback\n"); @@ -1693,39 +1708,56 @@ } case IVTV_IOC_S_START_DECODE: { - struct ivtv_cfg_start_decode *sd=(struct ivtv_cfg_start_decode *)arg; + struct ivtv_cfg_start_decode sd; - if ((sd->gop_offset < 0) || (sd->gop_offset > 15)) return -EINVAL; - if (sd->muted_audio_frames < 0) return -EINVAL; + if (copy_from_user(&sd, (struct ivtv_cfg_start_decode *) arg, + sizeof(sd))) + return -EFAULT; + + if ((sd.gop_offset < 0) || (sd.gop_offset > 15)) + return -EINVAL; + if (sd.muted_audio_frames < 0) + return -EINVAL; - itv->dec_options.gop_offset = sd->gop_offset; + itv->dec_options.gop_offset = sd.gop_offset; - itv->dec_options.mute_frames = sd->muted_audio_frames; + itv->dec_options.mute_frames = sd.muted_audio_frames; break; } case IVTV_IOC_S_STOP_DECODE: { - struct ivtv_cfg_stop_decode *sd = (struct ivtv_cfg_stop_decode *)arg; + struct ivtv_cfg_stop_decode sd; - if ((sd->hide_last < 0) || (sd->hide_last > 1)) return -EINVAL; - itv->dec_options.hide_last_frame = sd->hide_last; + if (copy_from_user(&sd, (struct ivtv_cfg_stop_decode *)arg, + sizeof(sd))) + return -EFAULT; - itv->dec_options.pts_low = (u32)(sd->pts_stop & 0xFFFFFFFF); - itv->dec_options.pts_hi = (u32)(sd->pts_stop >> 32); + if ((sd.hide_last < 0) || (sd.hide_last > 1)) + return -EINVAL; + itv->dec_options.hide_last_frame = sd.hide_last; + + itv->dec_options.pts_low = (u32)(sd.pts_stop & 0xFFFFFFFF); + itv->dec_options.pts_hi = (u32)(sd.pts_stop >> 32); break; } case IVTV_IOC_S_SLOW_FAST: { - struct ivtv_slow_fast *sf = (struct ivtv_slow_fast *)arg; + struct ivtv_slow_fast sf; u32 data[IVTV_MBOX_MAX_DATA], result; + + if (copy_from_user(&sf, (struct ivtv_slow_fast *)arg, + sizeof(sf))) + return -EFAULT; - if ((sf->scale < 0) || (sf->scale > 50)) return -EINVAL; - if ((sf->speed < 0) || (sf->speed > 1)) return -EINVAL; + if ((sf.scale < 0) || (sf.scale > 50)) + return -EINVAL; + if ((sf.speed < 0) || (sf.speed > 1)) + return -EINVAL; - data[0] = sf->scale; + data[0] = sf.scale; if (itv->dec_options.smooth) /* smooth ff */ data[0] |= 0x40000000; - if (sf->speed) /* fast forward */ + if (sf.speed) /* fast forward */ data[0] |= 0x80000000; data[1] = 1; /* Forward. Reverse not supported */ @@ -1749,7 +1781,7 @@ data[6] = itv->dec_options.sf_mute; /* # of frames to mute on normal speed resume */ - if (ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, + if (ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_PLAYBACK_SPEED, &result, 7, &data[0])) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: error in slow/fast mode\n"); @@ -1760,7 +1792,7 @@ case IVTV_IOC_PAUSE: { u32 data[IVTV_MBOX_MAX_DATA], result; data[0] = 0; - if (ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, + if (ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_PAUSE_PLAYBACK, &result, 1, &data[0])) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: error pausing\n"); @@ -2431,7 +2463,6 @@ } } return -EINVAL; - break; } case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */ struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; @@ -2557,7 +2588,7 @@ default: /* If it got here, it's probably not supported.. */ IVTV_DEBUG(IVTV_DEBUG_ERR,"ivtv-api.c: unknown ioctl 0x%08x\n", cmd); - return -EINVAL; + return -ENOTTY; break; } return 0; diff -ur ivtv.vanilla/driver/ivtv-driver.c ivtv/driver/ivtv-driver.c --- ivtv.vanilla/driver/ivtv-driver.c 2003-10-24 08:16:09.000000000 +0200 +++ ivtv/driver/ivtv-driver.c 2003-10-28 15:33:50.000000000 +0100 @@ -7,12 +7,6 @@ #include "ivtv.h" -inline u64 rdtsc64() { - u64 timestamp; - rdtscll(timestamp); - return timestamp; -} - /* mini header */ /* var to keep track of the number of array elements in use */ @@ -21,8 +15,8 @@ /* Master variable for all ivtv info */ struct ivtv ivtv_cards[IVTV_MAX_CARDS]; -/* needed for some reason .. one of the firmware cmds needs it*/ -int errno; +/* for the global data */ +spinlock_t ivtv_lock = SPIN_LOCK_UNLOCKED; /* add your revision and whatnot here */ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { @@ -36,8 +30,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id); -static int module_start(void); -static void module_cleanup(void); static void ivtv_remove(struct pci_dev *pci_dev); static int load_fw_direct(const char *fn, char *mem); struct ivtv_mailbox* ivtv_api_irqsafe(struct ivtv_mailbox *mbox, u32 cmd, @@ -50,29 +42,36 @@ unsigned int hack = 0; /* Parameter declarations */ -int num_devices = 1; -int yuv_buffers = 60; -int mpg_buffers = 30; -int vbi_buffers = 10; -int dec_mpg_buffers = 8; -int dec_yuv_buffers = 0; -int dec_mpg_qlen = 2; -int dec_yuv_qlen = 0; +static int num_devices = 1; +static int yuv_buffers = 60; +static int mpg_buffers = 100; +static int vbi_buffers = 10; +static int dec_mpg_buffers = 8; +static int dec_yuv_buffers; +static int dec_mpg_qlen = 2; +static int dec_yuv_qlen; #ifdef YUV_FIXUP -int yuv_fixup = 0; +static int yuv_fixup; #endif +int ivtv_pal = 0; + + /* low debugging by default */ #if 0 int debug = ( IVTV_DEBUG_ERR | IVTV_DEBUG_INFO | IVTV_DEBUG_API | IVTV_DEBUG_DMA | IVTV_DEBUG_IOCTL | IVTV_DEBUG_I2C | IVTV_DEBUG_IRQ ); #endif -int debug = 1; +int ivtv_debug = IVTV_DEBUG_ERR; /* tuner.h tuner type for ivtv card */ int tuner = -1; +int errno; + +unsigned long oldest_ts; + #ifdef YUV_FIXUP MODULE_PARM(yuv_fixup, "i"); MODULE_PARM_DESC(yuv_fixup, @@ -115,10 +114,13 @@ "\nNumber of 32K buffers to queue before dispatching to decoder\n" "Default: 0, Min:0, Max: \n"); -MODULE_PARM(debug, "i"); +MODULE_PARM(ivtv_debug, "i"); MODULE_PARM_DESC(debug, "\nDebug level (bitmask), default, errors only\n" "(debug=127 gives full debuging)\n"); +MODULE_PARM(ivtv_pal, "i"); +MODULE_PARM_DESC(ivtv_pal, "Use PAL as default video mode instead of NTSC\n"); + MODULE_AUTHOR("Kevin Thayer"); MODULE_DESCRIPTION("Alpha iTVC15 driver"); MODULE_SUPPORTED_DEVICE("iTVC15/16 mpg2 encoder (aka WinTV PVR 250/350)\n"); @@ -127,6 +129,16 @@ int SGarray_size = 0; int DSGarray_size = 0; +void ivtv_sleep_timeout(int timeout) +{ + int sleep = timeout; + + do { + set_current_state(TASK_UNINTERRUPTIBLE); + sleep = schedule_timeout(sleep); + } while (sleep); +} + /* ceiling function for ints.. */ int ivtv_ceil(int x, int y) { int floor = (int)(x/y); @@ -165,6 +177,8 @@ } } +/* must only be used as hints, not as a definitive answer. the answer could + * be wrong as soon as we return */ int ivtv_get_free_elements(struct ivtv_buffer_list *queue) { unsigned long flags; @@ -284,20 +298,25 @@ return -EINVAL; } - spin_lock_irqsave(&queue->lock, flags); + spin_lock_irqsave(&ivtv_lock, flags); /* FIXME ugly */ /* verify ivtv before continuing */ for (x = 0; x < ivtv_cards_active; x++) { - if (queue->vdev->priv == &ivtv_cards[x]) break; + if (queue->vdev->priv == &ivtv_cards[x]) + break; if (x == (ivtv_cards_active - 1)) { queue->elements = 0; - goto out; + spin_unlock_irqrestore(&ivtv_lock, flags); + return 0; } } + spin_unlock_irqrestore(&ivtv_lock, flags); + itv=(struct ivtv *)queue->vdev->priv; + spin_lock_irqsave(&queue->lock, flags); while (list_empty(&queue->list) == 0) { item = __ivtv_deq_buf(queue); /* FIXME no check to see if it's mapped or not */ @@ -312,7 +331,6 @@ } queue->elements = 0; -out: spin_unlock_irqrestore(&queue->lock, flags); return 0; } @@ -440,28 +458,26 @@ data[0] = 1; /* 0: render last frame, 1: stop NOW! :) */ data[1] = 0; /* "low 4 bytes of stop index" */ data[2] = 0; /* 0: stop immedeately */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, IVTV_API_DEC_STOP_PLAYBACK, + x = ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_STOP_PLAYBACK, &result, 3, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 2. Code %d\n",x); /*halt enc firmware */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_adm, IVTV_API_ENC_HALT_FW, + x = ivtv_api(itv->enc_mbox, &itv->sem_lock, IVTV_API_ENC_HALT_FW, &result, 0, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 3. Code %d\n",x); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100); + ivtv_sleep_timeout(HZ/100); /*halt dec firmware */ if (IVTV_250_V2 != itv->card_type) { - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, IVTV_API_DEC_HALT_FW, + x = ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_HALT_FW, &result, 0, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 4. Code %d\n",x); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(.01*HZ); + ivtv_sleep_timeout(HZ/100); } return 0; @@ -505,8 +521,7 @@ writel(IVTV_CMD_SPU_STOP, (IVTV_REG_SPU + itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(.01*HZ); + ivtv_sleep_timeout(HZ/100); IVTV_DEBUG(IVTV_DEBUG_INFO, "init Encoder SDRAM pre-charge\n"); writel(IVTV_CMD_SDRAM_PRECHARGE_INIT, @@ -524,9 +539,8 @@ writel(IVTV_CMD_SDRAM_REFRESH_INIT, (IVTV_REG_DEC_SDRAM_REFRESH + itv->reg_mem)); - IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for %dms (600 recommended)\n",(int)IVTV_SDRAM_SLEEPTIME*HZ); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(IVTV_SDRAM_SLEEPTIME*HZ); + IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for %dms (600 recommended)\n",(int)IVTV_SDRAM_SLEEPTIME); + ivtv_sleep_timeout(IVTV_SDRAM_SLEEPTIME); IVTV_DEBUG(IVTV_DEBUG_INFO, "Card ready for firmware!\n"); x = ivtv_firmware_copy(itv); @@ -540,8 +554,7 @@ (IVTV_REG_SPU+itv->reg_mem)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 1 sec\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ivtv_sleep_timeout(HZ); /*I guess this is read-modify-write :)*/ if (IVTV_250_V2 == itv->card_type) { @@ -554,8 +567,7 @@ } IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 1 sec\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); + ivtv_sleep_timeout(HZ); /* FIXME Send Status API commands to encoder and decoder to verify!*/ @@ -666,7 +678,7 @@ int ivtv_get_free_mailbox(struct ivtv_mailbox *mbox, struct semaphore* sem) { int mboxid; - + if (down_interruptible(sem)) return -ERESTARTSYS; mboxid = __ivtv_get_free_mailbox(mbox); up(sem); @@ -730,54 +742,40 @@ return 0; } -int ivtv_api_getresult(struct ivtv_mailbox *mbox, struct semaphore *sem, - u32 *result, u32 data[]) { +int __ivtv_api_getresult(struct ivtv_mailbox *mbox, u32 *result, u32 data[]) { u32 readdata; int count = 0; - if (NULL == mbox) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "invalid api mailbox\n"); - return -ENODEV; - } - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(.01*HZ); readdata = readl(&mbox->flags); while (!(readdata & IVTV_MBOX_FIRMWARE_DONE)) { /*FIXME this is a bad method*/ IVTV_DEBUG(IVTV_DEBUG_API, "[%d]mailbox not ready, sleeping for 10ms\n", count); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(.01*HZ); + ivtv_sleep_timeout(HZ/100); readdata = readl(&mbox->flags); /*will this work? heh hope so */ - if (count++ > 100) return -EBUSY; + if (count++ > 100) { + IVTV_DEBUG(IVTV_DEBUG_ERR, "timed out waiting for firmware\n"); + return -EBUSY; + } } - if (down_interruptible(sem)) - return -ERESTARTSYS; - *result = readl(&mbox->retval); for ( count=0; count < IVTV_MBOX_MAX_DATA; count++) data[count] = readl(&mbox->data[count]); - up(sem); return 0; } -int __ivtv_api_getresult(struct ivtv_mailbox *mbox, u32 *result, u32 data[]) { - u32 readdata; - int count = 0; +int ivtv_api_getresult(struct ivtv_mailbox *mbox, struct semaphore *sem, + u32 *result, u32 data[]) { - while (!(readdata = readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) { - yield(); - if (count++ > 100) return -EBUSY; - } + if (down_interruptible(sem)) + return -ERESTARTSYS; - *result = readl(&mbox->retval); - for (count = 0; count < IVTV_MBOX_MAX_DATA; count++) - data[count] = readl(&mbox->data[count]); + __ivtv_api_getresult(mbox, result, data); + up(sem); return 0; } @@ -854,7 +852,7 @@ /* Encoder */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Getting encoder firmware rev.\n"); - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_r, IVTV_API_ENC_GETVER, + x = ivtv_api(itv->enc_mbox, &itv->sem_lock, IVTV_API_ENC_GETVER, &result, 0, &data[0]); if (x) { IVTV_DEBUG(IVTV_DEBUG_ERR, @@ -868,7 +866,7 @@ if (itv->card_type != IVTV_250_V2) { /* Decoder */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Getting decoder firmware rev.\n"); - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_r, IVTV_API_DEC_GETVER, + x = ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_GETVER, &result, 0, &data[0]); if (x) { IVTV_DEBUG(IVTV_DEBUG_ERR, @@ -889,25 +887,29 @@ int x; id.itv = itv; - down(&itv->v4l2.v4l2_lock); + down(&itv->sem_lock); for (x = 0; x < itv->v4l2.streamcount;x++) { - if (itv->v4l2.streams[x].capturing==1) { + if (test_bit(IVTV_F_S_CAP, &itv->v4l2.streams[x].s_flags)) { id.type=x; ivtv_stop_capture(&id); } } - up(&itv->v4l2.v4l2_lock); + up(&itv->sem_lock); return 0; } int ivtv_stop_capture(struct ivtv_open_id *id) { struct ivtv *itv=id->itv; u32 data[IVTV_MBOX_MAX_DATA], result; + DECLARE_WAITQUEUE(wait, current); int type,subtype; int x; + /* sem_lock must be held */ + IVTV_ASSERT(sem_getcount(&itv->sem_lock) >= 1); + /* FIXME set 'die' ?? */ type = id->type; @@ -924,7 +926,7 @@ data[1] = 0; /*on/off: 0 = off */ data[2] = 0x10000000; /*intr_bit: 0x10000000 = digitizer */ data[3] = -1; /*mbox_id: -1: none */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_EVENT_NOTIFICATION, + x = __ivtv_api(itv->enc_mbox, IVTV_API_EVENT_NOTIFICATION, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopcap error 1. Code %d\n",x); @@ -934,18 +936,20 @@ data[0] = 0; /*when: 0 = end of GOP */ data[1] = type; /*type: 0 = mpeg */ data[2] = subtype; /*subtype: 3 = video+audio */ - x = ivtv_api(itv->enc_mbox, &itv->enc_sem_w, IVTV_API_END_CAPTURE, + x = __ivtv_api(itv->enc_mbox, IVTV_API_END_CAPTURE, &result, 3, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopcap error 2. Code %d\n",x); /* check if DMA is pending */ - if (itv->v4l2.streams[type].dma_pending) + if (test_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags)) IVTV_DEBUG(IVTV_DEBUG_ERR, "dma still pending! stopping anyway.\n"); + add_wait_queue(&itv->cap_w, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); /* only run these if we're shutting down the last cap */ if (atomic_read(&itv->capturing) == 0) { /* wait 1s for EOS interrupt */ - sleep_on_timeout(&itv->cap_w, 1*HZ); + ivtv_sleep_timeout(HZ); if (0==itv->graceful_eos) IVTV_DEBUG(IVTV_DEBUG_ERR, @@ -956,7 +960,8 @@ writel(itv->irqmask,(itv->reg_mem + IVTV_REG_IRQMASK)); IVTV_DEBUG(IVTV_DEBUG_IRQ, "IRQ Mask is now: 0x%08x\n", itv->irqmask); } - + set_current_state(TASK_RUNNING); + remove_wait_queue(&itv->cap_w, &wait); return 0; } @@ -966,12 +971,15 @@ struct ivtv_buffer *buf; int x; + /* sem_lock must be held */ + IVTV_ASSERT(sem_getcount(&itv->sem_lock) >= 1); + /* FIXME set 'die' ?? */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Decoder stop.\n"); /* stop decoder interrupt timeout */ - del_timer_sync(&itv->dec_timeout); + del_timer_sync(&itv->dec_timeout); /* only run these if we're shutting down the last cap */ if (atomic_read(&itv->decoding) == 0) { @@ -980,16 +988,14 @@ data[1] = 0; /* Enable/Disable: 0 = disabled, 1 = enabled */ data[2] = 0x00010000; /* Bit: interrupt bit to fire */ data[3] = -1; /* Mailbox to use: -1 = no mailbox needed */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, - IVTV_API_DEC_EVENT_NOTIFICATION, &result, 4, &data[0]); + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_EVENT_NOTIFICATION, &result, 4, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopDEC error 1. Code %d\n",x); /* end_capture */ data[0] = itv->dec_options.hide_last_frame; /* 0 = last frame, 1 = black */ data[1] = itv->dec_options.pts_low; /* when: pts low */ data[2] = itv->dec_options.pts_hi; /* when: pts hi */ - x = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_DEC_STOP_PLAYBACK, - &result, 3, &data[0]); + x = __ivtv_api(itv->dec_mbox, IVTV_API_DEC_STOP_PLAYBACK, &result, 3, &data[0]); if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stopDEC error 2. Code %d\n",x); } @@ -1018,38 +1024,32 @@ ivtv_enq_buf(&itv->v4l2.streams[id->type].free_q, buf); } - if (itv->v4l2.streams[id->type].dma_pending) { + if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[id->type].s_flags)) IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: clearing dma_pending\n"); - itv->v4l2.streams[id->type].dma_pending = 0; - } return 0; } -void ivtv_start_decode(struct ivtv *itv) { - return; -} - void ivtv_dec_timeout(unsigned long arg) { struct ivtv *itv = (struct ivtv *)arg; /* FIXME mpg only :/ */ struct ivtv_v4l2_stream *stream = &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG]; - if (!stream->dma_pending) - return; - - IVTV_DEBUG(IVTV_DEBUG_ERR, "ivtv_dec_timeout: lost IRQ; resetting...\n"); + if (!test_bit(IVTV_F_S_DMAP, &stream->s_flags)) + return; + IVTV_DEBUG(IVTV_DEBUG_ERR, "ivtv_dec_timeout: lost IRQ; resetting...\n"); #if 1 - ivtv_dec_DMA_done(itv); - /* kick it off again! */ - itv->dec_needs_data = 1; - ivtv_dec_sched_DMA(itv); + ivtv_dec_DMA_done(itv); + /* kick it off again! */ + set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); + ivtv_dec_sched_DMA(itv); #endif - IVTV_DEBUG(IVTV_DEBUG_ERR, "ivtv_dec_timeout: returning...\n"); + IVTV_DEBUG(IVTV_DEBUG_ERR, "ivtv_dec_timeout: returning...\n"); } +#if 0 static void ivtv_show_irq_status(struct ivtv* itv, u32 irqstat, u32 irqmask, u32 dmastat) { struct ivtv_mailbox* mbox8 = &itv->dec_mbox[8]; struct ivtv_mailbox* mbox9 = &itv->dec_mbox[9]; @@ -1102,8 +1102,8 @@ readl(&mbox9->data[1]), readl(&mbox9->data[2]), readl(&mbox9->data[3])); - } +#endif void ivtv_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { @@ -1131,11 +1131,19 @@ writel(combo, (itv->reg_mem + IVTV_REG_IRQSTATUS)); if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) { - ivtv_DMA_done_tasklet((unsigned long)itv); +#if 0 + tasklet_schedule(&itv->dma_done_tq); +#else + ivtv_DMA_done_tasklet((unsigned long) itv); +#endif IVTV_DEBUG(IVTV_DEBUG_IRQ, "Processed DMA-complete\n"); } if (combo & IVTV_IRQ_ENC_START_CAP) { - ivtv_sched_DMA_tasklet((unsigned long)itv); +#if 0 + tasklet_schedule(&itv->dma_sched_tq); +#else + ivtv_sched_DMA_tasklet((unsigned long) itv); +#endif IVTV_DEBUG(IVTV_DEBUG_IRQ, "Processed enc-startcap\n"); } if (combo & IVTV_IRQ_ENC_EOS) { @@ -1160,7 +1168,7 @@ } if (combo & IVTV_IRQ_DEC_DATA_REQ) { IVTV_DEBUG(IVTV_DEBUG_IRQ, "Decoder Data Request\n"); - itv->dec_needs_data = 1; + set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); ivtv_dec_sched_DMA(itv); } if (combo & IVTV_IRQ_DEC_IFRAME_DONE) { @@ -1216,9 +1224,8 @@ IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA Done tasklet\n"); for (y=0; y < itv->v4l2.streamcount; y++) { - if (itv->v4l2.streams[y].dma_pending) { + if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[y].s_flags)) { stmtype = y; - itv->v4l2.streams[y].dma_pending = 0; break; } } @@ -1231,14 +1238,13 @@ stream = &itv->v4l2.streams[y]; /* Silently return if we're in an overflow state */ - if (stream->overflow) { - stream->overflow = 0; + if (test_and_clear_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) return; - } /* check DMA status register */ result = readl(itv->reg_mem + IVTV_REG_DMASTATUS); + if (result & IVTV_DMA_WRITE_ERR) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA Error. Result: 0x%08x\n", result); return; @@ -1246,7 +1252,7 @@ if (0 == (result & IVTV_DMA_SUCCESS)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA interrupt, but no err and no " - "success. odd.\n"); + "success. odd %x.\n", result); return; } @@ -1269,24 +1275,25 @@ /*wake up client*/ wake_up(&stream->waitq); - - return; } int ivtv_ignore_DMA_req(struct ivtv *itv, u32 type) { - u32 data[IVTV_MBOX_MAX_DATA], result; + u32 data[IVTV_MBOX_MAX_DATA]; + + /* set these now, irq could happen right after ivtv_api call */ + set_bit(IVTV_F_S_OVERFLOW, &itv->v4l2.streams[type].s_flags); + set_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags); data[0] = type; data[0] = 0; data[1] = 0; /* ACK the DMA and continue */ - if (ivtv_api(itv->enc_mbox, &itv->enc_sem_w, - IVTV_API_SCHED_DMA_TO_HOST, &result, 2, &data[0])) { + if (ivtv_api_irqsafe(itv->enc_mbox, IVTV_API_SCHED_DMA_TO_HOST, 3, &data[0])) { IVTV_DEBUG(IVTV_DEBUG_ERR, "error sending DMA info\n"); + clear_bit(IVTV_F_S_OVERFLOW, &itv->v4l2.streams[type].s_flags); + clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags); return -EIO; } - itv->v4l2.streams[type].overflow = 1; - itv->v4l2.streams[type].dma_pending = 1; return 0; } @@ -1296,9 +1303,10 @@ u32 data[IVTV_MBOX_MAX_DATA], result; u32 type, size, offset; u32 UVsize=0, UVoffset=0, pts_stamp=0; - int x, bufs_needed, free; + int x, bufs_needed; int uvflag=0; struct ivtv *itv = (struct ivtv *) arg; + long sequence; IVTV_DEBUG(IVTV_DEBUG_INFO, "Sched DMA tasklet\n"); @@ -1350,7 +1358,6 @@ bufs_needed = ivtv_ceil(size, IVTV_DMA_BUF_SIZE); ivtv_ignore_DMA_req(itv, type); return; - break; case 3: /* VBI */ offset = data[1]; size = data[2]; @@ -1364,25 +1371,6 @@ "DMA/UNKNOWN type 0x%08x, NOT SUPPORTED\n", type); ivtv_ignore_DMA_req(itv, type); return; - break; - } - - free = ivtv_get_free_elements(&itv->v4l2.streams[type].free_q); - /* increment the sequence # */ - itv->v4l2.streams[type].seq++; - - IVTV_DEBUG(IVTV_DEBUG_INFO,"bufs_needed: %d, free: %d\n", bufs_needed, free); - - if (free < bufs_needed) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "Not enough free buffers, stream %d\n", - type); - printk(KERN_DEBUG "(fullq: %d, freeq: %d, dmaq: %d)\n", - itv->v4l2.streams[type].full_q.elements, - free, - itv->v4l2.streams[type].dma_q.elements); - - ivtv_ignore_DMA_req(itv, type); - return; } if (bufs_needed > SGarray_size) { @@ -1392,6 +1380,9 @@ return; } + /* increment the sequence # */ + sequence = ++itv->v4l2.streams[type].seq; + for (x = 0; x < bufs_needed; x++) { struct ivtv_buffer *buf; IVTV_DEBUG(IVTV_DEBUG_INFO, "size: %d 0x%08x\n", size, size); @@ -1405,14 +1396,19 @@ buf = ivtv_deq_buf(&itv->v4l2.streams[type].free_q); if (NULL == buf) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA buffer DeQueue failed!\n"); + struct ivtv_v4l2_stream *stream = &itv->v4l2.streams[type]; + IVTV_DEBUG(IVTV_DEBUG_ERR, "DMA buffer DeQueue failed! got %d, want %d\n", x + 1, bufs_needed); + IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: free_q: %d elements\n", stream->free_q.elements); + IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: dma_q: %d elements\n", stream->dma_q.elements); + IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: full_q: %d elements\n", stream->full_q.elements); ivtv_ignore_DMA_req(itv, type); return; } buf->readpos = 0; buf->buffer.index = x; - buf->buffer.sequence = itv->v4l2.streams[type].seq; + buf->buffer.sequence = sequence; + buf->ts = jiffies; if (size < (IVTV_DMA_BUF_SIZE & 0xffffff00)) { buf->buffer.bytesused = size; @@ -1430,11 +1426,13 @@ itv->SGarray[x].src = offset; offset += buf->buffer.bytesused; - /* FIXME no error checking on pci_map */ + /* unfortunately the pci dma api wasn't properly defined + * for handling mapping errors (running out of iommu space, + * for instance). 0 can be a valid bus address. */ buf->dma_handle = pci_map_single(itv->dev, (void *)buf->buffer.m.userptr, buf->buffer.bytesused, - PCI_DMA_TODEVICE); + PCI_DMA_FROMDEVICE); itv->SGarray[x].dst = buf->dma_handle; @@ -1463,11 +1461,8 @@ IVTV_DEBUG(IVTV_DEBUG_INFO, "Sched dma: addr: 0x%08x, array_size 0x%08x," " type 0x%08x\n", data[0], data[1], data[2]); + set_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[type].s_flags); ivtv_api_irqsafe(itv->enc_mbox, IVTV_API_SCHED_DMA_TO_HOST, 4, &data[0]); - - itv->v4l2.streams[type].dma_pending = 1; - - return; } /* FIXME this function does way more than it should */ @@ -1481,9 +1476,12 @@ IVTV_DEBUG(IVTV_DEBUG_INFO, "Found card #%d\n", ivtv_cards_active); + spin_lock_irq(&ivtv_lock); + /* Make sure we've got a place for this card */ if (ivtv_cards_active == IVTV_MAX_CARDS) { IVTV_DEBUG(IVTV_DEBUG_ERR, ":Maximum # of cards already detected (%d).\n", ivtv_cards_active); + spin_unlock_irq(&ivtv_lock); return -ENOMEM; } @@ -1491,6 +1489,10 @@ itv->dev = dev; itv->num = ivtv_cards_active; + ivtv_cards_active++; + + spin_unlock_irq(&ivtv_lock); + /* always remember what you think the irq mask should be */ itv->irqmask = 0; @@ -1528,27 +1530,20 @@ break; } - sema_init(&itv->enc_sem_r, 1); - sema_init(&itv->enc_sem_w, 1); - sema_init(&itv->enc_sem_adm, 1); - sema_init(&itv->dec_sem_r, 1); - sema_init(&itv->dec_sem_w, 1); - sema_init(&itv->dec_sem_adm, 1); - sema_init(&itv->dec_sched_dma_sem, 1); + init_MUTEX(&itv->sem_lock); itv->base_addr=pci_resource_start(dev,0); itv->enc_mbox = NULL; itv->dec_mbox = NULL; itv->io_mem = NULL; itv->reg_mem = NULL; + itv->i_flags = 0; atomic_set(&itv->capturing, 0); atomic_set(&itv->decoding, 0); - itv->dec_dma_pending = 0; itv->user_dma_to_device_state = NULL; /* Prepare list for action! */ INIT_LIST_HEAD(&itv->client_list); - init_waitqueue_head(&itv->read_w); init_waitqueue_head(&itv->cap_w); init_waitqueue_head(&itv->vsync_w); init_waitqueue_head(&itv->dec_master_w); @@ -1556,27 +1551,34 @@ itv->dec_timeout.function = ivtv_dec_timeout; itv->dec_timeout.data = (unsigned long)itv; + tasklet_init(&itv->dma_done_tq, ivtv_DMA_done_tasklet, (unsigned long) itv); + tasklet_init(&itv->dma_sched_tq, ivtv_sched_DMA_tasklet, (unsigned long) itv); + IVTV_DEBUG(IVTV_DEBUG_INFO, "base addr: 0x%08x\n", itv->base_addr); IVTV_DEBUG(IVTV_DEBUG_INFO, "Enabling pci device\n"); if (pci_enable_device(dev)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Can't enable device %d!\n",itv->num); - return -EIO; + retval = -EIO; + goto err; } if (pci_set_dma_mask(dev, 0xffffffff)) { IVTV_DEBUG(IVTV_DEBUG_ERR, KERN_WARNING "No suitable DMA available on card %d.\n", itv->num); - return -EIO; + retval = -EIO; + goto err; } if (!request_mem_region(pci_resource_start(dev,0), IVTV_IOREMAP_SIZE, IVTV_DEVNAME )) { - return -EBUSY; + retval = -EIO; + goto err; } /* Check for bus mastering */ pci_read_config_word(dev, PCI_COMMAND, &cmd); if (! (cmd & PCI_COMMAND_MASTER)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Bus Mastering is not enabled\n"); - return -EFAULT; + retval = -ENXIO; + goto free_mem; } else { IVTV_DEBUG(IVTV_DEBUG_INFO, "Bus Mastering Enabled."); @@ -1598,7 +1600,7 @@ if (!itv->io_mem) { IVTV_DEBUG(IVTV_DEBUG_ERR, IVTV_IOREMAP_ERROR); retval = -ENOMEM; - goto ivtv_ioremapfail; + goto free_mem; } /*map registers memory*/ @@ -1608,7 +1610,7 @@ if (!itv->reg_mem) { IVTV_DEBUG(IVTV_DEBUG_ERR, IVTV_IOREMAP_ERROR); retval = -ENOMEM; - goto ivtv_ioremapfail; + goto free_io; } IVTV_DEBUG(IVTV_DEBUG_IRQ, "Masking interrupts\n"); @@ -1618,17 +1620,9 @@ retval = request_irq(itv->dev->irq, ivtv_irq_handler, SA_SHIRQ | SA_INTERRUPT,IVTV_DEVNAME,(void *)itv); - if (retval==-EINVAL) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "Bad irq # or handler\n"); - goto ivtv_irqfail; - } - if (retval==-EBUSY) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "IRQ #%d is busy.\n", itv->dev->irq); - goto ivtv_irqfail; - } - if (retval < 0) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "Unknown irq error: %d\n", retval); - goto ivtv_irqfail; + if (retval) { + IVTV_DEBUG(IVTV_DEBUG_ERR, "failed to register irq %d\n", retval); + goto free_io; } /* save itv in the pci struct for later use*/ @@ -1639,10 +1633,9 @@ IVTV_DEBUG(IVTV_DEBUG_INFO, "activating i2c..\n"); if (init_ivtv_i2c(itv)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "i2c died! unloading\n"); - goto ivtv_i2cfail; + goto free_irq; } - ivtv_cards_active++; IVTV_DEBUG(IVTV_DEBUG_INFO, "Active card count: %d.\n", ivtv_cards_active); /*write firmware */ @@ -1650,7 +1643,7 @@ if (retval) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error initializing.\n"); retval = -ENOMEM; - goto ivtv_firm_fail; + goto free_i2c; } /*search for encoder/decoder mailboxes*/ @@ -1660,7 +1653,7 @@ if ((itv->enc_mbox == NULL) && (itv->dec_mbox ==NULL)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error locating firmware.\n"); retval = -ENOMEM; - goto ivtv_firm_fail; + goto free_i2c; } /*releasing unneeded iomapped memory (encoder+decoder)*/ @@ -1678,7 +1671,10 @@ /*Try and get firmware versions */ IVTV_DEBUG(IVTV_DEBUG_INFO, "Getting firmware version..\n"); retval = ivtv_firmware_versions(itv); - if (retval) IVTV_DEBUG(IVTV_DEBUG_ERR, "error %d getting version #!\n", retval); + if (retval) { + IVTV_DEBUG(IVTV_DEBUG_ERR, "error %d getting version #!\n", retval); + goto free_i2c; + } /* Allocate scatter-gather arrays*/ @@ -1693,7 +1689,7 @@ if (!(itv->SGarray)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error allocating SGarray[].\n"); retval = -ENOMEM; - goto ivtv_sg_fail; + goto free_i2c; } itv->SG_handle = pci_map_single(itv->dev, @@ -1710,7 +1706,7 @@ if (!(itv->DSGarray)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Error allocating DSGarray[].\n"); retval = -ENOMEM; - goto ivtv_dsg_fail; + goto free_sg; } itv->DSG_handle = pci_map_single(itv->dev, @@ -1730,19 +1726,25 @@ } /* set the standard */ - v.norm = VIDEO_MODE_NTSC; + if (!ivtv_pal) + v.norm = VIDEO_MODE_NTSC; + else + v.norm = VIDEO_MODE_PAL; + ivtv_call_i2c_client(itv,IVTV_TUNER_I2C_ADDR, VIDIOCSCHAN,&v); - /* set the channel */ - freq = 1076; /* ch. 4 67250*16/1000 */ - ivtv_call_i2c_client(itv,IVTV_TUNER_I2C_ADDR,VIDIOCSFREQ,&freq); + if (!ivtv_pal) { + /* set the channel */ + freq = 1076; /* ch. 4 67250*16/1000 */ + ivtv_call_i2c_client(itv,IVTV_TUNER_I2C_ADDR,VIDIOCSFREQ,&freq); + } retval = ivtv_v4l2_setup(itv); if (retval) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Problem starting v4l2\n"); goto ivtv_v4l2_fail; } - + return 0; ivtv_v4l2_fail: @@ -1752,24 +1754,28 @@ DSGarray_size), PCI_DMA_TODEVICE); kfree(itv->DSGarray); -ivtv_dsg_fail: +free_sg: pci_unmap_single(itv->dev, itv->SG_handle, (sizeof(struct ivtv_SG_element) * SGarray_size), PCI_DMA_TODEVICE); kfree(itv->SGarray); -ivtv_sg_fail: -ivtv_firm_fail: -ivtv_i2cfail: +free_i2c: + exit_ivtv_i2c(itv); +free_irq: free_irq(itv->dev->irq, (void *)itv); -ivtv_irqfail: +free_io: ivtv_iounmap(itv); -ivtv_ioremapfail: +free_mem: release_mem_region(pci_resource_start(itv->dev,0), IVTV_IOREMAP_SIZE); +err: IVTV_DEBUG(IVTV_DEBUG_ERR, "Error %d on init\n", retval); - return retval; + spin_lock_irq(&ivtv_lock); + ivtv_cards_active--; + spin_unlock_irq(&ivtv_lock); + return retval; } static void ivtv_remove(struct pci_dev *pci_dev) { @@ -1781,8 +1787,7 @@ writel(itv->irqmask, (itv->reg_mem + IVTV_REG_IRQMASK)); IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping thread\n"); - atomic_set(&itv->decoding, 0); - + atomic_set(&itv->decoding, 0); IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping card parts\n"); x = ivtv_stop_firmware(itv); @@ -1811,9 +1816,7 @@ PCI_DMA_TODEVICE); kfree(itv->DSGarray); - IVTV_DEBUG(IVTV_DEBUG_INFO, "unregistering i2c\n"); - if (0 == itv->i2c_rc) - i2c_bit_del_bus(&itv->i2c_adap); + exit_ivtv_i2c(itv); IVTV_DEBUG(IVTV_DEBUG_INFO, "releasing irq\n"); free_irq(itv->dev->irq, (void *)itv); @@ -1932,6 +1935,7 @@ unsigned long tid; struct ivtv_buffer *buf; struct ivtv_v4l2_stream *st=&itv->v4l2.streams[id->type]; + DECLARE_WAITQUEUE(wait, current); IVTV_DEBUG(IVTV_DEBUG_INFO, " Read stream.. \n"); @@ -1941,30 +1945,36 @@ return -EIO; } - sleepctr = 0; - /* FIXME find a way to gracefully exit capture */ - /* FIXME need spinlock here*/ - while (ivtv_get_free_elements(&st->full_q) == 0) { - - sleepctr++; - sleep_on_timeout(&st->waitq, IVTV_SLEEP_WAIT); - if(signal_pending(current)) - return -ERESTARTSYS; - + sleepctr = retval = 0; + buf = NULL; + add_wait_queue(&st->waitq, &wait); + do { if ((itv->trans_id == 0) && (sleepctr >= IVTV_MAX_DATA_SLEEP)) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Timeout waiting for data!\n"); - return -EIO; + retval = -EIO; + break; } - } - buf = ivtv_deq_peek_head(&st->full_q); + set_current_state(TASK_INTERRUPTIBLE); + buf = ivtv_deq_peek_head(&st->full_q); + if (buf) + break; + + ivtv_sleep_timeout(IVTV_SLEEP_WAIT); - if (buf == NULL) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "Error obtaining buffer\n"); - return -EIO; - } + if (signal_pending(current)) + retval = -ERESTARTSYS; + + sleepctr++; + } while (!retval); + __set_current_state(TASK_RUNNING); + remove_wait_queue(&st->waitq, &wait); + + /* an error (or signal) occured */ + if (retval) + return retval; /* Skip the first 4 bytes of mpg streams to help out * finicky decoders.. but not for iTVC16 */ @@ -2028,6 +2038,11 @@ /* really DeQ now */ buf = ivtv_deq_buf(&st->full_q); ivtv_enq_buf(&st->free_q, buf); + + if (jiffies - buf->ts > oldest_ts) { + oldest_ts = jiffies - buf->ts; + printk("buffer %lu jifs\n", jiffies - buf->ts); + } buf = ivtv_deq_peek_head(&st->full_q); if (buf) { @@ -2088,7 +2103,7 @@ struct ivtv *itv = id->itv; struct ivtv_v4l2_stream *stream=&itv->v4l2.streams[id->type]; struct ivtv_buffer *buf; - int copybytes=0, bytesread=0; + int copybytes=0, bytesread=0, retval=0; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_fill_dec_buffers, %d bytes\n", count); @@ -2106,15 +2121,31 @@ * than one, just need loop control logic for it, if it's * deemed necessary. */ while (bytesread == 0) { - while ((buf = ivtv_deq_peek_head(&stream->free_q)) == NULL) { - IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: free_q empty, waiting\n"); + DECLARE_WAITQUEUE(wait, current); - /* we'll get woken up if need-be */ - interruptible_sleep_on(&stream->waitq); - if(signal_pending(current)) return -ERESTARTSYS; + buf = NULL; + add_wait_queue(&stream->waitq, &wait); + do { + set_current_state(TASK_INTERRUPTIBLE); + buf = ivtv_deq_peek_head(&stream->free_q); + if (buf) + break; - if (itv->dec_needs_data) ivtv_dec_sched_DMA(id->itv); - } + schedule(); + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + + if (test_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags)) + ivtv_dec_sched_DMA(id->itv); + } while (!buf); + set_current_state(TASK_RUNNING); + remove_wait_queue(&stream->waitq, &wait); + + if (retval) + return retval; /* bytes left to send > free bytes in current buffer */ if ((count - bytesread) > @@ -2193,14 +2224,14 @@ IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_DMA\n"); /* fancy way of saying "if (ivtv->dec_needs_data == 0)" */ - if (itv->dec_needs_data == 0) { + if (!test_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: no data needed\n"); return 0; } if (in_interrupt()) { IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_dma from interrupt\n"); - if (down_trylock(&itv->dec_sched_dma_sem)) { + if (down_trylock(&itv->sem_lock)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_dma: userspace call in flight," " returning\n"); @@ -2208,14 +2239,15 @@ } } else { IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_dma from userspace\n"); - down_interruptible(&itv->dec_sched_dma_sem); + if (down_interruptible(&itv->sem_lock)) + return -ERESTARTSYS; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_dma: got semaphore\n"); #if 0 /* this always seemed to be true for me */ if (signal_pending(current)) { IVTV_DEBUG(IVTV_DEBUG_INFO,"ivtv_dec_sched_dma: signal while" " down(); returning\n"); /* FIXME need to up()? */ - itv->dec_needs_data = 1; + set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); return -ERESTARTSYS; } @@ -2249,15 +2281,15 @@ stream = &itv->v4l2.streams[type]; - if (itv->dec_dma_pending) { + if (test_bit(IVTV_F_I_DMAP, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: decoder busy, delaying\n"); - itv->dec_needs_data = 1; + set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); ret = -EBUSY; goto ivtv_dec_sched_dma_return; } /* If we got this far, we have data to send and it wants it */ - itv->dec_needs_data = 0; + clear_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); /* Get card mem addr and size from data array */ mem_offset = data[1]; @@ -2328,7 +2360,7 @@ if (x == 0) { /* no full buffers */ IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: Nothing to send\n"); - itv->dec_needs_data = 1; + set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); ret = -ENOSPC; goto ivtv_dec_sched_dma_return; } @@ -2342,8 +2374,8 @@ data[2] = hw_stream_type; /* note that we're DMA'ing */ - stream->dma_pending = 1; - itv->dec_dma_pending = 1; + set_bit(IVTV_F_S_DMAP, &stream->s_flags); + set_bit(IVTV_F_I_DMAP, &itv->i_flags); ivtv_api_irqsafe(itv->dec_mbox, IVTV_API_DEC_DMA_FROM_HOST, 3, &data[0]); IVTV_DEBUG(IVTV_DEBUG_INFO, @@ -2356,7 +2388,7 @@ ivtv_dec_sched_dma_return: IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: sched_dma returning\n"); - up(&itv->dec_sched_dma_sem); + up(&itv->sem_lock); return ret; } @@ -2367,13 +2399,12 @@ IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: DMA Done tasklet\n"); - itv->dec_dma_pending = 0; - mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); + clear_bit(IVTV_F_I_DMAP, &itv->i_flags); + mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) { - if (itv->v4l2.streams[y].dma_pending) { + if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[y].s_flags)) { stmtype = y; - itv->v4l2.streams[y].dma_pending = 0; break; } } @@ -2419,8 +2450,6 @@ /* wake up queue filler */ wake_up(&stream->waitq); wake_up(&itv->dec_master_w); - - return; } int ivtv_get_timing_info(struct ivtv *itv, struct ivtv_ioctl_framesync *info) { @@ -2434,7 +2463,7 @@ * frames played. fortunately, it sets the SCR timestamp to 0 * in that case, which it never is otherwise. cool, huh */ while (info->scr == 0) { /* eliminate bogus values, FIXME ugly */ - ret = ivtv_api(itv->dec_mbox, &itv->dec_sem_w, + ret = ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_TIMING_INFO,&result,0,&data[0]); if (ret) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: err sending timing info\n"); @@ -2449,26 +2478,26 @@ IVTV_DEBUG(IVTV_DEBUG_ERR,"Timeout getting frames played\n"); return -1; } - if (info->scr == 0) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(.02*HZ); - } + if (info->scr == 0) + ivtv_sleep_timeout(HZ/50); } return 0; } ssize_t ivtv_write(struct ivtv_open_id *id, const char *ubuf, size_t count) { +#if 0 u32 result, data[IVTV_MBOX_MAX_DATA]; u32 dec_cnt; - int bytes_written=0, ret; struct ivtv *itv=id->itv; +#endif + int bytes_written=0, ret; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_write\n"); #if 0 /* Lots of extra debugging stuff */ /* Last DMA status? */ - if (ivtv_api(itv->dec_mbox, &itv->dec_sem_w, + if (ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_DMA_STATUS,&result,0,&data[0])) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: error sending status req\n"); } @@ -2478,7 +2507,7 @@ data[0], data[1]); /* buffer fullness stats */ - if (ivtv_api(itv->dec_mbox, &itv->dec_sem_w, + if (ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_XFER_INFO,&result,0,&data[0])) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: error sending DMA info\n"); } @@ -2489,7 +2518,7 @@ /* Timing info. */ - if (ivtv_api(itv->dec_mbox, &itv->dec_sem_w, + if (ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_DEC_TIMING_INFO,&result,0,&data[0])) { IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: err sending timing info\n"); } @@ -2532,18 +2561,19 @@ /* add stream's waitq to the poll list */ poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait); - if (down_interruptible(&id->itv->v4l2.v4l2_lock)) + if (down_interruptible(&id->itv->sem_lock)) return -ERESTARTSYS; if(ivtv_dec_stream_has_space(id)) { mask |= POLLOUT | POLLWRNORM; /* Writable */ } - if(id->itv->v4l2.streams[id->type].capturing == 0) { + if (!test_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags)) { /* not capturing, makes no sense to poll */ mask = POLLERR; } + up(&id->itv->sem_lock); return mask; } @@ -2554,20 +2584,19 @@ /* add stream's waitq to the poll list */ poll_wait(filp, &id->itv->v4l2.streams[id->type].waitq, wait); + if (down_interruptible(&id->itv->sem_lock)) + return -ERESTARTSYS; + if(ivtv_stream_has_data(id)) { mask |= POLLIN | POLLRDNORM; /* readable */ } - if (down_interruptible(&id->itv->v4l2.v4l2_lock)) - return -ERESTARTSYS; - - if(id->itv->v4l2.streams[id->type].capturing == 0) { + if (!test_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags)) { /* not capturing, makes no sense to poll */ mask = POLLERR; } - up(&id->itv->v4l2.v4l2_lock); - + up(&id->itv->sem_lock); return mask; } @@ -2576,8 +2605,7 @@ int x,y; IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 10ms\n"); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(.01*HZ); + ivtv_sleep_timeout(HZ/100); if (NULL == mbox) { IVTV_DEBUG(IVTV_DEBUG_IOCTL, "Mailboxes not initialized!\n"); @@ -2607,8 +2635,8 @@ //struct ivtv *itv = filep->private_data; hack = 0; - printk("Debug: 0x%08x, IRQ 0x%08x, combo: 0x%08x\n", debug, IVTV_DEBUG_IRQ, - (debug & IVTV_DEBUG_IRQ)); + printk("Debug: 0x%08x, IRQ 0x%08x, combo: 0x%08x\n", ivtv_debug, IVTV_DEBUG_IRQ, + (ivtv_debug & IVTV_DEBUG_IRQ)); return 0; } @@ -2627,6 +2655,9 @@ int ivtv_close(struct ivtv_open_id *id) { struct ivtv *itv=id->itv; + /* sem_lock must be held */ + IVTV_ASSERT(sem_getcount(&itv->sem_lock) >= 1); + if( (id->type != IVTV_DEC_STREAM_TYPE_MPG) && (id->type != IVTV_DEC_STREAM_TYPE_YUV)) { if (atomic_read(&itv->capturing)) { atomic_dec(&itv->capturing); @@ -2721,7 +2752,7 @@ return -1; } - if (debug < 0) IVTV_DEBUG(IVTV_DEBUG_ERR, "debug value must be >= 0!\n"); + if (ivtv_debug < 0) IVTV_DEBUG(IVTV_DEBUG_ERR, "debug value must be >= 0!\n"); IVTV_DEBUG(IVTV_DEBUG_INFO, "Loading, I'll try to detect %d devices!\n", num_devices); @@ -2735,10 +2766,11 @@ ivtv_cards[loop_a].dev = NULL; } - SGarray_size = (mpg_buffers + yuv_buffers + vbi_buffers) * 2; - DSGarray_size = (dec_mpg_buffers + dec_yuv_buffers) * 2; + SGarray_size = (mpg_buffers + yuv_buffers + vbi_buffers) * 2; + DSGarray_size = (dec_mpg_buffers + dec_yuv_buffers) * 2; - IVTV_DEBUG(IVTV_DEBUG_ERR, "SGarray_size = %d, DSGarray_size = %d\n", SGarray_size, DSGarray_size); + IVTV_DEBUG(IVTV_DEBUG_ERR, "SGarray_size = %d, DSGarray_size = %d\n", + SGarray_size, DSGarray_size); IVTV_DEBUG(IVTV_DEBUG_INFO, "Scanning PCI bus..\n"); if (pci_module_init(&ivtv_pci_driver)) { diff -ur ivtv.vanilla/driver/ivtv-fb.c ivtv/driver/ivtv-fb.c --- ivtv.vanilla/driver/ivtv-fb.c 2003-10-24 07:38:41.000000000 +0200 +++ ivtv/driver/ivtv-fb.c 2003-10-28 15:33:50.000000000 +0100 @@ -128,7 +128,6 @@ #include #include -#include #include #include #include @@ -149,18 +148,18 @@ * card parameters */ -int ivtv_fb_card_id = 0; +static int ivtv_fb_card_id; /* Card selected as framebuffer for this module instance: */ -struct ivtv *ivtv_fb = NULL; +static struct ivtv *ivtv_fb; /* card */ -unsigned long video_base; /* physical addr */ -unsigned long fb_start_aligned_physaddr; /* video_base rounded down as required by hardware MTRRs */ -unsigned long fb_end_aligned_physaddr; /* video_base rounded up as required by hardware MTRRs */ -unsigned long video_rel_base; /* address relative to base of decoder memory */ -int video_size; -char *video_vbase; /* mapped */ +static unsigned long video_base; /* physical addr */ +static unsigned long fb_start_aligned_physaddr; /* video_base rounded down as required by hardware MTRRs */ +static unsigned long fb_end_aligned_physaddr; /* video_base rounded up as required by hardware MTRRs */ +static unsigned long video_rel_base; /* address relative to base of decoder memory */ +static int video_size; +static char *video_vbase; /* mapped */ /* mode */ static int video_width; @@ -181,9 +180,9 @@ u32 data[IVTV_MBOX_MAX_DATA], result; int rc; - printk("ivtv-fb: ivtv_api_fb_get_framebuffer\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_get_framebuffer\n"); - rc = ivtv_api(itv->dec_mbox, &itv->dec_sem_r, + rc = ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_GET_FRAMEBUFFER, &result, 0, &data[0]); *fbbase = (void *) data[0]; *fblength = data[1]; @@ -193,9 +192,9 @@ static inline int ivtv_api_fb_get_pixel_format(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_get_pixel_format\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_get_pixel_format\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_r, IVTV_API_FB_GET_PIXEL_FORMAT, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_GET_PIXEL_FORMAT, &result, 0, &data[0]); return data[0]; } @@ -205,9 +204,9 @@ { u32 data[IVTV_MBOX_MAX_DATA], result; data[0] = format; - printk("ivtv-fb: ivtv_api_fb_set_pixel_format\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_set_pixel_format\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_SET_PIXEL_FORMAT, &result, 1, &data[0]); return result; } @@ -215,9 +214,9 @@ static inline int ivtv_api_fb_get_state(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_get_state\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_get_state\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_r, IVTV_API_FB_GET_STATE, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_GET_STATE, &result, 0, &data[0]); return data[0]; } @@ -226,9 +225,9 @@ { u32 params[IVTV_MBOX_MAX_DATA], result; params[0] = enabled; - printk("ivtv-fb: ivtv_api_fb_set_state\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_set_state\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, IVTV_API_FB_SET_STATE, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_SET_STATE, &result, 1, ¶ms[0]); return result; } @@ -238,13 +237,13 @@ int width, int height) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_set_framebuffer_window\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_set_framebuffer_window\n"); data[0] = width; data[1] = height; data[2] = left; data[3] = top; - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_SET_FRAMEBUFFER_WINDOW, &result, 4, &data[0]); return result; } @@ -253,9 +252,9 @@ struct ivtv_osd_coords *osd) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_get_osd_coords\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_get_osd_coords\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_r, IVTV_API_FB_GET_OSD_COORDS, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_GET_OSD_COORDS, &result, 0, &data[0]); osd->offset = data[0] - video_rel_base; @@ -273,7 +272,7 @@ *osd) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_set_osd_coords\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_set_osd_coords\n"); data[0] = osd->offset + video_rel_base; data[1] = osd->pixel_stride; data[2] = osd->lines; @@ -281,7 +280,7 @@ data[4] = osd->y; // FIXME maybe wait on vsync? - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, IVTV_API_FB_SET_OSD_COORDS, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_SET_OSD_COORDS, &result, 5, &data[0]); return result; } @@ -290,9 +289,9 @@ struct rectangle *r) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_get_screen_coords\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_get_screen_coords\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_r, IVTV_API_FB_GET_SCREEN_COORDS, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_GET_SCREEN_COORDS, &result, 0, &data[0]); r->x0 = data[0]; @@ -307,13 +306,13 @@ const struct rectangle *r) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_set_screen_coords\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_set_screen_coords\n"); data[0] = r->x0; data[1] = r->y0; data[2] = r->x1; data[3] = r->y1; - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_SET_SCREEN_COORDS, &result, 4, &data[0]); return result; } @@ -321,9 +320,9 @@ static inline int ivtv_api_fb_get_global_alpha(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_get_global_alpha\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_get_global_alpha\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_r, IVTV_API_FB_GET_GLOBAL_ALPHA, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_GET_GLOBAL_ALPHA, &result, 0, &data[0]); return data[1]; } @@ -333,11 +332,11 @@ int alpha, int enable_local) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_set_global_alpha\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_set_global_alpha\n"); data[0] = enable_global; data[1] = alpha; data[2] = !enable_local; - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_SET_GLOBAL_ALPHA, &result, 3, &data[0]); return result; } @@ -345,9 +344,9 @@ static inline int ivtv_api_fb_get_flicker_state(struct ivtv *itv) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_get_flicker_state\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_get_flicker_state\n"); - ivtv_api(itv->dec_mbox, &itv->dec_sem_r, IVTV_API_FB_GET_FLICKER_STATE, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_GET_FLICKER_STATE, &result, 0, &data[0]); return data[0]; } @@ -356,10 +355,10 @@ int enabled) { u32 params[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_set_flicker_state\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_set_flicker_state\n"); params[0] = enabled; - ivtv_api(itv->dec_mbox, &itv->dec_sem_adm, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_SET_FLICKER_STATE, &result, 1, ¶ms[0]); return result; } @@ -371,7 +370,7 @@ u32 value) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk("ivtv-fb: ivtv_api_fb_blt_fill\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_blt_fill\n"); data[0] = rasterop; data[1] = alpha_mode; data[2] = alpha_mask_mode; @@ -382,7 +381,7 @@ data[7] = deststride; data[8] = value; - ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_FB_BLT_FILL, &result, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_BLT_FILL, &result, 9, &data[0]); return result; } @@ -394,8 +393,7 @@ int sourcestride, int sourceaddr) { u32 data[IVTV_MBOX_MAX_DATA], result; - printk - ("ivtv_api_fb_blt_copy: width = %d, height = %d, destaddr = %d, deststride = %d, sourcestride = %d, sourceaddr = %d\n", + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_api_fb_blt_copy: width = %d, height = %d, destaddr = %d, deststride = %d, sourcestride = %d, sourceaddr = %d\n", width, height, destaddr, deststride, sourcestride, sourceaddr); data[0] = rasterop; @@ -409,7 +407,7 @@ data[8] = sourcestride; data[9] = sourceaddr; - ivtv_api(itv->dec_mbox, &itv->dec_sem_w, IVTV_API_FB_BLT_COPY, &result, + ivtv_api(itv->dec_mbox, &itv->sem_lock, IVTV_API_FB_BLT_COPY, &result, 10, &data[0]); return result; } @@ -457,14 +455,14 @@ static int ivtvfb_update_var(int con, struct fb_info *info) { - printk("ivtv-fb: ivtvfb_update_var\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_update_var\n"); return 0; } static int ivtvfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) { - printk("ivtv-fb: ivtvfb_get_fix\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_get_fix\n"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, "iTVC15 TV out"); @@ -482,7 +480,7 @@ static int ivtvfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - printk("ivtv-fb: ivtvfb_get_var\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_get_var\n"); if (con == -1) memcpy(var, &ivtvfb_defined, sizeof(struct fb_var_screeninfo)); else @@ -496,7 +494,7 @@ struct display *display; struct display_switch *sw; - printk("ivtv-fb: ivtvfb_set_disp\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_set_disp\n"); if (con >= 0) display = &fb_display[con]; else @@ -529,7 +527,7 @@ struct fb_info *info) { int first=0; - printk("ivtv-fb: ivtvfb_set_var\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_set_var\n"); if (con >= 0) first = 1; if (var->xres != ivtvfb_defined.xres || @@ -562,14 +560,14 @@ static int ivtvfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - printk("ivtv-fb: ivtvfb_get_cmap\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_get_cmap\n"); return 0; } static int ivtvfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - printk("ivtv-fb: ivtvfb_set_cmap\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_set_cmap\n"); return 0; } @@ -580,7 +578,7 @@ int rc; unsigned long destaddr = ((y * video_width) + x) * 4; - printk("ivtv-fb: ivtv_fb_blt_copy\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_fb_blt_copy\n"); source_offset += shadow_framebuf_offset; rc = ivtv_api_fb_blt_copy(ivtv_fb, 0xa, 0x1, 0x0, width, height, @@ -621,7 +619,7 @@ int ivtvfb_alloc_user_dma_to_device(struct ivtvfb_user_dma_to_device *dma) { - printk("ivtv-fb: ivtvfb_alloc_user_dma_to_device\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_alloc_user_dma_to_device\n"); dma->page_count = 0; dma->sglist = (struct ivtv_SG_element *) kmalloc(sizeof(struct ivtv_SG_element) * @@ -650,8 +648,8 @@ { int i; int size_in_pages = (size_in_bytes + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - - printk("ivtv-fb: ivtvfb_prep_user_dma_to_device, dst: 0x%08x\n", + + IVTV_DEBUG_FB(IVTV_DEBUG_DMA, "ivtvfb_prep_user_dma_to_device, dst: 0x%08x\n", (unsigned int) ivtv_dest_addr); dma->page_count = size_in_pages; @@ -689,7 +687,7 @@ int ivtvfb_free_user_dma_to_device(struct ivtvfb_user_dma_to_device *dma) { int i; - printk("ivtv-fb: ivtvfb_free_user_dma_to_device\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_free_user_dma_to_device\n"); /* for (i = 0; i < dma->page_count; i++) { //++MTY NOTE: on ia32, pci_unmap_page() is a nop anyway... @@ -709,13 +707,13 @@ u32 data[IVTV_MBOX_MAX_DATA], result; u64 tstart; int rc; - printk("ivtv-fb: ivtvfb_execute_user_dma_to_device\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtvfb_execute_user_dma_to_device\n"); data[0] = dma->sg_dma_handle; data[1] = dma->page_count; data[2] = 0x1; // 0x1 = OSD data - printk("ivtvfb: Schedule FB DMA: physical address 0x%08x, " + IVTV_DEBUG_FB(IVTV_DEBUG_DMA, "Schedule FB DMA: physical address 0x%08x, " "arraysize 0x%08x, type 0x%08x\n", data[0], data[1], data[2]); flush_write_buffers(); @@ -726,20 +724,22 @@ rdtscll(tstart); - rc = ivtv_api(ivtv_fb->dec_mbox, &ivtv_fb->dec_sem_w, + rc = ivtv_api(ivtv_fb->dec_mbox, &ivtv_fb->sem_lock, IVTV_API_DEC_DMA_FROM_HOST, &result, 3, &data[0]); if (rc) { - printk("ivtvfb: error sending DMA info\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_ERR, "error sending DMA info\n"); } else { - ivtv_fb->dec_dma_pending = 1; + set_bit(IVTV_F_I_DMAP, &ivtv_fb->i_flags); } + /* what is the point of this?! -axboe */ +#if 0 up(&ivtv_fb->dec_sched_dma_sem); +#endif - printk("ivtv: started DMA request at timestamp %lld!\n", tstart); - printk("ivtvfb: OK, scheduled FB DMA!"); - + IVTV_DEBUG_FB(IVTV_DEBUG_DMA, "started DMA request at timestamp %lld!\n", tstart); + IVTV_DEBUG_FB(IVTV_DEBUG_DMA, "OK, scheduled FB DMA!"); return 0; } @@ -747,14 +747,15 @@ unsigned long destaddr, void *srcaddr, int count) { - printk("ivtv-fb: ivtv_fb_prep_frame\n"); + DECLARE_WAITQUEUE(wait, current); + int rc; + //if (!srcaddr || verify_area(...)) ... if ((destaddr + count) > video_size) return -E2BIG; destaddr = IVTV_DEC_MEM_START + video_rel_base + destaddr; - int rc; #ifdef IVTVFB_DEBUG_PER_FRAME printk("ivtv_fb_prep_frame: attempting to acquire semaphore..."); #endif @@ -767,28 +768,35 @@ ("ivtv_fb_prep_frame: acquired semaphore; scheduling the DMA..."); #endif - if(down_interruptible(&ivtv_fb->dec_sched_dma_sem)) { - return -ERESTARTSYS; - } + rc = 0; + add_wait_queue(&ivtv_fb->dec_master_w, &wait); + do { + set_current_state(TASK_INTERRUPTIBLE); + /* FIXME mini-race still .. need to port to 'stream' format */ + if (!test_bit(IVTV_F_I_DMAP, &ivtv_fb->i_flags)) + break; + + schedule(); + + if (signal_pending(current)) + rc = -ERESTARTSYS; + + } while (!rc); + set_current_state(TASK_RUNNING); + remove_wait_queue(&ivtv_fb->dec_master_w, &wait); + + if (rc) + return rc; - if (ivtv_fb->dec_dma_pending) { - /* FIXME mini-race still .. need to port to 'stream' format */ - interruptible_sleep_on(&ivtv_fb->dec_master_w); - if (ivtv_fb->dec_dma_pending) { - up(&ivtv_fb->dec_sched_dma_sem); - return -ERESTARTSYS; - } - } - if (0 != (rc = ivtvfb_prep_user_dma_to_device(&ivtvfb_current_fb_dma, destaddr, - (char *) srcaddr, count))) + (char *) srcaddr, count))) { - printk("ivtv_fb_prep_frame: err prep user dma to device\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_DMA, "err prep user dma to device=%x\n",rc); return rc; } if (0 != (rc = ivtvfb_execute_user_dma_to_device(&ivtvfb_current_fb_dma))) { - printk("ivtv_fb_prep_frame: err exec user dma to device\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_DMA, "err exec user dma to device=%x\n",rc); return rc; } @@ -801,7 +809,7 @@ int rc; - printk("ivtv-fb: ivtv_fb_ioctl\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "ivtv_fb_ioctl\n"); switch (cmd) { case 0x7777:{ while (MOD_IN_USE) MOD_DEC_USE_COUNT; @@ -813,8 +821,7 @@ state.status = (ivtv_api_fb_get_state(ivtv_fb) & 0x7); state.status |= (ivtv_api_fb_get_flicker_state(ivtv_fb) << 3); state.alpha = ivtv_api_fb_get_global_alpha(ivtv_fb); - printk - ("ivtv-fb: IVTVFB_IOCTL_GET_STATE: status = %lu, alpha = %lu\n", + IVTV_DEBUG_FB(IVTV_DEBUG_IOCTL, "IVTVFB_IOCTL_GET_STATE: status = %lu, alpha = %lu\n", state.status, state.alpha); if (copy_to_user((void *) arg, &state, sizeof(state))) return -EFAULT; @@ -824,8 +831,7 @@ struct ivtvfb_ioctl_state_info state; if (copy_from_user(&state, (void *) arg, sizeof(state))) return -EFAULT; - printk - ("ivtv-fb: IVTVFB_IOCTL_SET_STATE: status = %lu, alpha = %lu\n", + IVTV_DEBUG_FB(IVTV_DEBUG_IOCTL, "IVTVFB_IOCTL_SET_STATE: status = %lu, alpha = %lu\n", state.status, state.alpha); ivtv_api_fb_set_state(ivtv_fb, (state.status && IVTVFB_STATUS_ENABLED)); @@ -843,9 +849,9 @@ status & IVTVFB_STATUS_FLICKER_REDUCTION) ? 1 : 0); - printk("ivtv-fb: new state = %d\n", + IVTV_DEBUG_FB(IVTV_DEBUG_IOCTL, "new state = %d\n", ivtv_api_fb_get_state(ivtv_fb)); - printk("ivtv-fb: global alpha now = %d\n", + IVTV_DEBUG_FB(IVTV_DEBUG_IOCTL, "global alpha now = %d\n", ivtv_api_fb_get_global_alpha(ivtv_fb)); return 0; } @@ -938,23 +944,37 @@ rc = ivtv_api_fb_set_pixel_format(ivtv_fb, 4); // 4 = AlphaRGB 8:8:8:8 - printk(KERN_INFO "ivtv-fb: Current pixel format = %d\n", + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "Current pixel format = %d\n", ivtv_api_fb_get_pixel_format(ivtv_fb)); rc = ivtv_api_fb_get_framebuffer(ivtv_fb, (void **) &fbbase, &fblength); - printk(KERN_INFO - "ivtv-fb: Framebuffer is at decoder-relative address 0x%08x and has %d bytes.\n", + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "Framebuffer is at decoder-relative address 0x%08x and has %d bytes.\n", fbbase, fblength); rc = ivtv_api_fb_get_osd_coords(ivtv_fb, &osd); - printk(KERN_INFO - "ivtv-fb: OSD: offset = 0x%08x (max offset = 0x%08x), pixel_stride = %d, lines = %d, x = %d, y = %d\n", + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "OSD: offset = 0x%08x (max offset = 0x%08x), pixel_stride = %d, lines = %d, x = %d, y = %d\n", (u32)osd.offset, (u32)osd.max_offset, osd.pixel_stride, osd.lines, osd.x, osd.y); - rc = ivtv_api_fb_get_screen_coords(ivtv_fb, &rect); - printk(KERN_INFO "ivtv-fb: screen coords: [%d %d] -> [%d %d]\n", + /* setup OSD and screen for PAL */ + if (ivtv_pal) { + osd.lines = 576; + rc = ivtv_api_fb_set_osd_coords(ivtv_fb, &osd); + if (rc) + IVTV_DEBUG_FB(IVTV_DEBUG_ERR, "failed setting PAL osd\n"); + + rect.x0 = 0; + rect.x1 = 720; + rect.y0 = 0; + rect.y1 = 576; + rc = ivtv_api_fb_set_screen_coords(ivtv_fb, &rect); + if (rc) + IVTV_DEBUG_FB(IVTV_DEBUG_ERR, "failed setting PAL screen\n"); + } + + rc = ivtv_api_fb_get_screen_coords(ivtv_fb, &rect); + printk(KERN_INFO "ivtv-fb: screen coords: [%d %d] -> [%d %d]\n", rect.x0, rect.y0, rect.x1, rect.y1); printk(KERN_INFO "ivtv-fb: original global alpha = %d\n", @@ -1092,7 +1112,7 @@ static void ivtvfb_cleanup(void) { - printk("ivtv-fb: Unloading framebuffer module\n"); + IVTV_DEBUG_FB(IVTV_DEBUG_INFO, "Unloading framebuffer module\n"); unregister_framebuffer(&fb_info); iounmap(video_vbase); mtrr_del(-1, fb_start_aligned_physaddr, diff -ur ivtv.vanilla/driver/ivtv-i2c.c ivtv/driver/ivtv-i2c.c --- ivtv.vanilla/driver/ivtv-i2c.c 2003-10-03 09:08:05.000000000 +0200 +++ ivtv/driver/ivtv-i2c.c 2003-10-28 15:33:50.000000000 +0100 @@ -222,3 +222,10 @@ itv->i2c_rc = i2c_bit_add_bus(&itv->i2c_adap); return itv->i2c_rc; } + +void __devexit exit_ivtv_i2c(struct ivtv *itv) { + IVTV_DEBUG(IVTV_DEBUG_I2C, "i2c exit\n"); + + i2c_bit_del_bus(&itv->i2c_adap); +} + diff -ur ivtv.vanilla/driver/ivtv.h ivtv/driver/ivtv.h --- ivtv.vanilla/driver/ivtv.h 2003-10-24 08:16:04.000000000 +0200 +++ ivtv/driver/ivtv.h 2003-10-28 15:33:50.000000000 +0100 @@ -1,3 +1,6 @@ +#ifndef IVTV_H +#define IVTV_H + /* Header for ivtv project: * Driver for the iTVC15 chip. * Author: Kevin Thayer (nufan_wfk at yahoo.com) @@ -106,9 +109,9 @@ #define IVTV_DMA_MAX_XFER 0x00080000 /* 0x8000 = 32kbytes, 0x20000 = 128kbytes */ #define IVTV_DEC_MIN_BUF 0x00050000 /* want this many bytes+ in decoder buffer */ -#define IVTV_SLEEP_WAIT (.1 * HZ) /*100 ms*/ +#define IVTV_SLEEP_WAIT (HZ/10) /*100 ms*/ #define IVTV_MAX_DATA_SLEEP 30 -#define DEC_DMA_TIMEOUT (.1 * HZ) +#define DEC_DMA_TIMEOUT (HZ/10) #define IVTV_DMA_ERR_LIST 0x00000008 #define IVTV_DMA_ERR_WRITE 0x00000004 @@ -177,7 +180,7 @@ #define IVTV_CMD_SPU_STOP 0x00000001 #define IVTV_CMD_SDRAM_PRECHARGE_INIT 0x0000001A #define IVTV_CMD_SDRAM_REFRESH_INIT 0x80000640 -#define IVTV_SDRAM_SLEEPTIME .6 /*value in seconds*/ +#define IVTV_SDRAM_SLEEPTIME (60 * HZ / 100) /* 600ms */ /*Used for locating the firmware mailboxes*/ #define IVTV_FIRM_ENC_FILENAME "/lib/modules/ivtv-fw-enc.bin" @@ -287,7 +290,8 @@ #define IVTV_DEBUG_IOCTL (1 << 4) #define IVTV_DEBUG_I2C (1 << 5) #define IVTV_DEBUG_IRQ (1 << 6) -#define IVTV_DEBUG(x,args...) if(x&debug) printk("ivtv: " args); +#define IVTV_DEBUG(x,args...) if((x)&ivtv_debug) printk("ivtv: " args); +#define IVTV_DEBUG_FB(x,args...) if((x)&ivtv_debug) printk("ivtv-fb: " args); /* Temp saa7115 hack FIXME */ #define DECODER_SET_SIZE 76598 @@ -489,8 +493,9 @@ u32 stream_type; }; -int debug; - +extern int ivtv_debug; +extern int ivtv_pal; + /* Scatter-Gather array element, used in DMA transfers */ struct ivtv_SG_element { u32 src; @@ -521,6 +526,7 @@ dma_addr_t dma_handle; struct v4l2_buffer buffer; struct list_head list; + unsigned long ts; }; struct ivtv_buffer_list { @@ -557,14 +563,21 @@ int fr_field; /* 1 = show every field, 0 = show every frame */ }; +/* encoder */ +#define IVTV_F_S_DMAP 0 +#define IVTV_F_S_OVERFLOW 1 +#define IVTV_F_S_CAP 2 + +/* decoder */ +#define IVTV_F_I_DMAP 3 +#define IVTV_F_I_NEEDS_DATA 4 + struct ivtv_v4l2_stream { - int capturing; int buf_size; /* size of buffers this stream */ long id; long seq; int ubytes; /* bytes written back to user this frame */ - int dma_pending; - int overflow; + unsigned long s_flags; int v4l_reg_type; wait_queue_head_t waitq; struct video_device v4l2dev; @@ -595,7 +608,6 @@ struct ivtv_v4l2 { u32 capabilities; - struct semaphore v4l2_lock; struct ivtv_v4l2_table input; int audio_output; struct ivtv_v4l2_table output; @@ -637,15 +649,13 @@ struct ivtv_dec_options dec_options; int num; /* invalidate during init! */ int first_read; /* used to clean up stream */ - int first_write; /* don't schedule decodes until buffers full */ + unsigned long i_flags; atomic_t capturing; atomic_t decoding; - struct semaphore enc_sem_r, enc_sem_w, enc_sem_adm; - struct semaphore dec_sem_r, dec_sem_w, dec_sem_adm; - struct semaphore dec_sched_dma_sem; + struct semaphore sem_lock; int readslot,writeslot,overflow; - int graceful_eos, dma_pending; + int graceful_eos; long open_id; /* incremented each time an open occurs used as unique ID */ int sg_count; @@ -662,17 +672,13 @@ struct ivtv_mailbox *enc_mbox, *dec_mbox; unsigned char card_rev, *io_mem, *reg_mem; - /* FIXME read_w is going away soon */ - wait_queue_head_t read_w, cap_w, vsync_w; + wait_queue_head_t cap_w, vsync_w; /*FIXME perhaps move these to the v4l2_stream struct */ struct ivtv_SG_element *SGarray, *DSGarray; dma_addr_t SG_handle, DSG_handle; /* Decoder */ - int dec_dma_pending; - int dec_needs_data; - int dec_dma_reset; struct ivtv_ioctl_framesync dec_timestamp; wait_queue_head_t dec_master_w; struct timer_list dec_timeout; @@ -702,6 +708,7 @@ extern int yuv_buffers; extern int mpg_buffers; extern int vbi_buffers; +extern spinlock_t ivtv_lock; /*==============Prototypes==================*/ /* FIXME some of these proably need fine-tuning @@ -730,6 +737,7 @@ /* init + register i2c algo-bit adapter */ int __devinit init_ivtv_i2c(struct ivtv *itv); +void __devexit exit_ivtv_i2c(struct ivtv *itv); /* end i2c stuff */ @@ -754,6 +762,8 @@ u32 *result, u32 data[]); int ivtv_api(struct ivtv_mailbox *mbox, struct semaphore *sem, int cmd, u32 *result, int args, u32 data[]); +extern int __ivtv_api(struct ivtv_mailbox *mbox, int cmd, + u32 *result, int args, u32 data[]); int ivtv_v4l2_setup(struct ivtv *itv); /* Capture related */ @@ -762,7 +772,6 @@ long ivtv_read(struct ivtv_open_id *id, char *ubuf, size_t count); int ivtv_get_timing_info(struct ivtv *itv, struct ivtv_ioctl_framesync *info); ssize_t ivtv_write(struct ivtv_open_id *id, const char *buf, size_t count); -void ivtv_start_decode(struct ivtv *itv); int ivtv_stream_has_data(struct ivtv_open_id *id); unsigned int ivtv_poll(struct file *filp, poll_table *wait); unsigned int ivtv_dec_poll(struct file *filp, poll_table *wait); @@ -795,3 +804,17 @@ void ivtv_print_boxes(struct ivtv_mailbox *mbox); int tmk_test2(struct inode *inode, struct file *filep); int tmk_test1(struct inode *inode, struct file *filep); + +/* debug stuff, to get the locking right */ +#ifndef WARN_ON +#define WARN_ON(condition) do { \ + if (unlikely((condition)!=0)) { \ + printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \ + dump_stack(); \ + } \ +} while (0) +#endif + +#define IVTV_ASSERT(x) WARN_ON((x)) + +#endif diff -ur ivtv.vanilla/driver/msp3400.c ivtv/driver/msp3400.c --- ivtv.vanilla/driver/msp3400.c 2003-08-14 09:13:42.000000000 +0200 +++ ivtv/driver/msp3400.c 2003-10-28 15:33:50.000000000 +0100 @@ -41,24 +41,24 @@ #include #include #include -#include #include #include #include -#include #include +#include -#ifdef CONFIG_SMP #include -#include -#endif -/* kernel_thread */ -#define __KERNEL_SYSCALLS__ -#include +#include #include "audiochip.h" #include "msp3400.h" +#ifdef INIT_SIGHAND +#define SIGMASK_LOCK(current) (&(current)->sighand->siglock) +#else +#define SIGMASK_LOCK(current) (&(current)->sigmask_lock) +#endif + /* Addresses to scan */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; static unsigned short normal_i2c_range[] = {0x40,0x40,I2C_CLIENT_END}; @@ -758,20 +758,17 @@ struct CARRIER_DETECT *cd; int count, max1,max2,val1,val2, val,this; -#ifdef CONFIG_SMP - lock_kernel(); -#endif - daemonize(); + exit_files(current); + reparent_to_init(); + + spin_lock_irq(SIGMASK_LOCK(current)); sigfillset(¤t->blocked); + spin_unlock_irq(SIGMASK_LOCK(current)); strcpy(current->comm,"msp3400"); msp->thread = current; -#ifdef CONFIG_SMP - unlock_kernel(); -#endif - printk("msp3400: daemon started\n"); if(msp->notify != NULL) up(msp->notify); @@ -1013,21 +1010,19 @@ struct i2c_client *client = data; struct msp3400c *msp = client->data; int mode,val,i,std; - -#ifdef CONFIG_SMP - lock_kernel(); -#endif - + daemonize(); + exit_files(current); + reparent_to_init(); + + spin_lock_irq(¤t->sigmask_lock); sigfillset(¤t->blocked); + spin_unlock_irq(¤t->sigmask_lock); + strcpy(current->comm,"msp3410 [auto]"); msp->thread = current; -#ifdef CONFIG_SMP - unlock_kernel(); -#endif - printk("msp3410: daemon started\n"); if(msp->notify != NULL) up(msp->notify); diff -ur ivtv.vanilla/driver/saa7127.c ivtv/driver/saa7127.c --- ivtv.vanilla/driver/saa7127.c 2003-10-03 09:07:09.000000000 +0200 +++ ivtv/driver/saa7127.c 2003-10-28 15:33:50.000000000 +0100 @@ -52,7 +52,6 @@ #include #include -#include #include #include #include