saa7134-vbi.c 6.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 *
 * device driver for philips saa7134 based TV cards
 * video4linux video interface
 *
 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

19 20 21
#include "saa7134.h"
#include "saa7134-reg.h"

L
Linus Torvalds 已提交
22 23 24 25 26 27 28
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>

/* ------------------------------------------------------------------ */

29
static unsigned int vbi_debug;
L
Linus Torvalds 已提交
30 31 32 33 34 35 36
module_param(vbi_debug, int, 0644);
MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");

static unsigned int vbibufs = 4;
module_param(vbibufs, int, 0444);
MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");

37 38 39 40
#define vbi_dbg(fmt, arg...) do { \
	if (vbi_debug) \
		printk(KERN_DEBUG pr_fmt("vbi: " fmt), ## arg); \
	} while (0)
L
Linus Torvalds 已提交
41 42 43

/* ------------------------------------------------------------------ */

44
#define VBI_LINE_COUNT     17
L
Linus Torvalds 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57
#define VBI_LINE_LENGTH  2048
#define VBI_SCALE       0x200

static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf,
		      int task)
{
	struct saa7134_tvnorm *norm = dev->tvnorm;

	/* setup video scaler */
	saa_writeb(SAA7134_VBI_H_START1(task), norm->h_start     &  0xff);
	saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start     >> 8);
	saa_writeb(SAA7134_VBI_H_STOP1(task),  norm->h_stop      &  0xff);
	saa_writeb(SAA7134_VBI_H_STOP2(task),  norm->h_stop      >> 8);
58 59 60 61
	saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 &  0xff);
	saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8);
	saa_writeb(SAA7134_VBI_V_STOP1(task),  norm->vbi_v_stop_0  &  0xff);
	saa_writeb(SAA7134_VBI_V_STOP2(task),  norm->vbi_v_stop_0  >> 8);
L
Linus Torvalds 已提交
62 63 64 65 66 67

	saa_writeb(SAA7134_VBI_H_SCALE_INC1(task),        VBI_SCALE & 0xff);
	saa_writeb(SAA7134_VBI_H_SCALE_INC2(task),        VBI_SCALE >> 8);
	saa_writeb(SAA7134_VBI_PHASE_OFFSET_LUMA(task),   0x00);
	saa_writeb(SAA7134_VBI_PHASE_OFFSET_CHROMA(task), 0x00);

68 69 70 71
	saa_writeb(SAA7134_VBI_H_LEN1(task), dev->vbi_hlen & 0xff);
	saa_writeb(SAA7134_VBI_H_LEN2(task), dev->vbi_hlen >> 8);
	saa_writeb(SAA7134_VBI_V_LEN1(task), dev->vbi_vlen & 0xff);
	saa_writeb(SAA7134_VBI_V_LEN2(task), dev->vbi_vlen >> 8);
L
Linus Torvalds 已提交
72 73 74 75 76 77 78 79 80 81

	saa_andorb(SAA7134_DATA_PATH(task), 0xc0, 0x00);
}

/* ------------------------------------------------------------------ */

static int buffer_activate(struct saa7134_dev *dev,
			   struct saa7134_buf *buf,
			   struct saa7134_buf *next)
{
82
	struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv;
83
	unsigned long control, base;
L
Linus Torvalds 已提交
84

85
	vbi_dbg("buffer_activate [%p]\n", buf);
L
Linus Torvalds 已提交
86 87
	buf->top_seen = 0;

88 89
	task_init(dev, buf, TASK_A);
	task_init(dev, buf, TASK_B);
L
Linus Torvalds 已提交
90 91 92 93 94 95 96
	saa_writeb(SAA7134_OFMT_DATA_A, 0x06);
	saa_writeb(SAA7134_OFMT_DATA_B, 0x06);

	/* DMA: setup channel 2+3 (= VBI Task A+B) */
	base    = saa7134_buffer_base(buf);
	control = SAA7134_RS_CONTROL_BURST_16 |
		SAA7134_RS_CONTROL_ME |
H
Hans Verkuil 已提交
97
		(dmaq->pt.dma >> 12);
98
	saa_writel(SAA7134_RS_BA1(2), base);
99 100
	saa_writel(SAA7134_RS_BA2(2), base + dev->vbi_hlen * dev->vbi_vlen);
	saa_writel(SAA7134_RS_PITCH(2), dev->vbi_hlen);
101 102
	saa_writel(SAA7134_RS_CONTROL(2), control);
	saa_writel(SAA7134_RS_BA1(3), base);
103 104
	saa_writel(SAA7134_RS_BA2(3), base + dev->vbi_hlen * dev->vbi_vlen);
	saa_writel(SAA7134_RS_PITCH(3), dev->vbi_hlen);
105
	saa_writel(SAA7134_RS_CONTROL(3), control);
L
Linus Torvalds 已提交
106 107 108

	/* start DMA */
	saa7134_set_dmabits(dev);
H
Hans Verkuil 已提交
109
	mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT);
L
Linus Torvalds 已提交
110 111 112 113

	return 0;
}

H
Hans Verkuil 已提交
114
static int buffer_prepare(struct vb2_buffer *vb2)
L
Linus Torvalds 已提交
115
{
H
Hans Verkuil 已提交
116
	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
117
	struct saa7134_dev *dev = dmaq->dev;
118 119 120
	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
	struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
121
	unsigned int size;
L
Linus Torvalds 已提交
122

123 124 125 126
	if (dma->sgl->offset) {
		pr_err("The buffer is not page-aligned\n");
		return -EINVAL;
	}
127
	size = dev->vbi_hlen * dev->vbi_vlen * 2;
H
Hans Verkuil 已提交
128
	if (vb2_plane_size(vb2, 0) < size)
L
Linus Torvalds 已提交
129 130
		return -EINVAL;

H
Hans Verkuil 已提交
131
	vb2_set_plane_payload(vb2, 0, size);
L
Linus Torvalds 已提交
132

H
Hans Verkuil 已提交
133 134
	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
				    saa7134_buffer_startpage(buf));
L
Linus Torvalds 已提交
135 136
}

137
static int queue_setup(struct vb2_queue *q,
H
Hans Verkuil 已提交
138
			   unsigned int *nbuffers, unsigned int *nplanes,
139
			   unsigned int sizes[], struct device *alloc_devs[])
L
Linus Torvalds 已提交
140
{
H
Hans Verkuil 已提交
141
	struct saa7134_dmaqueue *dmaq = q->drv_priv;
142
	struct saa7134_dev *dev = dmaq->dev;
H
Hans Verkuil 已提交
143
	unsigned int size;
L
Linus Torvalds 已提交
144

145 146 147 148
	dev->vbi_vlen = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 + 1;
	if (dev->vbi_vlen > VBI_LINE_COUNT)
		dev->vbi_vlen = VBI_LINE_COUNT;
	dev->vbi_hlen = VBI_LINE_LENGTH;
H
Hans Verkuil 已提交
149 150 151 152 153
	size = dev->vbi_hlen * dev->vbi_vlen * 2;

	*nbuffers = saa7134_buffer_count(size, *nbuffers);
	*nplanes = 1;
	sizes[0] = size;
L
Linus Torvalds 已提交
154 155 156
	return 0;
}

H
Hans Verkuil 已提交
157
static int buffer_init(struct vb2_buffer *vb2)
L
Linus Torvalds 已提交
158
{
H
Hans Verkuil 已提交
159
	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
160 161
	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
L
Linus Torvalds 已提交
162

H
Hans Verkuil 已提交
163 164 165
	dmaq->curr = NULL;
	buf->activate = buffer_activate;
	return 0;
L
Linus Torvalds 已提交
166 167
}

H
Hans Verkuil 已提交
168 169 170 171 172 173 174 175 176
struct vb2_ops saa7134_vbi_qops = {
	.queue_setup	= queue_setup,
	.buf_init	= buffer_init,
	.buf_prepare	= buffer_prepare,
	.buf_queue	= saa7134_vb2_buffer_queue,
	.wait_prepare	= vb2_ops_wait_prepare,
	.wait_finish	= vb2_ops_wait_finish,
	.start_streaming = saa7134_vb2_start_streaming,
	.stop_streaming = saa7134_vb2_stop_streaming,
L
Linus Torvalds 已提交
177 178 179 180 181 182 183
};

/* ------------------------------------------------------------------ */

int saa7134_vbi_init1(struct saa7134_dev *dev)
{
	INIT_LIST_HEAD(&dev->vbi_q.queue);
G
Geliang Tang 已提交
184 185
	setup_timer(&dev->vbi_q.timeout, saa7134_buffer_timeout,
		    (unsigned long)(&dev->vbi_q));
L
Linus Torvalds 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
	dev->vbi_q.dev              = dev;

	if (vbibufs < 2)
		vbibufs = 2;
	if (vbibufs > VIDEO_MAX_FRAME)
		vbibufs = VIDEO_MAX_FRAME;
	return 0;
}

int saa7134_vbi_fini(struct saa7134_dev *dev)
{
	/* nothing */
	return 0;
}

void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
{
	spin_lock(&dev->slock);
	if (dev->vbi_q.curr) {
		/* make sure we have seen both fields */
		if ((status & 0x10) == 0x00) {
			dev->vbi_q.curr->top_seen = 1;
			goto done;
		}
		if (!dev->vbi_q.curr->top_seen)
			goto done;

H
Hans Verkuil 已提交
213
		saa7134_buffer_finish(dev, &dev->vbi_q, VB2_BUF_STATE_DONE);
L
Linus Torvalds 已提交
214
	}
215
	saa7134_buffer_next(dev, &dev->vbi_q);
L
Linus Torvalds 已提交
216 217 218 219

 done:
	spin_unlock(&dev->slock);
}