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