162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2013 Lubomir Rintel 362306a36Sopenharmony_ci * All rights reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 662306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 762306a36Sopenharmony_ci * are met: 862306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 962306a36Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 1062306a36Sopenharmony_ci * without modification. 1162306a36Sopenharmony_ci * 2. The name of the author may not be used to endorse or promote products 1262306a36Sopenharmony_ci * derived from this software without specific prior written permission. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 1562306a36Sopenharmony_ci * GNU General Public License ("GPL"). 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1862306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1962306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2062306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2162306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2262306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2362306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2462306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2562306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2662306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2762306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci/* 3062306a36Sopenharmony_ci * Fushicai USBTV007 Audio-Video Grabber Driver 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * No physical hardware was harmed running Windows during the 3362306a36Sopenharmony_ci * reverse-engineering activity 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <linux/module.h> 3762306a36Sopenharmony_ci#include <linux/slab.h> 3862306a36Sopenharmony_ci#include <linux/usb.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include <media/v4l2-device.h> 4162306a36Sopenharmony_ci#include <media/v4l2-ctrls.h> 4262306a36Sopenharmony_ci#include <media/videobuf2-v4l2.h> 4362306a36Sopenharmony_ci#include <media/videobuf2-vmalloc.h> 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* Hardware. */ 4662306a36Sopenharmony_ci#define USBTV_VIDEO_ENDP 0x81 4762306a36Sopenharmony_ci#define USBTV_AUDIO_ENDP 0x83 4862306a36Sopenharmony_ci#define USBTV_BASE 0xc000 4962306a36Sopenharmony_ci#define USBTV_CONTROL_REG 11 5062306a36Sopenharmony_ci#define USBTV_REQUEST_REG 12 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* Number of concurrent isochronous urbs submitted. 5362306a36Sopenharmony_ci * Higher numbers was seen to overly saturate the USB bus. */ 5462306a36Sopenharmony_ci#define USBTV_ISOC_TRANSFERS 16 5562306a36Sopenharmony_ci#define USBTV_ISOC_PACKETS 8 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define USBTV_CHUNK_SIZE 256 5862306a36Sopenharmony_ci#define USBTV_CHUNK 240 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define USBTV_AUDIO_URBSIZE 20480 6162306a36Sopenharmony_ci#define USBTV_AUDIO_HDRSIZE 4 6262306a36Sopenharmony_ci#define USBTV_AUDIO_BUFFER 65536 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* Chunk header. */ 6562306a36Sopenharmony_ci#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ 6662306a36Sopenharmony_ci == 0x88000000) 6762306a36Sopenharmony_ci#define USBTV_FRAME_ID(chunk) ((be32_to_cpu(chunk[0]) & 0x00ff0000) >> 16) 6862306a36Sopenharmony_ci#define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) 6962306a36Sopenharmony_ci#define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL | \ 7262306a36Sopenharmony_ci V4L2_STD_PAL_Nc | V4L2_STD_SECAM) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* parameters for supported TV norms */ 7562306a36Sopenharmony_cistruct usbtv_norm_params { 7662306a36Sopenharmony_ci v4l2_std_id norm; 7762306a36Sopenharmony_ci int cap_width, cap_height; 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* A single videobuf2 frame buffer. */ 8162306a36Sopenharmony_cistruct usbtv_buf { 8262306a36Sopenharmony_ci struct vb2_v4l2_buffer vb; 8362306a36Sopenharmony_ci struct list_head list; 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* Per-device structure. */ 8762306a36Sopenharmony_cistruct usbtv { 8862306a36Sopenharmony_ci struct device *dev; 8962306a36Sopenharmony_ci struct usb_device *udev; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* video */ 9262306a36Sopenharmony_ci struct v4l2_device v4l2_dev; 9362306a36Sopenharmony_ci struct v4l2_ctrl_handler ctrl; 9462306a36Sopenharmony_ci struct video_device vdev; 9562306a36Sopenharmony_ci struct vb2_queue vb2q; 9662306a36Sopenharmony_ci struct mutex v4l2_lock; 9762306a36Sopenharmony_ci struct mutex vb2q_lock; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* List of videobuf2 buffers protected by a lock. */ 10062306a36Sopenharmony_ci spinlock_t buflock; 10162306a36Sopenharmony_ci struct list_head bufs; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Number of currently processed frame, useful find 10462306a36Sopenharmony_ci * out when a new one begins. */ 10562306a36Sopenharmony_ci u32 frame_id; 10662306a36Sopenharmony_ci int chunks_done; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci enum { 10962306a36Sopenharmony_ci USBTV_COMPOSITE_INPUT, 11062306a36Sopenharmony_ci USBTV_SVIDEO_INPUT, 11162306a36Sopenharmony_ci } input; 11262306a36Sopenharmony_ci v4l2_std_id norm; 11362306a36Sopenharmony_ci int width, height; 11462306a36Sopenharmony_ci int n_chunks; 11562306a36Sopenharmony_ci int iso_size; 11662306a36Sopenharmony_ci int last_odd; 11762306a36Sopenharmony_ci unsigned int sequence; 11862306a36Sopenharmony_ci struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* audio */ 12162306a36Sopenharmony_ci struct snd_card *snd; 12262306a36Sopenharmony_ci struct snd_pcm_substream *snd_substream; 12362306a36Sopenharmony_ci atomic_t snd_stream; 12462306a36Sopenharmony_ci struct work_struct snd_trigger; 12562306a36Sopenharmony_ci struct urb *snd_bulk_urb; 12662306a36Sopenharmony_ci size_t snd_buffer_pos; 12762306a36Sopenharmony_ci size_t snd_period_pos; 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciint usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ciint usbtv_video_init(struct usbtv *usbtv); 13362306a36Sopenharmony_civoid usbtv_video_free(struct usbtv *usbtv); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ciint usbtv_audio_init(struct usbtv *usbtv); 13662306a36Sopenharmony_civoid usbtv_audio_free(struct usbtv *usbtv); 13762306a36Sopenharmony_civoid usbtv_audio_suspend(struct usbtv *usbtv); 13862306a36Sopenharmony_civoid usbtv_audio_resume(struct usbtv *usbtv); 139