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 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23#include <linux/init.h> 24#include <linux/list.h> 25#include <linux/module.h> 26#include <linux/kernel.h> 27#include <linux/delay.h> 28 29#include "saa7134-reg.h" 30#include "saa7134.h" 31 32/* ------------------------------------------------------------------ */ 33 34static unsigned int ts_debug; 35module_param(ts_debug, int, 0644); 36MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); 37 38#define dprintk(fmt, arg...) if (ts_debug) \ 39 printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg) 40 41/* ------------------------------------------------------------------ */ 42 43static int buffer_activate(struct saa7134_dev *dev, 44 struct saa7134_buf *buf, 45 struct saa7134_buf *next) 46{ 47 48 dprintk("buffer_activate [%p]",buf); 49 buf->vb.state = VIDEOBUF_ACTIVE; 50 buf->top_seen = 0; 51 52 if (NULL == next) 53 next = buf; 54 if (V4L2_FIELD_TOP == buf->vb.field) { 55 dprintk("- [top] buf=%p next=%p\n",buf,next); 56 saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf)); 57 saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next)); 58 } else { 59 dprintk("- [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 } 63 64 /* start DMA */ 65 saa7134_set_dmabits(dev); 66 67 mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT); 68 69 if (!dev->ts_started) 70 saa7134_ts_start(dev); 71 72 return 0; 73} 74 75static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, 76 enum v4l2_field field) 77{ 78 struct saa7134_dev *dev = q->priv_data; 79 struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); 80 unsigned int lines, llength, size; 81 int err; 82 83 dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]); 84 85 llength = TS_PACKET_SIZE; 86 lines = dev->ts.nr_packets; 87 88 size = lines * llength; 89 if (0 != buf->vb.baddr && buf->vb.bsize < size) 90 return -EINVAL; 91 92 if (buf->vb.size != size) { 93 saa7134_dma_free(q,buf); 94 } 95 96 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { 97 98 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); 99 100 dprintk("buffer_prepare: needs_init\n"); 101 102 buf->vb.width = llength; 103 buf->vb.height = lines; 104 buf->vb.size = size; 105 buf->pt = &dev->ts.pt_ts; 106 107 err = videobuf_iolock(q,&buf->vb,NULL); 108 if (err) 109 goto oops; 110 err = saa7134_pgtable_build(dev->pci,buf->pt, 111 dma->sglist, 112 dma->sglen, 113 saa7134_buffer_startpage(buf)); 114 if (err) 115 goto oops; 116 } 117 118 buf->vb.state = VIDEOBUF_PREPARED; 119 buf->activate = buffer_activate; 120 buf->vb.field = field; 121 return 0; 122 123 oops: 124 saa7134_dma_free(q,buf); 125 return err; 126} 127 128static int 129buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) 130{ 131 struct saa7134_dev *dev = q->priv_data; 132 133 *size = TS_PACKET_SIZE * dev->ts.nr_packets; 134 if (0 == *count) 135 *count = dev->ts.nr_bufs; 136 *count = saa7134_buffer_count(*size,*count); 137 138 return 0; 139} 140 141static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) 142{ 143 struct saa7134_dev *dev = q->priv_data; 144 struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); 145 146 saa7134_buffer_queue(dev,&dev->ts_q,buf); 147} 148 149static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) 150{ 151 struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); 152 struct saa7134_dev *dev = q->priv_data; 153 154 if (dev->ts_started) 155 saa7134_ts_stop(dev); 156 157 saa7134_dma_free(q,buf); 158} 159 160struct videobuf_queue_ops saa7134_ts_qops = { 161 .buf_setup = buffer_setup, 162 .buf_prepare = buffer_prepare, 163 .buf_queue = buffer_queue, 164 .buf_release = buffer_release, 165}; 166EXPORT_SYMBOL_GPL(saa7134_ts_qops); 167 168/* ----------------------------------------------------------- */ 169/* exported stuff */ 170 171static unsigned int tsbufs = 8; 172module_param(tsbufs, int, 0444); 173MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32"); 174 175static unsigned int ts_nr_packets = 64; 176module_param(ts_nr_packets, int, 0444); 177MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); 178 179int saa7134_ts_init_hw(struct saa7134_dev *dev) 180{ 181 /* deactivate TS softreset */ 182 saa_writeb(SAA7134_TS_SERIAL1, 0x00); 183 /* TSSOP high active, TSVAL high active, TSLOCK ignored */ 184 saa_writeb(SAA7134_TS_PARALLEL, 0x6c); 185 saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); 186 saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); 187 saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); 188 /* TSNOPIT=0, TSCOLAP=0 */ 189 saa_writeb(SAA7134_TS_DMA2, 190 ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); 191 192 return 0; 193} 194 195int saa7134_ts_init1(struct saa7134_dev *dev) 196{ 197 /* sanitycheck insmod options */ 198 if (tsbufs < 2) 199 tsbufs = 2; 200 if (tsbufs > VIDEO_MAX_FRAME) 201 tsbufs = VIDEO_MAX_FRAME; 202 if (ts_nr_packets < 4) 203 ts_nr_packets = 4; 204 if (ts_nr_packets > 312) 205 ts_nr_packets = 312; 206 dev->ts.nr_bufs = tsbufs; 207 dev->ts.nr_packets = ts_nr_packets; 208 209 INIT_LIST_HEAD(&dev->ts_q.queue); 210 init_timer(&dev->ts_q.timeout); 211 dev->ts_q.timeout.function = saa7134_buffer_timeout; 212 dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q); 213 dev->ts_q.dev = dev; 214 dev->ts_q.need_two = 1; 215 dev->ts_started = 0; 216 saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); 217 218 /* init TS hw */ 219 saa7134_ts_init_hw(dev); 220 221 return 0; 222} 223 224/* Function for stop TS */ 225int saa7134_ts_stop(struct saa7134_dev *dev) 226{ 227 dprintk("TS stop\n"); 228 229 BUG_ON(!dev->ts_started); 230 231 /* Stop TS stream */ 232 switch (saa7134_boards[dev->board].ts_type) { 233 case SAA7134_MPEG_TS_PARALLEL: 234 saa_writeb(SAA7134_TS_PARALLEL, 0x6c); 235 dev->ts_started = 0; 236 break; 237 case SAA7134_MPEG_TS_SERIAL: 238 saa_writeb(SAA7134_TS_SERIAL0, 0x40); 239 dev->ts_started = 0; 240 break; 241 } 242 return 0; 243} 244 245/* Function for start TS */ 246int saa7134_ts_start(struct saa7134_dev *dev) 247{ 248 dprintk("TS start\n"); 249 250 BUG_ON(dev->ts_started); 251 252 /* dma: setup channel 5 (= TS) */ 253 saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); 254 saa_writeb(SAA7134_TS_DMA1, 255 ((dev->ts.nr_packets - 1) >> 8) & 0xff); 256 /* TSNOPIT=0, TSCOLAP=0 */ 257 saa_writeb(SAA7134_TS_DMA2, 258 (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); 259 saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); 260 saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | 261 SAA7134_RS_CONTROL_ME | 262 (dev->ts.pt_ts.dma >> 12)); 263 264 /* reset hardware TS buffers */ 265 saa_writeb(SAA7134_TS_SERIAL1, 0x00); 266 saa_writeb(SAA7134_TS_SERIAL1, 0x03); 267 saa_writeb(SAA7134_TS_SERIAL1, 0x00); 268 saa_writeb(SAA7134_TS_SERIAL1, 0x01); 269 270 /* TS clock non-inverted */ 271 saa_writeb(SAA7134_TS_SERIAL1, 0x00); 272 273 /* Start TS stream */ 274 switch (saa7134_boards[dev->board].ts_type) { 275 case SAA7134_MPEG_TS_PARALLEL: 276 saa_writeb(SAA7134_TS_SERIAL0, 0x40); 277 saa_writeb(SAA7134_TS_PARALLEL, 0xec | 278 (saa7134_boards[dev->board].ts_force_val << 4)); 279 break; 280 case SAA7134_MPEG_TS_SERIAL: 281 saa_writeb(SAA7134_TS_SERIAL0, 0xd8); 282 saa_writeb(SAA7134_TS_PARALLEL, 0x6c | 283 (saa7134_boards[dev->board].ts_force_val << 4)); 284 saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc); 285 saa_writeb(SAA7134_TS_SERIAL1, 0x02); 286 break; 287 } 288 289 dev->ts_started = 1; 290 291 return 0; 292} 293 294int saa7134_ts_fini(struct saa7134_dev *dev) 295{ 296 saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts); 297 return 0; 298} 299 300void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status) 301{ 302 enum v4l2_field field; 303 304 spin_lock(&dev->slock); 305 if (dev->ts_q.curr) { 306 field = dev->ts_q.curr->vb.field; 307 if (field == V4L2_FIELD_TOP) { 308 if ((status & 0x100000) != 0x000000) 309 goto done; 310 } else { 311 if ((status & 0x100000) != 0x100000) 312 goto done; 313 } 314 saa7134_buffer_finish(dev,&dev->ts_q,VIDEOBUF_DONE); 315 } 316 saa7134_buffer_next(dev,&dev->ts_q); 317 318 done: 319 spin_unlock(&dev->slock); 320} 321 322/* ----------------------------------------------------------- */ 323/* 324 * Local variables: 325 * c-basic-offset: 8 326 * End: 327 */ 328