V4L/DVB (10135): v4l2: introduce v4l2_file_operations.
[safe/jmp/linux-2.6] / drivers / media / video / ivtv / ivtv-streams.c
index e05af62..854a950 100644 (file)
 #include "ivtv-cards.h"
 #include "ivtv-streams.h"
 
-static struct file_operations ivtv_v4l2_enc_fops = {
-      .owner = THIS_MODULE,
-      .read = ivtv_v4l2_read,
-      .write = ivtv_v4l2_write,
-      .open = ivtv_v4l2_open,
-      .ioctl = ivtv_v4l2_ioctl,
-      .release = ivtv_v4l2_close,
-      .poll = ivtv_v4l2_enc_poll,
+static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
+       .owner = THIS_MODULE,
+       .read = ivtv_v4l2_read,
+       .write = ivtv_v4l2_write,
+       .open = ivtv_v4l2_open,
+       .unlocked_ioctl = ivtv_v4l2_ioctl,
+       .release = ivtv_v4l2_close,
+       .poll = ivtv_v4l2_enc_poll,
 };
 
-static struct file_operations ivtv_v4l2_dec_fops = {
-      .owner = THIS_MODULE,
-      .read = ivtv_v4l2_read,
-      .write = ivtv_v4l2_write,
-      .open = ivtv_v4l2_open,
-      .ioctl = ivtv_v4l2_ioctl,
-      .release = ivtv_v4l2_close,
-      .poll = ivtv_v4l2_dec_poll,
+static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
+       .owner = THIS_MODULE,
+       .read = ivtv_v4l2_read,
+       .write = ivtv_v4l2_write,
+       .open = ivtv_v4l2_open,
+       .unlocked_ioctl = ivtv_v4l2_ioctl,
+       .release = ivtv_v4l2_close,
+       .poll = ivtv_v4l2_dec_poll,
 };
 
 #define IVTV_V4L2_DEC_MPG_OFFSET  16   /* offset from 0 to register decoder mpg v4l2 minors on */
@@ -73,10 +73,10 @@ static struct file_operations ivtv_v4l2_dec_fops = {
 static struct {
        const char *name;
        int vfl_type;
-       int minor_offset;
+       int num_offset;
        int dma, pio;
        enum v4l2_buf_type buf_type;
-       struct file_operations *fops;
+       const struct v4l2_file_operations *fops;
 } ivtv_stream_info[] = {
        {       /* IVTV_ENC_STREAM_TYPE_MPG */
                "encoder MPG",
@@ -166,12 +166,11 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
        ivtv_queue_init(&s->q_io);
 }
 
-static int ivtv_reg_dev(struct ivtv *itv, int type)
+static int ivtv_prep_dev(struct ivtv *itv, int type)
 {
        struct ivtv_stream *s = &itv->streams[type];
-       int vfl_type = ivtv_stream_info[type].vfl_type;
-       int minor_offset = ivtv_stream_info[type].minor_offset;
-       int minor;
+       int num_offset = ivtv_stream_info[type].num_offset;
+       int num = itv->instance + ivtv_first_minor + num_offset;
 
        /* These four fields are always initialized. If v4l2dev == NULL, then
           this stream is not in use. In that case no other fields but these
@@ -187,15 +186,9 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
        if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
                return 0;
 
-       if (minor_offset >= 0)
-               /* card number + user defined offset + device offset */
-               minor = itv->num + ivtv_first_minor + minor_offset;
-       else
-               minor = -1;
-
        /* User explicitly selected 0 buffers for these streams, so don't
           create them. */
-       if (minor >= 0 && ivtv_stream_info[type].dma != PCI_DMA_NONE &&
+       if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
            itv->options.kilobytes[type] == 0) {
                IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name);
                return 0;
@@ -210,87 +203,114 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
                return -ENOMEM;
        }
 
-       s->v4l2dev->type = VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
-                   VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               s->v4l2dev->type |= VID_TYPE_MPEG_DECODER;
-       }
-       snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s",
-                       itv->num, s->name);
+       snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "%s %s",
+                       itv->device.name, s->name);
 
-       s->v4l2dev->minor = minor;
-       s->v4l2dev->dev = &itv->dev->dev;
+       s->v4l2dev->num = num;
+       s->v4l2dev->v4l2_dev = &itv->device;
        s->v4l2dev->fops = ivtv_stream_info[type].fops;
        s->v4l2dev->release = video_device_release;
+       s->v4l2dev->tvnorms = V4L2_STD_ALL;
+       ivtv_set_funcs(s->v4l2dev);
+       return 0;
+}
 
-       if (minor >= 0) {
-               /* Register device. First try the desired minor, then any free one. */
-               if (video_register_device(s->v4l2dev, vfl_type, minor) &&
-                   video_register_device(s->v4l2dev, vfl_type, -1)) {
-                       IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n",
-                                       s->name, minor);
-                       video_device_release(s->v4l2dev);
-                       s->v4l2dev = NULL;
-                       return -ENOMEM;
-               }
+/* Initialize v4l2 variables and prepare v4l2 devices */
+int ivtv_streams_setup(struct ivtv *itv)
+{
+       int type;
+
+       /* Setup V4L2 Devices */
+       for (type = 0; type < IVTV_MAX_STREAMS; type++) {
+               /* Prepare device */
+               if (ivtv_prep_dev(itv, type))
+                       break;
+
+               if (itv->streams[type].v4l2dev == NULL)
+                       continue;
+
+               /* Allocate Stream */
+               if (ivtv_stream_alloc(&itv->streams[type]))
+                       break;
        }
-       else {
-               /* Don't register a 'hidden' stream (OSD) */
-               IVTV_INFO("Created framebuffer stream for %s\n", s->name);
+       if (type == IVTV_MAX_STREAMS)
                return 0;
+
+       /* One or more streams could not be initialized. Clean 'em all up. */
+       ivtv_streams_cleanup(itv, 0);
+       return -ENOMEM;
+}
+
+static int ivtv_reg_dev(struct ivtv *itv, int type)
+{
+       struct ivtv_stream *s = &itv->streams[type];
+       int vfl_type = ivtv_stream_info[type].vfl_type;
+       int num;
+
+       if (s->v4l2dev == NULL)
+               return 0;
+
+       num = s->v4l2dev->num;
+       /* card number + user defined offset + device offset */
+       if (type != IVTV_ENC_STREAM_TYPE_MPG) {
+               struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
+
+               if (s_mpg->v4l2dev)
+                       num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset;
        }
+       video_set_drvdata(s->v4l2dev, s);
+
+       /* Register device. First try the desired minor, then any free one. */
+       if (video_register_device(s->v4l2dev, vfl_type, num)) {
+               IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
+                               s->name, num);
+               video_device_release(s->v4l2dev);
+               s->v4l2dev = NULL;
+               return -ENOMEM;
+       }
+       num = s->v4l2dev->num;
 
        switch (vfl_type) {
        case VFL_TYPE_GRABBER:
                IVTV_INFO("Registered device video%d for %s (%d kB)\n",
-                       s->v4l2dev->minor, s->name, itv->options.kilobytes[type]);
+                       num, s->name, itv->options.kilobytes[type]);
                break;
        case VFL_TYPE_RADIO:
                IVTV_INFO("Registered device radio%d for %s\n",
-                       s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
+                       num, s->name);
                break;
        case VFL_TYPE_VBI:
                if (itv->options.kilobytes[type])
                        IVTV_INFO("Registered device vbi%d for %s (%d kB)\n",
-                               s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN,
-                               s->name, itv->options.kilobytes[type]);
+                               num, s->name, itv->options.kilobytes[type]);
                else
                        IVTV_INFO("Registered device vbi%d for %s\n",
-                               s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
+                               num, s->name);
                break;
        }
        return 0;
 }
 
-/* Initialize v4l2 variables and register v4l2 devices */
-int ivtv_streams_setup(struct ivtv *itv)
+/* Register v4l2 devices */
+int ivtv_streams_register(struct ivtv *itv)
 {
        int type;
+       int err = 0;
 
-       /* Setup V4L2 Devices */
-       for (type = 0; type < IVTV_MAX_STREAMS; type++) {
-               /* Register Device */
-               if (ivtv_reg_dev(itv, type))
-                       break;
-
-               if (itv->streams[type].v4l2dev == NULL)
-                       continue;
+       /* Register V4L2 devices */
+       for (type = 0; type < IVTV_MAX_STREAMS; type++)
+               err |= ivtv_reg_dev(itv, type);
 
-               /* Allocate Stream */
-               if (ivtv_stream_alloc(&itv->streams[type]))
-                       break;
-       }
-       if (type == IVTV_MAX_STREAMS) {
+       if (err == 0)
                return 0;
-       }
 
        /* One or more streams could not be initialized. Clean 'em all up. */
-       ivtv_streams_cleanup(itv);
+       ivtv_streams_cleanup(itv, 1);
        return -ENOMEM;
 }
 
 /* Unregister v4l2 devices */
-void ivtv_streams_cleanup(struct ivtv *itv)
+void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
 {
        int type;
 
@@ -303,17 +323,17 @@ void ivtv_streams_cleanup(struct ivtv *itv)
                        continue;
 
                ivtv_stream_free(&itv->streams[type]);
-               /* Free Device */
-               if (vdev->minor == -1) /* 'Hidden' never registered stream (OSD) */
-                       video_device_release(vdev);
-               else    /* All others, just unregister. */
+               /* Unregister or release device */
+               if (unregister)
                        video_unregister_device(vdev);
+               else
+                       video_device_release(vdev);
        }
 }
 
 static void ivtv_vbi_setup(struct ivtv *itv)
 {
-       int raw = itv->vbi.sliced_in->service_set == 0;
+       int raw = ivtv_raw_vbi(itv);
        u32 data[CX2341X_MBOX_MAX_DATA];
        int lines;
        int i;
@@ -321,18 +341,8 @@ static void ivtv_vbi_setup(struct ivtv *itv)
        /* Reset VBI */
        ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
 
-       if (itv->is_60hz) {
-               itv->vbi.count = 12;
-               itv->vbi.start[0] = 10;
-               itv->vbi.start[1] = 273;
-       } else {        /* PAL/SECAM */
-               itv->vbi.count = 18;
-               itv->vbi.start[0] = 6;
-               itv->vbi.start[1] = 318;
-       }
-
        /* setup VBI registers */
-       itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
+       v4l2_subdev_call(itv->sd_video, video, s_fmt, &itv->vbi.in);
 
        /* determine number of lines and total number of VBI bytes.
           A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
@@ -356,7 +366,7 @@ static void ivtv_vbi_setup(struct ivtv *itv)
        /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */
        data[1] = 1;
        /* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */
-       data[2] = raw ? 4 : 8;
+       data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size);
        /* The start/stop codes determine which VBI lines end up in the raw VBI data area.
           The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line
           is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video)
@@ -435,6 +445,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
 {
        u32 data[CX2341X_MBOX_MAX_DATA];
        struct ivtv *itv = s->itv;
+       struct cx2341x_mpeg_params *p = &itv->params;
        int captype = 0, subtype = 0;
        int enable_passthrough = 0;
 
@@ -455,7 +466,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
                }
                itv->mpg_data_received = itv->vbi_data_inserted = 0;
                itv->dualwatch_jiffies = jiffies;
-               itv->dualwatch_stereo_mode = itv->params.audio_properties & 0x0300;
+               itv->dualwatch_stereo_mode = p->audio_properties & 0x0300;
                itv->search_pack_header = 0;
                break;
 
@@ -487,9 +498,6 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
        s->subtype = subtype;
        s->buffers_stolen = 0;
 
-       /* mute/unmute video */
-       ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? 1 : 0);
-
        /* Clear Streamoff flags in case left from last capture */
        clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
 
@@ -546,7 +554,12 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
                                itv->pgm_info_offset, itv->pgm_info_num);
 
                /* Setup API for Stream */
-               cx2341x_update(itv, ivtv_api_func, NULL, &itv->params);
+               cx2341x_update(itv, ivtv_api_func, NULL, p);
+
+               /* mute if capturing radio */
+               if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
+                       ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
+                               1 | (p->video_mute_yuv << 8));
        }
 
        /* Vsync Setup */
@@ -563,10 +576,10 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
                clear_bit(IVTV_F_I_EOS, &itv->i_flags);
 
                /* Initialize Digitizer for Capture */
-               itv->video_dec_func(itv, VIDIOC_STREAMOFF, 0);
+               v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
                ivtv_msleep_timeout(300, 1);
                ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-               itv->video_dec_func(itv, VIDIOC_STREAMON, 0);
+               v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
        }
 
        /* begin_capture */
@@ -595,6 +608,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
 {
        u32 data[CX2341X_MBOX_MAX_DATA];
        struct ivtv *itv = s->itv;
+       struct cx2341x_mpeg_params *p = &itv->params;
        int datatype;
 
        if (s->v4l2dev == NULL)
@@ -633,7 +647,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
                break;
        }
        if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
-                       itv->params.width, itv->params.height, itv->params.audio_properties)) {
+                       p->width, p->height, p->audio_properties)) {
                IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
        }
        return 0;
@@ -651,27 +665,12 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
 
        IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset);
 
-       /* Clear Streamoff */
-       if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
-               /* Initialize Decoder */
-               /* Reprogram Decoder YUV Buffers for YUV */
-               write_reg(yuv_offset[0] >> 4, 0x82c);
-               write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
-               write_reg(yuv_offset[0] >> 4, 0x834);
-               write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
-
-               write_reg_sync(0x00000000 | (0x0c << 16) | (0x0b << 8), 0x2d24);
-
-               write_reg_sync(0x00108080, 0x2898);
-               /* Enable YUV decoder output */
-               write_reg_sync(0x01, IVTV_REG_VDM);
-       }
-
        ivtv_setup_v4l2_decode_stream(s);
 
        /* set dma size to 65536 bytes */
        ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536);
 
+       /* Clear Streamoff */
        clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
 
        /* Zero out decoder counters */
@@ -719,7 +718,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
        struct ivtv *itv = s->itv;
        DECLARE_WAITQUEUE(wait, current);
        int cap_type;
-       unsigned long then;
        int stopmode;
 
        if (s->v4l2dev == NULL)
@@ -762,21 +760,20 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
        /* when: 0 =  end of GOP  1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
        ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);
 
-       then = jiffies;
-
        if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
                if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
                        /* only run these if we're shutting down the last cap */
                        unsigned long duration;
+                       unsigned long then = jiffies;
 
-                       then = jiffies;
                        add_wait_queue(&itv->eos_waitq, &wait);
 
                        set_current_state(TASK_INTERRUPTIBLE);
 
                        /* wait 2s for EOS interrupt */
                        while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
-                               jiffies < then + msecs_to_jiffies (2000)) {
+                               time_before(jiffies,
+                                           then + msecs_to_jiffies(2000))) {
                                schedule_timeout(msecs_to_jiffies(10));
                        }
 
@@ -797,10 +794,9 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
                        }
                        set_current_state(TASK_RUNNING);
                        remove_wait_queue(&itv->eos_waitq, &wait);
+                       set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
                }
 
-               then = jiffies;
-
                /* Handle any pending interrupts */
                ivtv_msleep_timeout(100, 1);
        }