static void blackbird_codec_settings(struct cx8802_dev *dev)
 {
+       struct cx88_core *core = dev->core;
+
        /* assign frame size */
        blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-                               dev->height, dev->width);
+                               core->height, core->width);
 
-       dev->cxhdl.width = dev->width;
-       dev->cxhdl.height = dev->height;
+       dev->cxhdl.width = core->width;
+       dev->cxhdl.height = core->height;
        cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
        cx2341x_handler_setup(&dev->cxhdl);
 }
        struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
        struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
 
-       return cx8802_buf_prepare(vb->vb2_queue, dev, buf, dev->field);
+       return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
        return 0;
 }
 
-static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        struct cx8802_dev *dev = video_drvdata(file);
+       struct cx88_core *core = dev->core;
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
        f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count;
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.width        = dev->width;
-       f->fmt.pix.height       = dev->height;
-       f->fmt.pix.field        = dev->field;
-       dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
-               dev->width, dev->height, dev->field);
+       f->fmt.pix.width        = core->width;
+       f->fmt.pix.height       = core->height;
+       f->fmt.pix.field        = core->field;
        return 0;
 }
 
-static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                        struct v4l2_format *f)
 {
        struct cx8802_dev *dev = video_drvdata(file);
+       struct cx88_core *core = dev->core;
+       unsigned maxw, maxh;
+       enum v4l2_field field;
 
        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
        f->fmt.pix.bytesperline = 0;
        f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count;
        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
-               dev->width, dev->height, dev->field);
+
+       maxw = norm_maxw(core->tvnorm);
+       maxh = norm_maxh(core->tvnorm);
+
+       field = f->fmt.pix.field;
+
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+       case V4L2_FIELD_INTERLACED:
+       case V4L2_FIELD_SEQ_BT:
+       case V4L2_FIELD_SEQ_TB:
+               break;
+       default:
+               field = (f->fmt.pix.height > maxh / 2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+               break;
+       }
+       if (V4L2_FIELD_HAS_T_OR_B(field))
+               maxh /= 2;
+
+       v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+                             &f->fmt.pix.height, 32, maxh, 0, 0);
+       f->fmt.pix.field = field;
        return 0;
 }
 
-static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
        struct cx8802_dev *dev = video_drvdata(file);
        struct cx88_core  *core = dev->core;
 
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count;
-       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       dev->width              = f->fmt.pix.width;
-       dev->height             = f->fmt.pix.height;
-       dev->field         = f->fmt.pix.field;
+       vidioc_try_fmt_vid_cap(file, priv, f);
+       core->width = f->fmt.pix.width;
+       core->height = f->fmt.pix.height;
+       core->field = f->fmt.pix.field;
        cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
        blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
                                f->fmt.pix.height, f->fmt.pix.width);
-       dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
-               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
        return 0;
 }
 
 
        cx88_set_freq (core,f);
        blackbird_initialize_codec(dev);
-       cx88_set_scale(dev->core, dev->width, dev->height,
-                       dev->field);
+       cx88_set_scale(core, core->width, core->height,
+                       core->field);
        return 0;
 }
 
        if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
                goto fail_core;
 
-       dev->width = 720;
-       if (core->tvnorm & V4L2_STD_525_60) {
-               dev->height = 480;
-       } else {
-               dev->height = 576;
-       }
-       dev->field = V4L2_FIELD_INTERLACED;
        dev->cxhdl.port = CX2341X_PORT_STREAMING;
-       dev->cxhdl.width = dev->width;
-       dev->cxhdl.height = dev->height;
+       dev->cxhdl.width = core->width;
+       dev->cxhdl.height = core->height;
        dev->cxhdl.func = blackbird_mbox_func;
        dev->cxhdl.priv = dev;
        err = cx2341x_handler_init(&dev->cxhdl, 36);
 //     init_controls(core);
        cx88_set_tvnorm(core,core->tvnorm);
        cx88_video_mux(core,0);
-       cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
+       cx2341x_handler_set_50hz(&dev->cxhdl, core->height == 576);
        cx2341x_handler_setup(&dev->cxhdl);
 
        q = &dev->vb2_mpegq;
 
        core->nr = nr;
        sprintf(core->name, "cx88[%d]", core->nr);
 
+       core->tvnorm = V4L2_STD_NTSC_M;
+       core->width   = 320;
+       core->height  = 240;
+       core->field   = V4L2_FIELD_INTERLACED;
+
        strcpy(core->v4l2_dev.name, core->name);
        if (v4l2_device_register(NULL, &core->v4l2_dev)) {
                kfree(core);
 
        struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
        struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
 
-       return cx8802_buf_prepare(vb->vb2_queue, dev, buf, dev->field);
+       return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
 
        struct cx88_core *core = dev->core;
 
        dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
-               dev->width, dev->height, dev->field);
+               core->width, core->height, core->field);
 
        /* setup fifo + format */
        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
 /* ------------------------------------------------------------------ */
 
 int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
-                       struct cx88_buffer *buf, enum v4l2_field field)
+                       struct cx88_buffer *buf)
 {
        int size = dev->ts_packet_size * dev->ts_packet_count;
        struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
 
        /* setup fifo + format */
        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
                                buf->bpl, buf->risc.dma);
-       cx88_set_scale(core, dev->width, dev->height, dev->field);
+       cx88_set_scale(core, core->width, core->height, core->field);
        cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma);
 
        /* reset counter */
                           unsigned int sizes[], void *alloc_ctxs[])
 {
        struct cx8800_dev *dev = q->drv_priv;
+       struct cx88_core *core = dev->core;
 
        *num_planes = 1;
-       sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
+       sizes[0] = (dev->fmt->depth * core->width * core->height) >> 3;
        return 0;
 }
 
        struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
        int rc;
 
-       buf->bpl = dev->width * dev->fmt->depth >> 3;
+       buf->bpl = core->width * dev->fmt->depth >> 3;
 
-       if (vb2_plane_size(vb, 0) < dev->height * buf->bpl)
+       if (vb2_plane_size(vb, 0) < core->height * buf->bpl)
                return -EINVAL;
-       vb2_set_plane_payload(vb, 0, dev->height * buf->bpl);
+       vb2_set_plane_payload(vb, 0, core->height * buf->bpl);
 
        rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
        if (!rc)
                return -EIO;
 
-       switch (dev->field) {
+       switch (core->field) {
        case V4L2_FIELD_TOP:
                cx88_risc_buffer(dev->pci, &buf->risc,
                                 sgt->sgl, 0, UNSET,
-                                buf->bpl, 0, dev->height);
+                                buf->bpl, 0, core->height);
                break;
        case V4L2_FIELD_BOTTOM:
                cx88_risc_buffer(dev->pci, &buf->risc,
                                 sgt->sgl, UNSET, 0,
-                                buf->bpl, 0, dev->height);
+                                buf->bpl, 0, core->height);
                break;
        case V4L2_FIELD_SEQ_TB:
                cx88_risc_buffer(dev->pci, &buf->risc,
                                 sgt->sgl,
-                                0, buf->bpl * (dev->height >> 1),
+                                0, buf->bpl * (core->height >> 1),
                                 buf->bpl, 0,
-                                dev->height >> 1);
+                                core->height >> 1);
                break;
        case V4L2_FIELD_SEQ_BT:
                cx88_risc_buffer(dev->pci, &buf->risc,
                                 sgt->sgl,
-                                buf->bpl * (dev->height >> 1), 0,
+                                buf->bpl * (core->height >> 1), 0,
                                 buf->bpl, 0,
-                                dev->height >> 1);
+                                core->height >> 1);
                break;
        case V4L2_FIELD_INTERLACED:
        default:
                cx88_risc_buffer(dev->pci, &buf->risc,
                                 sgt->sgl, 0, buf->bpl,
                                 buf->bpl, buf->bpl,
-                                dev->height >> 1);
+                                core->height >> 1);
                break;
        }
        dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
                buf, buf->vb.v4l2_buf.index,
-               dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
+               core->width, core->height, dev->fmt->depth, dev->fmt->name,
                (unsigned long)buf->risc.dma);
        return 0;
 }
                                        struct v4l2_format *f)
 {
        struct cx8800_dev *dev = video_drvdata(file);
+       struct cx88_core *core = dev->core;
 
-       f->fmt.pix.width        = dev->width;
-       f->fmt.pix.height       = dev->height;
-       f->fmt.pix.field        = dev->field;
+       f->fmt.pix.width        = core->width;
+       f->fmt.pix.height       = core->height;
+       f->fmt.pix.field        = core->field;
        f->fmt.pix.pixelformat  = dev->fmt->fourcc;
        f->fmt.pix.bytesperline =
                (f->fmt.pix.width * dev->fmt->depth) >> 3;
        if (NULL == fmt)
                return -EINVAL;
 
-       field = f->fmt.pix.field;
-       maxw  = norm_maxw(core->tvnorm);
-       maxh  = norm_maxh(core->tvnorm);
+       maxw = norm_maxw(core->tvnorm);
+       maxh = norm_maxh(core->tvnorm);
 
-       if (V4L2_FIELD_ANY == field) {
-               field = (f->fmt.pix.height > maxh/2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_BOTTOM;
-       }
+       field = f->fmt.pix.field;
 
        switch (field) {
        case V4L2_FIELD_TOP:
        case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
        case V4L2_FIELD_INTERLACED:
+       case V4L2_FIELD_SEQ_BT:
+       case V4L2_FIELD_SEQ_TB:
                break;
        default:
-               return -EINVAL;
+               field = (f->fmt.pix.height > maxh / 2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+               break;
        }
+       if (V4L2_FIELD_HAS_T_OR_B(field))
+               maxh /= 2;
 
-       f->fmt.pix.field = field;
        v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
                              &f->fmt.pix.height, 32, maxh, 0, 0);
+       f->fmt.pix.field = field;
        f->fmt.pix.bytesperline =
                (f->fmt.pix.width * fmt->depth) >> 3;
        f->fmt.pix.sizeimage =
                                        struct v4l2_format *f)
 {
        struct cx8800_dev *dev = video_drvdata(file);
+       struct cx88_core *core = dev->core;
        int err = vidioc_try_fmt_vid_cap (file,priv,f);
 
        if (0 != err)
                return err;
-       dev->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
-       dev->width      = f->fmt.pix.width;
-       dev->height     = f->fmt.pix.height;
-       dev->field = f->fmt.pix.field;
+       dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       core->width = f->fmt.pix.width;
+       core->height = f->fmt.pix.height;
+       core->field = f->fmt.pix.field;
        return 0;
 }
 
 
        /* initialize driver struct */
        spin_lock_init(&dev->slock);
-       core->tvnorm = V4L2_STD_NTSC_M;
 
        /* init video dma queues */
        INIT_LIST_HEAD(&dev->vidq.active);
        /* Sets device info at pci_dev */
        pci_set_drvdata(pci_dev, dev);
 
-       dev->width   = 320;
-       dev->height  = 240;
-       dev->field   = V4L2_FIELD_INTERLACED;
-       dev->fmt     = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+       dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
        /* initial device configuration */
        mutex_lock(&core->lock);
 
        /* state info */
        struct task_struct         *kthread;
        v4l2_std_id                tvnorm;
+       unsigned                   width, height;
+       unsigned                   field;
        enum cx88_tvaudio          tvaudio;
        u32                        audiomode_manual;
        u32                        audiomode_current;
        unsigned char              pci_rev,pci_lat;
 
        const struct cx8800_fmt    *fmt;
-       unsigned int               width, height;
-       unsigned                   field;
 
        /* capture queues */
        struct cx88_dmaqueue       vidq;
 #if IS_ENABLED(CONFIG_VIDEO_CX88_BLACKBIRD)
        struct video_device        *mpeg_dev;
        u32                        mailbox;
-       int                        width;
-       int                        height;
-       unsigned                   field;
        unsigned char              mpeg_active; /* nonzero if mpeg encoder is active */
 
        /* mpeg params */
 /* cx88-mpeg.c                                                 */
 
 int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
-                       struct cx88_buffer *buf, enum v4l2_field field);
+                       struct cx88_buffer *buf);
 void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
 void cx8802_cancel_buffers(struct cx8802_dev *dev);
 int cx8802_start_dma(struct cx8802_dev    *dev,