linux/drivers/staging/media/dt3155v4l/dt3155v4l.c
<<
>>
Prefs
   1/***************************************************************************
   2 *   Copyright (C) 2006-2010 by Marin Mitov                                *
   3 *   mitov@issp.bas.bg                                                     *
   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                         *
  17 *   Free Software Foundation, Inc.,                                       *
  18 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  19 ***************************************************************************/
  20
  21#include <linux/module.h>
  22#include <linux/version.h>
  23#include <linux/stringify.h>
  24#include <linux/delay.h>
  25#include <linux/kthread.h>
  26#include <linux/slab.h>
  27#include <media/v4l2-dev.h>
  28#include <media/v4l2-ioctl.h>
  29#include <media/v4l2-common.h>
  30#include <media/videobuf2-dma-contig.h>
  31
  32#include "dt3155v4l.h"
  33
  34#define DT3155_DEVICE_ID 0x1223
  35
  36/* DT3155_CHUNK_SIZE is 4M (2^22) 8 full size buffers */
  37#define DT3155_CHUNK_SIZE (1U << 22)
  38
  39#define DT3155_COH_FLAGS (GFP_KERNEL | GFP_DMA32 | __GFP_COLD | __GFP_NOWARN)
  40
  41#define DT3155_BUF_SIZE (768 * 576)
  42
  43#ifdef CONFIG_DT3155_STREAMING
  44#define DT3155_CAPTURE_METHOD V4L2_CAP_STREAMING
  45#else
  46#define DT3155_CAPTURE_METHOD V4L2_CAP_READWRITE
  47#endif
  48
  49/*  global initializers (for all boards)  */
  50#ifdef CONFIG_DT3155_CCIR
  51static const u8 csr2_init = VT_50HZ;
  52#define DT3155_CURRENT_NORM V4L2_STD_625_50
  53static const unsigned int img_width = 768;
  54static const unsigned int img_height = 576;
  55static const unsigned int frames_per_sec = 25;
  56static const struct v4l2_fmtdesc frame_std[] = {
  57        {
  58        .index = 0,
  59        .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  60        .flags = 0,
  61        .description = "CCIR/50Hz 8 bits gray",
  62        .pixelformat = V4L2_PIX_FMT_GREY,
  63        },
  64};
  65#else
  66static const u8 csr2_init = VT_60HZ;
  67#define DT3155_CURRENT_NORM V4L2_STD_525_60
  68static const unsigned int img_width = 640;
  69static const unsigned int img_height = 480;
  70static const unsigned int frames_per_sec = 30;
  71static const struct v4l2_fmtdesc frame_std[] = {
  72        {
  73        .index = 0,
  74        .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  75        .flags = 0,
  76        .description = "RS-170/60Hz 8 bits gray",
  77        .pixelformat = V4L2_PIX_FMT_GREY,
  78        },
  79};
  80#endif
  81
  82#define NUM_OF_FORMATS ARRAY_SIZE(frame_std)
  83
  84static u8 config_init = ACQ_MODE_EVEN;
  85
  86/**
  87 * read_i2c_reg - reads an internal i2c register
  88 *
  89 * @addr:       dt3155 mmio base address
  90 * @index:      index (internal address) of register to read
  91 * @data:       pointer to byte the read data will be placed in
  92 *
  93 * returns:     zero on success or error code
  94 *
  95 * This function starts reading the specified (by index) register
  96 * and busy waits for the process to finish. The result is placed
  97 * in a byte pointed by data.
  98 */
  99static int
 100read_i2c_reg(void __iomem *addr, u8 index, u8 *data)
 101{
 102        u32 tmp = index;
 103
 104        iowrite32((tmp<<17) | IIC_READ, addr + IIC_CSR2);
 105        mmiowb();
 106        udelay(45); /* wait at least 43 usec for NEW_CYCLE to clear */
 107        if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
 108                return -EIO; /* error: NEW_CYCLE not cleared */
 109        tmp = ioread32(addr + IIC_CSR1);
 110        if (tmp & DIRECT_ABORT) {
 111                /* reset DIRECT_ABORT bit */
 112                iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
 113                return -EIO; /* error: DIRECT_ABORT set */
 114        }
 115        *data = tmp>>24;
 116        return 0;
 117}
 118
 119/**
 120 * write_i2c_reg - writes to an internal i2c register
 121 *
 122 * @addr:       dt3155 mmio base address
 123 * @index:      index (internal address) of register to read
 124 * @data:       data to be written
 125 *
 126 * returns:     zero on success or error code
 127 *
 128 * This function starts writting the specified (by index) register
 129 * and busy waits for the process to finish.
 130 */
 131static int
 132write_i2c_reg(void __iomem *addr, u8 index, u8 data)
 133{
 134        u32 tmp = index;
 135
 136        iowrite32((tmp<<17) | IIC_WRITE | data, addr + IIC_CSR2);
 137        mmiowb();
 138        udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
 139        if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
 140                return -EIO; /* error: NEW_CYCLE not cleared */
 141        if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
 142                /* reset DIRECT_ABORT bit */
 143                iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
 144                return -EIO; /* error: DIRECT_ABORT set */
 145        }
 146        return 0;
 147}
 148
 149/**
 150 * write_i2c_reg_nowait - writes to an internal i2c register
 151 *
 152 * @addr:       dt3155 mmio base address
 153 * @index:      index (internal address) of register to read
 154 * @data:       data to be written
 155 *
 156 * This function starts writting the specified (by index) register
 157 * and then returns.
 158 */
 159static void write_i2c_reg_nowait(void __iomem *addr, u8 index, u8 data)
 160{
 161        u32 tmp = index;
 162
 163        iowrite32((tmp<<17) | IIC_WRITE | data, addr + IIC_CSR2);
 164        mmiowb();
 165}
 166
 167/**
 168 * wait_i2c_reg - waits the read/write to finish
 169 *
 170 * @addr:       dt3155 mmio base address
 171 *
 172 * returns:     zero on success or error code
 173 *
 174 * This function waits reading/writting to finish.
 175 */
 176static int wait_i2c_reg(void __iomem *addr)
 177{
 178        if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
 179                udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
 180        if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
 181                return -EIO; /* error: NEW_CYCLE not cleared */
 182        if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
 183                /* reset DIRECT_ABORT bit */
 184                iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
 185                return -EIO; /* error: DIRECT_ABORT set */
 186        }
 187        return 0;
 188}
 189
 190static int
 191dt3155_start_acq(struct dt3155_priv *pd)
 192{
 193        struct vb2_buffer *vb = pd->curr_buf;
 194        dma_addr_t dma_addr;
 195
 196        dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
 197        iowrite32(dma_addr, pd->regs + EVEN_DMA_START);
 198        iowrite32(dma_addr + img_width, pd->regs + ODD_DMA_START);
 199        iowrite32(img_width, pd->regs + EVEN_DMA_STRIDE);
 200        iowrite32(img_width, pd->regs + ODD_DMA_STRIDE);
 201        /* enable interrupts, clear all irq flags */
 202        iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
 203                        FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
 204        iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
 205                  FLD_DN_ODD | FLD_DN_EVEN | CAP_CONT_EVEN | CAP_CONT_ODD,
 206                                                        pd->regs + CSR1);
 207        wait_i2c_reg(pd->regs);
 208        write_i2c_reg(pd->regs, CONFIG, pd->config);
 209        write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE);
 210        write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_DONE);
 211
 212        /*  start the board  */
 213        write_i2c_reg(pd->regs, CSR2, pd->csr2 | BUSY_EVEN | BUSY_ODD);
 214        return 0; /* success  */
 215}
 216
 217/*
 218 *      driver-specific callbacks (vb2_ops)
 219 */
 220static int
 221dt3155_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 222                unsigned int *num_buffers, unsigned int *num_planes,
 223                unsigned int sizes[], void *alloc_ctxs[])
 224
 225{
 226        struct dt3155_priv *pd = vb2_get_drv_priv(q);
 227        void *ret;
 228
 229        if (*num_buffers == 0)
 230                *num_buffers = 1;
 231        *num_planes = 1;
 232        sizes[0] = img_width * img_height;
 233        if (pd->q->alloc_ctx[0])
 234                return 0;
 235        ret = vb2_dma_contig_init_ctx(&pd->pdev->dev);
 236        if (IS_ERR(ret))
 237                return PTR_ERR(ret);
 238        pd->q->alloc_ctx[0] = ret;
 239        return 0;
 240}
 241
 242static void
 243dt3155_wait_prepare(struct vb2_queue *q)
 244{
 245        struct dt3155_priv *pd = vb2_get_drv_priv(q);
 246
 247        mutex_unlock(pd->vdev->lock);
 248}
 249
 250static void
 251dt3155_wait_finish(struct vb2_queue *q)
 252{
 253        struct dt3155_priv *pd = vb2_get_drv_priv(q);
 254
 255        mutex_lock(pd->vdev->lock);
 256}
 257
 258static int
 259dt3155_buf_prepare(struct vb2_buffer *vb)
 260{
 261        vb2_set_plane_payload(vb, 0, img_width * img_height);
 262        return 0;
 263}
 264
 265static void
 266dt3155_stop_streaming(struct vb2_queue *q)
 267{
 268        struct dt3155_priv *pd = vb2_get_drv_priv(q);
 269        struct vb2_buffer *vb;
 270
 271        spin_lock_irq(&pd->lock);
 272        while (!list_empty(&pd->dmaq)) {
 273                vb = list_first_entry(&pd->dmaq, typeof(*vb), done_entry);
 274                list_del(&vb->done_entry);
 275                vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 276        }
 277        spin_unlock_irq(&pd->lock);
 278        msleep(45); /* irq hendler will stop the hardware */
 279}
 280
 281static void
 282dt3155_buf_queue(struct vb2_buffer *vb)
 283{
 284        struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
 285
 286        /*  pd->q->streaming = 1 when dt3155_buf_queue() is invoked  */
 287        spin_lock_irq(&pd->lock);
 288        if (pd->curr_buf)
 289                list_add_tail(&vb->done_entry, &pd->dmaq);
 290        else {
 291                pd->curr_buf = vb;
 292                dt3155_start_acq(pd);
 293        }
 294        spin_unlock_irq(&pd->lock);
 295}
 296/*
 297 *      end driver-specific callbacks
 298 */
 299
 300static const struct vb2_ops q_ops = {
 301        .queue_setup = dt3155_queue_setup,
 302        .wait_prepare = dt3155_wait_prepare,
 303        .wait_finish = dt3155_wait_finish,
 304        .buf_prepare = dt3155_buf_prepare,
 305        .stop_streaming = dt3155_stop_streaming,
 306        .buf_queue = dt3155_buf_queue,
 307};
 308
 309static irqreturn_t
 310dt3155_irq_handler_even(int irq, void *dev_id)
 311{
 312        struct dt3155_priv *ipd = dev_id;
 313        struct vb2_buffer *ivb;
 314        dma_addr_t dma_addr;
 315        u32 tmp;
 316
 317        tmp = ioread32(ipd->regs + INT_CSR) & (FLD_START | FLD_END_ODD);
 318        if (!tmp)
 319                return IRQ_NONE;  /* not our irq */
 320        if ((tmp & FLD_START) && !(tmp & FLD_END_ODD)) {
 321                iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START,
 322                                                        ipd->regs + INT_CSR);
 323                ipd->field_count++;
 324                return IRQ_HANDLED; /* start of field irq */
 325        }
 326        if ((tmp & FLD_START) && (tmp & FLD_END_ODD))
 327                ipd->stats.start_before_end++;
 328        /*      check for corrupted fields     */
 329/*      write_i2c_reg(ipd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE);       */
 330/*      write_i2c_reg(ipd->regs, ODD_CSR, CSR_ERROR | CSR_DONE);        */
 331        tmp = ioread32(ipd->regs + CSR1) & (FLD_CRPT_EVEN | FLD_CRPT_ODD);
 332        if (tmp) {
 333                ipd->stats.corrupted_fields++;
 334                iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
 335                                                FLD_DN_ODD | FLD_DN_EVEN |
 336                                                CAP_CONT_EVEN | CAP_CONT_ODD,
 337                                                        ipd->regs + CSR1);
 338                mmiowb();
 339        }
 340
 341        spin_lock(&ipd->lock);
 342        if (ipd->curr_buf) {
 343                v4l2_get_timestamp(&ipd->curr_buf->v4l2_buf.timestamp);
 344                ipd->curr_buf->v4l2_buf.sequence = (ipd->field_count) >> 1;
 345                vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
 346        }
 347
 348        if (!ipd->q->streaming || list_empty(&ipd->dmaq))
 349                goto stop_dma;
 350        ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
 351        list_del(&ivb->done_entry);
 352        ipd->curr_buf = ivb;
 353        dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0);
 354        iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
 355        iowrite32(dma_addr + img_width, ipd->regs + ODD_DMA_START);
 356        iowrite32(img_width, ipd->regs + EVEN_DMA_STRIDE);
 357        iowrite32(img_width, ipd->regs + ODD_DMA_STRIDE);
 358        mmiowb();
 359        /* enable interrupts, clear all irq flags */
 360        iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
 361                        FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
 362        spin_unlock(&ipd->lock);
 363        return IRQ_HANDLED;
 364
 365stop_dma:
 366        ipd->curr_buf = NULL;
 367        /* stop the board */
 368        write_i2c_reg_nowait(ipd->regs, CSR2, ipd->csr2);
 369        iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
 370                  FLD_DN_ODD | FLD_DN_EVEN, ipd->regs + CSR1);
 371        /* disable interrupts, clear all irq flags */
 372        iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
 373        spin_unlock(&ipd->lock);
 374        return IRQ_HANDLED;
 375}
 376
 377static int
 378dt3155_open(struct file *filp)
 379{
 380        int ret = 0;
 381        struct dt3155_priv *pd = video_drvdata(filp);
 382
 383        if (mutex_lock_interruptible(&pd->mux))
 384                return -ERESTARTSYS;
 385        if (!pd->users) {
 386                pd->q = kzalloc(sizeof(*pd->q), GFP_KERNEL);
 387                if (!pd->q) {
 388                        ret = -ENOMEM;
 389                        goto err_alloc_queue;
 390                }
 391                pd->q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 392                pd->q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 393                pd->q->io_modes = VB2_READ | VB2_MMAP;
 394                pd->q->ops = &q_ops;
 395                pd->q->mem_ops = &vb2_dma_contig_memops;
 396                pd->q->drv_priv = pd;
 397                pd->curr_buf = NULL;
 398                pd->field_count = 0;
 399                ret = vb2_queue_init(pd->q);
 400                if (ret < 0)
 401                        goto err_request_irq;
 402                INIT_LIST_HEAD(&pd->dmaq);
 403                spin_lock_init(&pd->lock);
 404                /* disable all irqs, clear all irq flags */
 405                iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
 406                                                pd->regs + INT_CSR);
 407                ret = request_irq(pd->pdev->irq, dt3155_irq_handler_even,
 408                                                IRQF_SHARED, DT3155_NAME, pd);
 409                if (ret)
 410                        goto err_request_irq;
 411        }
 412        pd->users++;
 413        mutex_unlock(&pd->mux);
 414        return 0; /* success */
 415err_request_irq:
 416        kfree(pd->q);
 417        pd->q = NULL;
 418err_alloc_queue:
 419        mutex_unlock(&pd->mux);
 420        return ret;
 421}
 422
 423static int
 424dt3155_release(struct file *filp)
 425{
 426        struct dt3155_priv *pd = video_drvdata(filp);
 427
 428        mutex_lock(&pd->mux);
 429        pd->users--;
 430        BUG_ON(pd->users < 0);
 431        if (!pd->users) {
 432                vb2_queue_release(pd->q);
 433                free_irq(pd->pdev->irq, pd);
 434                if (pd->q->alloc_ctx[0])
 435                        vb2_dma_contig_cleanup_ctx(pd->q->alloc_ctx[0]);
 436                kfree(pd->q);
 437                pd->q = NULL;
 438        }
 439        mutex_unlock(&pd->mux);
 440        return 0;
 441}
 442
 443static ssize_t
 444dt3155_read(struct file *filp, char __user *user, size_t size, loff_t *loff)
 445{
 446        struct dt3155_priv *pd = video_drvdata(filp);
 447        ssize_t res;
 448
 449        if (mutex_lock_interruptible(&pd->mux))
 450                return -ERESTARTSYS;
 451        res = vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK);
 452        mutex_unlock(&pd->mux);
 453        return res;
 454}
 455
 456static unsigned int
 457dt3155_poll(struct file *filp, struct poll_table_struct *polltbl)
 458{
 459        struct dt3155_priv *pd = video_drvdata(filp);
 460        unsigned int res;
 461
 462        mutex_lock(&pd->mux);
 463        res = vb2_poll(pd->q, filp, polltbl);
 464        mutex_unlock(&pd->mux);
 465        return res;
 466}
 467
 468static int
 469dt3155_mmap(struct file *filp, struct vm_area_struct *vma)
 470{
 471        struct dt3155_priv *pd = video_drvdata(filp);
 472        int res;
 473
 474        if (mutex_lock_interruptible(&pd->mux))
 475                return -ERESTARTSYS;
 476        res = vb2_mmap(pd->q, vma);
 477        mutex_unlock(&pd->mux);
 478        return res;
 479}
 480
 481static const struct v4l2_file_operations dt3155_fops = {
 482        .owner = THIS_MODULE,
 483        .open = dt3155_open,
 484        .release = dt3155_release,
 485        .read = dt3155_read,
 486        .poll = dt3155_poll,
 487        .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
 488        .mmap = dt3155_mmap,
 489};
 490
 491static int
 492dt3155_ioc_streamon(struct file *filp, void *p, enum v4l2_buf_type type)
 493{
 494        struct dt3155_priv *pd = video_drvdata(filp);
 495
 496        return vb2_streamon(pd->q, type);
 497}
 498
 499static int
 500dt3155_ioc_streamoff(struct file *filp, void *p, enum v4l2_buf_type type)
 501{
 502        struct dt3155_priv *pd = video_drvdata(filp);
 503
 504        return vb2_streamoff(pd->q, type);
 505}
 506
 507static int
 508dt3155_ioc_querycap(struct file *filp, void *p, struct v4l2_capability *cap)
 509{
 510        struct dt3155_priv *pd = video_drvdata(filp);
 511
 512        strcpy(cap->driver, DT3155_NAME);
 513        strcpy(cap->card, DT3155_NAME " frame grabber");
 514        sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev));
 515        cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
 516                                DT3155_CAPTURE_METHOD;
 517        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 518        return 0;
 519}
 520
 521static int
 522dt3155_ioc_enum_fmt_vid_cap(struct file *filp, void *p, struct v4l2_fmtdesc *f)
 523{
 524        if (f->index >= NUM_OF_FORMATS)
 525                return -EINVAL;
 526        *f = frame_std[f->index];
 527        return 0;
 528}
 529
 530static int
 531dt3155_ioc_g_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
 532{
 533        if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 534                return -EINVAL;
 535        f->fmt.pix.width = img_width;
 536        f->fmt.pix.height = img_height;
 537        f->fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
 538        f->fmt.pix.field = V4L2_FIELD_NONE;
 539        f->fmt.pix.bytesperline = f->fmt.pix.width;
 540        f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height;
 541        f->fmt.pix.colorspace = 0;
 542        f->fmt.pix.priv = 0;
 543        return 0;
 544}
 545
 546static int
 547dt3155_ioc_try_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
 548{
 549        if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 550                return -EINVAL;
 551        if (f->fmt.pix.width == img_width &&
 552                f->fmt.pix.height == img_height &&
 553                f->fmt.pix.pixelformat == V4L2_PIX_FMT_GREY &&
 554                f->fmt.pix.field == V4L2_FIELD_NONE &&
 555                f->fmt.pix.bytesperline == f->fmt.pix.width &&
 556                f->fmt.pix.sizeimage == f->fmt.pix.width * f->fmt.pix.height)
 557                        return 0;
 558        else
 559                return -EINVAL;
 560}
 561
 562static int
 563dt3155_ioc_s_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
 564{
 565        return dt3155_ioc_g_fmt_vid_cap(filp, p, f);
 566}
 567
 568static int
 569dt3155_ioc_reqbufs(struct file *filp, void *p, struct v4l2_requestbuffers *b)
 570{
 571        struct dt3155_priv *pd = video_drvdata(filp);
 572
 573        return vb2_reqbufs(pd->q, b);
 574}
 575
 576static int
 577dt3155_ioc_querybuf(struct file *filp, void *p, struct v4l2_buffer *b)
 578{
 579        struct dt3155_priv *pd = video_drvdata(filp);
 580
 581        return vb2_querybuf(pd->q, b);
 582}
 583
 584static int
 585dt3155_ioc_qbuf(struct file *filp, void *p, struct v4l2_buffer *b)
 586{
 587        struct dt3155_priv *pd = video_drvdata(filp);
 588
 589        return vb2_qbuf(pd->q, b);
 590}
 591
 592static int
 593dt3155_ioc_dqbuf(struct file *filp, void *p, struct v4l2_buffer *b)
 594{
 595        struct dt3155_priv *pd = video_drvdata(filp);
 596
 597        return vb2_dqbuf(pd->q, b, filp->f_flags & O_NONBLOCK);
 598}
 599
 600static int
 601dt3155_ioc_querystd(struct file *filp, void *p, v4l2_std_id *norm)
 602{
 603        *norm = DT3155_CURRENT_NORM;
 604        return 0;
 605}
 606
 607static int
 608dt3155_ioc_g_std(struct file *filp, void *p, v4l2_std_id *norm)
 609{
 610        *norm = DT3155_CURRENT_NORM;
 611        return 0;
 612}
 613
 614static int
 615dt3155_ioc_s_std(struct file *filp, void *p, v4l2_std_id norm)
 616{
 617        if (norm & DT3155_CURRENT_NORM)
 618                return 0;
 619        return -EINVAL;
 620}
 621
 622static int
 623dt3155_ioc_enum_input(struct file *filp, void *p, struct v4l2_input *input)
 624{
 625        if (input->index)
 626                return -EINVAL;
 627        strcpy(input->name, "Coax in");
 628        input->type = V4L2_INPUT_TYPE_CAMERA;
 629        /*
 630         * FIXME: input->std = 0 according to v4l2 API
 631         * VIDIOC_G_STD, VIDIOC_S_STD, VIDIOC_QUERYSTD and VIDIOC_ENUMSTD
 632         * should return -EINVAL
 633         */
 634        input->std = DT3155_CURRENT_NORM;
 635        input->status = 0;/* FIXME: add sync detection & V4L2_IN_ST_NO_H_LOCK */
 636        return 0;
 637}
 638
 639static int
 640dt3155_ioc_g_input(struct file *filp, void *p, unsigned int *i)
 641{
 642        *i = 0;
 643        return 0;
 644}
 645
 646static int
 647dt3155_ioc_s_input(struct file *filp, void *p, unsigned int i)
 648{
 649        if (i)
 650                return -EINVAL;
 651        return 0;
 652}
 653
 654static int
 655dt3155_ioc_g_parm(struct file *filp, void *p, struct v4l2_streamparm *parms)
 656{
 657        if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 658                return -EINVAL;
 659        parms->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
 660        parms->parm.capture.capturemode = 0;
 661        parms->parm.capture.timeperframe.numerator = 1001;
 662        parms->parm.capture.timeperframe.denominator = frames_per_sec * 1000;
 663        parms->parm.capture.extendedmode = 0;
 664        parms->parm.capture.readbuffers = 1; /* FIXME: 2 buffers? */
 665        return 0;
 666}
 667
 668static int
 669dt3155_ioc_s_parm(struct file *filp, void *p, struct v4l2_streamparm *parms)
 670{
 671        if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 672                return -EINVAL;
 673        parms->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
 674        parms->parm.capture.capturemode = 0;
 675        parms->parm.capture.timeperframe.numerator = 1001;
 676        parms->parm.capture.timeperframe.denominator = frames_per_sec * 1000;
 677        parms->parm.capture.extendedmode = 0;
 678        parms->parm.capture.readbuffers = 1; /* FIXME: 2 buffers? */
 679        return 0;
 680}
 681
 682static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
 683        .vidioc_streamon = dt3155_ioc_streamon,
 684        .vidioc_streamoff = dt3155_ioc_streamoff,
 685        .vidioc_querycap = dt3155_ioc_querycap,
 686/*
 687        .vidioc_g_priority = dt3155_ioc_g_priority,
 688        .vidioc_s_priority = dt3155_ioc_s_priority,
 689*/
 690        .vidioc_enum_fmt_vid_cap = dt3155_ioc_enum_fmt_vid_cap,
 691        .vidioc_try_fmt_vid_cap = dt3155_ioc_try_fmt_vid_cap,
 692        .vidioc_g_fmt_vid_cap = dt3155_ioc_g_fmt_vid_cap,
 693        .vidioc_s_fmt_vid_cap = dt3155_ioc_s_fmt_vid_cap,
 694        .vidioc_reqbufs = dt3155_ioc_reqbufs,
 695        .vidioc_querybuf = dt3155_ioc_querybuf,
 696        .vidioc_qbuf = dt3155_ioc_qbuf,
 697        .vidioc_dqbuf = dt3155_ioc_dqbuf,
 698        .vidioc_querystd = dt3155_ioc_querystd,
 699        .vidioc_g_std = dt3155_ioc_g_std,
 700        .vidioc_s_std = dt3155_ioc_s_std,
 701        .vidioc_enum_input = dt3155_ioc_enum_input,
 702        .vidioc_g_input = dt3155_ioc_g_input,
 703        .vidioc_s_input = dt3155_ioc_s_input,
 704/*
 705        .vidioc_queryctrl = dt3155_ioc_queryctrl,
 706        .vidioc_g_ctrl = dt3155_ioc_g_ctrl,
 707        .vidioc_s_ctrl = dt3155_ioc_s_ctrl,
 708        .vidioc_querymenu = dt3155_ioc_querymenu,
 709        .vidioc_g_ext_ctrls = dt3155_ioc_g_ext_ctrls,
 710        .vidioc_s_ext_ctrls = dt3155_ioc_s_ext_ctrls,
 711*/
 712        .vidioc_g_parm = dt3155_ioc_g_parm,
 713        .vidioc_s_parm = dt3155_ioc_s_parm,
 714/*
 715        .vidioc_cropcap = dt3155_ioc_cropcap,
 716        .vidioc_g_crop = dt3155_ioc_g_crop,
 717        .vidioc_s_crop = dt3155_ioc_s_crop,
 718        .vidioc_enum_framesizes = dt3155_ioc_enum_framesizes,
 719        .vidioc_enum_frameintervals = dt3155_ioc_enum_frameintervals,
 720*/
 721};
 722
 723static int
 724dt3155_init_board(struct pci_dev *pdev)
 725{
 726        struct dt3155_priv *pd = pci_get_drvdata(pdev);
 727        void *buf_cpu;
 728        dma_addr_t buf_dma;
 729        int i;
 730        u8 tmp;
 731
 732        pci_set_master(pdev); /* dt3155 needs it */
 733
 734        /*  resetting the adapter  */
 735        iowrite32(FLD_CRPT_ODD | FLD_CRPT_EVEN | FLD_DN_ODD | FLD_DN_EVEN,
 736                                                        pd->regs + CSR1);
 737        mmiowb();
 738        msleep(20);
 739
 740        /*  initializing adaper registers  */
 741        iowrite32(FIFO_EN | SRST, pd->regs + CSR1);
 742        mmiowb();
 743        iowrite32(0xEEEEEE01, pd->regs + EVEN_PIXEL_FMT);
 744        iowrite32(0xEEEEEE01, pd->regs + ODD_PIXEL_FMT);
 745        iowrite32(0x00000020, pd->regs + FIFO_TRIGER);
 746        iowrite32(0x00000103, pd->regs + XFER_MODE);
 747        iowrite32(0, pd->regs + RETRY_WAIT_CNT);
 748        iowrite32(0, pd->regs + INT_CSR);
 749        iowrite32(1, pd->regs + EVEN_FLD_MASK);
 750        iowrite32(1, pd->regs + ODD_FLD_MASK);
 751        iowrite32(0, pd->regs + MASK_LENGTH);
 752        iowrite32(0x0005007C, pd->regs + FIFO_FLAG_CNT);
 753        iowrite32(0x01010101, pd->regs + IIC_CLK_DUR);
 754        mmiowb();
 755
 756        /* verifying that we have a DT3155 board (not just a SAA7116 chip) */
 757        read_i2c_reg(pd->regs, DT_ID, &tmp);
 758        if (tmp != DT3155_ID)
 759                return -ENODEV;
 760
 761        /* initialize AD LUT */
 762        write_i2c_reg(pd->regs, AD_ADDR, 0);
 763        for (i = 0; i < 256; i++)
 764                write_i2c_reg(pd->regs, AD_LUT, i);
 765
 766        /* initialize ADC references */
 767        /* FIXME: pos_ref & neg_ref depend on VT_50HZ */
 768        write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
 769        write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
 770        write_i2c_reg(pd->regs, AD_ADDR, AD_POS_REF);
 771        write_i2c_reg(pd->regs, AD_CMD, 34);
 772        write_i2c_reg(pd->regs, AD_ADDR, AD_NEG_REF);
 773        write_i2c_reg(pd->regs, AD_CMD, 0);
 774
 775        /* initialize PM LUT */
 776        write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM);
 777        for (i = 0; i < 256; i++) {
 778                write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
 779                write_i2c_reg(pd->regs, PM_LUT_DATA, i);
 780        }
 781        write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM | PM_LUT_SEL);
 782        for (i = 0; i < 256; i++) {
 783                write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
 784                write_i2c_reg(pd->regs, PM_LUT_DATA, i);
 785        }
 786        write_i2c_reg(pd->regs, CONFIG, pd->config); /*  ACQ_MODE_EVEN  */
 787
 788        /* select channel 1 for input and set sync level */
 789        write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
 790        write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
 791
 792        /* allocate memory, and initialize the DMA machine */
 793        buf_cpu = dma_alloc_coherent(&pdev->dev, DT3155_BUF_SIZE, &buf_dma,
 794                                                                GFP_KERNEL);
 795        if (!buf_cpu)
 796                return -ENOMEM;
 797        iowrite32(buf_dma, pd->regs + EVEN_DMA_START);
 798        iowrite32(buf_dma, pd->regs + ODD_DMA_START);
 799        iowrite32(0, pd->regs + EVEN_DMA_STRIDE);
 800        iowrite32(0, pd->regs + ODD_DMA_STRIDE);
 801
 802        /*  Perform a pseudo even field acquire    */
 803        iowrite32(FIFO_EN | SRST | CAP_CONT_ODD, pd->regs + CSR1);
 804        write_i2c_reg(pd->regs, CSR2, pd->csr2 | SYNC_SNTL);
 805        write_i2c_reg(pd->regs, CONFIG, pd->config);
 806        write_i2c_reg(pd->regs, EVEN_CSR, CSR_SNGL);
 807        write_i2c_reg(pd->regs, CSR2, pd->csr2 | BUSY_EVEN | SYNC_SNTL);
 808        msleep(100);
 809        read_i2c_reg(pd->regs, CSR2, &tmp);
 810        write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_SNGL | CSR_DONE);
 811        write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_SNGL | CSR_DONE);
 812        write_i2c_reg(pd->regs, CSR2, pd->csr2);
 813        iowrite32(FIFO_EN | SRST | FLD_DN_EVEN | FLD_DN_ODD, pd->regs + CSR1);
 814
 815        /*  deallocate memory  */
 816        dma_free_coherent(&pdev->dev, DT3155_BUF_SIZE, buf_cpu, buf_dma);
 817        if (tmp & BUSY_EVEN)
 818                return -EIO;
 819        return 0;
 820}
 821
 822static struct video_device dt3155_vdev = {
 823        .name = DT3155_NAME,
 824        .fops = &dt3155_fops,
 825        .ioctl_ops = &dt3155_ioctl_ops,
 826        .minor = -1,
 827        .release = video_device_release,
 828        .tvnorms = DT3155_CURRENT_NORM,
 829};
 830
 831/* same as in drivers/base/dma-coherent.c */
 832struct dma_coherent_mem {
 833        void            *virt_base;
 834        dma_addr_t      device_base;
 835        int             size;
 836        int             flags;
 837        unsigned long   *bitmap;
 838};
 839
 840static int
 841dt3155_alloc_coherent(struct device *dev, size_t size, int flags)
 842{
 843        struct dma_coherent_mem *mem;
 844        dma_addr_t dev_base;
 845        int pages = size >> PAGE_SHIFT;
 846        int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
 847
 848        if ((flags & DMA_MEMORY_MAP) == 0)
 849                goto out;
 850        if (!size)
 851                goto out;
 852        if (dev->dma_mem)
 853                goto out;
 854
 855        mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 856        if (!mem)
 857                goto out;
 858        mem->virt_base = dma_alloc_coherent(dev, size, &dev_base,
 859                                                        DT3155_COH_FLAGS);
 860        if (!mem->virt_base)
 861                goto err_alloc_coherent;
 862        mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
 863        if (!mem->bitmap)
 864                goto err_bitmap;
 865
 866        /* coherent_dma_mask is already set to 32 bits */
 867        mem->device_base = dev_base;
 868        mem->size = pages;
 869        mem->flags = flags;
 870        dev->dma_mem = mem;
 871        return DMA_MEMORY_MAP;
 872
 873err_bitmap:
 874        dma_free_coherent(dev, size, mem->virt_base, dev_base);
 875err_alloc_coherent:
 876        kfree(mem);
 877out:
 878        return 0;
 879}
 880
 881static void
 882dt3155_free_coherent(struct device *dev)
 883{
 884        struct dma_coherent_mem *mem = dev->dma_mem;
 885
 886        if (!mem)
 887                return;
 888        dev->dma_mem = NULL;
 889        dma_free_coherent(dev, mem->size << PAGE_SHIFT,
 890                                        mem->virt_base, mem->device_base);
 891        kfree(mem->bitmap);
 892        kfree(mem);
 893}
 894
 895static int
 896dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 897{
 898        int err;
 899        struct dt3155_priv *pd;
 900
 901        err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
 902        if (err)
 903                return -ENODEV;
 904        pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 905        if (!pd)
 906                return -ENOMEM;
 907        pd->vdev = video_device_alloc();
 908        if (!pd->vdev) {
 909                err = -ENOMEM;
 910                goto err_video_device_alloc;
 911        }
 912        *pd->vdev = dt3155_vdev;
 913        pci_set_drvdata(pdev, pd);    /* for use in dt3155_remove() */
 914        video_set_drvdata(pd->vdev, pd);  /* for use in video_fops */
 915        pd->users = 0;
 916        pd->pdev = pdev;
 917        INIT_LIST_HEAD(&pd->dmaq);
 918        mutex_init(&pd->mux);
 919        pd->vdev->lock = &pd->mux; /* for locking v4l2_file_operations */
 920        spin_lock_init(&pd->lock);
 921        pd->csr2 = csr2_init;
 922        pd->config = config_init;
 923        err = pci_enable_device(pdev);
 924        if (err)
 925                goto err_enable_dev;
 926        err = pci_request_region(pdev, 0, pci_name(pdev));
 927        if (err)
 928                goto err_req_region;
 929        pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
 930        if (!pd->regs) {
 931                err = -ENOMEM;
 932                goto err_pci_iomap;
 933        }
 934        err = dt3155_init_board(pdev);
 935        if (err)
 936                goto err_init_board;
 937        err = video_register_device(pd->vdev, VFL_TYPE_GRABBER, -1);
 938        if (err)
 939                goto err_init_board;
 940        if (dt3155_alloc_coherent(&pdev->dev, DT3155_CHUNK_SIZE,
 941                                                        DMA_MEMORY_MAP))
 942                dev_info(&pdev->dev, "preallocated 8 buffers\n");
 943        dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev->minor);
 944        return 0;  /*   success   */
 945
 946err_init_board:
 947        pci_iounmap(pdev, pd->regs);
 948err_pci_iomap:
 949        pci_release_region(pdev, 0);
 950err_req_region:
 951        pci_disable_device(pdev);
 952err_enable_dev:
 953        video_device_release(pd->vdev);
 954err_video_device_alloc:
 955        kfree(pd);
 956        return err;
 957}
 958
 959static void
 960dt3155_remove(struct pci_dev *pdev)
 961{
 962        struct dt3155_priv *pd = pci_get_drvdata(pdev);
 963
 964        dt3155_free_coherent(&pdev->dev);
 965        video_unregister_device(pd->vdev);
 966        pci_iounmap(pdev, pd->regs);
 967        pci_release_region(pdev, 0);
 968        pci_disable_device(pdev);
 969        /*
 970         * video_device_release() is invoked automatically
 971         * see: struct video_device dt3155_vdev
 972         */
 973        kfree(pd);
 974}
 975
 976static const struct pci_device_id pci_ids[] = {
 977        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, DT3155_DEVICE_ID) },
 978        { 0, /* zero marks the end */ },
 979};
 980MODULE_DEVICE_TABLE(pci, pci_ids);
 981
 982static struct pci_driver pci_driver = {
 983        .name = DT3155_NAME,
 984        .id_table = pci_ids,
 985        .probe = dt3155_probe,
 986        .remove = dt3155_remove,
 987};
 988
 989module_pci_driver(pci_driver);
 990
 991MODULE_DESCRIPTION("video4linux pci-driver for dt3155 frame grabber");
 992MODULE_AUTHOR("Marin Mitov <mitov@issp.bas.bg>");
 993MODULE_VERSION(DT3155_VERSION);
 994MODULE_LICENSE("GPL");
 995
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.