linux/drivers/staging/media/solo6x10/v4l2-enc.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
   3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18 */
  19
  20#include <linux/kernel.h>
  21#include <linux/module.h>
  22#include <linux/kthread.h>
  23#include <linux/freezer.h>
  24#include <media/v4l2-ioctl.h>
  25#include <media/v4l2-common.h>
  26#include <media/videobuf-dma-sg.h>
  27#include "solo6x10.h"
  28#include "tw28.h"
  29#include "solo6x10-jpeg.h"
  30
  31#define MIN_VID_BUFFERS         4
  32#define FRAME_BUF_SIZE          (128 * 1024)
  33#define MP4_QS                  16
  34
  35static int solo_enc_thread(void *data);
  36
  37extern unsigned video_nr;
  38
  39struct solo_enc_fh {
  40        struct                  solo_enc_dev *enc;
  41        u32                     fmt;
  42        u16                     rd_idx;
  43        u8                      enc_on;
  44        enum solo_enc_types     type;
  45        struct videobuf_queue   vidq;
  46        struct list_head        vidq_active;
  47        struct task_struct      *kthread;
  48        struct p2m_desc         desc[SOLO_NR_P2M_DESC];
  49};
  50
  51static const u32 solo_user_ctrls[] = {
  52        V4L2_CID_BRIGHTNESS,
  53        V4L2_CID_CONTRAST,
  54        V4L2_CID_SATURATION,
  55        V4L2_CID_HUE,
  56        V4L2_CID_SHARPNESS,
  57        0
  58};
  59
  60static const u32 solo_mpeg_ctrls[] = {
  61        V4L2_CID_MPEG_VIDEO_ENCODING,
  62        V4L2_CID_MPEG_VIDEO_GOP_SIZE,
  63        0
  64};
  65
  66static const u32 solo_private_ctrls[] = {
  67        V4L2_CID_MOTION_ENABLE,
  68        V4L2_CID_MOTION_THRESHOLD,
  69        0
  70};
  71
  72static const u32 solo_fmtx_ctrls[] = {
  73        V4L2_CID_RDS_TX_RADIO_TEXT,
  74        0
  75};
  76
  77static const u32 *solo_ctrl_classes[] = {
  78        solo_user_ctrls,
  79        solo_mpeg_ctrls,
  80        solo_fmtx_ctrls,
  81        solo_private_ctrls,
  82        NULL
  83};
  84
  85static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
  86{
  87        struct solo_dev *solo_dev = solo_enc->solo_dev;
  88        u8 ch = solo_enc->ch;
  89
  90        if (solo_dev->motion_mask & (1 << ch))
  91                return 1;
  92        return 0;
  93}
  94
  95static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
  96{
  97        struct solo_dev *solo_dev = solo_enc->solo_dev;
  98        u8 ch = solo_enc->ch;
  99
 100        spin_lock(&solo_enc->lock);
 101
 102        if (on)
 103                solo_dev->motion_mask |= (1 << ch);
 104        else
 105                solo_dev->motion_mask &= ~(1 << ch);
 106
 107        /* Do this regardless of if we are turning on or off */
 108        solo_reg_write(solo_enc->solo_dev, SOLO_VI_MOT_CLEAR,
 109                       1 << solo_enc->ch);
 110        solo_enc->motion_detected = 0;
 111
 112        solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
 113                       SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
 114                       (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
 115
 116        if (solo_dev->motion_mask)
 117                solo_irq_on(solo_dev, SOLO_IRQ_MOTION);
 118        else
 119                solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
 120
 121        spin_unlock(&solo_enc->lock);
 122}
 123
 124/* Should be called with solo_enc->lock held */
 125static void solo_update_mode(struct solo_enc_dev *solo_enc)
 126{
 127        struct solo_dev *solo_dev = solo_enc->solo_dev;
 128
 129        assert_spin_locked(&solo_enc->lock);
 130
 131        solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
 132        solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
 133
 134        switch (solo_enc->mode) {
 135        case SOLO_ENC_MODE_CIF:
 136                solo_enc->width = solo_dev->video_hsize >> 1;
 137                solo_enc->height = solo_dev->video_vsize;
 138                break;
 139        case SOLO_ENC_MODE_D1:
 140                solo_enc->width = solo_dev->video_hsize;
 141                solo_enc->height = solo_dev->video_vsize << 1;
 142                solo_enc->bw_weight <<= 2;
 143                break;
 144        default:
 145                WARN(1, "mode is unknown\n");
 146        }
 147}
 148
 149/* Should be called with solo_enc->lock held */
 150static int solo_enc_on(struct solo_enc_fh *fh)
 151{
 152        struct solo_enc_dev *solo_enc = fh->enc;
 153        u8 ch = solo_enc->ch;
 154        struct solo_dev *solo_dev = solo_enc->solo_dev;
 155        u8 interval;
 156
 157        assert_spin_locked(&solo_enc->lock);
 158
 159        if (fh->enc_on)
 160                return 0;
 161
 162        solo_update_mode(solo_enc);
 163
 164        /* Make sure to bw check on first reader */
 165        if (!atomic_read(&solo_enc->readers)) {
 166                if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
 167                        return -EBUSY;
 168                else
 169                        solo_dev->enc_bw_remain -= solo_enc->bw_weight;
 170        }
 171
 172        fh->enc_on = 1;
 173        fh->rd_idx = solo_enc->solo_dev->enc_wr_idx;
 174
 175        if (fh->type == SOLO_ENC_TYPE_EXT)
 176                solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
 177
 178        if (atomic_inc_return(&solo_enc->readers) > 1)
 179                return 0;
 180
 181        /* Disable all encoding for this channel */
 182        solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
 183
 184        /* Common for both std and ext encoding */
 185        solo_reg_write(solo_dev, SOLO_VE_CH_INTL(ch),
 186                       solo_enc->interlaced ? 1 : 0);
 187
 188        if (solo_enc->interlaced)
 189                interval = solo_enc->interval - 1;
 190        else
 191                interval = solo_enc->interval;
 192
 193        /* Standard encoding only */
 194        solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), solo_enc->gop);
 195        solo_reg_write(solo_dev, SOLO_VE_CH_QP(ch), solo_enc->qp);
 196        solo_reg_write(solo_dev, SOLO_CAP_CH_INTV(ch), interval);
 197
 198        /* Extended encoding only */
 199        solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(ch), solo_enc->gop);
 200        solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(ch), solo_enc->qp);
 201        solo_reg_write(solo_dev, SOLO_CAP_CH_INTV_E(ch), interval);
 202
 203        /* Enables the standard encoder */
 204        solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
 205
 206        /* Settle down Beavis... */
 207        mdelay(10);
 208
 209        return 0;
 210}
 211
 212static void solo_enc_off(struct solo_enc_fh *fh)
 213{
 214        struct solo_enc_dev *solo_enc = fh->enc;
 215        struct solo_dev *solo_dev = solo_enc->solo_dev;
 216
 217        if (!fh->enc_on)
 218                return;
 219
 220        if (fh->kthread) {
 221                kthread_stop(fh->kthread);
 222                fh->kthread = NULL;
 223        }
 224
 225        solo_dev->enc_bw_remain += solo_enc->bw_weight;
 226        fh->enc_on = 0;
 227
 228        if (atomic_dec_return(&solo_enc->readers) > 0)
 229                return;
 230
 231        solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
 232        solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
 233}
 234
 235static int solo_start_fh_thread(struct solo_enc_fh *fh)
 236{
 237        struct solo_enc_dev *solo_enc = fh->enc;
 238
 239        fh->kthread = kthread_run(solo_enc_thread, fh, SOLO6X10_NAME "_enc");
 240
 241        /* Oops, we had a problem */
 242        if (IS_ERR(fh->kthread)) {
 243                spin_lock(&solo_enc->lock);
 244                solo_enc_off(fh);
 245                spin_unlock(&solo_enc->lock);
 246
 247                return PTR_ERR(fh->kthread);
 248        }
 249
 250        return 0;
 251}
 252
 253static void enc_reset_gop(struct solo_dev *solo_dev, u8 ch)
 254{
 255        BUG_ON(ch >= solo_dev->nr_chans);
 256        solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), 1);
 257        solo_dev->v4l2_enc[ch]->reset_gop = 1;
 258}
 259
 260static int enc_gop_reset(struct solo_dev *solo_dev, u8 ch, u8 vop)
 261{
 262        BUG_ON(ch >= solo_dev->nr_chans);
 263        if (!solo_dev->v4l2_enc[ch]->reset_gop)
 264                return 0;
 265        if (vop)
 266                return 1;
 267        solo_dev->v4l2_enc[ch]->reset_gop = 0;
 268        solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch),
 269                       solo_dev->v4l2_enc[ch]->gop);
 270        return 0;
 271}
 272
 273static void enc_write_sg(struct scatterlist *sglist, void *buf, int size)
 274{
 275        struct scatterlist *sg;
 276        u8 *src = buf;
 277
 278        for (sg = sglist; sg && size > 0; sg = sg_next(sg)) {
 279                u8 *p = sg_virt(sg);
 280                size_t len = sg_dma_len(sg);
 281                int i;
 282
 283                for (i = 0; i < len && size; i++)
 284                        p[i] = *(src++);
 285        }
 286}
 287
 288static int enc_get_mpeg_dma_sg(struct solo_dev *solo_dev,
 289                               struct p2m_desc *desc,
 290                               struct scatterlist *sglist, int skip,
 291                               unsigned int off, unsigned int size)
 292{
 293        int ret;
 294
 295        if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
 296                return -EINVAL;
 297
 298        if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
 299                return solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E,
 300                                       desc, 0, sglist, skip,
 301                                       SOLO_MP4E_EXT_ADDR(solo_dev) + off, size);
 302        }
 303
 304        /* Buffer wrap */
 305        ret = solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E, desc, 0,
 306                              sglist, skip, SOLO_MP4E_EXT_ADDR(solo_dev) + off,
 307                              SOLO_MP4E_EXT_SIZE(solo_dev) - off);
 308
 309        ret |= solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E, desc, 0,
 310                               sglist, skip + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
 311                               SOLO_MP4E_EXT_ADDR(solo_dev),
 312                               size + off - SOLO_MP4E_EXT_SIZE(solo_dev));
 313
 314        return ret;
 315}
 316
 317static int enc_get_mpeg_dma_t(struct solo_dev *solo_dev,
 318                              dma_addr_t buf, unsigned int off,
 319                              unsigned int size)
 320{
 321        int ret;
 322
 323        if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
 324                return -EINVAL;
 325
 326        if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
 327                return solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf,
 328                                      SOLO_MP4E_EXT_ADDR(solo_dev) + off, size);
 329        }
 330
 331        /* Buffer wrap */
 332        ret = solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf,
 333                             SOLO_MP4E_EXT_ADDR(solo_dev) + off,
 334                             SOLO_MP4E_EXT_SIZE(solo_dev) - off);
 335
 336        ret |= solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0,
 337                              buf + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
 338                              SOLO_MP4E_EXT_ADDR(solo_dev),
 339                              size + off - SOLO_MP4E_EXT_SIZE(solo_dev));
 340
 341        return ret;
 342}
 343
 344static int enc_get_mpeg_dma(struct solo_dev *solo_dev, void *buf,
 345                            unsigned int off, unsigned int size)
 346{
 347        int ret;
 348
 349        dma_addr_t dma_addr = pci_map_single(solo_dev->pdev, buf, size,
 350                                             PCI_DMA_FROMDEVICE);
 351        ret = enc_get_mpeg_dma_t(solo_dev, dma_addr, off, size);
 352        pci_unmap_single(solo_dev->pdev, dma_addr, size, PCI_DMA_FROMDEVICE);
 353
 354        return ret;
 355}
 356
 357static int enc_get_jpeg_dma_sg(struct solo_dev *solo_dev,
 358                               struct p2m_desc *desc,
 359                               struct scatterlist *sglist, int skip,
 360                               unsigned int off, unsigned int size)
 361{
 362        int ret;
 363
 364        if (off > SOLO_JPEG_EXT_SIZE(solo_dev))
 365                return -EINVAL;
 366
 367        if (off + size <= SOLO_JPEG_EXT_SIZE(solo_dev)) {
 368                return solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG,
 369                                       desc, 0, sglist, skip,
 370                                       SOLO_JPEG_EXT_ADDR(solo_dev) + off, size);
 371        }
 372
 373        /* Buffer wrap */
 374        ret = solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG, desc, 0,
 375                              sglist, skip, SOLO_JPEG_EXT_ADDR(solo_dev) + off,
 376                              SOLO_JPEG_EXT_SIZE(solo_dev) - off);
 377
 378        ret |= solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG, desc, 0,
 379                               sglist, skip + SOLO_JPEG_EXT_SIZE(solo_dev) - off,
 380                               SOLO_JPEG_EXT_ADDR(solo_dev),
 381                               size + off - SOLO_JPEG_EXT_SIZE(solo_dev));
 382
 383        return ret;
 384}
 385
 386/* Returns true of __chk is within the first __range bytes of __off */
 387#define OFF_IN_RANGE(__off, __range, __chk) \
 388        ((__off <= __chk) && ((__off + __range) >= __chk))
 389
 390static void solo_jpeg_header(struct solo_enc_dev *solo_enc,
 391                             struct videobuf_dmabuf *vbuf)
 392{
 393        struct scatterlist *sg;
 394        void *src = jpeg_header;
 395        size_t copied = 0;
 396        size_t to_copy = sizeof(jpeg_header);
 397
 398        for (sg = vbuf->sglist; sg && copied < to_copy; sg = sg_next(sg)) {
 399                size_t this_copy = min(sg_dma_len(sg),
 400                                       (unsigned int)(to_copy - copied));
 401                u8 *p = sg_virt(sg);
 402
 403                memcpy(p, src + copied, this_copy);
 404
 405                if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 5))
 406                        p[(SOF0_START + 5) - copied] =
 407                                0xff & (solo_enc->height >> 8);
 408                if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 6))
 409                        p[(SOF0_START + 6) - copied] = 0xff & solo_enc->height;
 410                if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 7))
 411                        p[(SOF0_START + 7) - copied] =
 412                                0xff & (solo_enc->width >> 8);
 413                if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 8))
 414                        p[(SOF0_START + 8) - copied] = 0xff & solo_enc->width;
 415
 416                copied += this_copy;
 417        }
 418}
 419
 420static int solo_fill_jpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
 421                          struct videobuf_buffer *vb,
 422                          struct videobuf_dmabuf *vbuf)
 423{
 424        struct solo_dev *solo_dev = fh->enc->solo_dev;
 425        int size = enc_buf->jpeg_size;
 426
 427        /* Copy the header first (direct write) */
 428        solo_jpeg_header(fh->enc, vbuf);
 429
 430        vb->size = size + sizeof(jpeg_header);
 431
 432        /* Grab the jpeg frame */
 433        return enc_get_jpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist,
 434                                   sizeof(jpeg_header),
 435                                   enc_buf->jpeg_off, size);
 436}
 437
 438static inline int vop_interlaced(__le32 *vh)
 439{
 440        return (__le32_to_cpu(vh[0]) >> 30) & 1;
 441}
 442
 443static inline u32 vop_size(__le32 *vh)
 444{
 445        return __le32_to_cpu(vh[0]) & 0xFFFFF;
 446}
 447
 448static inline u8 vop_hsize(__le32 *vh)
 449{
 450        return (__le32_to_cpu(vh[1]) >> 8) & 0xFF;
 451}
 452
 453static inline u8 vop_vsize(__le32 *vh)
 454{
 455        return __le32_to_cpu(vh[1]) & 0xFF;
 456}
 457
 458/* must be called with *bits % 8 = 0 */
 459static void write_bytes(u8 **out, unsigned *bits, const u8 *src, unsigned count)
 460{
 461        memcpy(*out, src, count);
 462        *out += count;
 463        *bits += count * 8;
 464}
 465
 466static void write_bits(u8 **out, unsigned *bits, u32 value, unsigned count)
 467{
 468
 469        value <<= 32 - count; // shift to the right
 470
 471        while (count--) {
 472                **out <<= 1;
 473                **out |= !!(value & (1 << 31)); /* MSB */
 474                value <<= 1;
 475                if (++(*bits) % 8 == 0)
 476                        (*out)++;
 477        }
 478}
 479
 480static void write_ue(u8 **out, unsigned *bits, unsigned value) /* H.264 only */
 481{
 482        uint32_t max = 0, cnt = 0;
 483
 484        while (value > max) {
 485                max = (max + 2) * 2 - 2;
 486                cnt++;
 487        }
 488        write_bits(out, bits, 1, cnt + 1);
 489        write_bits(out, bits, ~(max - value), cnt);
 490}
 491
 492static void write_se(u8 **out, unsigned *bits, int value) /* H.264 only */
 493{
 494        if (value <= 0)
 495                write_ue(out, bits, -value * 2);
 496        else
 497                write_ue(out, bits, value * 2 - 1);
 498}
 499
 500static void write_mpeg4_end(u8 **out, unsigned *bits)
 501{
 502        write_bits(out, bits, 0, 1);
 503        /* align on 32-bit boundary */
 504        if (*bits % 32)
 505                write_bits(out, bits, 0xFFFFFFFF, 32 - *bits % 32);
 506}
 507
 508static void write_h264_end(u8 **out, unsigned *bits, int align)
 509{
 510        write_bits(out, bits, 1, 1);
 511        while ((*bits) % 8)
 512                write_bits(out, bits, 0, 1);
 513        if (align)
 514                while ((*bits) % 32)
 515                        write_bits(out, bits, 0, 1);
 516}
 517
 518static void mpeg4_write_vol(u8 **out, struct solo_dev *solo_dev,
 519                            __le32 *vh, unsigned fps, unsigned interval)
 520{
 521        static const u8 hdr[] = {
 522                0, 0, 1, 0x00 /* video_object_start_code */,
 523                0, 0, 1, 0x20 /* video_object_layer_start_code */
 524        };
 525        unsigned bits = 0;
 526        unsigned width = vop_hsize(vh) << 4;
 527        unsigned height = vop_vsize(vh) << 4;
 528        unsigned interlaced = vop_interlaced(vh);
 529
 530        write_bytes(out, &bits, hdr, sizeof(hdr));
 531        write_bits(out, &bits,    0,  1); /* random_accessible_vol */
 532        write_bits(out, &bits, 0x04,  8); /* video_object_type_indication: main */
 533        write_bits(out, &bits,    1,  1); /* is_object_layer_identifier */
 534        write_bits(out, &bits,    2,  4); /* video_object_layer_verid: table V2-39 */
 535        write_bits(out, &bits,    0,  3); /* video_object_layer_priority */
 536        if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
 537                write_bits(out, &bits,  3,  4); /* aspect_ratio_info, assuming 4:3 */
 538        else
 539                write_bits(out, &bits,  2,  4);
 540        write_bits(out, &bits,    1,  1); /* vol_control_parameters */
 541        write_bits(out, &bits,    1,  2); /* chroma_format: 4:2:0 */
 542        write_bits(out, &bits,    1,  1); /* low_delay */
 543        write_bits(out, &bits,    0,  1); /* vbv_parameters */
 544        write_bits(out, &bits,    0,  2); /* video_object_layer_shape: rectangular */
 545        write_bits(out, &bits,    1,  1); /* marker_bit */
 546        write_bits(out, &bits,  fps, 16); /* vop_time_increment_resolution */
 547        write_bits(out, &bits,    1,  1); /* marker_bit */
 548        write_bits(out, &bits,    1,  1); /* fixed_vop_rate */
 549        write_bits(out, &bits, interval, 15); /* fixed_vop_time_increment */
 550        write_bits(out, &bits,    1,  1); /* marker_bit */
 551        write_bits(out, &bits, width, 13); /* video_object_layer_width */
 552        write_bits(out, &bits,    1,  1); /* marker_bit */
 553        write_bits(out, &bits, height, 13); /* video_object_layer_height */
 554        write_bits(out, &bits,    1,  1); /* marker_bit */
 555        write_bits(out, &bits, interlaced, 1); /* interlaced */
 556        write_bits(out, &bits,    1,  1); /* obmc_disable */
 557        write_bits(out, &bits,    0,  2); /* sprite_enable */
 558        write_bits(out, &bits,    0,  1); /* not_8_bit */
 559        write_bits(out, &bits,    1,  0); /* quant_type */
 560        write_bits(out, &bits,    0,  1); /* load_intra_quant_mat */
 561        write_bits(out, &bits,    0,  1); /* load_nonintra_quant_mat */
 562        write_bits(out, &bits,    0,  1); /* quarter_sample */
 563        write_bits(out, &bits,    1,  1); /* complexity_estimation_disable */
 564        write_bits(out, &bits,    1,  1); /* resync_marker_disable */
 565        write_bits(out, &bits,    0,  1); /* data_partitioned */
 566        write_bits(out, &bits,    0,  1); /* newpred_enable */
 567        write_bits(out, &bits,    0,  1); /* reduced_resolution_vop_enable */
 568        write_bits(out, &bits,    0,  1); /* scalability */
 569        write_mpeg4_end(out, &bits);
 570}
 571
 572static void h264_write_vol(u8 **out, struct solo_dev *solo_dev, __le32 *vh)
 573{
 574        static const u8 sps[] = {
 575                0, 0, 0, 1 /* start code */, 0x67, 66 /* profile_idc */,
 576                0 /* constraints */, 30 /* level_idc */
 577        };
 578        static const u8 pps[] = {
 579                0, 0, 0, 1 /* start code */, 0x68
 580        };
 581
 582        unsigned bits = 0;
 583        unsigned mbs_w = vop_hsize(vh);
 584        unsigned mbs_h = vop_vsize(vh);
 585
 586        write_bytes(out, &bits, sps, sizeof(sps));
 587        write_ue(out, &bits,   0);      /* seq_parameter_set_id */
 588        write_ue(out, &bits,   5);      /* log2_max_frame_num_minus4 */
 589        write_ue(out, &bits,   0);      /* pic_order_cnt_type */
 590        write_ue(out, &bits,   6);      /* log2_max_pic_order_cnt_lsb_minus4 */
 591        write_ue(out, &bits,   1);      /* max_num_ref_frames */
 592        write_bits(out, &bits, 0, 1);   /* gaps_in_frame_num_value_allowed_flag */
 593        write_ue(out, &bits, mbs_w - 1);        /* pic_width_in_mbs_minus1 */
 594        write_ue(out, &bits, mbs_h - 1);        /* pic_height_in_map_units_minus1 */
 595        write_bits(out, &bits, 1, 1);   /* frame_mbs_only_flag */
 596        write_bits(out, &bits, 1, 1);   /* direct_8x8_frame_field_flag */
 597        write_bits(out, &bits, 0, 1);   /* frame_cropping_flag */
 598        write_bits(out, &bits, 0, 1);   /* vui_parameters_present_flag */
 599        write_h264_end(out, &bits, 0);
 600
 601        write_bytes(out, &bits, pps, sizeof(pps));
 602        write_ue(out, &bits,   0);      /* pic_parameter_set_id */
 603        write_ue(out, &bits,   0);      /* seq_parameter_set_id */
 604        write_bits(out, &bits, 0, 1);   /* entropy_coding_mode_flag */
 605        write_bits(out, &bits, 0, 1);   /* bottom_field_pic_order_in_frame_present_flag */
 606        write_ue(out, &bits,   0);      /* num_slice_groups_minus1 */
 607        write_ue(out, &bits,   0);      /* num_ref_idx_l0_default_active_minus1 */
 608        write_ue(out, &bits,   0);      /* num_ref_idx_l1_default_active_minus1 */
 609        write_bits(out, &bits, 0, 1);   /* weighted_pred_flag */
 610        write_bits(out, &bits, 0, 2);   /* weighted_bipred_idc */
 611        write_se(out, &bits,   0);      /* pic_init_qp_minus26 */
 612        write_se(out, &bits,   0);      /* pic_init_qs_minus26 */
 613        write_se(out, &bits,   2);      /* chroma_qp_index_offset */
 614        write_bits(out, &bits, 0, 1);   /* deblocking_filter_control_present_flag */
 615        write_bits(out, &bits, 1, 1);   /* constrained_intra_pred_flag */
 616        write_bits(out, &bits, 0, 1);   /* redundant_pic_cnt_present_flag */
 617        write_h264_end(out, &bits, 1);
 618}
 619
 620static int solo_fill_mpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
 621                          struct videobuf_buffer *vb,
 622                          struct videobuf_dmabuf *vbuf)
 623{
 624        struct solo_enc_dev *solo_enc = fh->enc;
 625        struct solo_dev *solo_dev = solo_enc->solo_dev;
 626
 627#define VH_WORDS 16
 628#define MAX_VOL_HEADER_LENGTH 64
 629
 630        __le32 vh[VH_WORDS];
 631        int ret;
 632        int frame_size, frame_off;
 633        int skip = 0;
 634
 635        if (WARN_ON_ONCE(enc_buf->size <= sizeof(vh)))
 636                return -EINVAL;
 637
 638        /* First get the hardware vop header (not real mpeg) */
 639        ret = enc_get_mpeg_dma(solo_dev, vh, enc_buf->off, sizeof(vh));
 640        if (WARN_ON_ONCE(ret))
 641                return ret;
 642
 643        if (WARN_ON_ONCE(vop_size(vh) > enc_buf->size))
 644                return -EINVAL;
 645
 646        vb->width = vop_hsize(vh) << 4;
 647        vb->height = vop_vsize(vh) << 4;
 648        vb->size = vop_size(vh);
 649
 650        /* If this is a key frame, add extra m4v header */
 651        if (!enc_buf->vop) {
 652                u8 header[MAX_VOL_HEADER_LENGTH], *out = header;
 653
 654                if (solo_dev->flags & FLAGS_6110)
 655                        h264_write_vol(&out, solo_dev, vh);
 656                else
 657                        mpeg4_write_vol(&out, solo_dev, vh,
 658                                        solo_dev->fps * 1000,
 659                                        solo_enc->interval * 1000);
 660                skip = out - header;
 661                enc_write_sg(vbuf->sglist, header, skip);
 662                /* Adjust the dma buffer past this header */
 663                vb->size += skip;
 664        }
 665
 666        /* Now get the actual mpeg payload */
 667        frame_off = (enc_buf->off + sizeof(vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
 668        frame_size = enc_buf->size - sizeof(vh);
 669
 670        ret = enc_get_mpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist,
 671                                  skip, frame_off, frame_size);
 672        WARN_ON_ONCE(ret);
 673
 674        return ret;
 675}
 676
 677static void solo_enc_fillbuf(struct solo_enc_fh *fh,
 678                            struct videobuf_buffer *vb)
 679{
 680        struct solo_enc_dev *solo_enc = fh->enc;
 681        struct solo_dev *solo_dev = solo_enc->solo_dev;
 682        struct solo_enc_buf *enc_buf = NULL;
 683        struct videobuf_dmabuf *vbuf;
 684        int ret;
 685        int error = 1;
 686        u16 idx = fh->rd_idx;
 687
 688        while (idx != solo_dev->enc_wr_idx) {
 689                struct solo_enc_buf *ebuf = &solo_dev->enc_buf[idx];
 690
 691                idx = (idx + 1) % SOLO_NR_RING_BUFS;
 692
 693                if (ebuf->ch != solo_enc->ch)
 694                        continue;
 695
 696                if (fh->fmt == V4L2_PIX_FMT_MPEG) {
 697                        if (fh->type == ebuf->type) {
 698                                enc_buf = ebuf;
 699                                break;
 700                        }
 701                } else {
 702                        /* For mjpeg, keep reading to the newest frame */
 703                        enc_buf = ebuf;
 704                }
 705        }
 706
 707        fh->rd_idx = idx;
 708
 709        if (WARN_ON_ONCE(!enc_buf))
 710                goto buf_err;
 711
 712        if ((fh->fmt == V4L2_PIX_FMT_MPEG &&
 713             vb->bsize < enc_buf->size) ||
 714            (fh->fmt == V4L2_PIX_FMT_MJPEG &&
 715             vb->bsize < (enc_buf->jpeg_size + sizeof(jpeg_header)))) {
 716                WARN_ON_ONCE(1);
 717                goto buf_err;
 718        }
 719
 720        vbuf = videobuf_to_dma(vb);
 721        if (WARN_ON_ONCE(!vbuf))
 722                goto buf_err;
 723
 724        if (fh->fmt == V4L2_PIX_FMT_MPEG)
 725                ret = solo_fill_mpeg(fh, enc_buf, vb, vbuf);
 726        else
 727                ret = solo_fill_jpeg(fh, enc_buf, vb, vbuf);
 728
 729        if (!ret)
 730                error = 0;
 731
 732buf_err:
 733        if (error) {
 734                vb->state = VIDEOBUF_ERROR;
 735        } else {
 736                vb->field_count++;
 737                vb->ts = enc_buf->ts;
 738                vb->state = VIDEOBUF_DONE;
 739        }
 740
 741        wake_up(&vb->done);
 742
 743        return;
 744}
 745
 746static void solo_enc_thread_try(struct solo_enc_fh *fh)
 747{
 748        struct solo_enc_dev *solo_enc = fh->enc;
 749        struct solo_dev *solo_dev = solo_enc->solo_dev;
 750        struct videobuf_buffer *vb;
 751
 752        for (;;) {
 753                spin_lock(&solo_enc->lock);
 754
 755                if (fh->rd_idx == solo_dev->enc_wr_idx)
 756                        break;
 757
 758                if (list_empty(&fh->vidq_active))
 759                        break;
 760
 761                vb = list_first_entry(&fh->vidq_active,
 762                                      struct videobuf_buffer, queue);
 763
 764                if (!waitqueue_active(&vb->done))
 765                        break;
 766
 767                list_del(&vb->queue);
 768
 769                spin_unlock(&solo_enc->lock);
 770
 771                solo_enc_fillbuf(fh, vb);
 772        }
 773
 774        assert_spin_locked(&solo_enc->lock);
 775        spin_unlock(&solo_enc->lock);
 776}
 777
 778static int solo_enc_thread(void *data)
 779{
 780        struct solo_enc_fh *fh = data;
 781        struct solo_enc_dev *solo_enc = fh->enc;
 782        DECLARE_WAITQUEUE(wait, current);
 783
 784        set_freezable();
 785        add_wait_queue(&solo_enc->thread_wait, &wait);
 786
 787        for (;;) {
 788                long timeout = schedule_timeout_interruptible(HZ);
 789                if (timeout == -ERESTARTSYS || kthread_should_stop())
 790                        break;
 791                solo_enc_thread_try(fh);
 792                try_to_freeze();
 793        }
 794
 795        remove_wait_queue(&solo_enc->thread_wait, &wait);
 796
 797        return 0;
 798}
 799
 800void solo_motion_isr(struct solo_dev *solo_dev)
 801{
 802        u32 status;
 803        int i;
 804
 805        solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_MOTION);
 806
 807        status = solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS);
 808
 809        for (i = 0; i < solo_dev->nr_chans; i++) {
 810                struct solo_enc_dev *solo_enc = solo_dev->v4l2_enc[i];
 811
 812                BUG_ON(solo_enc == NULL);
 813
 814                if (solo_enc->motion_detected)
 815                        continue;
 816                if (!(status & (1 << i)))
 817                        continue;
 818
 819                solo_enc->motion_detected = 1;
 820        }
 821}
 822
 823void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
 824{
 825        struct solo_enc_buf *enc_buf;
 826        u32 mpeg_current, mpeg_next, mpeg_size;
 827        u32 jpeg_current, jpeg_next, jpeg_size;
 828        u32 reg_mpeg_size;
 829        u8 cur_q, vop_type;
 830        u8 ch;
 831        enum solo_enc_types enc_type;
 832
 833        solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_ENCODER);
 834
 835        cur_q = ((solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xF) + 1) % MP4_QS;
 836
 837        reg_mpeg_size = ((solo_reg_read(solo_dev, SOLO_VE_STATE(0)) & 0xFFFFF) + 64 + 8) & ~7;
 838
 839        while (solo_dev->enc_idx != cur_q) {
 840                mpeg_current = solo_reg_read(solo_dev,
 841                                        SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
 842                jpeg_current = solo_reg_read(solo_dev,
 843                                        SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
 844                solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
 845                mpeg_next = solo_reg_read(solo_dev,
 846                                        SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
 847                jpeg_next = solo_reg_read(solo_dev,
 848                                        SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
 849
 850                ch = (mpeg_current >> 24) & 0x1f;
 851                if (ch >= SOLO_MAX_CHANNELS) {
 852                        ch -= SOLO_MAX_CHANNELS;
 853                        enc_type = SOLO_ENC_TYPE_EXT;
 854                } else
 855                        enc_type = SOLO_ENC_TYPE_STD;
 856
 857                vop_type = (mpeg_current >> 29) & 3;
 858
 859                mpeg_current &= 0x00ffffff;
 860                mpeg_next    &= 0x00ffffff;
 861                jpeg_current &= 0x00ffffff;
 862                jpeg_next    &= 0x00ffffff;
 863
 864                mpeg_size = (SOLO_MP4E_EXT_SIZE(solo_dev) +
 865                             mpeg_next - mpeg_current) %
 866                            SOLO_MP4E_EXT_SIZE(solo_dev);
 867
 868                jpeg_size = (SOLO_JPEG_EXT_SIZE(solo_dev) +
 869                             jpeg_next - jpeg_current) %
 870                            SOLO_JPEG_EXT_SIZE(solo_dev);
 871
 872                /* XXX I think this means we had a ring overflow? */
 873                if (mpeg_current > mpeg_next && mpeg_size != reg_mpeg_size) {
 874                        enc_reset_gop(solo_dev, ch);
 875                        continue;
 876                }
 877
 878                /* When resetting the GOP, skip frames until I-frame */
 879                if (enc_gop_reset(solo_dev, ch, vop_type))
 880                        continue;
 881
 882                enc_buf = &solo_dev->enc_buf[solo_dev->enc_wr_idx];
 883
 884                enc_buf->vop = vop_type;
 885                enc_buf->ch = ch;
 886                enc_buf->off = mpeg_current;
 887                enc_buf->size = mpeg_size;
 888                enc_buf->jpeg_off = jpeg_current;
 889                enc_buf->jpeg_size = jpeg_size;
 890                enc_buf->type = enc_type;
 891
 892                do_gettimeofday(&enc_buf->ts);
 893
 894                solo_dev->enc_wr_idx = (solo_dev->enc_wr_idx + 1) %
 895                                        SOLO_NR_RING_BUFS;
 896
 897                wake_up_interruptible(&solo_dev->v4l2_enc[ch]->thread_wait);
 898        }
 899
 900        return;
 901}
 902
 903static int solo_enc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
 904                              unsigned int *size)
 905{
 906        *size = FRAME_BUF_SIZE;
 907
 908        if (*count < MIN_VID_BUFFERS)
 909                *count = MIN_VID_BUFFERS;
 910
 911        return 0;
 912}
 913
 914static int solo_enc_buf_prepare(struct videobuf_queue *vq,
 915                                struct videobuf_buffer *vb,
 916                                enum v4l2_field field)
 917{
 918        struct solo_enc_fh *fh = vq->priv_data;
 919        struct solo_enc_dev *solo_enc = fh->enc;
 920
 921        vb->size = FRAME_BUF_SIZE;
 922        if (vb->baddr != 0 && vb->bsize < vb->size)
 923                return -EINVAL;
 924
 925        /* These properties only change when queue is idle */
 926        vb->width = solo_enc->width;
 927        vb->height = solo_enc->height;
 928        vb->field  = field;
 929
 930        if (vb->state == VIDEOBUF_NEEDS_INIT) {
 931                int rc = videobuf_iolock(vq, vb, NULL);
 932                if (rc < 0) {
 933                        struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
 934                        videobuf_dma_unmap(vq->dev, dma);
 935                        videobuf_dma_free(dma);
 936                        vb->state = VIDEOBUF_NEEDS_INIT;
 937                        return rc;
 938                }
 939        }
 940        vb->state = VIDEOBUF_PREPARED;
 941
 942        return 0;
 943}
 944
 945static void solo_enc_buf_queue(struct videobuf_queue *vq,
 946                               struct videobuf_buffer *vb)
 947{
 948        struct solo_enc_fh *fh = vq->priv_data;
 949
 950        vb->state = VIDEOBUF_QUEUED;
 951        list_add_tail(&vb->queue, &fh->vidq_active);
 952        wake_up_interruptible(&fh->enc->thread_wait);
 953}
 954
 955static void solo_enc_buf_release(struct videobuf_queue *vq,
 956                                 struct videobuf_buffer *vb)
 957{
 958        struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
 959
 960        videobuf_dma_unmap(vq->dev, dma);
 961        videobuf_dma_free(dma);
 962        vb->state = VIDEOBUF_NEEDS_INIT;
 963}
 964
 965static struct videobuf_queue_ops solo_enc_video_qops = {
 966        .buf_setup      = solo_enc_buf_setup,
 967        .buf_prepare    = solo_enc_buf_prepare,
 968        .buf_queue      = solo_enc_buf_queue,
 969        .buf_release    = solo_enc_buf_release,
 970};
 971
 972static unsigned int solo_enc_poll(struct file *file,
 973                                  struct poll_table_struct *wait)
 974{
 975        struct solo_enc_fh *fh = file->private_data;
 976
 977        return videobuf_poll_stream(file, &fh->vidq, wait);
 978}
 979
 980static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma)
 981{
 982        struct solo_enc_fh *fh = file->private_data;
 983
 984        return videobuf_mmap_mapper(&fh->vidq, vma);
 985}
 986
 987static int solo_enc_open(struct file *file)
 988{
 989        struct solo_enc_dev *solo_enc = video_drvdata(file);
 990        struct solo_enc_fh *fh;
 991
 992        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
 993        if (fh == NULL)
 994                return -ENOMEM;
 995
 996        fh->enc = solo_enc;
 997        file->private_data = fh;
 998        INIT_LIST_HEAD(&fh->vidq_active);
 999        fh->fmt = V4L2_PIX_FMT_MPEG;
1000        fh->type = SOLO_ENC_TYPE_STD;
1001
1002        videobuf_queue_sg_init(&fh->vidq, &solo_enc_video_qops,
1003                               &solo_enc->solo_dev->pdev->dev,
1004                               &solo_enc->lock,
1005                               V4L2_BUF_TYPE_VIDEO_CAPTURE,
1006                               V4L2_FIELD_INTERLACED,
1007                               sizeof(struct videobuf_buffer), fh, NULL);
1008
1009        return 0;
1010}
1011
1012static ssize_t solo_enc_read(struct file *file, char __user *data,
1013                             size_t count, loff_t *ppos)
1014{
1015        struct solo_enc_fh *fh = file->private_data;
1016        struct solo_enc_dev *solo_enc = fh->enc;
1017
1018        /* Make sure the encoder is on */
1019        if (!fh->enc_on) {
1020                int ret;
1021
1022                spin_lock(&solo_enc->lock);
1023                ret = solo_enc_on(fh);
1024                spin_unlock(&solo_enc->lock);
1025                if (ret)
1026                        return ret;
1027
1028                ret = solo_start_fh_thread(fh);
1029                if (ret)
1030                        return ret;
1031        }
1032
1033        return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
1034                                    file->f_flags & O_NONBLOCK);
1035}
1036
1037static int solo_enc_release(struct file *file)
1038{
1039        struct solo_enc_fh *fh = file->private_data;
1040        struct solo_enc_dev *solo_enc = fh->enc;
1041
1042        videobuf_stop(&fh->vidq);
1043        videobuf_mmap_free(&fh->vidq);
1044
1045        spin_lock(&solo_enc->lock);
1046        solo_enc_off(fh);
1047        spin_unlock(&solo_enc->lock);
1048
1049        kfree(fh);
1050
1051        return 0;
1052}
1053
1054static int solo_enc_querycap(struct file *file, void  *priv,
1055                             struct v4l2_capability *cap)
1056{
1057        struct solo_enc_fh *fh = priv;
1058        struct solo_enc_dev *solo_enc = fh->enc;
1059        struct solo_dev *solo_dev = solo_enc->solo_dev;
1060
1061        strcpy(cap->driver, SOLO6X10_NAME);
1062        snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
1063                 solo_enc->ch);
1064        snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
1065                 pci_name(solo_dev->pdev));
1066        cap->version = SOLO6X10_VER_NUM;
1067        cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
1068                                V4L2_CAP_READWRITE |
1069                                V4L2_CAP_STREAMING;
1070        return 0;
1071}
1072
1073static int solo_enc_enum_input(struct file *file, void *priv,
1074                               struct v4l2_input *input)
1075{
1076        struct solo_enc_fh *fh = priv;
1077        struct solo_enc_dev *solo_enc = fh->enc;
1078        struct solo_dev *solo_dev = solo_enc->solo_dev;
1079
1080        if (input->index)
1081                return -EINVAL;
1082
1083        snprintf(input->name, sizeof(input->name), "Encoder %d",
1084                 solo_enc->ch + 1);
1085        input->type = V4L2_INPUT_TYPE_CAMERA;
1086
1087        if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
1088                input->std = V4L2_STD_NTSC_M;
1089        else
1090                input->std = V4L2_STD_PAL_B;
1091
1092        if (!tw28_get_video_status(solo_dev, solo_enc->ch))
1093                input->status = V4L2_IN_ST_NO_SIGNAL;
1094
1095        return 0;
1096}
1097
1098static int solo_enc_set_input(struct file *file, void *priv, unsigned int index)
1099{
1100        if (index)
1101                return -EINVAL;
1102
1103        return 0;
1104}
1105
1106static int solo_enc_get_input(struct file *file, void *priv,
1107                              unsigned int *index)
1108{
1109        *index = 0;
1110
1111        return 0;
1112}
1113
1114static int solo_enc_enum_fmt_cap(struct file *file, void *priv,
1115                                 struct v4l2_fmtdesc *f)
1116{
1117        switch (f->index) {
1118        case 0:
1119                f->pixelformat = V4L2_PIX_FMT_MPEG;
1120                strcpy(f->description, "MPEG-4 AVC");
1121                break;
1122        case 1:
1123                f->pixelformat = V4L2_PIX_FMT_MJPEG;
1124                strcpy(f->description, "MJPEG");
1125                break;
1126        default:
1127                return -EINVAL;
1128        }
1129
1130        f->flags = V4L2_FMT_FLAG_COMPRESSED;
1131
1132        return 0;
1133}
1134
1135static int solo_enc_try_fmt_cap(struct file *file, void *priv,
1136                            struct v4l2_format *f)
1137{
1138        struct solo_enc_fh *fh = priv;
1139        struct solo_enc_dev *solo_enc = fh->enc;
1140        struct solo_dev *solo_dev = solo_enc->solo_dev;
1141        struct v4l2_pix_format *pix = &f->fmt.pix;
1142
1143        if (pix->pixelformat != V4L2_PIX_FMT_MPEG &&
1144            pix->pixelformat != V4L2_PIX_FMT_MJPEG)
1145                return -EINVAL;
1146
1147        /* We cannot change width/height in mid read */
1148        if (atomic_read(&solo_enc->readers) > 0) {
1149                if (pix->width != solo_enc->width ||
1150                    pix->height != solo_enc->height)
1151                        return -EBUSY;
1152        }
1153
1154        if (pix->width < solo_dev->video_hsize ||
1155            pix->height < solo_dev->video_vsize << 1) {
1156                /* Default to CIF 1/2 size */
1157                pix->width = solo_dev->video_hsize >> 1;
1158                pix->height = solo_dev->video_vsize;
1159        } else {
1160                /* Full frame */
1161                pix->width = solo_dev->video_hsize;
1162                pix->height = solo_dev->video_vsize << 1;
1163        }
1164
1165        if (pix->field == V4L2_FIELD_ANY)
1166                pix->field = V4L2_FIELD_INTERLACED;
1167        else if (pix->field != V4L2_FIELD_INTERLACED)
1168                pix->field = V4L2_FIELD_INTERLACED;
1169
1170        /* Just set these */
1171        pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
1172        pix->sizeimage = FRAME_BUF_SIZE;
1173
1174        return 0;
1175}
1176
1177static int solo_enc_set_fmt_cap(struct file *file, void *priv,
1178                                struct v4l2_format *f)
1179{
1180        struct solo_enc_fh *fh = priv;
1181        struct solo_enc_dev *solo_enc = fh->enc;
1182        struct solo_dev *solo_dev = solo_enc->solo_dev;
1183        struct v4l2_pix_format *pix = &f->fmt.pix;
1184        int ret;
1185
1186        spin_lock(&solo_enc->lock);
1187
1188        ret = solo_enc_try_fmt_cap(file, priv, f);
1189        if (ret) {
1190                spin_unlock(&solo_enc->lock);
1191                return ret;
1192        }
1193
1194        if (pix->width == solo_dev->video_hsize)
1195                solo_enc->mode = SOLO_ENC_MODE_D1;
1196        else
1197                solo_enc->mode = SOLO_ENC_MODE_CIF;
1198
1199        /* This does not change the encoder at all */
1200        fh->fmt = pix->pixelformat;
1201
1202        if (pix->priv)
1203                fh->type = SOLO_ENC_TYPE_EXT;
1204        ret = solo_enc_on(fh);
1205
1206        spin_unlock(&solo_enc->lock);
1207
1208        if (ret)
1209                return ret;
1210
1211        return solo_start_fh_thread(fh);
1212}
1213
1214static int solo_enc_get_fmt_cap(struct file *file, void *priv,
1215                                struct v4l2_format *f)
1216{
1217        struct solo_enc_fh *fh = priv;
1218        struct solo_enc_dev *solo_enc = fh->enc;
1219        struct v4l2_pix_format *pix = &f->fmt.pix;
1220
1221        pix->width = solo_enc->width;
1222        pix->height = solo_enc->height;
1223        pix->pixelformat = fh->fmt;
1224        pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
1225                     V4L2_FIELD_NONE;
1226        pix->sizeimage = FRAME_BUF_SIZE;
1227        pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
1228
1229        return 0;
1230}
1231
1232static int solo_enc_reqbufs(struct file *file, void *priv,
1233                            struct v4l2_requestbuffers *req)
1234{
1235        struct solo_enc_fh *fh = priv;
1236
1237        return videobuf_reqbufs(&fh->vidq, req);
1238}
1239
1240static int solo_enc_querybuf(struct file *file, void *priv,
1241                             struct v4l2_buffer *buf)
1242{
1243        struct solo_enc_fh *fh = priv;
1244
1245        return videobuf_querybuf(&fh->vidq, buf);
1246}
1247
1248static int solo_enc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
1249{
1250        struct solo_enc_fh *fh = priv;
1251
1252        return videobuf_qbuf(&fh->vidq, buf);
1253}
1254
1255static int solo_enc_dqbuf(struct file *file, void *priv,
1256                          struct v4l2_buffer *buf)
1257{
1258        struct solo_enc_fh *fh = priv;
1259        struct solo_enc_dev *solo_enc = fh->enc;
1260        int ret;
1261
1262        /* Make sure the encoder is on */
1263        if (!fh->enc_on) {
1264                spin_lock(&solo_enc->lock);
1265                ret = solo_enc_on(fh);
1266                spin_unlock(&solo_enc->lock);
1267                if (ret)
1268                        return ret;
1269
1270                ret = solo_start_fh_thread(fh);
1271                if (ret)
1272                        return ret;
1273        }
1274
1275        ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
1276        if (ret)
1277                return ret;
1278
1279        /* Signal motion detection */
1280        if (solo_is_motion_on(solo_enc)) {
1281                buf->flags |= V4L2_BUF_FLAG_MOTION_ON;
1282                if (solo_enc->motion_detected) {
1283                        buf->flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
1284                        solo_reg_write(solo_enc->solo_dev, SOLO_VI_MOT_CLEAR,
1285                                       1 << solo_enc->ch);
1286                        solo_enc->motion_detected = 0;
1287                }
1288        }
1289
1290        /* Check for key frame on mpeg data */
1291        if (fh->fmt == V4L2_PIX_FMT_MPEG) {
1292                struct videobuf_dmabuf *vbuf =
1293                                videobuf_to_dma(fh->vidq.bufs[buf->index]);
1294
1295                if (vbuf) {
1296                        u8 *p = sg_virt(vbuf->sglist);
1297                        if (p[3] == 0x00)
1298                                buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
1299                        else
1300                                buf->flags |= V4L2_BUF_FLAG_PFRAME;
1301                }
1302        }
1303
1304        return 0;
1305}
1306
1307static int solo_enc_streamon(struct file *file, void *priv,
1308                             enum v4l2_buf_type i)
1309{
1310        struct solo_enc_fh *fh = priv;
1311
1312        if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1313                return -EINVAL;
1314
1315        return videobuf_streamon(&fh->vidq);
1316}
1317
1318static int solo_enc_streamoff(struct file *file, void *priv,
1319                              enum v4l2_buf_type i)
1320{
1321        struct solo_enc_fh *fh = priv;
1322
1323        if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1324                return -EINVAL;
1325
1326        return videobuf_streamoff(&fh->vidq);
1327}
1328
1329static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id *i)
1330{
1331        return 0;
1332}
1333
1334static int solo_enum_framesizes(struct file *file, void *priv,
1335                                struct v4l2_frmsizeenum *fsize)
1336{
1337        struct solo_enc_fh *fh = priv;
1338        struct solo_dev *solo_dev = fh->enc->solo_dev;
1339
1340        if (fsize->pixel_format != V4L2_PIX_FMT_MPEG)
1341                return -EINVAL;
1342
1343        switch (fsize->index) {
1344        case 0:
1345                fsize->discrete.width = solo_dev->video_hsize >> 1;
1346                fsize->discrete.height = solo_dev->video_vsize;
1347                break;
1348        case 1:
1349                fsize->discrete.width = solo_dev->video_hsize;
1350                fsize->discrete.height = solo_dev->video_vsize << 1;
1351                break;
1352        default:
1353                return -EINVAL;
1354        }
1355
1356        fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1357
1358        return 0;
1359}
1360
1361static int solo_enum_frameintervals(struct file *file, void *priv,
1362                                    struct v4l2_frmivalenum *fintv)
1363{
1364        struct solo_enc_fh *fh = priv;
1365        struct solo_dev *solo_dev = fh->enc->solo_dev;
1366
1367        if (fintv->pixel_format != V4L2_PIX_FMT_MPEG || fintv->index)
1368                return -EINVAL;
1369
1370        fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
1371
1372        fintv->stepwise.min.numerator = solo_dev->fps;
1373        fintv->stepwise.min.denominator = 1;
1374
1375        fintv->stepwise.max.numerator = solo_dev->fps;
1376        fintv->stepwise.max.denominator = 15;
1377
1378        fintv->stepwise.step.numerator = 1;
1379        fintv->stepwise.step.denominator = 1;
1380
1381        return 0;
1382}
1383
1384static int solo_g_parm(struct file *file, void *priv,
1385                       struct v4l2_streamparm *sp)
1386{
1387        struct solo_enc_fh *fh = priv;
1388        struct solo_enc_dev *solo_enc = fh->enc;
1389        struct solo_dev *solo_dev = solo_enc->solo_dev;
1390        struct v4l2_captureparm *cp = &sp->parm.capture;
1391
1392        cp->capability = V4L2_CAP_TIMEPERFRAME;
1393        cp->timeperframe.numerator = solo_enc->interval;
1394        cp->timeperframe.denominator = solo_dev->fps;
1395        cp->capturemode = 0;
1396        /* XXX: Shouldn't we be able to get/set this from videobuf? */
1397        cp->readbuffers = 2;
1398
1399        return 0;
1400}
1401
1402static int solo_s_parm(struct file *file, void *priv,
1403                       struct v4l2_streamparm *sp)
1404{
1405        struct solo_enc_fh *fh = priv;
1406        struct solo_enc_dev *solo_enc = fh->enc;
1407        struct solo_dev *solo_dev = solo_enc->solo_dev;
1408        struct v4l2_captureparm *cp = &sp->parm.capture;
1409
1410        spin_lock(&solo_enc->lock);
1411
1412        if (atomic_read(&solo_enc->readers) > 0) {
1413                spin_unlock(&solo_enc->lock);
1414                return -EBUSY;
1415        }
1416
1417        if ((cp->timeperframe.numerator == 0) ||
1418            (cp->timeperframe.denominator == 0)) {
1419                /* reset framerate */
1420                cp->timeperframe.numerator = 1;
1421                cp->timeperframe.denominator = solo_dev->fps;
1422        }
1423
1424        if (cp->timeperframe.denominator != solo_dev->fps)
1425                cp->timeperframe.denominator = solo_dev->fps;
1426
1427        if (cp->timeperframe.numerator > 15)
1428                cp->timeperframe.numerator = 15;
1429
1430        solo_enc->interval = cp->timeperframe.numerator;
1431
1432        cp->capability = V4L2_CAP_TIMEPERFRAME;
1433
1434        solo_enc->gop = max(solo_dev->fps / solo_enc->interval, 1);
1435        solo_update_mode(solo_enc);
1436
1437        spin_unlock(&solo_enc->lock);
1438
1439        return 0;
1440}
1441
1442static int solo_queryctrl(struct file *file, void *priv,
1443                          struct v4l2_queryctrl *qc)
1444{
1445        struct solo_enc_fh *fh = priv;
1446        struct solo_enc_dev *solo_enc = fh->enc;
1447        struct solo_dev *solo_dev = solo_enc->solo_dev;
1448
1449        qc->id = v4l2_ctrl_next(solo_ctrl_classes, qc->id);
1450        if (!qc->id)
1451                return -EINVAL;
1452
1453        switch (qc->id) {
1454        case V4L2_CID_BRIGHTNESS:
1455        case V4L2_CID_CONTRAST:
1456        case V4L2_CID_SATURATION:
1457        case V4L2_CID_HUE:
1458                return v4l2_ctrl_query_fill(qc, 0x00, 0xff, 1, 0x80);
1459        case V4L2_CID_SHARPNESS:
1460                return v4l2_ctrl_query_fill(qc, 0x00, 0x0f, 1, 0x00);
1461        case V4L2_CID_MPEG_VIDEO_ENCODING:
1462                return v4l2_ctrl_query_fill(
1463                        qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
1464                        V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
1465                        V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
1466        case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1467                return v4l2_ctrl_query_fill(qc, 1, 255, 1, solo_dev->fps);
1468#ifdef PRIVATE_CIDS
1469        case V4L2_CID_MOTION_THRESHOLD:
1470                qc->flags |= V4L2_CTRL_FLAG_SLIDER;
1471                qc->type = V4L2_CTRL_TYPE_INTEGER;
1472                qc->minimum = 0;
1473                qc->maximum = 0xffff;
1474                qc->step = 1;
1475                qc->default_value = SOLO_DEF_MOT_THRESH;
1476                strlcpy(qc->name, "Motion Detection Threshold",
1477                        sizeof(qc->name));
1478                return 0;
1479        case V4L2_CID_MOTION_ENABLE:
1480                qc->type = V4L2_CTRL_TYPE_BOOLEAN;
1481                qc->minimum = 0;
1482                qc->maximum = qc->step = 1;
1483                qc->default_value = 0;
1484                strlcpy(qc->name, "Motion Detection Enable", sizeof(qc->name));
1485                return 0;
1486#else
1487        case V4L2_CID_MOTION_THRESHOLD:
1488                return v4l2_ctrl_query_fill(qc, 0, 0xffff, 1,
1489                                            SOLO_DEF_MOT_THRESH);
1490        case V4L2_CID_MOTION_ENABLE:
1491                return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
1492#endif
1493        case V4L2_CID_RDS_TX_RADIO_TEXT:
1494                qc->type = V4L2_CTRL_TYPE_STRING;
1495                qc->minimum = 0;
1496                qc->maximum = OSD_TEXT_MAX;
1497                qc->step = 1;
1498                qc->default_value = 0;
1499                strlcpy(qc->name, "OSD Text", sizeof(qc->name));
1500                return 0;
1501        }
1502
1503        return -EINVAL;
1504}
1505
1506static int solo_querymenu(struct file *file, void *priv,
1507                          struct v4l2_querymenu *qmenu)
1508{
1509        struct v4l2_queryctrl qctrl;
1510        int err;
1511
1512        qctrl.id = qmenu->id;
1513        err = solo_queryctrl(file, priv, &qctrl);
1514        if (err)
1515                return err;
1516
1517        return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
1518}
1519
1520static int solo_g_ctrl(struct file *file, void *priv,
1521                       struct v4l2_control *ctrl)
1522{
1523        struct solo_enc_fh *fh = priv;
1524        struct solo_enc_dev *solo_enc = fh->enc;
1525        struct solo_dev *solo_dev = solo_enc->solo_dev;
1526
1527        switch (ctrl->id) {
1528        case V4L2_CID_BRIGHTNESS:
1529        case V4L2_CID_CONTRAST:
1530        case V4L2_CID_SATURATION:
1531        case V4L2_CID_HUE:
1532        case V4L2_CID_SHARPNESS:
1533                return tw28_get_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
1534                                         &ctrl->value);
1535        case V4L2_CID_MPEG_VIDEO_ENCODING:
1536                ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
1537                break;
1538        case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1539                ctrl->value = solo_enc->gop;
1540                break;
1541        case V4L2_CID_MOTION_THRESHOLD:
1542                ctrl->value = solo_enc->motion_thresh;
1543                break;
1544        case V4L2_CID_MOTION_ENABLE:
1545                ctrl->value = solo_is_motion_on(solo_enc);
1546                break;
1547        default:
1548                return -EINVAL;
1549        }
1550
1551        return 0;
1552}
1553
1554static int solo_s_ctrl(struct file *file, void *priv,
1555                       struct v4l2_control *ctrl)
1556{
1557        struct solo_enc_fh *fh = priv;
1558        struct solo_enc_dev *solo_enc = fh->enc;
1559        struct solo_dev *solo_dev = solo_enc->solo_dev;
1560
1561        switch (ctrl->id) {
1562        case V4L2_CID_BRIGHTNESS:
1563        case V4L2_CID_CONTRAST:
1564        case V4L2_CID_SATURATION:
1565        case V4L2_CID_HUE:
1566        case V4L2_CID_SHARPNESS:
1567                return tw28_set_ctrl_val(solo_dev, ctrl->id, solo_enc->ch,
1568                                         ctrl->value);
1569        case V4L2_CID_MPEG_VIDEO_ENCODING:
1570                if (ctrl->value != V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC)
1571                        return -ERANGE;
1572                break;
1573        case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1574                if (ctrl->value < 1 || ctrl->value > 255)
1575                        return -ERANGE;
1576                solo_enc->gop = ctrl->value;
1577                solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch),
1578                               solo_enc->gop);
1579                solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch),
1580                               solo_enc->gop);
1581                break;
1582        case V4L2_CID_MOTION_THRESHOLD:
1583                /* TODO accept value on lower 16-bits and use high
1584                 * 16-bits to assign the value to a specific block */
1585                if (ctrl->value < 0 || ctrl->value > 0xffff)
1586                        return -ERANGE;
1587                solo_enc->motion_thresh = ctrl->value;
1588                solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->value);
1589                break;
1590        case V4L2_CID_MOTION_ENABLE:
1591                solo_motion_toggle(solo_enc, ctrl->value);
1592                break;
1593        default:
1594                return -EINVAL;
1595        }
1596
1597        return 0;
1598}
1599
1600static int solo_s_ext_ctrls(struct file *file, void *priv,
1601                            struct v4l2_ext_controls *ctrls)
1602{
1603        struct solo_enc_fh *fh = priv;
1604        struct solo_enc_dev *solo_enc = fh->enc;
1605        int i;
1606
1607        for (i = 0; i < ctrls->count; i++) {
1608                struct v4l2_ext_control *ctrl = (ctrls->controls + i);
1609                int err;
1610
1611                switch (ctrl->id) {
1612                case V4L2_CID_RDS_TX_RADIO_TEXT:
1613                        if (ctrl->size - 1 > OSD_TEXT_MAX)
1614                                err = -ERANGE;
1615                        else {
1616                                err = copy_from_user(solo_enc->osd_text,
1617                                                     ctrl->string,
1618                                                     OSD_TEXT_MAX);
1619                                solo_enc->osd_text[OSD_TEXT_MAX] = '\0';
1620                                if (!err)
1621                                        err = solo_osd_print(solo_enc);
1622                        }
1623                        break;
1624                default:
1625                        err = -EINVAL;
1626                }
1627
1628                if (err < 0) {
1629                        ctrls->error_idx = i;
1630                        return err;
1631                }
1632        }
1633
1634        return 0;
1635}
1636
1637static int solo_g_ext_ctrls(struct file *file, void *priv,
1638                            struct v4l2_ext_controls *ctrls)
1639{
1640        struct solo_enc_fh *fh = priv;
1641        struct solo_enc_dev *solo_enc = fh->enc;
1642        int i;
1643
1644        for (i = 0; i < ctrls->count; i++) {
1645                struct v4l2_ext_control *ctrl = (ctrls->controls + i);
1646                int err;
1647
1648                switch (ctrl->id) {
1649                case V4L2_CID_RDS_TX_RADIO_TEXT:
1650                        if (ctrl->size < OSD_TEXT_MAX) {
1651                                ctrl->size = OSD_TEXT_MAX;
1652                                err = -ENOSPC;
1653                        } else {
1654                                err = copy_to_user(ctrl->string,
1655                                                   solo_enc->osd_text,
1656                                                   OSD_TEXT_MAX);
1657                        }
1658                        break;
1659                default:
1660                        err = -EINVAL;
1661                }
1662
1663                if (err < 0) {
1664                        ctrls->error_idx = i;
1665                        return err;
1666                }
1667        }
1668
1669        return 0;
1670}
1671
1672static const struct v4l2_file_operations solo_enc_fops = {
1673        .owner                  = THIS_MODULE,
1674        .open                   = solo_enc_open,
1675        .release                = solo_enc_release,
1676        .read                   = solo_enc_read,
1677        .poll                   = solo_enc_poll,
1678        .mmap                   = solo_enc_mmap,
1679        .ioctl                  = video_ioctl2,
1680};
1681
1682static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
1683        .vidioc_querycap                = solo_enc_querycap,
1684        .vidioc_s_std                   = solo_enc_s_std,
1685        /* Input callbacks */
1686        .vidioc_enum_input              = solo_enc_enum_input,
1687        .vidioc_s_input                 = solo_enc_set_input,
1688        .vidioc_g_input                 = solo_enc_get_input,
1689        /* Video capture format callbacks */
1690        .vidioc_enum_fmt_vid_cap        = solo_enc_enum_fmt_cap,
1691        .vidioc_try_fmt_vid_cap         = solo_enc_try_fmt_cap,
1692        .vidioc_s_fmt_vid_cap           = solo_enc_set_fmt_cap,
1693        .vidioc_g_fmt_vid_cap           = solo_enc_get_fmt_cap,
1694        /* Streaming I/O */
1695        .vidioc_reqbufs                 = solo_enc_reqbufs,
1696        .vidioc_querybuf                = solo_enc_querybuf,
1697        .vidioc_qbuf                    = solo_enc_qbuf,
1698        .vidioc_dqbuf                   = solo_enc_dqbuf,
1699        .vidioc_streamon                = solo_enc_streamon,
1700        .vidioc_streamoff               = solo_enc_streamoff,
1701        /* Frame size and interval */
1702        .vidioc_enum_framesizes         = solo_enum_framesizes,
1703        .vidioc_enum_frameintervals     = solo_enum_frameintervals,
1704        /* Video capture parameters */
1705        .vidioc_s_parm                  = solo_s_parm,
1706        .vidioc_g_parm                  = solo_g_parm,
1707        /* Controls */
1708        .vidioc_queryctrl               = solo_queryctrl,
1709        .vidioc_querymenu               = solo_querymenu,
1710        .vidioc_g_ctrl                  = solo_g_ctrl,
1711        .vidioc_s_ctrl                  = solo_s_ctrl,
1712        .vidioc_g_ext_ctrls             = solo_g_ext_ctrls,
1713        .vidioc_s_ext_ctrls             = solo_s_ext_ctrls,
1714};
1715
1716static struct video_device solo_enc_template = {
1717        .name                   = SOLO6X10_NAME,
1718        .fops                   = &solo_enc_fops,
1719        .ioctl_ops              = &solo_enc_ioctl_ops,
1720        .minor                  = -1,
1721        .release                = video_device_release,
1722
1723        .tvnorms                = V4L2_STD_NTSC_M | V4L2_STD_PAL_B,
1724        .current_norm           = V4L2_STD_NTSC_M,
1725};
1726
1727static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
1728{
1729        struct solo_enc_dev *solo_enc;
1730        int ret;
1731
1732        solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
1733        if (!solo_enc)
1734                return ERR_PTR(-ENOMEM);
1735
1736        solo_enc->vfd = video_device_alloc();
1737        if (!solo_enc->vfd) {
1738                kfree(solo_enc);
1739                return ERR_PTR(-ENOMEM);
1740        }
1741
1742        solo_enc->solo_dev = solo_dev;
1743        solo_enc->ch = ch;
1744
1745        *solo_enc->vfd = solo_enc_template;
1746        solo_enc->vfd->parent = &solo_dev->pdev->dev;
1747        ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER,
1748                                    video_nr);
1749        if (ret < 0) {
1750                video_device_release(solo_enc->vfd);
1751                kfree(solo_enc);
1752                return ERR_PTR(ret);
1753        }
1754
1755        video_set_drvdata(solo_enc->vfd, solo_enc);
1756
1757        snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
1758                 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
1759                 solo_enc->vfd->num);
1760
1761        if (video_nr != -1)
1762                video_nr++;
1763
1764        spin_lock_init(&solo_enc->lock);
1765        init_waitqueue_head(&solo_enc->thread_wait);
1766        atomic_set(&solo_enc->readers, 0);
1767
1768        solo_enc->qp = SOLO_DEFAULT_QP;
1769        solo_enc->gop = solo_dev->fps;
1770        solo_enc->interval = 1;
1771        solo_enc->mode = SOLO_ENC_MODE_CIF;
1772        solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
1773
1774        spin_lock(&solo_enc->lock);
1775        solo_update_mode(solo_enc);
1776        spin_unlock(&solo_enc->lock);
1777
1778        return solo_enc;
1779}
1780
1781static void solo_enc_free(struct solo_enc_dev *solo_enc)
1782{
1783        if (solo_enc == NULL)
1784                return;
1785
1786        video_unregister_device(solo_enc->vfd);
1787        kfree(solo_enc);
1788}
1789
1790int solo_enc_v4l2_init(struct solo_dev *solo_dev)
1791{
1792        int i;
1793
1794        for (i = 0; i < solo_dev->nr_chans; i++) {
1795                solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i);
1796                if (IS_ERR(solo_dev->v4l2_enc[i]))
1797                        break;
1798        }
1799
1800        if (i != solo_dev->nr_chans) {
1801                int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
1802                while (i--)
1803                        solo_enc_free(solo_dev->v4l2_enc[i]);
1804                return ret;
1805        }
1806
1807        /* D1@MAX-FPS * 4 */
1808        solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
1809
1810        dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
1811                 solo_dev->v4l2_enc[0]->vfd->num,
1812                 solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
1813
1814        return 0;
1815}
1816
1817void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
1818{
1819        int i;
1820
1821        solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
1822
1823        for (i = 0; i < solo_dev->nr_chans; i++)
1824                solo_enc_free(solo_dev->v4l2_enc[i]);
1825}
1826