saa7134-empress.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
1/* 2 * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $ 3 * 4 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21#include <linux/init.h> 22#include <linux/list.h> 23#include <linux/module.h> 24#include <linux/moduleparam.h> 25#include <linux/kernel.h> 26#include <linux/slab.h> 27#include <linux/delay.h> 28 29#include "saa7134-reg.h" 30#include "saa7134.h" 31 32#include <media/saa6752hs.h> 33 34/* ------------------------------------------------------------------ */ 35 36MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); 37MODULE_LICENSE("GPL"); 38 39static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; 40module_param_array(empress_nr, int, NULL, 0444); 41MODULE_PARM_DESC(empress_nr,"ts device number"); 42 43static unsigned int debug = 0; 44module_param(debug, int, 0644); 45MODULE_PARM_DESC(debug,"enable debug messages"); 46 47#define dprintk(fmt, arg...) if (debug) \ 48 printk(KERN_DEBUG "%s/empress: " fmt, dev->name , ## arg) 49 50/* ------------------------------------------------------------------ */ 51 52static void ts_reset_encoder(struct saa7134_dev* dev) 53{ 54 if (!dev->empress_started) 55 return; 56 57 saa_writeb(SAA7134_SPECIAL_MODE, 0x00); 58 msleep(10); 59 saa_writeb(SAA7134_SPECIAL_MODE, 0x01); 60 msleep(100); 61 dev->empress_started = 0; 62} 63 64static int ts_init_encoder(struct saa7134_dev* dev) 65{ 66 ts_reset_encoder(dev); 67 saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL); 68 dev->empress_started = 1; 69 return 0; 70} 71 72/* ------------------------------------------------------------------ */ 73 74static int ts_open(struct inode *inode, struct file *file) 75{ 76 int minor = iminor(inode); 77 struct saa7134_dev *h,*dev = NULL; 78 struct list_head *list; 79 int err; 80 81 list_for_each(list,&saa7134_devlist) { 82 h = list_entry(list, struct saa7134_dev, devlist); 83 if (h->empress_dev && h->empress_dev->minor == minor) 84 dev = h; 85 } 86 if (NULL == dev) 87 return -ENODEV; 88 89 dprintk("open minor=%d\n",minor); 90 err = -EBUSY; 91 if (down_trylock(&dev->empress_tsq.lock)) 92 goto done; 93 if (dev->empress_users) 94 goto done_up; 95 96 dev->empress_users++; 97 file->private_data = dev; 98 err = 0; 99 100done_up: 101 up(&dev->empress_tsq.lock); 102done: 103 return err; 104} 105 106static int ts_release(struct inode *inode, struct file *file) 107{ 108 struct saa7134_dev *dev = file->private_data; 109 110 if (dev->empress_tsq.streaming) 111 videobuf_streamoff(&dev->empress_tsq); 112 down(&dev->empress_tsq.lock); 113 if (dev->empress_tsq.reading) 114 videobuf_read_stop(&dev->empress_tsq); 115 videobuf_mmap_free(&dev->empress_tsq); 116 dev->empress_users--; 117 118 /* stop the encoder */ 119 ts_reset_encoder(dev); 120 121 up(&dev->empress_tsq.lock); 122 return 0; 123} 124 125static ssize_t 126ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos) 127{ 128 struct saa7134_dev *dev = file->private_data; 129 130 if (!dev->empress_started) 131 ts_init_encoder(dev); 132 133 return videobuf_read_stream(&dev->empress_tsq, 134 data, count, ppos, 0, 135 file->f_flags & O_NONBLOCK); 136} 137 138static unsigned int 139ts_poll(struct file *file, struct poll_table_struct *wait) 140{ 141 struct saa7134_dev *dev = file->private_data; 142 143 return videobuf_poll_stream(file, &dev->empress_tsq, wait); 144} 145 146 147static int 148ts_mmap(struct file *file, struct vm_area_struct * vma) 149{ 150 struct saa7134_dev *dev = file->private_data; 151 152 return videobuf_mmap_mapper(&dev->empress_tsq, vma); 153} 154 155/* 156 * This function is _not_ called directly, but from 157 * video_generic_ioctl (and maybe others). userspace 158 * copying is done already, arg is a kernel pointer. 159 */ 160static int ts_do_ioctl(struct inode *inode, struct file *file, 161 unsigned int cmd, void *arg) 162{ 163 struct saa7134_dev *dev = file->private_data; 164 165 if (debug > 1) 166 saa7134_print_ioctl(dev->name,cmd); 167 switch (cmd) { 168 case VIDIOC_QUERYCAP: 169 { 170 struct v4l2_capability *cap = arg; 171 172 memset(cap,0,sizeof(*cap)); 173 strcpy(cap->driver, "saa7134"); 174 strlcpy(cap->card, saa7134_boards[dev->board].name, 175 sizeof(cap->card)); 176 sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); 177 cap->version = SAA7134_VERSION_CODE; 178 cap->capabilities = 179 V4L2_CAP_VIDEO_CAPTURE | 180 V4L2_CAP_READWRITE | 181 V4L2_CAP_STREAMING; 182 return 0; 183 } 184 185 /* --- input switching --------------------------------------- */ 186 case VIDIOC_ENUMINPUT: 187 { 188 struct v4l2_input *i = arg; 189 190 if (i->index != 0) 191 return -EINVAL; 192 i->type = V4L2_INPUT_TYPE_CAMERA; 193 strcpy(i->name,"CCIR656"); 194 return 0; 195 } 196 case VIDIOC_G_INPUT: 197 { 198 int *i = arg; 199 *i = 0; 200 return 0; 201 } 202 case VIDIOC_S_INPUT: 203 { 204 int *i = arg; 205 206 if (*i != 0) 207 return -EINVAL; 208 return 0; 209 } 210 /* --- capture ioctls ---------------------------------------- */ 211 212 case VIDIOC_ENUM_FMT: 213 { 214 struct v4l2_fmtdesc *f = arg; 215 int index; 216 217 index = f->index; 218 if (index != 0) 219 return -EINVAL; 220 221 memset(f,0,sizeof(*f)); 222 f->index = index; 223 strlcpy(f->description, "MPEG TS", sizeof(f->description)); 224 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 225 f->pixelformat = V4L2_PIX_FMT_MPEG; 226 return 0; 227 } 228 229 case VIDIOC_G_FMT: 230 { 231 struct v4l2_format *f = arg; 232 233 memset(f,0,sizeof(*f)); 234 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 235 236 /* FIXME: translate subsampling type EMPRESS into 237 * width/height: */ 238 f->fmt.pix.width = 720; /* D1 */ 239 f->fmt.pix.height = 576; 240 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 241 f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; 242 return 0; 243 } 244 245 case VIDIOC_S_FMT: 246 { 247 struct v4l2_format *f = arg; 248 249 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 250 return -EINVAL; 251 252 /* 253 FIXME: translate and round width/height into EMPRESS 254 subsample type: 255 256 type | PAL | NTSC 257 --------------------------- 258 SIF | 352x288 | 352x240 259 1/2 D1 | 352x576 | 352x480 260 2/3 D1 | 480x576 | 480x480 261 D1 | 720x576 | 720x480 262 */ 263 264 f->fmt.pix.width = 720; /* D1 */ 265 f->fmt.pix.height = 576; 266 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 267 f->fmt.pix.sizeimage = TS_PACKET_SIZE* dev->ts.nr_packets; 268 return 0; 269 } 270 271 case VIDIOC_REQBUFS: 272 return videobuf_reqbufs(&dev->empress_tsq,arg); 273 274 case VIDIOC_QUERYBUF: 275 return videobuf_querybuf(&dev->empress_tsq,arg); 276 277 case VIDIOC_QBUF: 278 return videobuf_qbuf(&dev->empress_tsq,arg); 279 280 case VIDIOC_DQBUF: 281 return videobuf_dqbuf(&dev->empress_tsq,arg, 282 file->f_flags & O_NONBLOCK); 283 284 case VIDIOC_STREAMON: 285 return videobuf_streamon(&dev->empress_tsq); 286 287 case VIDIOC_STREAMOFF: 288 return videobuf_streamoff(&dev->empress_tsq); 289 290 case VIDIOC_QUERYCTRL: 291 case VIDIOC_G_CTRL: 292 case VIDIOC_S_CTRL: 293 return saa7134_common_ioctl(dev, cmd, arg); 294 295 case VIDIOC_S_MPEGCOMP: 296 saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg); 297 ts_init_encoder(dev); 298 return 0; 299 case VIDIOC_G_MPEGCOMP: 300 saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg); 301 return 0; 302 303 default: 304 return -ENOIOCTLCMD; 305 } 306 return 0; 307} 308 309static int ts_ioctl(struct inode *inode, struct file *file, 310 unsigned int cmd, unsigned long arg) 311{ 312 return video_usercopy(inode, file, cmd, arg, ts_do_ioctl); 313} 314 315static struct file_operations ts_fops = 316{ 317 .owner = THIS_MODULE, 318 .open = ts_open, 319 .release = ts_release, 320 .read = ts_read, 321 .poll = ts_poll, 322 .mmap = ts_mmap, 323 .ioctl = ts_ioctl, 324 .llseek = no_llseek, 325}; 326 327/* ----------------------------------------------------------- */ 328 329static struct video_device saa7134_empress_template = 330{ 331 .name = "saa7134-empress", 332 .type = 0 /* FIXME */, 333 .type2 = 0 /* FIXME */, 334 .hardware = 0, 335 .fops = &ts_fops, 336 .minor = -1, 337}; 338 339static void empress_signal_update(void* data) 340{ 341 struct saa7134_dev* dev = (struct saa7134_dev*) data; 342 343 if (dev->nosignal) { 344 dprintk("no video signal\n"); 345 ts_reset_encoder(dev); 346 } else { 347 dprintk("video signal acquired\n"); 348 if (dev->empress_users) 349 ts_init_encoder(dev); 350 } 351} 352 353static void empress_signal_change(struct saa7134_dev *dev) 354{ 355 schedule_work(&dev->empress_workqueue); 356} 357 358 359static int empress_init(struct saa7134_dev *dev) 360{ 361 int err; 362 363 dprintk("%s: %s\n",dev->name,__FUNCTION__); 364 dev->empress_dev = video_device_alloc(); 365 if (NULL == dev->empress_dev) 366 return -ENOMEM; 367 *(dev->empress_dev) = saa7134_empress_template; 368 dev->empress_dev->dev = &dev->pci->dev; 369 dev->empress_dev->release = video_device_release; 370 snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name), 371 "%s empress (%s)", dev->name, 372 saa7134_boards[dev->board].name); 373 374 INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev); 375 376 err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, 377 empress_nr[dev->nr]); 378 if (err < 0) { 379 printk(KERN_INFO "%s: can't register video device\n", 380 dev->name); 381 video_device_release(dev->empress_dev); 382 dev->empress_dev = NULL; 383 return err; 384 } 385 printk(KERN_INFO "%s: registered device video%d [mpeg]\n", 386 dev->name,dev->empress_dev->minor & 0x1f); 387 388 videobuf_queue_init(&dev->empress_tsq, &saa7134_ts_qops, 389 dev->pci, &dev->slock, 390 V4L2_BUF_TYPE_VIDEO_CAPTURE, 391 V4L2_FIELD_ALTERNATE, 392 sizeof(struct saa7134_buf), 393 dev); 394 395 empress_signal_update(dev); 396 return 0; 397} 398 399static int empress_fini(struct saa7134_dev *dev) 400{ 401 dprintk("%s: %s\n",dev->name,__FUNCTION__); 402 403 if (NULL == dev->empress_dev) 404 return 0; 405 flush_scheduled_work(); 406 video_unregister_device(dev->empress_dev); 407 dev->empress_dev = NULL; 408 return 0; 409} 410 411static struct saa7134_mpeg_ops empress_ops = { 412 .type = SAA7134_MPEG_EMPRESS, 413 .init = empress_init, 414 .fini = empress_fini, 415 .signal_change = empress_signal_change, 416}; 417 418static int __init empress_register(void) 419{ 420 return saa7134_ts_register(&empress_ops); 421} 422 423static void __exit empress_unregister(void) 424{ 425 saa7134_ts_unregister(&empress_ops); 426} 427 428module_init(empress_register); 429module_exit(empress_unregister); 430 431/* ----------------------------------------------------------- */ 432/* 433 * Local variables: 434 * c-basic-offset: 8 435 * End: 436 */ 437