linux/drivers/media/pci/saa7134/saa7134-ts.c
<<
>>
Prefs
   1/*
   2 *
   3 * device driver for philips saa7134 based TV cards
   4 * video4linux video interface
   5 *
   6 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
   7 *
   8 *  This program is free software; you can redistribute it and/or modify
   9 *  it under the terms of the GNU General Public License as published by
  10 *  the Free Software Foundation; either version 2 of the License, or
  11 *  (at your option) any later version.
  12 *
  13 *  This program is distributed in the hope that it will be useful,
  14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *  GNU General Public License for more details.
  17 */
  18
  19#include "saa7134.h"
  20#include "saa7134-reg.h"
  21
  22#include <linux/init.h>
  23#include <linux/list.h>
  24#include <linux/module.h>
  25#include <linux/kernel.h>
  26#include <linux/delay.h>
  27
  28/* ------------------------------------------------------------------ */
  29
  30static unsigned int ts_debug;
  31module_param(ts_debug, int, 0644);
  32MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
  33
  34#define ts_dbg(fmt, arg...) do { \
  35        if (ts_debug) \
  36                printk(KERN_DEBUG pr_fmt("ts: " fmt), ## arg); \
  37        } while (0)
  38
  39/* ------------------------------------------------------------------ */
  40static int buffer_activate(struct saa7134_dev *dev,
  41                           struct saa7134_buf *buf,
  42                           struct saa7134_buf *next)
  43{
  44
  45        ts_dbg("buffer_activate [%p]", buf);
  46        buf->top_seen = 0;
  47
  48        if (!dev->ts_started)
  49                dev->ts_field = V4L2_FIELD_TOP;
  50
  51        if (NULL == next)
  52                next = buf;
  53        if (V4L2_FIELD_TOP == dev->ts_field) {
  54                ts_dbg("- [top]     buf=%p next=%p\n", buf, next);
  55                saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
  56                saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
  57                dev->ts_field = V4L2_FIELD_BOTTOM;
  58        } else {
  59                ts_dbg("- [bottom]  buf=%p next=%p\n", buf, next);
  60                saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
  61                saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
  62                dev->ts_field = V4L2_FIELD_TOP;
  63        }
  64
  65        /* start DMA */
  66        saa7134_set_dmabits(dev);
  67
  68        mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT);
  69
  70        if (!dev->ts_started)
  71                saa7134_ts_start(dev);
  72
  73        return 0;
  74}
  75
  76int saa7134_ts_buffer_init(struct vb2_buffer *vb2)
  77{
  78        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
  79        struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
  80        struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
  81
  82        dmaq->curr = NULL;
  83        buf->activate = buffer_activate;
  84
  85        return 0;
  86}
  87EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init);
  88
  89int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
  90{
  91        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
  92        struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
  93        struct saa7134_dev *dev = dmaq->dev;
  94        struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
  95        struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
  96        unsigned int lines, llength, size;
  97
  98        ts_dbg("buffer_prepare [%p]\n", buf);
  99
 100        llength = TS_PACKET_SIZE;
 101        lines = dev->ts.nr_packets;
 102
 103        size = lines * llength;
 104        if (vb2_plane_size(vb2, 0) < size)
 105                return -EINVAL;
 106
 107        vb2_set_plane_payload(vb2, 0, size);
 108        vbuf->field = dev->field;
 109
 110        return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 111                                    saa7134_buffer_startpage(buf));
 112}
 113EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
 114
 115int saa7134_ts_queue_setup(struct vb2_queue *q,
 116                           unsigned int *nbuffers, unsigned int *nplanes,
 117                           unsigned int sizes[], struct device *alloc_devs[])
 118{
 119        struct saa7134_dmaqueue *dmaq = q->drv_priv;
 120        struct saa7134_dev *dev = dmaq->dev;
 121        int size = TS_PACKET_SIZE * dev->ts.nr_packets;
 122
 123        if (0 == *nbuffers)
 124                *nbuffers = dev->ts.nr_bufs;
 125        *nbuffers = saa7134_buffer_count(size, *nbuffers);
 126        if (*nbuffers < 3)
 127                *nbuffers = 3;
 128        *nplanes = 1;
 129        sizes[0] = size;
 130        return 0;
 131}
 132EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup);
 133
 134int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count)
 135{
 136        struct saa7134_dmaqueue *dmaq = vq->drv_priv;
 137        struct saa7134_dev *dev = dmaq->dev;
 138
 139        /*
 140         * Planar video capture and TS share the same DMA channel,
 141         * so only one can be active at a time.
 142         */
 143        if (vb2_is_busy(&dev->video_vbq) && dev->fmt->planar) {
 144                struct saa7134_buf *buf, *tmp;
 145
 146                list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
 147                        list_del(&buf->entry);
 148                        vb2_buffer_done(&buf->vb2.vb2_buf,
 149                                        VB2_BUF_STATE_QUEUED);
 150                }
 151                if (dmaq->curr) {
 152                        vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,
 153                                        VB2_BUF_STATE_QUEUED);
 154                        dmaq->curr = NULL;
 155                }
 156                return -EBUSY;
 157        }
 158        dmaq->seq_nr = 0;
 159        return 0;
 160}
 161EXPORT_SYMBOL_GPL(saa7134_ts_start_streaming);
 162
 163void saa7134_ts_stop_streaming(struct vb2_queue *vq)
 164{
 165        struct saa7134_dmaqueue *dmaq = vq->drv_priv;
 166        struct saa7134_dev *dev = dmaq->dev;
 167
 168        saa7134_ts_stop(dev);
 169        saa7134_stop_streaming(dev, dmaq);
 170}
 171EXPORT_SYMBOL_GPL(saa7134_ts_stop_streaming);
 172
 173struct vb2_ops saa7134_ts_qops = {
 174        .queue_setup    = saa7134_ts_queue_setup,
 175        .buf_init       = saa7134_ts_buffer_init,
 176        .buf_prepare    = saa7134_ts_buffer_prepare,
 177        .buf_queue      = saa7134_vb2_buffer_queue,
 178        .wait_prepare   = vb2_ops_wait_prepare,
 179        .wait_finish    = vb2_ops_wait_finish,
 180        .stop_streaming = saa7134_ts_stop_streaming,
 181};
 182EXPORT_SYMBOL_GPL(saa7134_ts_qops);
 183
 184/* ----------------------------------------------------------- */
 185/* exported stuff                                              */
 186
 187static unsigned int tsbufs = 8;
 188module_param(tsbufs, int, 0444);
 189MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32");
 190
 191static unsigned int ts_nr_packets = 64;
 192module_param(ts_nr_packets, int, 0444);
 193MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
 194
 195int saa7134_ts_init_hw(struct saa7134_dev *dev)
 196{
 197        /* deactivate TS softreset */
 198        saa_writeb(SAA7134_TS_SERIAL1, 0x00);
 199        /* TSSOP high active, TSVAL high active, TSLOCK ignored */
 200        saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
 201        saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
 202        saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
 203        saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
 204        /* TSNOPIT=0, TSCOLAP=0 */
 205        saa_writeb(SAA7134_TS_DMA2,
 206                ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00));
 207
 208        return 0;
 209}
 210
 211int saa7134_ts_init1(struct saa7134_dev *dev)
 212{
 213        /* sanitycheck insmod options */
 214        if (tsbufs < 2)
 215                tsbufs = 2;
 216        if (tsbufs > VIDEO_MAX_FRAME)
 217                tsbufs = VIDEO_MAX_FRAME;
 218        if (ts_nr_packets < 4)
 219                ts_nr_packets = 4;
 220        if (ts_nr_packets > 312)
 221                ts_nr_packets = 312;
 222        dev->ts.nr_bufs    = tsbufs;
 223        dev->ts.nr_packets = ts_nr_packets;
 224
 225        INIT_LIST_HEAD(&dev->ts_q.queue);
 226        timer_setup(&dev->ts_q.timeout, saa7134_buffer_timeout, 0);
 227        dev->ts_q.dev              = dev;
 228        dev->ts_q.need_two         = 1;
 229        dev->ts_started            = 0;
 230        saa7134_pgtable_alloc(dev->pci, &dev->ts_q.pt);
 231
 232        /* init TS hw */
 233        saa7134_ts_init_hw(dev);
 234
 235        return 0;
 236}
 237
 238/* Function for stop TS */
 239int saa7134_ts_stop(struct saa7134_dev *dev)
 240{
 241        ts_dbg("TS stop\n");
 242
 243        if (!dev->ts_started)
 244                return 0;
 245
 246        /* Stop TS stream */
 247        switch (saa7134_boards[dev->board].ts_type) {
 248        case SAA7134_MPEG_TS_PARALLEL:
 249                saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
 250                dev->ts_started = 0;
 251                break;
 252        case SAA7134_MPEG_TS_SERIAL:
 253                saa_writeb(SAA7134_TS_SERIAL0, 0x40);
 254                dev->ts_started = 0;
 255                break;
 256        }
 257        return 0;
 258}
 259
 260/* Function for start TS */
 261int saa7134_ts_start(struct saa7134_dev *dev)
 262{
 263        ts_dbg("TS start\n");
 264
 265        if (WARN_ON(dev->ts_started))
 266                return 0;
 267
 268        /* dma: setup channel 5 (= TS) */
 269        saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
 270        saa_writeb(SAA7134_TS_DMA1,
 271                ((dev->ts.nr_packets - 1) >> 8) & 0xff);
 272        /* TSNOPIT=0, TSCOLAP=0 */
 273        saa_writeb(SAA7134_TS_DMA2,
 274                (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
 275        saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
 276        saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
 277                                          SAA7134_RS_CONTROL_ME |
 278                                          (dev->ts_q.pt.dma >> 12));
 279
 280        /* reset hardware TS buffers */
 281        saa_writeb(SAA7134_TS_SERIAL1, 0x00);
 282        saa_writeb(SAA7134_TS_SERIAL1, 0x03);
 283        saa_writeb(SAA7134_TS_SERIAL1, 0x00);
 284        saa_writeb(SAA7134_TS_SERIAL1, 0x01);
 285
 286        /* TS clock non-inverted */
 287        saa_writeb(SAA7134_TS_SERIAL1, 0x00);
 288
 289        /* Start TS stream */
 290        switch (saa7134_boards[dev->board].ts_type) {
 291        case SAA7134_MPEG_TS_PARALLEL:
 292                saa_writeb(SAA7134_TS_SERIAL0, 0x40);
 293                saa_writeb(SAA7134_TS_PARALLEL, 0xec |
 294                        (saa7134_boards[dev->board].ts_force_val << 4));
 295                break;
 296        case SAA7134_MPEG_TS_SERIAL:
 297                saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
 298                saa_writeb(SAA7134_TS_PARALLEL, 0x6c |
 299                        (saa7134_boards[dev->board].ts_force_val << 4));
 300                saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
 301                saa_writeb(SAA7134_TS_SERIAL1, 0x02);
 302                break;
 303        }
 304
 305        dev->ts_started = 1;
 306
 307        return 0;
 308}
 309
 310int saa7134_ts_fini(struct saa7134_dev *dev)
 311{
 312        saa7134_pgtable_free(dev->pci, &dev->ts_q.pt);
 313        return 0;
 314}
 315
 316void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
 317{
 318        enum v4l2_field field;
 319
 320        spin_lock(&dev->slock);
 321        if (dev->ts_q.curr) {
 322                field = dev->ts_field;
 323                if (field != V4L2_FIELD_TOP) {
 324                        if ((status & 0x100000) != 0x000000)
 325                                goto done;
 326                } else {
 327                        if ((status & 0x100000) != 0x100000)
 328                                goto done;
 329                }
 330                saa7134_buffer_finish(dev, &dev->ts_q, VB2_BUF_STATE_DONE);
 331        }
 332        saa7134_buffer_next(dev,&dev->ts_q);
 333
 334 done:
 335        spin_unlock(&dev->slock);
 336}
 337