Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
0004  *
0005  * Original author:
0006  * Ben Collins <bcollins@ubuntu.com>
0007  *
0008  * Additional work by:
0009  * John Brooks <john.brooks@bluecherry.net>
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/kthread.h>
0015 #include <linux/freezer.h>
0016 
0017 #include <media/v4l2-ioctl.h>
0018 #include <media/v4l2-common.h>
0019 #include <media/v4l2-event.h>
0020 #include <media/videobuf2-dma-sg.h>
0021 
0022 #include "solo6x10.h"
0023 #include "solo6x10-tw28.h"
0024 #include "solo6x10-jpeg.h"
0025 
0026 #define MIN_VID_BUFFERS     2
0027 #define FRAME_BUF_SIZE      (400 * 1024)
0028 #define MP4_QS          16
0029 #define DMA_ALIGN       4096
0030 
0031 /* 6010 M4V */
0032 static u8 vop_6010_ntsc_d1[] = {
0033     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
0034     0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
0035     0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
0036     0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
0037 };
0038 
0039 static u8 vop_6010_ntsc_cif[] = {
0040     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
0041     0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
0042     0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
0043     0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
0044 };
0045 
0046 static u8 vop_6010_pal_d1[] = {
0047     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
0048     0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
0049     0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
0050     0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
0051 };
0052 
0053 static u8 vop_6010_pal_cif[] = {
0054     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
0055     0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
0056     0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
0057     0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
0058 };
0059 
0060 /* 6110 h.264 */
0061 static u8 vop_6110_ntsc_d1[] = {
0062     0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
0063     0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
0064     0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
0065 };
0066 
0067 static u8 vop_6110_ntsc_cif[] = {
0068     0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
0069     0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
0070     0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
0071 };
0072 
0073 static u8 vop_6110_pal_d1[] = {
0074     0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
0075     0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
0076     0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
0077 };
0078 
0079 static u8 vop_6110_pal_cif[] = {
0080     0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
0081     0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
0082     0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
0083 };
0084 
0085 typedef __le32 vop_header[16];
0086 
0087 struct solo_enc_buf {
0088     enum solo_enc_types type;
0089     const vop_header    *vh;
0090     int         motion;
0091 };
0092 
0093 static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
0094 {
0095     struct solo_dev *solo_dev = solo_enc->solo_dev;
0096 
0097     return (solo_dev->motion_mask >> solo_enc->ch) & 1;
0098 }
0099 
0100 static int solo_motion_detected(struct solo_enc_dev *solo_enc)
0101 {
0102     struct solo_dev *solo_dev = solo_enc->solo_dev;
0103     unsigned long flags;
0104     u32 ch_mask = 1 << solo_enc->ch;
0105     int ret = 0;
0106 
0107     spin_lock_irqsave(&solo_enc->motion_lock, flags);
0108     if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
0109         solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
0110         ret = 1;
0111     }
0112     spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
0113 
0114     return ret;
0115 }
0116 
0117 static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
0118 {
0119     struct solo_dev *solo_dev = solo_enc->solo_dev;
0120     u32 mask = 1 << solo_enc->ch;
0121     unsigned long flags;
0122 
0123     spin_lock_irqsave(&solo_enc->motion_lock, flags);
0124 
0125     if (on)
0126         solo_dev->motion_mask |= mask;
0127     else
0128         solo_dev->motion_mask &= ~mask;
0129 
0130     solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
0131 
0132     solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
0133                SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
0134                (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
0135 
0136     spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
0137 }
0138 
0139 void solo_update_mode(struct solo_enc_dev *solo_enc)
0140 {
0141     struct solo_dev *solo_dev = solo_enc->solo_dev;
0142     int vop_len;
0143     u8 *vop;
0144 
0145     solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
0146     solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
0147 
0148     if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
0149         solo_enc->width = solo_dev->video_hsize >> 1;
0150         solo_enc->height = solo_dev->video_vsize;
0151         if (solo_dev->type == SOLO_DEV_6110) {
0152             if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
0153                 vop = vop_6110_ntsc_cif;
0154                 vop_len = sizeof(vop_6110_ntsc_cif);
0155             } else {
0156                 vop = vop_6110_pal_cif;
0157                 vop_len = sizeof(vop_6110_pal_cif);
0158             }
0159         } else {
0160             if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
0161                 vop = vop_6010_ntsc_cif;
0162                 vop_len = sizeof(vop_6010_ntsc_cif);
0163             } else {
0164                 vop = vop_6010_pal_cif;
0165                 vop_len = sizeof(vop_6010_pal_cif);
0166             }
0167         }
0168     } else {
0169         solo_enc->width = solo_dev->video_hsize;
0170         solo_enc->height = solo_dev->video_vsize << 1;
0171         solo_enc->bw_weight <<= 2;
0172         if (solo_dev->type == SOLO_DEV_6110) {
0173             if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
0174                 vop = vop_6110_ntsc_d1;
0175                 vop_len = sizeof(vop_6110_ntsc_d1);
0176             } else {
0177                 vop = vop_6110_pal_d1;
0178                 vop_len = sizeof(vop_6110_pal_d1);
0179             }
0180         } else {
0181             if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
0182                 vop = vop_6010_ntsc_d1;
0183                 vop_len = sizeof(vop_6010_ntsc_d1);
0184             } else {
0185                 vop = vop_6010_pal_d1;
0186                 vop_len = sizeof(vop_6010_pal_d1);
0187             }
0188         }
0189     }
0190 
0191     memcpy(solo_enc->vop, vop, vop_len);
0192 
0193     /* Some fixups for 6010/M4V */
0194     if (solo_dev->type == SOLO_DEV_6010) {
0195         u16 fps = solo_dev->fps * 1000;
0196         u16 interval = solo_enc->interval * 1000;
0197 
0198         vop = solo_enc->vop;
0199 
0200         /* Frame rate and interval */
0201         vop[22] = fps >> 4;
0202         vop[23] = ((fps << 4) & 0xf0) | 0x0c
0203             | ((interval >> 13) & 0x3);
0204         vop[24] = (interval >> 5) & 0xff;
0205         vop[25] = ((interval << 3) & 0xf8) | 0x04;
0206     }
0207 
0208     solo_enc->vop_len = vop_len;
0209 
0210     /* Now handle the jpeg header */
0211     vop = solo_enc->jpeg_header;
0212     vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
0213     vop[SOF0_START + 6] = 0xff & solo_enc->height;
0214     vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
0215     vop[SOF0_START + 8] = 0xff & solo_enc->width;
0216 
0217     memcpy(vop + DQT_START,
0218            jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
0219 }
0220 
0221 static int solo_enc_on(struct solo_enc_dev *solo_enc)
0222 {
0223     u8 ch = solo_enc->ch;
0224     struct solo_dev *solo_dev = solo_enc->solo_dev;
0225     u8 interval;
0226 
0227     solo_update_mode(solo_enc);
0228 
0229     /* Make sure to do a bandwidth check */
0230     if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
0231         return -EBUSY;
0232     solo_enc->sequence = 0;
0233     solo_dev->enc_bw_remain -= solo_enc->bw_weight;
0234 
0235     if (solo_enc->type == SOLO_ENC_TYPE_EXT)
0236         solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
0237 
0238     /* Disable all encoding for this channel */
0239     solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
0240 
0241     /* Common for both std and ext encoding */
0242     solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
0243                solo_enc->interlaced ? 1 : 0);
0244 
0245     if (solo_enc->interlaced)
0246         interval = solo_enc->interval - 1;
0247     else
0248         interval = solo_enc->interval;
0249 
0250     /* Standard encoding only */
0251     solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
0252     solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
0253     solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
0254 
0255     /* Extended encoding only */
0256     solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
0257     solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
0258     solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
0259 
0260     /* Enables the standard encoder */
0261     solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
0262 
0263     return 0;
0264 }
0265 
0266 static void solo_enc_off(struct solo_enc_dev *solo_enc)
0267 {
0268     struct solo_dev *solo_dev = solo_enc->solo_dev;
0269 
0270     solo_dev->enc_bw_remain += solo_enc->bw_weight;
0271 
0272     solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
0273     solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
0274 }
0275 
0276 static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
0277                   unsigned int off, unsigned int size)
0278 {
0279     int ret;
0280 
0281     if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
0282         return -EINVAL;
0283 
0284     /* Single shot */
0285     if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
0286         return solo_p2m_dma_t(solo_dev, 0, dma,
0287                       SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
0288                       0, 0);
0289     }
0290 
0291     /* Buffer wrap */
0292     ret = solo_p2m_dma_t(solo_dev, 0, dma,
0293                  SOLO_MP4E_EXT_ADDR(solo_dev) + off,
0294                  SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
0295 
0296     if (!ret) {
0297         ret = solo_p2m_dma_t(solo_dev, 0,
0298                  dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
0299                  SOLO_MP4E_EXT_ADDR(solo_dev),
0300                  size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
0301     }
0302 
0303     return ret;
0304 }
0305 
0306 /* Build a descriptor queue out of an SG list and send it to the P2M for
0307  * processing. */
0308 static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
0309               struct sg_table *vbuf, int off, int size,
0310               unsigned int base, unsigned int base_size)
0311 {
0312     struct solo_dev *solo_dev = solo_enc->solo_dev;
0313     struct scatterlist *sg;
0314     int i;
0315     int ret;
0316 
0317     if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
0318         return -EINVAL;
0319 
0320     solo_enc->desc_count = 1;
0321 
0322     for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
0323         struct solo_p2m_desc *desc;
0324         dma_addr_t dma;
0325         int len;
0326         int left = base_size - off;
0327 
0328         desc = &solo_enc->desc_items[solo_enc->desc_count++];
0329         dma = sg_dma_address(sg);
0330         len = sg_dma_len(sg);
0331 
0332         /* We assume this is smaller than the scatter size */
0333         BUG_ON(skip >= len);
0334         if (skip) {
0335             len -= skip;
0336             dma += skip;
0337             size -= skip;
0338             skip = 0;
0339         }
0340 
0341         len = min(len, size);
0342 
0343         if (len <= left) {
0344             /* Single descriptor */
0345             solo_p2m_fill_desc(desc, 0, dma, base + off,
0346                        len, 0, 0);
0347         } else {
0348             /* Buffer wrap */
0349             /* XXX: Do these as separate DMA requests, to avoid
0350                timeout errors triggered by awkwardly sized
0351                descriptors. See
0352                <https://github.com/bluecherrydvr/solo6x10/issues/8>
0353              */
0354             ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
0355                          left, 0, 0);
0356             if (ret)
0357                 return ret;
0358 
0359             ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
0360                          len - left, 0, 0);
0361             if (ret)
0362                 return ret;
0363 
0364             solo_enc->desc_count--;
0365         }
0366 
0367         size -= len;
0368         if (size <= 0)
0369             break;
0370 
0371         off += len;
0372         if (off >= base_size)
0373             off -= base_size;
0374 
0375         /* Because we may use two descriptors per loop */
0376         if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
0377             ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
0378                         solo_enc->desc_dma,
0379                         solo_enc->desc_count - 1);
0380             if (ret)
0381                 return ret;
0382             solo_enc->desc_count = 1;
0383         }
0384     }
0385 
0386     if (solo_enc->desc_count <= 1)
0387         return 0;
0388 
0389     return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
0390             solo_enc->desc_dma, solo_enc->desc_count - 1);
0391 }
0392 
0393 /* Extract values from VOP header - VE_STATUSxx */
0394 static inline __always_unused int vop_interlaced(const vop_header *vh)
0395 {
0396     return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
0397 }
0398 
0399 static inline __always_unused u8 vop_channel(const vop_header *vh)
0400 {
0401     return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F;
0402 }
0403 
0404 static inline u8 vop_type(const vop_header *vh)
0405 {
0406     return (__le32_to_cpu((*vh)[0]) >> 22) & 3;
0407 }
0408 
0409 static inline u32 vop_mpeg_size(const vop_header *vh)
0410 {
0411     return __le32_to_cpu((*vh)[0]) & 0xFFFFF;
0412 }
0413 
0414 static inline u8 __always_unused vop_hsize(const vop_header *vh)
0415 {
0416     return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
0417 }
0418 
0419 static inline u8 __always_unused vop_vsize(const vop_header *vh)
0420 {
0421     return __le32_to_cpu((*vh)[1]) & 0xFF;
0422 }
0423 
0424 static inline u32 vop_mpeg_offset(const vop_header *vh)
0425 {
0426     return __le32_to_cpu((*vh)[2]);
0427 }
0428 
0429 static inline u32 vop_jpeg_offset(const vop_header *vh)
0430 {
0431     return __le32_to_cpu((*vh)[3]);
0432 }
0433 
0434 static inline u32 vop_jpeg_size(const vop_header *vh)
0435 {
0436     return __le32_to_cpu((*vh)[4]) & 0xFFFFF;
0437 }
0438 
0439 static inline u32 __always_unused vop_sec(const vop_header *vh)
0440 {
0441     return __le32_to_cpu((*vh)[5]);
0442 }
0443 
0444 static inline __always_unused u32 vop_usec(const vop_header *vh)
0445 {
0446     return __le32_to_cpu((*vh)[6]);
0447 }
0448 
0449 static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
0450               struct vb2_buffer *vb, const vop_header *vh)
0451 {
0452     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0453     struct solo_dev *solo_dev = solo_enc->solo_dev;
0454     struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
0455     int frame_size;
0456 
0457     vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
0458 
0459     if (vb2_plane_size(vb, 0) < vop_jpeg_size(vh) + solo_enc->jpeg_len)
0460         return -EIO;
0461 
0462     frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
0463     vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
0464 
0465     return solo_send_desc(solo_enc, solo_enc->jpeg_len, sgt,
0466                  vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
0467                  frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
0468                  SOLO_JPEG_EXT_SIZE(solo_dev));
0469 }
0470 
0471 static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
0472         struct vb2_buffer *vb, const vop_header *vh)
0473 {
0474     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0475     struct solo_dev *solo_dev = solo_enc->solo_dev;
0476     struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
0477     int frame_off, frame_size;
0478     int skip = 0;
0479 
0480     if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
0481         return -EIO;
0482 
0483     /* If this is a key frame, add extra header */
0484     vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
0485         V4L2_BUF_FLAG_BFRAME);
0486     if (!vop_type(vh)) {
0487         skip = solo_enc->vop_len;
0488         vbuf->flags |= V4L2_BUF_FLAG_KEYFRAME;
0489         vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh) +
0490             solo_enc->vop_len);
0491     } else {
0492         vbuf->flags |= V4L2_BUF_FLAG_PFRAME;
0493         vb2_set_plane_payload(vb, 0, vop_mpeg_size(vh));
0494     }
0495 
0496     /* Now get the actual mpeg payload */
0497     frame_off = (vop_mpeg_offset(vh) - SOLO_MP4E_EXT_ADDR(solo_dev) +
0498         sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
0499     frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
0500 
0501     return solo_send_desc(solo_enc, skip, sgt, frame_off, frame_size,
0502             SOLO_MP4E_EXT_ADDR(solo_dev),
0503             SOLO_MP4E_EXT_SIZE(solo_dev));
0504 }
0505 
0506 static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
0507                 struct vb2_buffer *vb, struct solo_enc_buf *enc_buf)
0508 {
0509     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0510     const vop_header *vh = enc_buf->vh;
0511     int ret;
0512 
0513     switch (solo_enc->fmt) {
0514     case V4L2_PIX_FMT_MPEG4:
0515     case V4L2_PIX_FMT_H264:
0516         ret = solo_fill_mpeg(solo_enc, vb, vh);
0517         break;
0518     default: /* V4L2_PIX_FMT_MJPEG */
0519         ret = solo_fill_jpeg(solo_enc, vb, vh);
0520         break;
0521     }
0522 
0523     if (!ret) {
0524         vbuf->sequence = solo_enc->sequence++;
0525         vb->timestamp = ktime_get_ns();
0526 
0527         /* Check for motion flags */
0528         if (solo_is_motion_on(solo_enc) && enc_buf->motion) {
0529             struct v4l2_event ev = {
0530                 .type = V4L2_EVENT_MOTION_DET,
0531                 .u.motion_det = {
0532                     .flags
0533                     = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
0534                     .frame_sequence = vbuf->sequence,
0535                     .region_mask = enc_buf->motion ? 1 : 0,
0536                 },
0537             };
0538 
0539             v4l2_event_queue(solo_enc->vfd, &ev);
0540         }
0541     }
0542 
0543     vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
0544 
0545     return ret;
0546 }
0547 
0548 static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
0549                 struct solo_enc_buf *enc_buf)
0550 {
0551     struct solo_vb2_buf *vb;
0552     unsigned long flags;
0553 
0554     mutex_lock(&solo_enc->lock);
0555     if (solo_enc->type != enc_buf->type)
0556         goto unlock;
0557 
0558     spin_lock_irqsave(&solo_enc->av_lock, flags);
0559     if (list_empty(&solo_enc->vidq_active)) {
0560         spin_unlock_irqrestore(&solo_enc->av_lock, flags);
0561         goto unlock;
0562     }
0563     vb = list_first_entry(&solo_enc->vidq_active, struct solo_vb2_buf,
0564         list);
0565     list_del(&vb->list);
0566     spin_unlock_irqrestore(&solo_enc->av_lock, flags);
0567 
0568     solo_enc_fillbuf(solo_enc, &vb->vb.vb2_buf, enc_buf);
0569 unlock:
0570     mutex_unlock(&solo_enc->lock);
0571 }
0572 
0573 void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
0574 {
0575     wake_up_interruptible_all(&solo_dev->ring_thread_wait);
0576 }
0577 
0578 static void solo_handle_ring(struct solo_dev *solo_dev)
0579 {
0580     for (;;) {
0581         struct solo_enc_dev *solo_enc;
0582         struct solo_enc_buf enc_buf;
0583         u32 mpeg_current, off;
0584         u8 ch;
0585         u8 cur_q;
0586 
0587         /* Check if the hardware has any new ones in the queue */
0588         cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
0589         if (cur_q == solo_dev->enc_idx)
0590             break;
0591 
0592         mpeg_current = solo_reg_read(solo_dev,
0593                     SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
0594         solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
0595 
0596         ch = (mpeg_current >> 24) & 0x1f;
0597         off = mpeg_current & 0x00ffffff;
0598 
0599         if (ch >= SOLO_MAX_CHANNELS) {
0600             ch -= SOLO_MAX_CHANNELS;
0601             enc_buf.type = SOLO_ENC_TYPE_EXT;
0602         } else
0603             enc_buf.type = SOLO_ENC_TYPE_STD;
0604 
0605         solo_enc = solo_dev->v4l2_enc[ch];
0606         if (solo_enc == NULL) {
0607             dev_err(&solo_dev->pdev->dev,
0608                 "Got spurious packet for channel %d\n", ch);
0609             continue;
0610         }
0611 
0612         /* FAIL... */
0613         if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
0614                      sizeof(vop_header)))
0615             continue;
0616 
0617         enc_buf.vh = solo_dev->vh_buf;
0618 
0619         /* Sanity check */
0620         if (vop_mpeg_offset(enc_buf.vh) !=
0621             SOLO_MP4E_EXT_ADDR(solo_dev) + off)
0622             continue;
0623 
0624         if (solo_motion_detected(solo_enc))
0625             enc_buf.motion = 1;
0626         else
0627             enc_buf.motion = 0;
0628 
0629         solo_enc_handle_one(solo_enc, &enc_buf);
0630     }
0631 }
0632 
0633 static int solo_ring_thread(void *data)
0634 {
0635     struct solo_dev *solo_dev = data;
0636     DECLARE_WAITQUEUE(wait, current);
0637 
0638     set_freezable();
0639     add_wait_queue(&solo_dev->ring_thread_wait, &wait);
0640 
0641     for (;;) {
0642         long timeout = schedule_timeout_interruptible(HZ);
0643 
0644         if (timeout == -ERESTARTSYS || kthread_should_stop())
0645             break;
0646         solo_handle_ring(solo_dev);
0647         try_to_freeze();
0648     }
0649 
0650     remove_wait_queue(&solo_dev->ring_thread_wait, &wait);
0651 
0652     return 0;
0653 }
0654 
0655 static int solo_enc_queue_setup(struct vb2_queue *q,
0656                 unsigned int *num_buffers,
0657                 unsigned int *num_planes, unsigned int sizes[],
0658                 struct device *alloc_devs[])
0659 {
0660     sizes[0] = FRAME_BUF_SIZE;
0661     *num_planes = 1;
0662 
0663     if (*num_buffers < MIN_VID_BUFFERS)
0664         *num_buffers = MIN_VID_BUFFERS;
0665 
0666     return 0;
0667 }
0668 
0669 static void solo_enc_buf_queue(struct vb2_buffer *vb)
0670 {
0671     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0672     struct vb2_queue *vq = vb->vb2_queue;
0673     struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vq);
0674     struct solo_vb2_buf *solo_vb =
0675         container_of(vbuf, struct solo_vb2_buf, vb);
0676 
0677     spin_lock(&solo_enc->av_lock);
0678     list_add_tail(&solo_vb->list, &solo_enc->vidq_active);
0679     spin_unlock(&solo_enc->av_lock);
0680 }
0681 
0682 static int solo_ring_start(struct solo_dev *solo_dev)
0683 {
0684     solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
0685                         SOLO6X10_NAME "_ring");
0686     if (IS_ERR(solo_dev->ring_thread)) {
0687         int err = PTR_ERR(solo_dev->ring_thread);
0688 
0689         solo_dev->ring_thread = NULL;
0690         return err;
0691     }
0692 
0693     solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
0694 
0695     return 0;
0696 }
0697 
0698 static void solo_ring_stop(struct solo_dev *solo_dev)
0699 {
0700     if (solo_dev->ring_thread) {
0701         kthread_stop(solo_dev->ring_thread);
0702         solo_dev->ring_thread = NULL;
0703     }
0704 
0705     solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
0706 }
0707 
0708 static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
0709 {
0710     struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
0711 
0712     return solo_enc_on(solo_enc);
0713 }
0714 
0715 static void solo_enc_stop_streaming(struct vb2_queue *q)
0716 {
0717     struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
0718     unsigned long flags;
0719 
0720     spin_lock_irqsave(&solo_enc->av_lock, flags);
0721     solo_enc_off(solo_enc);
0722     while (!list_empty(&solo_enc->vidq_active)) {
0723         struct solo_vb2_buf *buf = list_entry(
0724                 solo_enc->vidq_active.next,
0725                 struct solo_vb2_buf, list);
0726 
0727         list_del(&buf->list);
0728         vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
0729     }
0730     spin_unlock_irqrestore(&solo_enc->av_lock, flags);
0731 }
0732 
0733 static void solo_enc_buf_finish(struct vb2_buffer *vb)
0734 {
0735     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0736     struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
0737     struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
0738 
0739     switch (solo_enc->fmt) {
0740     case V4L2_PIX_FMT_MPEG4:
0741     case V4L2_PIX_FMT_H264:
0742         if (vbuf->flags & V4L2_BUF_FLAG_KEYFRAME)
0743             sg_copy_from_buffer(sgt->sgl, sgt->nents,
0744                     solo_enc->vop, solo_enc->vop_len);
0745         break;
0746     default: /* V4L2_PIX_FMT_MJPEG */
0747         sg_copy_from_buffer(sgt->sgl, sgt->nents,
0748                 solo_enc->jpeg_header, solo_enc->jpeg_len);
0749         break;
0750     }
0751 }
0752 
0753 static const struct vb2_ops solo_enc_video_qops = {
0754     .queue_setup    = solo_enc_queue_setup,
0755     .buf_queue  = solo_enc_buf_queue,
0756     .buf_finish = solo_enc_buf_finish,
0757     .start_streaming = solo_enc_start_streaming,
0758     .stop_streaming = solo_enc_stop_streaming,
0759     .wait_prepare   = vb2_ops_wait_prepare,
0760     .wait_finish    = vb2_ops_wait_finish,
0761 };
0762 
0763 static int solo_enc_querycap(struct file *file, void  *priv,
0764                  struct v4l2_capability *cap)
0765 {
0766     struct solo_enc_dev *solo_enc = video_drvdata(file);
0767 
0768     strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
0769     snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
0770          solo_enc->ch);
0771     return 0;
0772 }
0773 
0774 static int solo_enc_enum_input(struct file *file, void *priv,
0775                    struct v4l2_input *input)
0776 {
0777     struct solo_enc_dev *solo_enc = video_drvdata(file);
0778     struct solo_dev *solo_dev = solo_enc->solo_dev;
0779 
0780     if (input->index)
0781         return -EINVAL;
0782 
0783     snprintf(input->name, sizeof(input->name), "Encoder %d",
0784          solo_enc->ch + 1);
0785     input->type = V4L2_INPUT_TYPE_CAMERA;
0786     input->std = solo_enc->vfd->tvnorms;
0787 
0788     if (!tw28_get_video_status(solo_dev, solo_enc->ch))
0789         input->status = V4L2_IN_ST_NO_SIGNAL;
0790 
0791     return 0;
0792 }
0793 
0794 static int solo_enc_set_input(struct file *file, void *priv,
0795                   unsigned int index)
0796 {
0797     if (index)
0798         return -EINVAL;
0799 
0800     return 0;
0801 }
0802 
0803 static int solo_enc_get_input(struct file *file, void *priv,
0804                   unsigned int *index)
0805 {
0806     *index = 0;
0807 
0808     return 0;
0809 }
0810 
0811 static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
0812                  struct v4l2_fmtdesc *f)
0813 {
0814     struct solo_enc_dev *solo_enc = video_drvdata(file);
0815     int dev_type = solo_enc->solo_dev->type;
0816 
0817     switch (f->index) {
0818     case 0:
0819         switch (dev_type) {
0820         case SOLO_DEV_6010:
0821             f->pixelformat = V4L2_PIX_FMT_MPEG4;
0822             break;
0823         case SOLO_DEV_6110:
0824             f->pixelformat = V4L2_PIX_FMT_H264;
0825             break;
0826         }
0827         break;
0828     case 1:
0829         f->pixelformat = V4L2_PIX_FMT_MJPEG;
0830         break;
0831     default:
0832         return -EINVAL;
0833     }
0834     return 0;
0835 }
0836 
0837 static inline int solo_valid_pixfmt(u32 pixfmt, int dev_type)
0838 {
0839     return (pixfmt == V4L2_PIX_FMT_H264 && dev_type == SOLO_DEV_6110)
0840         || (pixfmt == V4L2_PIX_FMT_MPEG4 && dev_type == SOLO_DEV_6010)
0841         || pixfmt == V4L2_PIX_FMT_MJPEG ? 0 : -EINVAL;
0842 }
0843 
0844 static int solo_enc_try_fmt_cap(struct file *file, void *priv,
0845                 struct v4l2_format *f)
0846 {
0847     struct solo_enc_dev *solo_enc = video_drvdata(file);
0848     struct solo_dev *solo_dev = solo_enc->solo_dev;
0849     struct v4l2_pix_format *pix = &f->fmt.pix;
0850 
0851     if (solo_valid_pixfmt(pix->pixelformat, solo_dev->type))
0852         return -EINVAL;
0853 
0854     if (pix->width < solo_dev->video_hsize ||
0855         pix->height < solo_dev->video_vsize << 1) {
0856         /* Default to CIF 1/2 size */
0857         pix->width = solo_dev->video_hsize >> 1;
0858         pix->height = solo_dev->video_vsize;
0859     } else {
0860         /* Full frame */
0861         pix->width = solo_dev->video_hsize;
0862         pix->height = solo_dev->video_vsize << 1;
0863     }
0864 
0865     switch (pix->field) {
0866     case V4L2_FIELD_NONE:
0867     case V4L2_FIELD_INTERLACED:
0868         break;
0869     case V4L2_FIELD_ANY:
0870     default:
0871         pix->field = V4L2_FIELD_INTERLACED;
0872         break;
0873     }
0874 
0875     /* Just set these */
0876     pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
0877     pix->sizeimage = FRAME_BUF_SIZE;
0878     pix->bytesperline = 0;
0879 
0880     return 0;
0881 }
0882 
0883 static int solo_enc_set_fmt_cap(struct file *file, void *priv,
0884                 struct v4l2_format *f)
0885 {
0886     struct solo_enc_dev *solo_enc = video_drvdata(file);
0887     struct solo_dev *solo_dev = solo_enc->solo_dev;
0888     struct v4l2_pix_format *pix = &f->fmt.pix;
0889     int ret;
0890 
0891     if (vb2_is_busy(&solo_enc->vidq))
0892         return -EBUSY;
0893 
0894     ret = solo_enc_try_fmt_cap(file, priv, f);
0895     if (ret)
0896         return ret;
0897 
0898     if (pix->width == solo_dev->video_hsize)
0899         solo_enc->mode = SOLO_ENC_MODE_D1;
0900     else
0901         solo_enc->mode = SOLO_ENC_MODE_CIF;
0902 
0903     /* This does not change the encoder at all */
0904     solo_enc->fmt = pix->pixelformat;
0905 
0906     /*
0907      * More information is needed about these 'extended' types. As far
0908      * as I can tell these are basically additional video streams with
0909      * different MPEG encoding attributes that can run in parallel with
0910      * the main stream. If so, then this should be implemented as a
0911      * second video node. Abusing priv like this is certainly not the
0912      * right approach.
0913     if (pix->priv)
0914         solo_enc->type = SOLO_ENC_TYPE_EXT;
0915      */
0916     solo_update_mode(solo_enc);
0917     return 0;
0918 }
0919 
0920 static int solo_enc_get_fmt_cap(struct file *file, void *priv,
0921                 struct v4l2_format *f)
0922 {
0923     struct solo_enc_dev *solo_enc = video_drvdata(file);
0924     struct v4l2_pix_format *pix = &f->fmt.pix;
0925 
0926     pix->width = solo_enc->width;
0927     pix->height = solo_enc->height;
0928     pix->pixelformat = solo_enc->fmt;
0929     pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
0930              V4L2_FIELD_NONE;
0931     pix->sizeimage = FRAME_BUF_SIZE;
0932     pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
0933 
0934     return 0;
0935 }
0936 
0937 static int solo_enc_g_std(struct file *file, void *priv, v4l2_std_id *i)
0938 {
0939     struct solo_enc_dev *solo_enc = video_drvdata(file);
0940     struct solo_dev *solo_dev = solo_enc->solo_dev;
0941 
0942     if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
0943         *i = V4L2_STD_NTSC_M;
0944     else
0945         *i = V4L2_STD_PAL;
0946     return 0;
0947 }
0948 
0949 static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id std)
0950 {
0951     struct solo_enc_dev *solo_enc = video_drvdata(file);
0952 
0953     return solo_set_video_type(solo_enc->solo_dev, std & V4L2_STD_625_50);
0954 }
0955 
0956 static int solo_enum_framesizes(struct file *file, void *priv,
0957                 struct v4l2_frmsizeenum *fsize)
0958 {
0959     struct solo_enc_dev *solo_enc = video_drvdata(file);
0960     struct solo_dev *solo_dev = solo_enc->solo_dev;
0961 
0962     if (solo_valid_pixfmt(fsize->pixel_format, solo_dev->type))
0963         return -EINVAL;
0964 
0965     switch (fsize->index) {
0966     case 0:
0967         fsize->discrete.width = solo_dev->video_hsize >> 1;
0968         fsize->discrete.height = solo_dev->video_vsize;
0969         break;
0970     case 1:
0971         fsize->discrete.width = solo_dev->video_hsize;
0972         fsize->discrete.height = solo_dev->video_vsize << 1;
0973         break;
0974     default:
0975         return -EINVAL;
0976     }
0977 
0978     fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
0979 
0980     return 0;
0981 }
0982 
0983 static int solo_enum_frameintervals(struct file *file, void *priv,
0984                     struct v4l2_frmivalenum *fintv)
0985 {
0986     struct solo_enc_dev *solo_enc = video_drvdata(file);
0987     struct solo_dev *solo_dev = solo_enc->solo_dev;
0988 
0989     if (solo_valid_pixfmt(fintv->pixel_format, solo_dev->type))
0990         return -EINVAL;
0991     if (fintv->index)
0992         return -EINVAL;
0993     if ((fintv->width != solo_dev->video_hsize >> 1 ||
0994          fintv->height != solo_dev->video_vsize) &&
0995         (fintv->width != solo_dev->video_hsize ||
0996          fintv->height != solo_dev->video_vsize << 1))
0997         return -EINVAL;
0998 
0999     fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
1000 
1001     fintv->stepwise.min.numerator = 1;
1002     fintv->stepwise.min.denominator = solo_dev->fps;
1003 
1004     fintv->stepwise.max.numerator = 15;
1005     fintv->stepwise.max.denominator = solo_dev->fps;
1006 
1007     fintv->stepwise.step.numerator = 1;
1008     fintv->stepwise.step.denominator = solo_dev->fps;
1009 
1010     return 0;
1011 }
1012 
1013 static int solo_g_parm(struct file *file, void *priv,
1014                struct v4l2_streamparm *sp)
1015 {
1016     struct solo_enc_dev *solo_enc = video_drvdata(file);
1017     struct v4l2_captureparm *cp = &sp->parm.capture;
1018 
1019     cp->capability = V4L2_CAP_TIMEPERFRAME;
1020     cp->timeperframe.numerator = solo_enc->interval;
1021     cp->timeperframe.denominator = solo_enc->solo_dev->fps;
1022     cp->capturemode = 0;
1023     /* XXX: Shouldn't we be able to get/set this from videobuf? */
1024     cp->readbuffers = 2;
1025 
1026     return 0;
1027 }
1028 
1029 static inline int calc_interval(u8 fps, u32 n, u32 d)
1030 {
1031     if (!n || !d)
1032         return 1;
1033     if (d == fps)
1034         return n;
1035     n *= fps;
1036     return min(15U, n / d + (n % d >= (fps >> 1)));
1037 }
1038 
1039 static int solo_s_parm(struct file *file, void *priv,
1040                struct v4l2_streamparm *sp)
1041 {
1042     struct solo_enc_dev *solo_enc = video_drvdata(file);
1043     struct v4l2_fract *t = &sp->parm.capture.timeperframe;
1044     u8 fps = solo_enc->solo_dev->fps;
1045 
1046     if (vb2_is_streaming(&solo_enc->vidq))
1047         return -EBUSY;
1048 
1049     solo_enc->interval = calc_interval(fps, t->numerator, t->denominator);
1050     solo_update_mode(solo_enc);
1051     return solo_g_parm(file, priv, sp);
1052 }
1053 
1054 static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
1055 {
1056     struct solo_enc_dev *solo_enc =
1057         container_of(ctrl->handler, struct solo_enc_dev, hdl);
1058     struct solo_dev *solo_dev = solo_enc->solo_dev;
1059     int err;
1060 
1061     switch (ctrl->id) {
1062     case V4L2_CID_BRIGHTNESS:
1063     case V4L2_CID_CONTRAST:
1064     case V4L2_CID_SATURATION:
1065     case V4L2_CID_HUE:
1066     case V4L2_CID_SHARPNESS:
1067         return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
1068                      ctrl->val);
1069     case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1070         solo_enc->gop = ctrl->val;
1071         solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
1072         solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
1073         return 0;
1074     case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
1075         solo_enc->qp = ctrl->val;
1076         solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
1077         solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
1078         return 0;
1079     case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
1080         solo_enc->motion_thresh = ctrl->val << 8;
1081         if (!solo_enc->motion_global || !solo_enc->motion_enabled)
1082             return 0;
1083         return solo_set_motion_threshold(solo_dev, solo_enc->ch,
1084                 solo_enc->motion_thresh);
1085     case V4L2_CID_DETECT_MD_MODE:
1086         solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
1087         solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
1088         if (ctrl->val) {
1089             if (solo_enc->motion_global)
1090                 err = solo_set_motion_threshold(solo_dev, solo_enc->ch,
1091                     solo_enc->motion_thresh);
1092             else
1093                 err = solo_set_motion_block(solo_dev, solo_enc->ch,
1094                     solo_enc->md_thresholds->p_cur.p_u16);
1095             if (err)
1096                 return err;
1097         }
1098         solo_motion_toggle(solo_enc, ctrl->val);
1099         return 0;
1100     case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
1101         if (solo_enc->motion_enabled && !solo_enc->motion_global)
1102             return solo_set_motion_block(solo_dev, solo_enc->ch,
1103                     solo_enc->md_thresholds->p_new.p_u16);
1104         break;
1105     case V4L2_CID_OSD_TEXT:
1106         strscpy(solo_enc->osd_text, ctrl->p_new.p_char,
1107             sizeof(solo_enc->osd_text));
1108         return solo_osd_print(solo_enc);
1109     default:
1110         return -EINVAL;
1111     }
1112 
1113     return 0;
1114 }
1115 
1116 static int solo_subscribe_event(struct v4l2_fh *fh,
1117                 const struct v4l2_event_subscription *sub)
1118 {
1119 
1120     switch (sub->type) {
1121     case V4L2_EVENT_MOTION_DET:
1122         /* Allow for up to 30 events (1 second for NTSC) to be
1123          * stored. */
1124         return v4l2_event_subscribe(fh, sub, 30, NULL);
1125     default:
1126         return v4l2_ctrl_subscribe_event(fh, sub);
1127     }
1128 }
1129 
1130 static const struct v4l2_file_operations solo_enc_fops = {
1131     .owner          = THIS_MODULE,
1132     .open           = v4l2_fh_open,
1133     .release        = vb2_fop_release,
1134     .read           = vb2_fop_read,
1135     .poll           = vb2_fop_poll,
1136     .mmap           = vb2_fop_mmap,
1137     .unlocked_ioctl     = video_ioctl2,
1138 };
1139 
1140 static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
1141     .vidioc_querycap        = solo_enc_querycap,
1142     .vidioc_s_std           = solo_enc_s_std,
1143     .vidioc_g_std           = solo_enc_g_std,
1144     /* Input callbacks */
1145     .vidioc_enum_input      = solo_enc_enum_input,
1146     .vidioc_s_input         = solo_enc_set_input,
1147     .vidioc_g_input         = solo_enc_get_input,
1148     /* Video capture format callbacks */
1149     .vidioc_enum_fmt_vid_cap    = solo_enc_enum_fmt_cap,
1150     .vidioc_try_fmt_vid_cap     = solo_enc_try_fmt_cap,
1151     .vidioc_s_fmt_vid_cap       = solo_enc_set_fmt_cap,
1152     .vidioc_g_fmt_vid_cap       = solo_enc_get_fmt_cap,
1153     /* Streaming I/O */
1154     .vidioc_reqbufs         = vb2_ioctl_reqbufs,
1155     .vidioc_querybuf        = vb2_ioctl_querybuf,
1156     .vidioc_qbuf            = vb2_ioctl_qbuf,
1157     .vidioc_dqbuf           = vb2_ioctl_dqbuf,
1158     .vidioc_streamon        = vb2_ioctl_streamon,
1159     .vidioc_streamoff       = vb2_ioctl_streamoff,
1160     /* Frame size and interval */
1161     .vidioc_enum_framesizes     = solo_enum_framesizes,
1162     .vidioc_enum_frameintervals = solo_enum_frameintervals,
1163     /* Video capture parameters */
1164     .vidioc_s_parm          = solo_s_parm,
1165     .vidioc_g_parm          = solo_g_parm,
1166     /* Logging and events */
1167     .vidioc_log_status      = v4l2_ctrl_log_status,
1168     .vidioc_subscribe_event     = solo_subscribe_event,
1169     .vidioc_unsubscribe_event   = v4l2_event_unsubscribe,
1170 };
1171 
1172 static const struct video_device solo_enc_template = {
1173     .name           = SOLO6X10_NAME,
1174     .fops           = &solo_enc_fops,
1175     .ioctl_ops      = &solo_enc_ioctl_ops,
1176     .minor          = -1,
1177     .release        = video_device_release,
1178     .tvnorms        = V4L2_STD_NTSC_M | V4L2_STD_PAL,
1179     .device_caps        = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
1180                   V4L2_CAP_STREAMING,
1181 };
1182 
1183 static const struct v4l2_ctrl_ops solo_ctrl_ops = {
1184     .s_ctrl = solo_s_ctrl,
1185 };
1186 
1187 static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
1188     .ops = &solo_ctrl_ops,
1189     .id = V4L2_CID_OSD_TEXT,
1190     .name = "OSD Text",
1191     .type = V4L2_CTRL_TYPE_STRING,
1192     .max = OSD_TEXT_MAX,
1193     .step = 1,
1194 };
1195 
1196 /* Motion Detection Threshold matrix */
1197 static const struct v4l2_ctrl_config solo_md_thresholds = {
1198     .ops = &solo_ctrl_ops,
1199     .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
1200     .dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
1201     .def = SOLO_DEF_MOT_THRESH,
1202     .max = 65535,
1203     .step = 1,
1204 };
1205 
1206 static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
1207                        u8 ch, unsigned nr)
1208 {
1209     struct solo_enc_dev *solo_enc;
1210     struct v4l2_ctrl_handler *hdl;
1211     int ret;
1212 
1213     solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
1214     if (!solo_enc)
1215         return ERR_PTR(-ENOMEM);
1216 
1217     hdl = &solo_enc->hdl;
1218     v4l2_ctrl_handler_init(hdl, 10);
1219     v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1220             V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1221     v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1222             V4L2_CID_CONTRAST, 0, 255, 1, 128);
1223     v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1224             V4L2_CID_SATURATION, 0, 255, 1, 128);
1225     v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1226             V4L2_CID_HUE, 0, 255, 1, 128);
1227     if (tw28_has_sharpness(solo_dev, ch))
1228         v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1229             V4L2_CID_SHARPNESS, 0, 15, 1, 0);
1230     v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1231             V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
1232     v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1233             V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
1234     v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
1235             V4L2_CID_DETECT_MD_MODE,
1236             V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
1237             V4L2_DETECT_MD_MODE_DISABLED);
1238     v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
1239             V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
1240             SOLO_DEF_MOT_THRESH >> 8);
1241     v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
1242     solo_enc->md_thresholds =
1243         v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
1244     if (hdl->error) {
1245         ret = hdl->error;
1246         goto hdl_free;
1247     }
1248 
1249     solo_enc->solo_dev = solo_dev;
1250     solo_enc->ch = ch;
1251     mutex_init(&solo_enc->lock);
1252     spin_lock_init(&solo_enc->av_lock);
1253     INIT_LIST_HEAD(&solo_enc->vidq_active);
1254     solo_enc->fmt = (solo_dev->type == SOLO_DEV_6010) ?
1255         V4L2_PIX_FMT_MPEG4 : V4L2_PIX_FMT_H264;
1256     solo_enc->type = SOLO_ENC_TYPE_STD;
1257 
1258     solo_enc->qp = SOLO_DEFAULT_QP;
1259     solo_enc->gop = solo_dev->fps;
1260     solo_enc->interval = 1;
1261     solo_enc->mode = SOLO_ENC_MODE_CIF;
1262     solo_enc->motion_global = true;
1263     solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
1264     solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1265     solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1266     solo_enc->vidq.ops = &solo_enc_video_qops;
1267     solo_enc->vidq.mem_ops = &vb2_dma_sg_memops;
1268     solo_enc->vidq.drv_priv = solo_enc;
1269     solo_enc->vidq.gfp_flags = __GFP_DMA32 | __GFP_KSWAPD_RECLAIM;
1270     solo_enc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1271     solo_enc->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
1272     solo_enc->vidq.lock = &solo_enc->lock;
1273     solo_enc->vidq.dev = &solo_dev->pdev->dev;
1274     ret = vb2_queue_init(&solo_enc->vidq);
1275     if (ret)
1276         goto hdl_free;
1277     solo_update_mode(solo_enc);
1278 
1279     spin_lock_init(&solo_enc->motion_lock);
1280 
1281     /* Initialize this per encoder */
1282     solo_enc->jpeg_len = sizeof(jpeg_header);
1283     memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
1284 
1285     solo_enc->desc_nelts = 32;
1286     solo_enc->desc_items = dma_alloc_coherent(&solo_dev->pdev->dev,
1287                           sizeof(struct solo_p2m_desc) *
1288                           solo_enc->desc_nelts,
1289                           &solo_enc->desc_dma,
1290                           GFP_KERNEL);
1291     ret = -ENOMEM;
1292     if (solo_enc->desc_items == NULL)
1293         goto hdl_free;
1294 
1295     solo_enc->vfd = video_device_alloc();
1296     if (!solo_enc->vfd)
1297         goto pci_free;
1298 
1299     *solo_enc->vfd = solo_enc_template;
1300     solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
1301     solo_enc->vfd->ctrl_handler = hdl;
1302     solo_enc->vfd->queue = &solo_enc->vidq;
1303     solo_enc->vfd->lock = &solo_enc->lock;
1304     video_set_drvdata(solo_enc->vfd, solo_enc);
1305     ret = video_register_device(solo_enc->vfd, VFL_TYPE_VIDEO, nr);
1306     if (ret < 0)
1307         goto vdev_release;
1308 
1309     snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
1310          "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
1311          solo_enc->vfd->num);
1312 
1313     return solo_enc;
1314 
1315 vdev_release:
1316     video_device_release(solo_enc->vfd);
1317 pci_free:
1318     dma_free_coherent(&solo_enc->solo_dev->pdev->dev,
1319               sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
1320               solo_enc->desc_items, solo_enc->desc_dma);
1321 hdl_free:
1322     v4l2_ctrl_handler_free(hdl);
1323     kfree(solo_enc);
1324     return ERR_PTR(ret);
1325 }
1326 
1327 static void solo_enc_free(struct solo_enc_dev *solo_enc)
1328 {
1329     if (solo_enc == NULL)
1330         return;
1331 
1332     dma_free_coherent(&solo_enc->solo_dev->pdev->dev,
1333               sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
1334               solo_enc->desc_items, solo_enc->desc_dma);
1335     video_unregister_device(solo_enc->vfd);
1336     v4l2_ctrl_handler_free(&solo_enc->hdl);
1337     kfree(solo_enc);
1338 }
1339 
1340 int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
1341 {
1342     int i;
1343 
1344     init_waitqueue_head(&solo_dev->ring_thread_wait);
1345 
1346     solo_dev->vh_size = sizeof(vop_header);
1347     solo_dev->vh_buf = dma_alloc_coherent(&solo_dev->pdev->dev,
1348                           solo_dev->vh_size,
1349                           &solo_dev->vh_dma, GFP_KERNEL);
1350     if (solo_dev->vh_buf == NULL)
1351         return -ENOMEM;
1352 
1353     for (i = 0; i < solo_dev->nr_chans; i++) {
1354         solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
1355         if (IS_ERR(solo_dev->v4l2_enc[i]))
1356             break;
1357     }
1358 
1359     if (i != solo_dev->nr_chans) {
1360         int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
1361 
1362         while (i--)
1363             solo_enc_free(solo_dev->v4l2_enc[i]);
1364         dma_free_coherent(&solo_dev->pdev->dev, solo_dev->vh_size,
1365                   solo_dev->vh_buf, solo_dev->vh_dma);
1366         solo_dev->vh_buf = NULL;
1367         return ret;
1368     }
1369 
1370     if (solo_dev->type == SOLO_DEV_6010)
1371         solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
1372     else
1373         solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
1374 
1375     dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
1376          solo_dev->v4l2_enc[0]->vfd->num,
1377          solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
1378 
1379     return solo_ring_start(solo_dev);
1380 }
1381 
1382 void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
1383 {
1384     int i;
1385 
1386     solo_ring_stop(solo_dev);
1387 
1388     for (i = 0; i < solo_dev->nr_chans; i++)
1389         solo_enc_free(solo_dev->v4l2_enc[i]);
1390 
1391     if (solo_dev->vh_buf)
1392         dma_free_coherent(&solo_dev->pdev->dev, solo_dev->vh_size,
1393                   solo_dev->vh_buf, solo_dev->vh_dma);
1394 }