0001
0002
0003
0004
0005
0006
0007
0008
0009
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
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
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
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
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
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
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
0239 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
0240
0241
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
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
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
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
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
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
0307
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
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
0345 solo_p2m_fill_desc(desc, 0, dma, base + off,
0346 len, 0, 0);
0347 } else {
0348
0349
0350
0351
0352
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
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
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
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
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:
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
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
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
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
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:
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
0857 pix->width = solo_dev->video_hsize >> 1;
0858 pix->height = solo_dev->video_vsize;
0859 } else {
0860
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
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
0904 solo_enc->fmt = pix->pixelformat;
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
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
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
1123
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
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
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
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
1161 .vidioc_enum_framesizes = solo_enum_framesizes,
1162 .vidioc_enum_frameintervals = solo_enum_frameintervals,
1163
1164 .vidioc_s_parm = solo_s_parm,
1165 .vidioc_g_parm = solo_g_parm,
1166
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
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
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 }