18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2013 Lubomir Rintel 38c2ecf20Sopenharmony_ci * All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 68c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 78c2ecf20Sopenharmony_ci * are met: 88c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 98c2ecf20Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 108c2ecf20Sopenharmony_ci * without modification. 118c2ecf20Sopenharmony_ci * 2. The name of the author may not be used to endorse or promote products 128c2ecf20Sopenharmony_ci * derived from this software without specific prior written permission. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 158c2ecf20Sopenharmony_ci * GNU General Public License ("GPL"). 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 188c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 198c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 208c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 218c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 228c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 238c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 248c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 258c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 268c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 278c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Fushicai USBTV007 Audio-Video Grabber Driver 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * No physical hardware was harmed running Windows during the 338c2ecf20Sopenharmony_ci * reverse-engineering activity 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <linux/module.h> 378c2ecf20Sopenharmony_ci#include <linux/slab.h> 388c2ecf20Sopenharmony_ci#include <linux/usb.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include <media/v4l2-device.h> 418c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h> 428c2ecf20Sopenharmony_ci#include <media/videobuf2-v4l2.h> 438c2ecf20Sopenharmony_ci#include <media/videobuf2-vmalloc.h> 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Hardware. */ 468c2ecf20Sopenharmony_ci#define USBTV_VIDEO_ENDP 0x81 478c2ecf20Sopenharmony_ci#define USBTV_AUDIO_ENDP 0x83 488c2ecf20Sopenharmony_ci#define USBTV_BASE 0xc000 498c2ecf20Sopenharmony_ci#define USBTV_CONTROL_REG 11 508c2ecf20Sopenharmony_ci#define USBTV_REQUEST_REG 12 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* Number of concurrent isochronous urbs submitted. 538c2ecf20Sopenharmony_ci * Higher numbers was seen to overly saturate the USB bus. */ 548c2ecf20Sopenharmony_ci#define USBTV_ISOC_TRANSFERS 16 558c2ecf20Sopenharmony_ci#define USBTV_ISOC_PACKETS 8 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#define USBTV_CHUNK_SIZE 256 588c2ecf20Sopenharmony_ci#define USBTV_CHUNK 240 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define USBTV_AUDIO_URBSIZE 20480 618c2ecf20Sopenharmony_ci#define USBTV_AUDIO_HDRSIZE 4 628c2ecf20Sopenharmony_ci#define USBTV_AUDIO_BUFFER 65536 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* Chunk header. */ 658c2ecf20Sopenharmony_ci#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ 668c2ecf20Sopenharmony_ci == 0x88000000) 678c2ecf20Sopenharmony_ci#define USBTV_FRAME_ID(chunk) ((be32_to_cpu(chunk[0]) & 0x00ff0000) >> 16) 688c2ecf20Sopenharmony_ci#define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) 698c2ecf20Sopenharmony_ci#define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL | V4L2_STD_SECAM) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* parameters for supported TV norms */ 748c2ecf20Sopenharmony_cistruct usbtv_norm_params { 758c2ecf20Sopenharmony_ci v4l2_std_id norm; 768c2ecf20Sopenharmony_ci int cap_width, cap_height; 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* A single videobuf2 frame buffer. */ 808c2ecf20Sopenharmony_cistruct usbtv_buf { 818c2ecf20Sopenharmony_ci struct vb2_v4l2_buffer vb; 828c2ecf20Sopenharmony_ci struct list_head list; 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* Per-device structure. */ 868c2ecf20Sopenharmony_cistruct usbtv { 878c2ecf20Sopenharmony_ci struct device *dev; 888c2ecf20Sopenharmony_ci struct usb_device *udev; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* video */ 918c2ecf20Sopenharmony_ci struct v4l2_device v4l2_dev; 928c2ecf20Sopenharmony_ci struct v4l2_ctrl_handler ctrl; 938c2ecf20Sopenharmony_ci struct video_device vdev; 948c2ecf20Sopenharmony_ci struct vb2_queue vb2q; 958c2ecf20Sopenharmony_ci struct mutex v4l2_lock; 968c2ecf20Sopenharmony_ci struct mutex vb2q_lock; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* List of videobuf2 buffers protected by a lock. */ 998c2ecf20Sopenharmony_ci spinlock_t buflock; 1008c2ecf20Sopenharmony_ci struct list_head bufs; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* Number of currently processed frame, useful find 1038c2ecf20Sopenharmony_ci * out when a new one begins. */ 1048c2ecf20Sopenharmony_ci u32 frame_id; 1058c2ecf20Sopenharmony_ci int chunks_done; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci enum { 1088c2ecf20Sopenharmony_ci USBTV_COMPOSITE_INPUT, 1098c2ecf20Sopenharmony_ci USBTV_SVIDEO_INPUT, 1108c2ecf20Sopenharmony_ci } input; 1118c2ecf20Sopenharmony_ci v4l2_std_id norm; 1128c2ecf20Sopenharmony_ci int width, height; 1138c2ecf20Sopenharmony_ci int n_chunks; 1148c2ecf20Sopenharmony_ci int iso_size; 1158c2ecf20Sopenharmony_ci int last_odd; 1168c2ecf20Sopenharmony_ci unsigned int sequence; 1178c2ecf20Sopenharmony_ci struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* audio */ 1208c2ecf20Sopenharmony_ci struct snd_card *snd; 1218c2ecf20Sopenharmony_ci struct snd_pcm_substream *snd_substream; 1228c2ecf20Sopenharmony_ci atomic_t snd_stream; 1238c2ecf20Sopenharmony_ci struct work_struct snd_trigger; 1248c2ecf20Sopenharmony_ci struct urb *snd_bulk_urb; 1258c2ecf20Sopenharmony_ci size_t snd_buffer_pos; 1268c2ecf20Sopenharmony_ci size_t snd_period_pos; 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ciint usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ciint usbtv_video_init(struct usbtv *usbtv); 1328c2ecf20Sopenharmony_civoid usbtv_video_free(struct usbtv *usbtv); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ciint usbtv_audio_init(struct usbtv *usbtv); 1358c2ecf20Sopenharmony_civoid usbtv_audio_free(struct usbtv *usbtv); 1368c2ecf20Sopenharmony_civoid usbtv_audio_suspend(struct usbtv *usbtv); 1378c2ecf20Sopenharmony_civoid usbtv_audio_resume(struct usbtv *usbtv); 138