Path: blob/master/drivers/media/video/au0828/au0828-video.c
17980 views
/*1* Auvitek AU0828 USB Bridge (Analog video support)2*3* Copyright (C) 2009 Devin Heitmueller <[email protected]>4* Copyright (C) 2005-2008 Auvitek International, Ltd.5*6* This program is free software; you can redistribute it and/or7* modify it under the terms of the GNU General Public License8* As published by the Free Software Foundation; either version 29* of the License, or (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 of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program; if not, write to the Free Software18* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA19* 02110-1301, USA.20*/2122/* Developer Notes:23*24* VBI support is not yet working25* The hardware scaler supported is unimplemented26* AC97 audio support is unimplemented (only i2s audio mode)27*28*/2930#include <linux/module.h>31#include <linux/slab.h>32#include <linux/init.h>33#include <linux/device.h>34#include <linux/suspend.h>35#include <linux/version.h>36#include <media/v4l2-common.h>37#include <media/v4l2-ioctl.h>38#include <media/v4l2-chip-ident.h>39#include <media/tuner.h>40#include "au0828.h"41#include "au0828-reg.h"4243static DEFINE_MUTEX(au0828_sysfs_lock);4445#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)4647/* ------------------------------------------------------------------48Videobuf operations49------------------------------------------------------------------*/5051static unsigned int isoc_debug;52module_param(isoc_debug, int, 0644);53MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");5455#define au0828_isocdbg(fmt, arg...) \56do {\57if (isoc_debug) { \58printk(KERN_INFO "au0828 %s :"fmt, \59__func__ , ##arg); \60} \61} while (0)6263static inline void print_err_status(struct au0828_dev *dev,64int packet, int status)65{66char *errmsg = "Unknown";6768switch (status) {69case -ENOENT:70errmsg = "unlinked synchronuously";71break;72case -ECONNRESET:73errmsg = "unlinked asynchronuously";74break;75case -ENOSR:76errmsg = "Buffer error (overrun)";77break;78case -EPIPE:79errmsg = "Stalled (device not responding)";80break;81case -EOVERFLOW:82errmsg = "Babble (bad cable?)";83break;84case -EPROTO:85errmsg = "Bit-stuff error (bad cable?)";86break;87case -EILSEQ:88errmsg = "CRC/Timeout (could be anything)";89break;90case -ETIME:91errmsg = "Device does not respond";92break;93}94if (packet < 0) {95au0828_isocdbg("URB status %d [%s].\n", status, errmsg);96} else {97au0828_isocdbg("URB packet %d, status %d [%s].\n",98packet, status, errmsg);99}100}101102static int check_dev(struct au0828_dev *dev)103{104if (dev->dev_state & DEV_DISCONNECTED) {105printk(KERN_INFO "v4l2 ioctl: device not present\n");106return -ENODEV;107}108109if (dev->dev_state & DEV_MISCONFIGURED) {110printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "111"close and open it again\n");112return -EIO;113}114return 0;115}116117/*118* IRQ callback, called by URB callback119*/120static void au0828_irq_callback(struct urb *urb)121{122struct au0828_dmaqueue *dma_q = urb->context;123struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);124unsigned long flags = 0;125int rc, i;126127switch (urb->status) {128case 0: /* success */129case -ETIMEDOUT: /* NAK */130break;131case -ECONNRESET: /* kill */132case -ENOENT:133case -ESHUTDOWN:134au0828_isocdbg("au0828_irq_callback called: status kill\n");135return;136default: /* unknown error */137au0828_isocdbg("urb completition error %d.\n", urb->status);138break;139}140141/* Copy data from URB */142spin_lock_irqsave(&dev->slock, flags);143rc = dev->isoc_ctl.isoc_copy(dev, urb);144spin_unlock_irqrestore(&dev->slock, flags);145146/* Reset urb buffers */147for (i = 0; i < urb->number_of_packets; i++) {148urb->iso_frame_desc[i].status = 0;149urb->iso_frame_desc[i].actual_length = 0;150}151urb->status = 0;152153urb->status = usb_submit_urb(urb, GFP_ATOMIC);154if (urb->status) {155au0828_isocdbg("urb resubmit failed (error=%i)\n",156urb->status);157}158}159160/*161* Stop and Deallocate URBs162*/163void au0828_uninit_isoc(struct au0828_dev *dev)164{165struct urb *urb;166int i;167168au0828_isocdbg("au0828: called au0828_uninit_isoc\n");169170dev->isoc_ctl.nfields = -1;171for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {172urb = dev->isoc_ctl.urb[i];173if (urb) {174if (!irqs_disabled())175usb_kill_urb(urb);176else177usb_unlink_urb(urb);178179if (dev->isoc_ctl.transfer_buffer[i]) {180usb_free_coherent(dev->usbdev,181urb->transfer_buffer_length,182dev->isoc_ctl.transfer_buffer[i],183urb->transfer_dma);184}185usb_free_urb(urb);186dev->isoc_ctl.urb[i] = NULL;187}188dev->isoc_ctl.transfer_buffer[i] = NULL;189}190191kfree(dev->isoc_ctl.urb);192kfree(dev->isoc_ctl.transfer_buffer);193194dev->isoc_ctl.urb = NULL;195dev->isoc_ctl.transfer_buffer = NULL;196dev->isoc_ctl.num_bufs = 0;197}198199/*200* Allocate URBs and start IRQ201*/202int au0828_init_isoc(struct au0828_dev *dev, int max_packets,203int num_bufs, int max_pkt_size,204int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))205{206struct au0828_dmaqueue *dma_q = &dev->vidq;207int i;208int sb_size, pipe;209struct urb *urb;210int j, k;211int rc;212213au0828_isocdbg("au0828: called au0828_prepare_isoc\n");214215/* De-allocates all pending stuff */216au0828_uninit_isoc(dev);217218dev->isoc_ctl.isoc_copy = isoc_copy;219dev->isoc_ctl.num_bufs = num_bufs;220221dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);222if (!dev->isoc_ctl.urb) {223au0828_isocdbg("cannot alloc memory for usb buffers\n");224return -ENOMEM;225}226227dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,228GFP_KERNEL);229if (!dev->isoc_ctl.transfer_buffer) {230au0828_isocdbg("cannot allocate memory for usb transfer\n");231kfree(dev->isoc_ctl.urb);232return -ENOMEM;233}234235dev->isoc_ctl.max_pkt_size = max_pkt_size;236dev->isoc_ctl.buf = NULL;237238sb_size = max_packets * dev->isoc_ctl.max_pkt_size;239240/* allocate urbs and transfer buffers */241for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {242urb = usb_alloc_urb(max_packets, GFP_KERNEL);243if (!urb) {244au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);245au0828_uninit_isoc(dev);246return -ENOMEM;247}248dev->isoc_ctl.urb[i] = urb;249250dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,251sb_size, GFP_KERNEL, &urb->transfer_dma);252if (!dev->isoc_ctl.transfer_buffer[i]) {253printk("unable to allocate %i bytes for transfer"254" buffer %i%s\n",255sb_size, i,256in_interrupt() ? " while in int" : "");257au0828_uninit_isoc(dev);258return -ENOMEM;259}260memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);261262pipe = usb_rcvisocpipe(dev->usbdev,263dev->isoc_in_endpointaddr),264265usb_fill_int_urb(urb, dev->usbdev, pipe,266dev->isoc_ctl.transfer_buffer[i], sb_size,267au0828_irq_callback, dma_q, 1);268269urb->number_of_packets = max_packets;270urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;271272k = 0;273for (j = 0; j < max_packets; j++) {274urb->iso_frame_desc[j].offset = k;275urb->iso_frame_desc[j].length =276dev->isoc_ctl.max_pkt_size;277k += dev->isoc_ctl.max_pkt_size;278}279}280281init_waitqueue_head(&dma_q->wq);282283/* submit urbs and enables IRQ */284for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {285rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);286if (rc) {287au0828_isocdbg("submit of urb %i failed (error=%i)\n",288i, rc);289au0828_uninit_isoc(dev);290return rc;291}292}293294return 0;295}296297/*298* Announces that a buffer were filled and request the next299*/300static inline void buffer_filled(struct au0828_dev *dev,301struct au0828_dmaqueue *dma_q,302struct au0828_buffer *buf)303{304/* Advice that buffer was filled */305au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);306307buf->vb.state = VIDEOBUF_DONE;308buf->vb.field_count++;309do_gettimeofday(&buf->vb.ts);310311dev->isoc_ctl.buf = NULL;312313list_del(&buf->vb.queue);314wake_up(&buf->vb.done);315}316317static inline void vbi_buffer_filled(struct au0828_dev *dev,318struct au0828_dmaqueue *dma_q,319struct au0828_buffer *buf)320{321/* Advice that buffer was filled */322au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);323324buf->vb.state = VIDEOBUF_DONE;325buf->vb.field_count++;326do_gettimeofday(&buf->vb.ts);327328dev->isoc_ctl.vbi_buf = NULL;329330list_del(&buf->vb.queue);331wake_up(&buf->vb.done);332}333334/*335* Identify the buffer header type and properly handles336*/337static void au0828_copy_video(struct au0828_dev *dev,338struct au0828_dmaqueue *dma_q,339struct au0828_buffer *buf,340unsigned char *p,341unsigned char *outp, unsigned long len)342{343void *fieldstart, *startwrite, *startread;344int linesdone, currlinedone, offset, lencopy, remain;345int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */346347if (len == 0)348return;349350if (dma_q->pos + len > buf->vb.size)351len = buf->vb.size - dma_q->pos;352353startread = p;354remain = len;355356/* Interlaces frame */357if (buf->top_field)358fieldstart = outp;359else360fieldstart = outp + bytesperline;361362linesdone = dma_q->pos / bytesperline;363currlinedone = dma_q->pos % bytesperline;364offset = linesdone * bytesperline * 2 + currlinedone;365startwrite = fieldstart + offset;366lencopy = bytesperline - currlinedone;367lencopy = lencopy > remain ? remain : lencopy;368369if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {370au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",371((char *)startwrite + lencopy) -372((char *)outp + buf->vb.size));373remain = (char *)outp + buf->vb.size - (char *)startwrite;374lencopy = remain;375}376if (lencopy <= 0)377return;378memcpy(startwrite, startread, lencopy);379380remain -= lencopy;381382while (remain > 0) {383startwrite += lencopy + bytesperline;384startread += lencopy;385if (bytesperline > remain)386lencopy = remain;387else388lencopy = bytesperline;389390if ((char *)startwrite + lencopy > (char *)outp +391buf->vb.size) {392au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",393((char *)startwrite + lencopy) -394((char *)outp + buf->vb.size));395lencopy = remain = (char *)outp + buf->vb.size -396(char *)startwrite;397}398if (lencopy <= 0)399break;400401memcpy(startwrite, startread, lencopy);402403remain -= lencopy;404}405406if (offset > 1440) {407/* We have enough data to check for greenscreen */408if (outp[0] < 0x60 && outp[1440] < 0x60)409dev->greenscreen_detected = 1;410}411412dma_q->pos += len;413}414415/*416* video-buf generic routine to get the next available buffer417*/418static inline void get_next_buf(struct au0828_dmaqueue *dma_q,419struct au0828_buffer **buf)420{421struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);422423if (list_empty(&dma_q->active)) {424au0828_isocdbg("No active queue to serve\n");425dev->isoc_ctl.buf = NULL;426*buf = NULL;427return;428}429430/* Get the next buffer */431*buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);432dev->isoc_ctl.buf = *buf;433434return;435}436437static void au0828_copy_vbi(struct au0828_dev *dev,438struct au0828_dmaqueue *dma_q,439struct au0828_buffer *buf,440unsigned char *p,441unsigned char *outp, unsigned long len)442{443unsigned char *startwrite, *startread;444int bytesperline;445int i, j = 0;446447if (dev == NULL) {448au0828_isocdbg("dev is null\n");449return;450}451452if (dma_q == NULL) {453au0828_isocdbg("dma_q is null\n");454return;455}456if (buf == NULL)457return;458if (p == NULL) {459au0828_isocdbg("p is null\n");460return;461}462if (outp == NULL) {463au0828_isocdbg("outp is null\n");464return;465}466467bytesperline = dev->vbi_width;468469if (dma_q->pos + len > buf->vb.size)470len = buf->vb.size - dma_q->pos;471472startread = p;473startwrite = outp + (dma_q->pos / 2);474475/* Make sure the bottom field populates the second half of the frame */476if (buf->top_field == 0)477startwrite += bytesperline * dev->vbi_height;478479for (i = 0; i < len; i += 2)480startwrite[j++] = startread[i+1];481482dma_q->pos += len;483}484485486/*487* video-buf generic routine to get the next available VBI buffer488*/489static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,490struct au0828_buffer **buf)491{492struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);493char *outp;494495if (list_empty(&dma_q->active)) {496au0828_isocdbg("No active queue to serve\n");497dev->isoc_ctl.vbi_buf = NULL;498*buf = NULL;499return;500}501502/* Get the next buffer */503*buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);504/* Cleans up buffer - Useful for testing for frame/URB loss */505outp = videobuf_to_vmalloc(&(*buf)->vb);506memset(outp, 0x00, (*buf)->vb.size);507508dev->isoc_ctl.vbi_buf = *buf;509510return;511}512513/*514* Controls the isoc copy of each urb packet515*/516static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)517{518struct au0828_buffer *buf;519struct au0828_buffer *vbi_buf;520struct au0828_dmaqueue *dma_q = urb->context;521struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;522unsigned char *outp = NULL;523unsigned char *vbioutp = NULL;524int i, len = 0, rc = 1;525unsigned char *p;526unsigned char fbyte;527unsigned int vbi_field_size;528unsigned int remain, lencopy;529530if (!dev)531return 0;532533if ((dev->dev_state & DEV_DISCONNECTED) ||534(dev->dev_state & DEV_MISCONFIGURED))535return 0;536537if (urb->status < 0) {538print_err_status(dev, -1, urb->status);539if (urb->status == -ENOENT)540return 0;541}542543buf = dev->isoc_ctl.buf;544if (buf != NULL)545outp = videobuf_to_vmalloc(&buf->vb);546547vbi_buf = dev->isoc_ctl.vbi_buf;548if (vbi_buf != NULL)549vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);550551for (i = 0; i < urb->number_of_packets; i++) {552int status = urb->iso_frame_desc[i].status;553554if (status < 0) {555print_err_status(dev, i, status);556if (urb->iso_frame_desc[i].status != -EPROTO)557continue;558}559560if (urb->iso_frame_desc[i].actual_length <= 0)561continue;562563if (urb->iso_frame_desc[i].actual_length >564dev->max_pkt_size) {565au0828_isocdbg("packet bigger than packet size");566continue;567}568569p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;570fbyte = p[0];571len = urb->iso_frame_desc[i].actual_length - 4;572p += 4;573574if (fbyte & 0x80) {575len -= 4;576p += 4;577au0828_isocdbg("Video frame %s\n",578(fbyte & 0x40) ? "odd" : "even");579if (fbyte & 0x40) {580/* VBI */581if (vbi_buf != NULL)582vbi_buffer_filled(dev,583vbi_dma_q,584vbi_buf);585vbi_get_next_buf(vbi_dma_q, &vbi_buf);586if (vbi_buf == NULL)587vbioutp = NULL;588else589vbioutp = videobuf_to_vmalloc(590&vbi_buf->vb);591592/* Video */593if (buf != NULL)594buffer_filled(dev, dma_q, buf);595get_next_buf(dma_q, &buf);596if (buf == NULL)597outp = NULL;598else599outp = videobuf_to_vmalloc(&buf->vb);600601/* As long as isoc traffic is arriving, keep602resetting the timer */603if (dev->vid_timeout_running)604mod_timer(&dev->vid_timeout,605jiffies + (HZ / 10));606if (dev->vbi_timeout_running)607mod_timer(&dev->vbi_timeout,608jiffies + (HZ / 10));609}610611if (buf != NULL) {612if (fbyte & 0x40)613buf->top_field = 1;614else615buf->top_field = 0;616}617618if (vbi_buf != NULL) {619if (fbyte & 0x40)620vbi_buf->top_field = 1;621else622vbi_buf->top_field = 0;623}624625dev->vbi_read = 0;626vbi_dma_q->pos = 0;627dma_q->pos = 0;628}629630vbi_field_size = dev->vbi_width * dev->vbi_height * 2;631if (dev->vbi_read < vbi_field_size) {632remain = vbi_field_size - dev->vbi_read;633if (len < remain)634lencopy = len;635else636lencopy = remain;637638if (vbi_buf != NULL)639au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,640vbioutp, len);641642len -= lencopy;643p += lencopy;644dev->vbi_read += lencopy;645}646647if (dev->vbi_read >= vbi_field_size && buf != NULL)648au0828_copy_video(dev, dma_q, buf, p, outp, len);649}650return rc;651}652653static int654buffer_setup(struct videobuf_queue *vq, unsigned int *count,655unsigned int *size)656{657struct au0828_fh *fh = vq->priv_data;658*size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;659660if (0 == *count)661*count = AU0828_DEF_BUF;662663if (*count < AU0828_MIN_BUF)664*count = AU0828_MIN_BUF;665return 0;666}667668/* This is called *without* dev->slock held; please keep it that way */669static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)670{671struct au0828_fh *fh = vq->priv_data;672struct au0828_dev *dev = fh->dev;673unsigned long flags = 0;674if (in_interrupt())675BUG();676677/* We used to wait for the buffer to finish here, but this didn't work678because, as we were keeping the state as VIDEOBUF_QUEUED,679videobuf_queue_cancel marked it as finished for us.680(Also, it could wedge forever if the hardware was misconfigured.)681682This should be safe; by the time we get here, the buffer isn't683queued anymore. If we ever start marking the buffers as684VIDEOBUF_ACTIVE, it won't be, though.685*/686spin_lock_irqsave(&dev->slock, flags);687if (dev->isoc_ctl.buf == buf)688dev->isoc_ctl.buf = NULL;689spin_unlock_irqrestore(&dev->slock, flags);690691videobuf_vmalloc_free(&buf->vb);692buf->vb.state = VIDEOBUF_NEEDS_INIT;693}694695static int696buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,697enum v4l2_field field)698{699struct au0828_fh *fh = vq->priv_data;700struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);701struct au0828_dev *dev = fh->dev;702int rc = 0, urb_init = 0;703704buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;705706if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)707return -EINVAL;708709buf->vb.width = dev->width;710buf->vb.height = dev->height;711buf->vb.field = field;712713if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {714rc = videobuf_iolock(vq, &buf->vb, NULL);715if (rc < 0) {716printk(KERN_INFO "videobuf_iolock failed\n");717goto fail;718}719}720721if (!dev->isoc_ctl.num_bufs)722urb_init = 1;723724if (urb_init) {725rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,726AU0828_MAX_ISO_BUFS, dev->max_pkt_size,727au0828_isoc_copy);728if (rc < 0) {729printk(KERN_INFO "au0828_init_isoc failed\n");730goto fail;731}732}733734buf->vb.state = VIDEOBUF_PREPARED;735return 0;736737fail:738free_buffer(vq, buf);739return rc;740}741742static void743buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)744{745struct au0828_buffer *buf = container_of(vb,746struct au0828_buffer,747vb);748struct au0828_fh *fh = vq->priv_data;749struct au0828_dev *dev = fh->dev;750struct au0828_dmaqueue *vidq = &dev->vidq;751752buf->vb.state = VIDEOBUF_QUEUED;753list_add_tail(&buf->vb.queue, &vidq->active);754}755756static void buffer_release(struct videobuf_queue *vq,757struct videobuf_buffer *vb)758{759struct au0828_buffer *buf = container_of(vb,760struct au0828_buffer,761vb);762763free_buffer(vq, buf);764}765766static struct videobuf_queue_ops au0828_video_qops = {767.buf_setup = buffer_setup,768.buf_prepare = buffer_prepare,769.buf_queue = buffer_queue,770.buf_release = buffer_release,771};772773/* ------------------------------------------------------------------774V4L2 interface775------------------------------------------------------------------*/776777static int au0828_i2s_init(struct au0828_dev *dev)778{779/* Enable i2s mode */780au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);781return 0;782}783784/*785* Auvitek au0828 analog stream enable786* Please set interface0 to AS5 before enable the stream787*/788int au0828_analog_stream_enable(struct au0828_dev *d)789{790dprintk(1, "au0828_analog_stream_enable called\n");791au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);792au0828_writereg(d, 0x106, 0x00);793/* set x position */794au0828_writereg(d, 0x110, 0x00);795au0828_writereg(d, 0x111, 0x00);796au0828_writereg(d, 0x114, 0xa0);797au0828_writereg(d, 0x115, 0x05);798/* set y position */799au0828_writereg(d, 0x112, 0x00);800au0828_writereg(d, 0x113, 0x00);801au0828_writereg(d, 0x116, 0xf2);802au0828_writereg(d, 0x117, 0x00);803au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);804805return 0;806}807808int au0828_analog_stream_disable(struct au0828_dev *d)809{810dprintk(1, "au0828_analog_stream_disable called\n");811au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);812return 0;813}814815void au0828_analog_stream_reset(struct au0828_dev *dev)816{817dprintk(1, "au0828_analog_stream_reset called\n");818au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);819mdelay(30);820au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);821}822823/*824* Some operations needs to stop current streaming825*/826static int au0828_stream_interrupt(struct au0828_dev *dev)827{828int ret = 0;829830dev->stream_state = STREAM_INTERRUPT;831if (dev->dev_state == DEV_DISCONNECTED)832return -ENODEV;833else if (ret) {834dev->dev_state = DEV_MISCONFIGURED;835dprintk(1, "%s device is misconfigured!\n", __func__);836return ret;837}838return 0;839}840841/*842* au0828_release_resources843* unregister v4l2 devices844*/845void au0828_analog_unregister(struct au0828_dev *dev)846{847dprintk(1, "au0828_release_resources called\n");848mutex_lock(&au0828_sysfs_lock);849850if (dev->vdev)851video_unregister_device(dev->vdev);852if (dev->vbi_dev)853video_unregister_device(dev->vbi_dev);854855mutex_unlock(&au0828_sysfs_lock);856}857858859/* Usage lock check functions */860static int res_get(struct au0828_fh *fh, unsigned int bit)861{862struct au0828_dev *dev = fh->dev;863864if (fh->resources & bit)865/* have it already allocated */866return 1;867868/* is it free? */869mutex_lock(&dev->lock);870if (dev->resources & bit) {871/* no, someone else uses it */872mutex_unlock(&dev->lock);873return 0;874}875/* it's free, grab it */876fh->resources |= bit;877dev->resources |= bit;878dprintk(1, "res: get %d\n", bit);879mutex_unlock(&dev->lock);880return 1;881}882883static int res_check(struct au0828_fh *fh, unsigned int bit)884{885return fh->resources & bit;886}887888static int res_locked(struct au0828_dev *dev, unsigned int bit)889{890return dev->resources & bit;891}892893static void res_free(struct au0828_fh *fh, unsigned int bits)894{895struct au0828_dev *dev = fh->dev;896897BUG_ON((fh->resources & bits) != bits);898899mutex_lock(&dev->lock);900fh->resources &= ~bits;901dev->resources &= ~bits;902dprintk(1, "res: put %d\n", bits);903mutex_unlock(&dev->lock);904}905906static int get_ressource(struct au0828_fh *fh)907{908switch (fh->type) {909case V4L2_BUF_TYPE_VIDEO_CAPTURE:910return AU0828_RESOURCE_VIDEO;911case V4L2_BUF_TYPE_VBI_CAPTURE:912return AU0828_RESOURCE_VBI;913default:914BUG();915return 0;916}917}918919/* This function ensures that video frames continue to be delivered even if920the ITU-656 input isn't receiving any data (thereby preventing applications921such as tvtime from hanging) */922void au0828_vid_buffer_timeout(unsigned long data)923{924struct au0828_dev *dev = (struct au0828_dev *) data;925struct au0828_dmaqueue *dma_q = &dev->vidq;926struct au0828_buffer *buf;927unsigned char *vid_data;928unsigned long flags = 0;929930spin_lock_irqsave(&dev->slock, flags);931932buf = dev->isoc_ctl.buf;933if (buf != NULL) {934vid_data = videobuf_to_vmalloc(&buf->vb);935memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */936buffer_filled(dev, dma_q, buf);937}938get_next_buf(dma_q, &buf);939940if (dev->vid_timeout_running == 1)941mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));942943spin_unlock_irqrestore(&dev->slock, flags);944}945946void au0828_vbi_buffer_timeout(unsigned long data)947{948struct au0828_dev *dev = (struct au0828_dev *) data;949struct au0828_dmaqueue *dma_q = &dev->vbiq;950struct au0828_buffer *buf;951unsigned char *vbi_data;952unsigned long flags = 0;953954spin_lock_irqsave(&dev->slock, flags);955956buf = dev->isoc_ctl.vbi_buf;957if (buf != NULL) {958vbi_data = videobuf_to_vmalloc(&buf->vb);959memset(vbi_data, 0x00, buf->vb.size);960vbi_buffer_filled(dev, dma_q, buf);961}962vbi_get_next_buf(dma_q, &buf);963964if (dev->vbi_timeout_running == 1)965mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));966spin_unlock_irqrestore(&dev->slock, flags);967}968969970static int au0828_v4l2_open(struct file *filp)971{972int ret = 0;973struct video_device *vdev = video_devdata(filp);974struct au0828_dev *dev = video_drvdata(filp);975struct au0828_fh *fh;976int type;977978switch (vdev->vfl_type) {979case VFL_TYPE_GRABBER:980type = V4L2_BUF_TYPE_VIDEO_CAPTURE;981break;982case VFL_TYPE_VBI:983type = V4L2_BUF_TYPE_VBI_CAPTURE;984break;985default:986return -EINVAL;987}988989fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);990if (NULL == fh) {991dprintk(1, "Failed allocate au0828_fh struct!\n");992return -ENOMEM;993}994995fh->type = type;996fh->dev = dev;997filp->private_data = fh;998999if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {1000/* set au0828 interface0 to AS5 here again */1001ret = usb_set_interface(dev->usbdev, 0, 5);1002if (ret < 0) {1003printk(KERN_INFO "Au0828 can't set alternate to 5!\n");1004return -EBUSY;1005}1006dev->width = NTSC_STD_W;1007dev->height = NTSC_STD_H;1008dev->frame_size = dev->width * dev->height * 2;1009dev->field_size = dev->width * dev->height;1010dev->bytesperline = dev->width * 2;10111012au0828_analog_stream_enable(dev);1013au0828_analog_stream_reset(dev);10141015/* If we were doing ac97 instead of i2s, it would go here...*/1016au0828_i2s_init(dev);10171018dev->stream_state = STREAM_OFF;1019dev->dev_state |= DEV_INITIALIZED;1020}10211022dev->users++;10231024videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,1025NULL, &dev->slock,1026V4L2_BUF_TYPE_VIDEO_CAPTURE,1027V4L2_FIELD_INTERLACED,1028sizeof(struct au0828_buffer), fh, NULL);10291030/* VBI Setup */1031dev->vbi_width = 720;1032dev->vbi_height = 1;1033videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,1034NULL, &dev->slock,1035V4L2_BUF_TYPE_VBI_CAPTURE,1036V4L2_FIELD_SEQ_TB,1037sizeof(struct au0828_buffer), fh, NULL);10381039return ret;1040}10411042static int au0828_v4l2_close(struct file *filp)1043{1044int ret;1045struct au0828_fh *fh = filp->private_data;1046struct au0828_dev *dev = fh->dev;10471048if (res_check(fh, AU0828_RESOURCE_VIDEO)) {1049/* Cancel timeout thread in case they didn't call streamoff */1050dev->vid_timeout_running = 0;1051del_timer_sync(&dev->vid_timeout);10521053videobuf_stop(&fh->vb_vidq);1054res_free(fh, AU0828_RESOURCE_VIDEO);1055}10561057if (res_check(fh, AU0828_RESOURCE_VBI)) {1058/* Cancel timeout thread in case they didn't call streamoff */1059dev->vbi_timeout_running = 0;1060del_timer_sync(&dev->vbi_timeout);10611062videobuf_stop(&fh->vb_vbiq);1063res_free(fh, AU0828_RESOURCE_VBI);1064}10651066if (dev->users == 1) {1067if (dev->dev_state & DEV_DISCONNECTED) {1068au0828_analog_unregister(dev);1069kfree(dev);1070return 0;1071}10721073au0828_analog_stream_disable(dev);10741075au0828_uninit_isoc(dev);10761077/* Save some power by putting tuner to sleep */1078v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);10791080/* When close the device, set the usb intf0 into alt0 to free1081USB bandwidth */1082ret = usb_set_interface(dev->usbdev, 0, 0);1083if (ret < 0)1084printk(KERN_INFO "Au0828 can't set alternate to 0!\n");1085}10861087videobuf_mmap_free(&fh->vb_vidq);1088videobuf_mmap_free(&fh->vb_vbiq);1089kfree(fh);1090dev->users--;1091wake_up_interruptible_nr(&dev->open, 1);1092return 0;1093}10941095static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,1096size_t count, loff_t *pos)1097{1098struct au0828_fh *fh = filp->private_data;1099struct au0828_dev *dev = fh->dev;1100int rc;11011102rc = check_dev(dev);1103if (rc < 0)1104return rc;11051106if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {1107if (res_locked(dev, AU0828_RESOURCE_VIDEO))1108return -EBUSY;11091110return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,1111filp->f_flags & O_NONBLOCK);1112}11131114if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {1115if (!res_get(fh, AU0828_RESOURCE_VBI))1116return -EBUSY;11171118if (dev->vbi_timeout_running == 0) {1119/* Handle case where caller tries to read without1120calling streamon first */1121dev->vbi_timeout_running = 1;1122mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));1123}11241125return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,1126filp->f_flags & O_NONBLOCK);1127}11281129return 0;1130}11311132static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)1133{1134struct au0828_fh *fh = filp->private_data;1135struct au0828_dev *dev = fh->dev;1136int rc;11371138rc = check_dev(dev);1139if (rc < 0)1140return rc;11411142if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {1143if (!res_get(fh, AU0828_RESOURCE_VIDEO))1144return POLLERR;1145return videobuf_poll_stream(filp, &fh->vb_vidq, wait);1146} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {1147if (!res_get(fh, AU0828_RESOURCE_VBI))1148return POLLERR;1149return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);1150} else {1151return POLLERR;1152}1153}11541155static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)1156{1157struct au0828_fh *fh = filp->private_data;1158struct au0828_dev *dev = fh->dev;1159int rc;11601161rc = check_dev(dev);1162if (rc < 0)1163return rc;11641165if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)1166rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);1167else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)1168rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);11691170return rc;1171}11721173static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,1174struct v4l2_format *format)1175{1176int ret;1177int width = format->fmt.pix.width;1178int height = format->fmt.pix.height;11791180if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1181return -EINVAL;11821183/* If they are demanding a format other than the one we support,1184bail out (tvtime asks for UYVY and then retries with YUYV) */1185if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)1186return -EINVAL;11871188/* format->fmt.pix.width only support 720 and height 480 */1189if (width != 720)1190width = 720;1191if (height != 480)1192height = 480;11931194format->fmt.pix.width = width;1195format->fmt.pix.height = height;1196format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;1197format->fmt.pix.bytesperline = width * 2;1198format->fmt.pix.sizeimage = width * height * 2;1199format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;1200format->fmt.pix.field = V4L2_FIELD_INTERLACED;12011202if (cmd == VIDIOC_TRY_FMT)1203return 0;12041205/* maybe set new image format, driver current only support 720*480 */1206dev->width = width;1207dev->height = height;1208dev->frame_size = width * height * 2;1209dev->field_size = width * height;1210dev->bytesperline = width * 2;12111212if (dev->stream_state == STREAM_ON) {1213dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");1214ret = au0828_stream_interrupt(dev);1215if (ret != 0) {1216dprintk(1, "error interrupting video stream!\n");1217return ret;1218}1219}12201221/* set au0828 interface0 to AS5 here again */1222ret = usb_set_interface(dev->usbdev, 0, 5);1223if (ret < 0) {1224printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");1225return -EBUSY;1226}12271228au0828_analog_stream_enable(dev);12291230return 0;1231}123212331234static int vidioc_queryctrl(struct file *file, void *priv,1235struct v4l2_queryctrl *qc)1236{1237struct au0828_fh *fh = priv;1238struct au0828_dev *dev = fh->dev;1239v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);1240if (qc->type)1241return 0;1242else1243return -EINVAL;1244}12451246static int vidioc_querycap(struct file *file, void *priv,1247struct v4l2_capability *cap)1248{1249struct au0828_fh *fh = priv;1250struct au0828_dev *dev = fh->dev;12511252strlcpy(cap->driver, "au0828", sizeof(cap->driver));1253strlcpy(cap->card, dev->board.name, sizeof(cap->card));1254strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));12551256cap->version = AU0828_VERSION_CODE;12571258/*set the device capabilities */1259cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |1260V4L2_CAP_VBI_CAPTURE |1261V4L2_CAP_AUDIO |1262V4L2_CAP_READWRITE |1263V4L2_CAP_STREAMING |1264V4L2_CAP_TUNER;1265return 0;1266}12671268static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,1269struct v4l2_fmtdesc *f)1270{1271if (f->index)1272return -EINVAL;12731274f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;1275strcpy(f->description, "Packed YUV2");12761277f->flags = 0;1278f->pixelformat = V4L2_PIX_FMT_UYVY;12791280return 0;1281}12821283static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,1284struct v4l2_format *f)1285{1286struct au0828_fh *fh = priv;1287struct au0828_dev *dev = fh->dev;12881289f->fmt.pix.width = dev->width;1290f->fmt.pix.height = dev->height;1291f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;1292f->fmt.pix.bytesperline = dev->bytesperline;1293f->fmt.pix.sizeimage = dev->frame_size;1294f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */1295f->fmt.pix.field = V4L2_FIELD_INTERLACED;1296return 0;1297}12981299static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,1300struct v4l2_format *f)1301{1302struct au0828_fh *fh = priv;1303struct au0828_dev *dev = fh->dev;13041305return au0828_set_format(dev, VIDIOC_TRY_FMT, f);1306}13071308static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,1309struct v4l2_format *f)1310{1311struct au0828_fh *fh = priv;1312struct au0828_dev *dev = fh->dev;1313int rc;13141315rc = check_dev(dev);1316if (rc < 0)1317return rc;13181319mutex_lock(&dev->lock);13201321if (videobuf_queue_is_busy(&fh->vb_vidq)) {1322printk(KERN_INFO "%s queue busy\n", __func__);1323rc = -EBUSY;1324goto out;1325}13261327rc = au0828_set_format(dev, VIDIOC_S_FMT, f);1328out:1329mutex_unlock(&dev->lock);1330return rc;1331}13321333static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)1334{1335struct au0828_fh *fh = priv;1336struct au0828_dev *dev = fh->dev;13371338/* FIXME: when we support something other than NTSC, we are going to1339have to make the au0828 bridge adjust the size of its capture1340buffer, which is currently hardcoded at 720x480 */13411342v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);1343return 0;1344}13451346static int vidioc_enum_input(struct file *file, void *priv,1347struct v4l2_input *input)1348{1349struct au0828_fh *fh = priv;1350struct au0828_dev *dev = fh->dev;1351unsigned int tmp;13521353static const char *inames[] = {1354[AU0828_VMUX_UNDEFINED] = "Undefined",1355[AU0828_VMUX_COMPOSITE] = "Composite",1356[AU0828_VMUX_SVIDEO] = "S-Video",1357[AU0828_VMUX_CABLE] = "Cable TV",1358[AU0828_VMUX_TELEVISION] = "Television",1359[AU0828_VMUX_DVB] = "DVB",1360[AU0828_VMUX_DEBUG] = "tv debug"1361};13621363tmp = input->index;13641365if (tmp >= AU0828_MAX_INPUT)1366return -EINVAL;1367if (AUVI_INPUT(tmp).type == 0)1368return -EINVAL;13691370input->index = tmp;1371strcpy(input->name, inames[AUVI_INPUT(tmp).type]);1372if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||1373(AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))1374input->type |= V4L2_INPUT_TYPE_TUNER;1375else1376input->type |= V4L2_INPUT_TYPE_CAMERA;13771378input->std = dev->vdev->tvnorms;13791380return 0;1381}13821383static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)1384{1385struct au0828_fh *fh = priv;1386struct au0828_dev *dev = fh->dev;1387*i = dev->ctrl_input;1388return 0;1389}13901391static int vidioc_s_input(struct file *file, void *priv, unsigned int index)1392{1393struct au0828_fh *fh = priv;1394struct au0828_dev *dev = fh->dev;1395int i;13961397dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,1398index);1399if (index >= AU0828_MAX_INPUT)1400return -EINVAL;1401if (AUVI_INPUT(index).type == 0)1402return -EINVAL;1403dev->ctrl_input = index;14041405switch (AUVI_INPUT(index).type) {1406case AU0828_VMUX_SVIDEO:1407dev->input_type = AU0828_VMUX_SVIDEO;1408break;1409case AU0828_VMUX_COMPOSITE:1410dev->input_type = AU0828_VMUX_COMPOSITE;1411break;1412case AU0828_VMUX_TELEVISION:1413dev->input_type = AU0828_VMUX_TELEVISION;1414break;1415default:1416dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",1417AUVI_INPUT(index).type);1418break;1419}14201421v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,1422AUVI_INPUT(index).vmux, 0, 0);14231424for (i = 0; i < AU0828_MAX_INPUT; i++) {1425int enable = 0;1426if (AUVI_INPUT(i).audio_setup == NULL)1427continue;14281429if (i == index)1430enable = 1;1431else1432enable = 0;1433if (enable) {1434(AUVI_INPUT(i).audio_setup)(dev, enable);1435} else {1436/* Make sure we leave it turned on if some1437other input is routed to this callback */1438if ((AUVI_INPUT(i).audio_setup) !=1439((AUVI_INPUT(index).audio_setup))) {1440(AUVI_INPUT(i).audio_setup)(dev, enable);1441}1442}1443}14441445v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,1446AUVI_INPUT(index).amux, 0, 0);1447return 0;1448}14491450static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)1451{1452struct au0828_fh *fh = priv;1453struct au0828_dev *dev = fh->dev;1454unsigned int index = a->index;14551456if (a->index > 1)1457return -EINVAL;14581459index = dev->ctrl_ainput;1460if (index == 0)1461strcpy(a->name, "Television");1462else1463strcpy(a->name, "Line in");14641465a->capability = V4L2_AUDCAP_STEREO;1466a->index = index;1467return 0;1468}14691470static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)1471{1472struct au0828_fh *fh = priv;1473struct au0828_dev *dev = fh->dev;1474if (a->index != dev->ctrl_ainput)1475return -EINVAL;1476return 0;1477}14781479static int vidioc_g_ctrl(struct file *file, void *priv,1480struct v4l2_control *ctrl)1481{1482struct au0828_fh *fh = priv;1483struct au0828_dev *dev = fh->dev;14841485v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);1486return 0;14871488}14891490static int vidioc_s_ctrl(struct file *file, void *priv,1491struct v4l2_control *ctrl)1492{1493struct au0828_fh *fh = priv;1494struct au0828_dev *dev = fh->dev;1495v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);1496return 0;1497}14981499static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)1500{1501struct au0828_fh *fh = priv;1502struct au0828_dev *dev = fh->dev;15031504if (t->index != 0)1505return -EINVAL;15061507strcpy(t->name, "Auvitek tuner");1508v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);1509return 0;1510}15111512static int vidioc_s_tuner(struct file *file, void *priv,1513struct v4l2_tuner *t)1514{1515struct au0828_fh *fh = priv;1516struct au0828_dev *dev = fh->dev;15171518if (t->index != 0)1519return -EINVAL;15201521t->type = V4L2_TUNER_ANALOG_TV;1522v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);1523dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,1524t->afc);1525return 0;15261527}15281529static int vidioc_g_frequency(struct file *file, void *priv,1530struct v4l2_frequency *freq)1531{1532struct au0828_fh *fh = priv;1533struct au0828_dev *dev = fh->dev;15341535freq->type = V4L2_TUNER_ANALOG_TV;1536freq->frequency = dev->ctrl_freq;1537return 0;1538}15391540static int vidioc_s_frequency(struct file *file, void *priv,1541struct v4l2_frequency *freq)1542{1543struct au0828_fh *fh = priv;1544struct au0828_dev *dev = fh->dev;15451546if (freq->tuner != 0)1547return -EINVAL;1548if (freq->type != V4L2_TUNER_ANALOG_TV)1549return -EINVAL;15501551dev->ctrl_freq = freq->frequency;15521553v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);15541555au0828_analog_stream_reset(dev);15561557return 0;1558}155915601561/* RAW VBI ioctls */15621563static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,1564struct v4l2_format *format)1565{1566struct au0828_fh *fh = priv;1567struct au0828_dev *dev = fh->dev;15681569format->fmt.vbi.samples_per_line = dev->vbi_width;1570format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;1571format->fmt.vbi.offset = 0;1572format->fmt.vbi.flags = 0;1573format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;15741575format->fmt.vbi.count[0] = dev->vbi_height;1576format->fmt.vbi.count[1] = dev->vbi_height;1577format->fmt.vbi.start[0] = 21;1578format->fmt.vbi.start[1] = 284;15791580return 0;1581}15821583static int vidioc_g_chip_ident(struct file *file, void *priv,1584struct v4l2_dbg_chip_ident *chip)1585{1586struct au0828_fh *fh = priv;1587struct au0828_dev *dev = fh->dev;1588chip->ident = V4L2_IDENT_NONE;1589chip->revision = 0;15901591if (v4l2_chip_match_host(&chip->match)) {1592chip->ident = V4L2_IDENT_AU0828;1593return 0;1594}15951596v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);1597if (chip->ident == V4L2_IDENT_NONE)1598return -EINVAL;15991600return 0;1601}16021603static int vidioc_cropcap(struct file *file, void *priv,1604struct v4l2_cropcap *cc)1605{1606struct au0828_fh *fh = priv;1607struct au0828_dev *dev = fh->dev;16081609if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1610return -EINVAL;16111612cc->bounds.left = 0;1613cc->bounds.top = 0;1614cc->bounds.width = dev->width;1615cc->bounds.height = dev->height;16161617cc->defrect = cc->bounds;16181619cc->pixelaspect.numerator = 54;1620cc->pixelaspect.denominator = 59;16211622return 0;1623}16241625static int vidioc_streamon(struct file *file, void *priv,1626enum v4l2_buf_type type)1627{1628struct au0828_fh *fh = priv;1629struct au0828_dev *dev = fh->dev;1630int rc = -EINVAL;16311632rc = check_dev(dev);1633if (rc < 0)1634return rc;16351636if (unlikely(type != fh->type))1637return -EINVAL;16381639dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",1640fh, type, fh->resources, dev->resources);16411642if (unlikely(!res_get(fh, get_ressource(fh))))1643return -EBUSY;16441645if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {1646au0828_analog_stream_enable(dev);1647v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);1648}16491650if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {1651rc = videobuf_streamon(&fh->vb_vidq);1652dev->vid_timeout_running = 1;1653mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));1654} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {1655rc = videobuf_streamon(&fh->vb_vbiq);1656dev->vbi_timeout_running = 1;1657mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));1658}16591660return rc;1661}16621663static int vidioc_streamoff(struct file *file, void *priv,1664enum v4l2_buf_type type)1665{1666struct au0828_fh *fh = priv;1667struct au0828_dev *dev = fh->dev;1668int rc;1669int i;16701671rc = check_dev(dev);1672if (rc < 0)1673return rc;16741675if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&1676fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)1677return -EINVAL;1678if (type != fh->type)1679return -EINVAL;16801681dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",1682fh, type, fh->resources, dev->resources);16831684if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {1685dev->vid_timeout_running = 0;1686del_timer_sync(&dev->vid_timeout);16871688v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);1689rc = au0828_stream_interrupt(dev);1690if (rc != 0)1691return rc;16921693for (i = 0; i < AU0828_MAX_INPUT; i++) {1694if (AUVI_INPUT(i).audio_setup == NULL)1695continue;1696(AUVI_INPUT(i).audio_setup)(dev, 0);1697}16981699videobuf_streamoff(&fh->vb_vidq);1700res_free(fh, AU0828_RESOURCE_VIDEO);1701} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {1702dev->vbi_timeout_running = 0;1703del_timer_sync(&dev->vbi_timeout);17041705videobuf_streamoff(&fh->vb_vbiq);1706res_free(fh, AU0828_RESOURCE_VBI);1707}17081709return 0;1710}17111712#ifdef CONFIG_VIDEO_ADV_DEBUG1713static int vidioc_g_register(struct file *file, void *priv,1714struct v4l2_dbg_register *reg)1715{1716struct au0828_fh *fh = priv;1717struct au0828_dev *dev = fh->dev;17181719switch (reg->match.type) {1720case V4L2_CHIP_MATCH_I2C_DRIVER:1721v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);1722return 0;1723default:1724return -EINVAL;1725}1726}17271728static int vidioc_s_register(struct file *file, void *priv,1729struct v4l2_dbg_register *reg)1730{1731struct au0828_fh *fh = priv;1732struct au0828_dev *dev = fh->dev;17331734switch (reg->match.type) {1735case V4L2_CHIP_MATCH_I2C_DRIVER:1736v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);1737return 0;1738default:1739return -EINVAL;1740}1741return 0;1742}1743#endif17441745static int vidioc_reqbufs(struct file *file, void *priv,1746struct v4l2_requestbuffers *rb)1747{1748struct au0828_fh *fh = priv;1749struct au0828_dev *dev = fh->dev;1750int rc;17511752rc = check_dev(dev);1753if (rc < 0)1754return rc;17551756if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)1757rc = videobuf_reqbufs(&fh->vb_vidq, rb);1758else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)1759rc = videobuf_reqbufs(&fh->vb_vbiq, rb);17601761return rc;1762}17631764static int vidioc_querybuf(struct file *file, void *priv,1765struct v4l2_buffer *b)1766{1767struct au0828_fh *fh = priv;1768struct au0828_dev *dev = fh->dev;1769int rc;17701771rc = check_dev(dev);1772if (rc < 0)1773return rc;17741775if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)1776rc = videobuf_querybuf(&fh->vb_vidq, b);1777else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)1778rc = videobuf_querybuf(&fh->vb_vbiq, b);17791780return rc;1781}17821783static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)1784{1785struct au0828_fh *fh = priv;1786struct au0828_dev *dev = fh->dev;1787int rc;17881789rc = check_dev(dev);1790if (rc < 0)1791return rc;17921793if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)1794rc = videobuf_qbuf(&fh->vb_vidq, b);1795else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)1796rc = videobuf_qbuf(&fh->vb_vbiq, b);17971798return rc;1799}18001801static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)1802{1803struct au0828_fh *fh = priv;1804struct au0828_dev *dev = fh->dev;1805int rc;18061807rc = check_dev(dev);1808if (rc < 0)1809return rc;18101811/* Workaround for a bug in the au0828 hardware design that sometimes1812results in the colorspace being inverted */1813if (dev->greenscreen_detected == 1) {1814dprintk(1, "Detected green frame. Resetting stream...\n");1815au0828_analog_stream_reset(dev);1816dev->greenscreen_detected = 0;1817}18181819if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)1820rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);1821else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)1822rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);18231824return rc;1825}18261827static struct v4l2_file_operations au0828_v4l_fops = {1828.owner = THIS_MODULE,1829.open = au0828_v4l2_open,1830.release = au0828_v4l2_close,1831.read = au0828_v4l2_read,1832.poll = au0828_v4l2_poll,1833.mmap = au0828_v4l2_mmap,1834.ioctl = video_ioctl2,1835};18361837static const struct v4l2_ioctl_ops video_ioctl_ops = {1838.vidioc_querycap = vidioc_querycap,1839.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,1840.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,1841.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,1842.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,1843.vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,1844.vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,1845.vidioc_g_audio = vidioc_g_audio,1846.vidioc_s_audio = vidioc_s_audio,1847.vidioc_cropcap = vidioc_cropcap,1848.vidioc_reqbufs = vidioc_reqbufs,1849.vidioc_querybuf = vidioc_querybuf,1850.vidioc_qbuf = vidioc_qbuf,1851.vidioc_dqbuf = vidioc_dqbuf,1852.vidioc_s_std = vidioc_s_std,1853.vidioc_enum_input = vidioc_enum_input,1854.vidioc_g_input = vidioc_g_input,1855.vidioc_s_input = vidioc_s_input,1856.vidioc_queryctrl = vidioc_queryctrl,1857.vidioc_g_ctrl = vidioc_g_ctrl,1858.vidioc_s_ctrl = vidioc_s_ctrl,1859.vidioc_streamon = vidioc_streamon,1860.vidioc_streamoff = vidioc_streamoff,1861.vidioc_g_tuner = vidioc_g_tuner,1862.vidioc_s_tuner = vidioc_s_tuner,1863.vidioc_g_frequency = vidioc_g_frequency,1864.vidioc_s_frequency = vidioc_s_frequency,1865#ifdef CONFIG_VIDEO_ADV_DEBUG1866.vidioc_g_register = vidioc_g_register,1867.vidioc_s_register = vidioc_s_register,1868#endif1869.vidioc_g_chip_ident = vidioc_g_chip_ident,1870};18711872static const struct video_device au0828_video_template = {1873.fops = &au0828_v4l_fops,1874.release = video_device_release,1875.ioctl_ops = &video_ioctl_ops,1876.tvnorms = V4L2_STD_NTSC_M,1877.current_norm = V4L2_STD_NTSC_M,1878};18791880/**************************************************************************/18811882int au0828_analog_register(struct au0828_dev *dev,1883struct usb_interface *interface)1884{1885int retval = -ENOMEM;1886struct usb_host_interface *iface_desc;1887struct usb_endpoint_descriptor *endpoint;1888int i;18891890dprintk(1, "au0828_analog_register called!\n");18911892/* set au0828 usb interface0 to as5 */1893retval = usb_set_interface(dev->usbdev,1894interface->cur_altsetting->desc.bInterfaceNumber, 5);1895if (retval != 0) {1896printk(KERN_INFO "Failure setting usb interface0 to as5\n");1897return retval;1898}18991900/* Figure out which endpoint has the isoc interface */1901iface_desc = interface->cur_altsetting;1902for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {1903endpoint = &iface_desc->endpoint[i].desc;1904if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)1905== USB_DIR_IN) &&1906((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)1907== USB_ENDPOINT_XFER_ISOC)) {19081909/* we find our isoc in endpoint */1910u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);1911dev->max_pkt_size = (tmp & 0x07ff) *1912(((tmp & 0x1800) >> 11) + 1);1913dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;1914}1915}1916if (!(dev->isoc_in_endpointaddr)) {1917printk(KERN_INFO "Could not locate isoc endpoint\n");1918kfree(dev);1919return -ENODEV;1920}19211922init_waitqueue_head(&dev->open);1923spin_lock_init(&dev->slock);1924mutex_init(&dev->lock);19251926/* init video dma queues */1927INIT_LIST_HEAD(&dev->vidq.active);1928INIT_LIST_HEAD(&dev->vidq.queued);1929INIT_LIST_HEAD(&dev->vbiq.active);1930INIT_LIST_HEAD(&dev->vbiq.queued);19311932dev->vid_timeout.function = au0828_vid_buffer_timeout;1933dev->vid_timeout.data = (unsigned long) dev;1934init_timer(&dev->vid_timeout);19351936dev->vbi_timeout.function = au0828_vbi_buffer_timeout;1937dev->vbi_timeout.data = (unsigned long) dev;1938init_timer(&dev->vbi_timeout);19391940dev->width = NTSC_STD_W;1941dev->height = NTSC_STD_H;1942dev->field_size = dev->width * dev->height;1943dev->frame_size = dev->field_size << 1;1944dev->bytesperline = dev->width << 1;1945dev->ctrl_ainput = 0;19461947/* allocate and fill v4l2 video struct */1948dev->vdev = video_device_alloc();1949if (NULL == dev->vdev) {1950dprintk(1, "Can't allocate video_device.\n");1951return -ENOMEM;1952}19531954/* allocate the VBI struct */1955dev->vbi_dev = video_device_alloc();1956if (NULL == dev->vbi_dev) {1957dprintk(1, "Can't allocate vbi_device.\n");1958kfree(dev->vdev);1959return -ENOMEM;1960}19611962/* Fill the video capture device struct */1963*dev->vdev = au0828_video_template;1964dev->vdev->parent = &dev->usbdev->dev;1965strcpy(dev->vdev->name, "au0828a video");19661967/* Setup the VBI device */1968*dev->vbi_dev = au0828_video_template;1969dev->vbi_dev->parent = &dev->usbdev->dev;1970strcpy(dev->vbi_dev->name, "au0828a vbi");19711972/* Register the v4l2 device */1973video_set_drvdata(dev->vdev, dev);1974retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);1975if (retval != 0) {1976dprintk(1, "unable to register video device (error = %d).\n",1977retval);1978video_device_release(dev->vdev);1979return -ENODEV;1980}19811982/* Register the vbi device */1983video_set_drvdata(dev->vbi_dev, dev);1984retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);1985if (retval != 0) {1986dprintk(1, "unable to register vbi device (error = %d).\n",1987retval);1988video_device_release(dev->vbi_dev);1989video_device_release(dev->vdev);1990return -ENODEV;1991}19921993dprintk(1, "%s completed!\n", __func__);19941995return 0;1996}1997199819992000