^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Copyright (c) 2007 Michel Ludwig <michel.ludwig@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // - Fixed module load/unload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/random.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <media/tuner.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/freezer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "tm6000-regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "tm6000.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Limits minimum and default number of buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TM6000_MIN_BUF 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define TM6000_DEF_BUF 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define TM6000_NUM_URB_BUF 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Declare static vars that will be used as parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static int radio_nr = -1; /* /dev/radioN, -1 for autodetect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static bool keep_urb; /* keep urb buffers allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Debug level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int tm6000_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) EXPORT_SYMBOL_GPL(tm6000_debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static struct tm6000_fmt format[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .fourcc = V4L2_PIX_FMT_YUYV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .depth = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .fourcc = V4L2_PIX_FMT_UYVY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .depth = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .fourcc = V4L2_PIX_FMT_TM6000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .depth = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * DMA and thread functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define norm_maxw(a) 720
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define norm_maxh(a) 576
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define norm_minw(a) norm_maxw(a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define norm_minh(a) norm_maxh(a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * video-buf generic routine to get the next available buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct tm6000_buffer **buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (list_empty(&dma_q->active)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *buf = list_entry(dma_q->active.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct tm6000_buffer, vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Announces that a buffer were filled and request the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static inline void buffer_filled(struct tm6000_core *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct tm6000_dmaqueue *dma_q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct tm6000_buffer *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Advice that buffer was filled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) buf->vb.state = VIDEOBUF_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) buf->vb.field_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) buf->vb.ts = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) list_del(&buf->vb.queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) wake_up(&buf->vb.done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * Identify the tm5600/6000 buffer header type and properly handles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int copy_streams(u8 *data, unsigned long len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct tm6000_dmaqueue *dma_q = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u8 *ptr = data, *endp = data+len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned long header = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct tm6000_buffer *vbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) char *voutp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned int linewidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!dev->radio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* get video buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) get_next_buf(dma_q, &vbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (!vbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) voutp = videobuf_to_vmalloc(&vbuf->vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!voutp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) for (ptr = data; ptr < endp;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (!dev->isoc_ctl.cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (dev->isoc_ctl.tmp_buf_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* from last urb or packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) header = dev->isoc_ctl.tmp_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (4 - dev->isoc_ctl.tmp_buf_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) memcpy((u8 *)&header +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev->isoc_ctl.tmp_buf_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 4 - dev->isoc_ctl.tmp_buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ptr += 4 - dev->isoc_ctl.tmp_buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dev->isoc_ctl.tmp_buf_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (ptr + 3 >= endp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* have incomplete header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) dev->isoc_ctl.tmp_buf_len = endp - ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) memcpy(&dev->isoc_ctl.tmp_buf, ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dev->isoc_ctl.tmp_buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Seek for sync */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) for (; ptr < endp - 3; ptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (*(ptr + 3) == 0x47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* Get message header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) header = *(unsigned long *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ptr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* split the header fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) size = ((header & 0x7e) << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (size > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) block = (header >> 7) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) field = (header >> 11) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) line = (header >> 12) & 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) cmd = (header >> 21) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Validates header fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (size > TM6000_URB_MSG_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) size = TM6000_URB_MSG_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) pktsize = TM6000_URB_MSG_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * calculate position in buffer and change the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) case TM6000_URB_MSG_VIDEO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (!dev->radio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if ((dev->isoc_ctl.vfield != field) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) (field == 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * Announces that a new buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * were filled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) buffer_filled(dev, dma_q, vbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dprintk(dev, V4L2_DEBUG_ISOC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) "new buffer filled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) get_next_buf(dma_q, &vbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!vbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) voutp = videobuf_to_vmalloc(&vbuf->vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!voutp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) memset(voutp, 0, vbuf->vb.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) linewidth = vbuf->vb.width << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pos = ((line << 1) - field - 1) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) linewidth + block * TM6000_URB_MSG_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Don't allow to write out of the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (pos + size > vbuf->vb.size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) cmd = TM6000_URB_MSG_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dev->isoc_ctl.vfield = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case TM6000_URB_MSG_VBI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) case TM6000_URB_MSG_AUDIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case TM6000_URB_MSG_PTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) size = pktsize; /* Size is always 180 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Continue the last copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) cmd = dev->isoc_ctl.cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) size = dev->isoc_ctl.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) pos = dev->isoc_ctl.pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) pktsize = dev->isoc_ctl.pktsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) field = dev->isoc_ctl.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) cpysize = (endp - ptr > size) ? size : endp - ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (cpysize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* copy data in different buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) case TM6000_URB_MSG_VIDEO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* Fills video buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (vbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) memcpy(&voutp[pos], ptr, cpysize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case TM6000_URB_MSG_AUDIO: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (i = 0; i < cpysize; i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) swab16s((u16 *)(ptr + i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case TM6000_URB_MSG_VBI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Need some code to copy vbi buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) case TM6000_URB_MSG_PTS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Need some code to copy pts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u32 pts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) pts = *(u32 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) field, pts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (ptr + pktsize > endp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * End of URB packet, but cmd processing is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * complete. Preserve the state for a next packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dev->isoc_ctl.pos = pos + cpysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) dev->isoc_ctl.size = size - cpysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) dev->isoc_ctl.cmd = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) dev->isoc_ctl.field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dev->isoc_ctl.pktsize = pktsize - (endp - ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ptr += endp - ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) dev->isoc_ctl.cmd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ptr += pktsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Identify the tm5600/6000 buffer header type and properly handles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int copy_multiplexed(u8 *ptr, unsigned long len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct tm6000_dmaqueue *dma_q = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned int pos = dev->isoc_ctl.pos, cpysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct tm6000_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) char *outp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) get_next_buf(dma_q, &buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) outp = videobuf_to_vmalloc(&buf->vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!outp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) while (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) cpysize = min(len, buf->vb.size-pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) memcpy(&outp[pos], ptr, cpysize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pos += cpysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ptr += cpysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) len -= cpysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (pos >= buf->vb.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Announces that a new buffer were filled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) buffer_filled(dev, dma_q, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) get_next_buf(dma_q, &buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) outp = videobuf_to_vmalloc(&(buf->vb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (!outp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dev->isoc_ctl.pos = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static inline void print_err_status(struct tm6000_core *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int packet, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) char *errmsg = "Unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) switch (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) errmsg = "unlinked synchronously";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) errmsg = "unlinked asynchronously";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) case -ENOSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) errmsg = "Buffer error (overrun)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case -EPIPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) errmsg = "Stalled (device not responding)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case -EOVERFLOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) errmsg = "Babble (bad cable?)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case -EPROTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) errmsg = "Bit-stuff error (bad cable?)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case -EILSEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) errmsg = "CRC/Timeout (could be anything)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) case -ETIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) errmsg = "Device does not respond";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (packet < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) status, errmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) packet, status, errmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * Controls the isoc copy of each urb packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static inline int tm6000_isoc_copy(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct tm6000_dmaqueue *dma_q = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int i, len = 0, rc = 1, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (urb->status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) print_err_status(dev, -1, urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) for (i = 0; i < urb->number_of_packets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) status = urb->iso_frame_desc[i].status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) print_err_status(dev, i, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) len = urb->iso_frame_desc[i].actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!urb->iso_frame_desc[i].status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) rc = copy_multiplexed(p, len, urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (rc <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) copy_streams(p, len, urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * URB control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * IRQ callback, called by URB callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static void tm6000_irq_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct tm6000_dmaqueue *dma_q = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) switch (urb->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case -ETIMEDOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) tm6000_err("urb completion error %d.\n", urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) spin_lock_irqsave(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) tm6000_isoc_copy(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) spin_unlock_irqrestore(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* Reset urb buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) for (i = 0; i < urb->number_of_packets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) urb->iso_frame_desc[i].status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) urb->iso_frame_desc[i].actual_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) urb->status = usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (urb->status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) tm6000_err("urb resubmit failed (error=%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Allocate URB buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int tm6000_alloc_urb_buffers(struct tm6000_core *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int num_bufs = TM6000_NUM_URB_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (dev->urb_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) dev->urb_buffer = kmalloc_array(num_bufs, sizeof(*dev->urb_buffer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (!dev->urb_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) dev->urb_dma = kmalloc_array(num_bufs, sizeof(*dev->urb_dma),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!dev->urb_dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) for (i = 0; i < num_bufs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) dev->urb_buffer[i] = usb_alloc_coherent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) dev->udev, dev->urb_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) GFP_KERNEL, &dev->urb_dma[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!dev->urb_buffer[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) tm6000_err("unable to allocate %i bytes for transfer buffer %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) dev->urb_size, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) memset(dev->urb_buffer[i], 0, dev->urb_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * Free URB buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int tm6000_free_urb_buffers(struct tm6000_core *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!dev->urb_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) for (i = 0; i < TM6000_NUM_URB_BUF; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (dev->urb_buffer[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) usb_free_coherent(dev->udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) dev->urb_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) dev->urb_buffer[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dev->urb_dma[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) dev->urb_buffer[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) kfree(dev->urb_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) kfree(dev->urb_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) dev->urb_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dev->urb_dma = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * Stop and Deallocate URBs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static void tm6000_uninit_isoc(struct tm6000_core *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct urb *urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) dev->isoc_ctl.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) urb = dev->isoc_ctl.urb[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (urb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) usb_kill_urb(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) usb_unlink_urb(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) usb_free_urb(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) dev->isoc_ctl.urb[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev->isoc_ctl.transfer_buffer[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (!keep_urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) tm6000_free_urb_buffers(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) kfree(dev->isoc_ctl.urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) kfree(dev->isoc_ctl.transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) dev->isoc_ctl.urb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) dev->isoc_ctl.transfer_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) dev->isoc_ctl.num_bufs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * Assign URBs and start IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static int tm6000_prepare_isoc(struct tm6000_core *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct tm6000_dmaqueue *dma_q = &dev->vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int i, j, sb_size, pipe, size, max_packets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int num_bufs = TM6000_NUM_URB_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct urb *urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* De-allocates all pending stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) tm6000_uninit_isoc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /* Stop interrupt USB pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) tm6000_ir_int_stop(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) usb_set_interface(dev->udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) dev->isoc_in.bInterfaceNumber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dev->isoc_in.bAlternateSetting);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* Start interrupt USB pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) tm6000_ir_int_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) pipe = usb_rcvisocpipe(dev->udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) dev->isoc_in.endp->desc.bEndpointAddress &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) USB_ENDPOINT_NUMBER_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (size > dev->isoc_in.maxsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) size = dev->isoc_in.maxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) dev->isoc_ctl.max_pkt_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) max_packets = TM6000_MAX_ISO_PACKETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) sb_size = max_packets * size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev->urb_size = sb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) dev->isoc_ctl.num_bufs = num_bufs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) dev->isoc_ctl.urb = kmalloc_array(num_bufs, sizeof(void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (!dev->isoc_ctl.urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) dev->isoc_ctl.transfer_buffer = kmalloc_array(num_bufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) sizeof(void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (!dev->isoc_ctl.transfer_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) kfree(dev->isoc_ctl.urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets (%d bytes) of %d bytes each to handle %u size\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) max_packets, num_bufs, sb_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) dev->isoc_in.maxsize, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (tm6000_alloc_urb_buffers(dev) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) tm6000_err("cannot allocate memory for urb buffers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* call free, as some buffers might have been allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) tm6000_free_urb_buffers(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) kfree(dev->isoc_ctl.urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) kfree(dev->isoc_ctl.transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* allocate urbs and transfer buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) urb = usb_alloc_urb(max_packets, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!urb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) tm6000_uninit_isoc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) tm6000_free_urb_buffers(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) dev->isoc_ctl.urb[i] = urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) urb->transfer_dma = dev->urb_dma[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) dev->isoc_ctl.transfer_buffer[i] = dev->urb_buffer[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) usb_fill_bulk_urb(urb, dev->udev, pipe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) dev->isoc_ctl.transfer_buffer[i], sb_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) tm6000_irq_callback, dma_q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) urb->interval = dev->isoc_in.endp->desc.bInterval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) urb->number_of_packets = max_packets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) for (j = 0; j < max_packets; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) urb->iso_frame_desc[j].offset = size * j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) urb->iso_frame_desc[j].length = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static int tm6000_start_thread(struct tm6000_core *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct tm6000_dmaqueue *dma_q = &dev->vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) dma_q->frame = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) dma_q->ini_jiffies = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) init_waitqueue_head(&dma_q->wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* submit urbs and enables IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) tm6000_err("submit of urb %i failed (error=%i)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) tm6000_uninit_isoc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /* ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * Videobuf operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct tm6000_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) *size = fh->fmt->depth * fh->width * fh->height >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (0 == *count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) *count = TM6000_DEF_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (*count < TM6000_MIN_BUF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) *count = TM6000_MIN_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) while (*size * *count > vid_limit * 1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) (*count)--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct tm6000_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) BUG_ON(in_interrupt());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /* We used to wait for the buffer to finish here, but this didn't work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) because, as we were keeping the state as VIDEOBUF_QUEUED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) videobuf_queue_cancel marked it as finished for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) (Also, it could wedge forever if the hardware was misconfigured.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) This should be safe; by the time we get here, the buffer isn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) queued anymore. If we ever start marking the buffers as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) VIDEOBUF_ACTIVE, it won't be, though.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) spin_lock_irqsave(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (dev->isoc_ctl.buf == buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) dev->isoc_ctl.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) spin_unlock_irqrestore(&dev->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) videobuf_vmalloc_free(&buf->vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) buf->vb.state = VIDEOBUF_NEEDS_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) enum v4l2_field field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) struct tm6000_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) BUG_ON(NULL == fh->fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* FIXME: It assumes depth=2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* The only currently supported format is 16 bits/pixel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (buf->fmt != fh->fmt ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) buf->vb.width != fh->width ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) buf->vb.height != fh->height ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) buf->vb.field != field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) buf->fmt = fh->fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) buf->vb.width = fh->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) buf->vb.height = fh->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) buf->vb.field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) buf->vb.state = VIDEOBUF_NEEDS_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) rc = videobuf_iolock(vq, &buf->vb, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (!dev->isoc_ctl.num_bufs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) rc = tm6000_prepare_isoc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) rc = tm6000_start_thread(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) buf->vb.state = VIDEOBUF_PREPARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) free_buffer(vq, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) struct tm6000_fh *fh = vq->priv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct tm6000_dmaqueue *vidq = &dev->vidq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) buf->vb.state = VIDEOBUF_QUEUED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) list_add_tail(&buf->vb.queue, &vidq->active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) free_buffer(vq, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static const struct videobuf_queue_ops tm6000_video_qops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .buf_setup = buffer_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .buf_prepare = buffer_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .buf_queue = buffer_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .buf_release = buffer_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * IOCTL handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* Is the current fh handling it? if so, that's OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (dev->resources == fh && dev->is_res_read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /* Is the current fh handling it? if so, that's OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (dev->resources == fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) bool is_res_read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* Is the current fh handling it? if so, that's OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (dev->resources == fh && dev->is_res_read == is_res_read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* is it free? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (dev->resources)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /* grab it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) dev->resources = fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) dev->is_res_read = is_res_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) /* Is the current fh handling it? if so, that's OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (dev->resources != fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) dev->resources = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /* ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * IOCTL vidioc handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int vidioc_querycap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) strscpy(cap->driver, "tm6000", sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) strscpy(cap->card, "Trident TM5600/6000/6010", sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) V4L2_CAP_DEVICE_CAPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (dev->tuner_type != TUNER_ABSENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) cap->capabilities |= V4L2_CAP_TUNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (dev->caps.has_radio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) cap->capabilities |= V4L2_CAP_RADIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (f->index >= ARRAY_SIZE(format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) f->pixelformat = format[f->index].fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) f->fmt.pix.width = fh->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) f->fmt.pix.height = fh->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) f->fmt.pix.field = fh->vb_vidq.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) f->fmt.pix.pixelformat = fh->fmt->fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) f->fmt.pix.bytesperline =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) (f->fmt.pix.width * fh->fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) f->fmt.pix.sizeimage =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) f->fmt.pix.height * f->fmt.pix.bytesperline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) for (i = 0; i < ARRAY_SIZE(format); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (format[i].fourcc == fourcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return format+i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct tm6000_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) enum v4l2_field field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) fmt = format_by_fourcc(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (NULL == fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) dprintk(dev, 2, "Fourcc format (0x%08x) invalid.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) field = f->fmt.pix.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) field = V4L2_FIELD_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) tm6000_get_std_res(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) f->fmt.pix.width = dev->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) f->fmt.pix.height = dev->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) f->fmt.pix.width &= ~0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) f->fmt.pix.field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) f->fmt.pix.bytesperline =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) (f->fmt.pix.width * fmt->depth) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) f->fmt.pix.sizeimage =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) f->fmt.pix.height * f->fmt.pix.bytesperline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /*FIXME: This seems to be generic enough to be at videodev2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) int ret = vidioc_try_fmt_vid_cap(file, fh, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) fh->width = f->fmt.pix.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) fh->height = f->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) fh->vb_vidq.field = f->fmt.pix.field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) fh->type = f->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) dev->fourcc = f->fmt.pix.pixelformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) tm6000_set_fourcc_format(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) static int vidioc_reqbufs(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct v4l2_requestbuffers *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return videobuf_reqbufs(&fh->vb_vidq, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static int vidioc_querybuf(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct v4l2_buffer *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return videobuf_querybuf(&fh->vb_vidq, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return videobuf_qbuf(&fh->vb_vidq, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return videobuf_dqbuf(&fh->vb_vidq, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) file->f_flags & O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (i != fh->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (!res_get(dev, fh, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return videobuf_streamon(&fh->vb_vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (i != fh->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) videobuf_streamoff(&fh->vb_vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) res_free(dev, fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) dev->norm = norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) rc = tm6000_init_analog_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) fh->width = dev->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) fh->height = dev->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, dev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) *norm = dev->norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static const char *iname[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) [TM6000_INPUT_TV] = "Television",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) [TM6000_INPUT_COMPOSITE1] = "Composite 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) [TM6000_INPUT_COMPOSITE2] = "Composite 2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) [TM6000_INPUT_SVIDEO] = "S-Video",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int vidioc_enum_input(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct v4l2_input *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) unsigned int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) n = i->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (n >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (!dev->vinput[n].type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) i->index = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (dev->vinput[n].type == TM6000_INPUT_TV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) i->type = V4L2_INPUT_TYPE_TUNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) i->type = V4L2_INPUT_TYPE_CAMERA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) strscpy(i->name, iname[dev->vinput[n].type], sizeof(i->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) i->std = TM6000_STD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) *i = dev->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (i >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (!dev->vinput[i].type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) dev->input = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) rc = vidioc_s_std(file, priv, dev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) /* --- controls ---------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static int tm6000_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) struct tm6000_core *dev = container_of(ctrl->handler, struct tm6000_core, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) u8 val = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) case V4L2_CID_HUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) static const struct v4l2_ctrl_ops tm6000_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) .s_ctrl = tm6000_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) static int tm6000_radio_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) struct tm6000_core *dev = container_of(ctrl->handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) struct tm6000_core, radio_ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) u8 val = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case V4L2_CID_AUDIO_MUTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) dev->ctl_mute = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) tm6000_tvaudio_set_mute(dev, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) case V4L2_CID_AUDIO_VOLUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) dev->ctl_volume = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) tm6000_set_volume(dev, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static const struct v4l2_ctrl_ops tm6000_radio_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) .s_ctrl = tm6000_radio_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) static int vidioc_g_tuner(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) struct v4l2_tuner *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (UNSET == dev->tuner_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (0 != t->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) strscpy(t->name, "Television", sizeof(t->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) t->type = V4L2_TUNER_ANALOG_TV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) t->rangehigh = 0xffffffffUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) t->rxsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) t->audmode = dev->amode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) static int vidioc_s_tuner(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) const struct v4l2_tuner *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (UNSET == dev->tuner_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (0 != t->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (t->audmode > V4L2_TUNER_MODE_STEREO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) dev->amode = V4L2_TUNER_MODE_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) dev->amode = t->audmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) dprintk(dev, 3, "audio mode: %x\n", t->audmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) static int vidioc_g_frequency(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct v4l2_frequency *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (UNSET == dev->tuner_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (f->tuner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) f->frequency = dev->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) static int vidioc_s_frequency(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) const struct v4l2_frequency *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) struct tm6000_fh *fh = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (UNSET == dev->tuner_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (f->tuner != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) dev->freq = f->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) static int radio_g_tuner(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) struct v4l2_tuner *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) struct tm6000_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (0 != t->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) memset(t, 0, sizeof(*t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) strscpy(t->name, "Radio", sizeof(t->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) t->type = V4L2_TUNER_RADIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) t->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) t->rxsubchans = V4L2_TUNER_SUB_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) t->audmode = V4L2_TUNER_MODE_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static int radio_s_tuner(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) const struct v4l2_tuner *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct tm6000_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (0 != t->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) /* ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) File operations for the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) ------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) static int __tm6000_open(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) struct video_device *vdev = video_devdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) struct tm6000_core *dev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) struct tm6000_fh *fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) int radio = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) video_device_node_name(vdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) switch (vdev->vfl_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) case VFL_TYPE_VIDEO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) case VFL_TYPE_VBI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) type = V4L2_BUF_TYPE_VBI_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) case VFL_TYPE_RADIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) radio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) /* If more than one user, mutex should be added */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) dev->users++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) video_device_node_name(vdev), v4l2_type_names[type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) dev->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) /* allocate + initialize per filehandle data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) fh = kzalloc(sizeof(*fh), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (NULL == fh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) dev->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) v4l2_fh_init(&fh->fh, vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) file->private_data = fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) fh->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) fh->radio = radio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) dev->radio = radio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) fh->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) dev->fourcc = format[0].fourcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) fh->fmt = format_by_fourcc(dev->fourcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) tm6000_get_std_res(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) fh->width = dev->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) fh->height = dev->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=%p, dev=%p, dev->vidq=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) fh, dev, &dev->vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty queued=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) list_empty(&dev->vidq.queued));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty active=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) list_empty(&dev->vidq.active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) /* initialize hardware on analog mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) rc = tm6000_init_analog_mode(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) v4l2_fh_exit(&fh->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) kfree(fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) dev->mode = TM6000_MODE_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (!fh->radio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) NULL, &dev->slock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) fh->type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) V4L2_FIELD_INTERLACED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) sizeof(struct tm6000_buffer), fh, &dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) tm6000_set_audio_rinput(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) tm6000_prepare_isoc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) tm6000_start_thread(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) v4l2_fh_add(&fh->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) static int tm6000_open(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) struct video_device *vdev = video_devdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) mutex_lock(vdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) res = __tm6000_open(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) mutex_unlock(vdev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) struct tm6000_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (!res_get(fh->dev, fh, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if (mutex_lock_interruptible(&dev->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) res = videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) file->f_flags & O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) static __poll_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) __tm6000_poll(struct file *file, struct poll_table_struct *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) __poll_t req_events = poll_requested_events(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) struct tm6000_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) struct tm6000_buffer *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) __poll_t res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) if (v4l2_event_pending(&fh->fh))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) res = EPOLLPRI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) else if (req_events & EPOLLPRI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) poll_wait(file, &fh->fh.wait, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) return res | EPOLLERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (!!is_res_streaming(fh->dev, fh))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return res | EPOLLERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (!is_res_read(fh->dev, fh)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /* streaming capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (list_empty(&fh->vb_vidq.stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) return res | EPOLLERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) poll_wait(file, &buf->vb.done, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (buf->vb.state == VIDEOBUF_DONE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) buf->vb.state == VIDEOBUF_ERROR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) return res | EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) } else if (req_events & (EPOLLIN | EPOLLRDNORM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /* read() capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) return res | videobuf_poll_stream(file, &fh->vb_vidq, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) static __poll_t tm6000_poll(struct file *file, struct poll_table_struct *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) struct tm6000_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) __poll_t res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) mutex_lock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) res = __tm6000_poll(file, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) static int tm6000_release(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) struct tm6000_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) struct video_device *vdev = video_devdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) video_device_node_name(vdev), dev->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) mutex_lock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) dev->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) res_free(dev, fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) if (!dev->users) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) tm6000_uninit_isoc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /* Stop interrupt USB pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) tm6000_ir_int_stop(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) usb_reset_configuration(dev->udev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (dev->int_in.endp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) usb_set_interface(dev->udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) dev->isoc_in.bInterfaceNumber, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) usb_set_interface(dev->udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) dev->isoc_in.bInterfaceNumber, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) /* Start interrupt USB pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) tm6000_ir_int_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (!fh->radio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) videobuf_mmap_free(&fh->vb_vidq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) v4l2_fh_del(&fh->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) v4l2_fh_exit(&fh->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) kfree(fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) struct tm6000_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) struct tm6000_core *dev = fh->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (mutex_lock_interruptible(&dev->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) res = videobuf_mmap_mapper(&fh->vb_vidq, vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) mutex_unlock(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) static const struct v4l2_file_operations tm6000_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) .open = tm6000_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) .release = tm6000_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) .read = tm6000_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) .poll = tm6000_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) .mmap = tm6000_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) static const struct v4l2_ioctl_ops video_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) .vidioc_querycap = vidioc_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) .vidioc_s_std = vidioc_s_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) .vidioc_g_std = vidioc_g_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) .vidioc_enum_input = vidioc_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) .vidioc_g_input = vidioc_g_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) .vidioc_s_input = vidioc_s_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) .vidioc_g_tuner = vidioc_g_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) .vidioc_s_tuner = vidioc_s_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) .vidioc_g_frequency = vidioc_g_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) .vidioc_s_frequency = vidioc_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) .vidioc_streamon = vidioc_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) .vidioc_streamoff = vidioc_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) .vidioc_reqbufs = vidioc_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) .vidioc_querybuf = vidioc_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) .vidioc_qbuf = vidioc_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) .vidioc_dqbuf = vidioc_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) static struct video_device tm6000_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) .name = "tm6000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) .fops = &tm6000_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) .ioctl_ops = &video_ioctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) .release = video_device_release_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) .tvnorms = TM6000_STD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) static const struct v4l2_file_operations radio_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) .open = tm6000_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) .poll = v4l2_ctrl_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) .release = tm6000_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) static const struct v4l2_ioctl_ops radio_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) .vidioc_querycap = vidioc_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) .vidioc_g_tuner = radio_g_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) .vidioc_s_tuner = radio_s_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) .vidioc_g_frequency = vidioc_g_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) .vidioc_s_frequency = vidioc_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) static struct video_device tm6000_radio_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) .name = "tm6000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) .fops = &radio_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) .ioctl_ops = &radio_ioctl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) /* -----------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) * Initialization and module stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) * ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) static void vdev_init(struct tm6000_core *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct video_device *vfd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) const struct video_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) *template, const char *type_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) *vfd = *template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) vfd->v4l2_dev = &dev->v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) vfd->release = video_device_release_empty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) vfd->lock = &dev->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) video_set_drvdata(vfd, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) int tm6000_v4l2_register(struct tm6000_core *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) v4l2_ctrl_handler_init(&dev->ctrl_handler, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) V4L2_CID_AUDIO_VOLUME, -15, 15, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) V4L2_CID_BRIGHTNESS, 0, 255, 1, 54);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) V4L2_CID_CONTRAST, 0, 255, 1, 119);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) V4L2_CID_SATURATION, 0, 255, 1, 112);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) V4L2_CID_HUE, -128, 127, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) v4l2_ctrl_add_handler(&dev->ctrl_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) &dev->radio_ctrl_handler, NULL, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (dev->radio_ctrl_handler.error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) ret = dev->radio_ctrl_handler.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (!ret && dev->ctrl_handler.error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) ret = dev->ctrl_handler.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) goto free_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) vdev_init(dev, &dev->vfd, &tm6000_template, "video");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) dev->vfd.ctrl_handler = &dev->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) dev->vfd.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) V4L2_CAP_READWRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) if (dev->tuner_type != TUNER_ABSENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) dev->vfd.device_caps |= V4L2_CAP_TUNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) /* init video dma queues */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) INIT_LIST_HEAD(&dev->vidq.active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) INIT_LIST_HEAD(&dev->vidq.queued);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) ret = video_register_device(&dev->vfd, VFL_TYPE_VIDEO, video_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) printk(KERN_INFO "%s: can't register video device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) goto free_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) printk(KERN_INFO "%s: registered device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) dev->name, video_device_node_name(&dev->vfd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) if (dev->caps.has_radio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) vdev_init(dev, &dev->radio_dev, &tm6000_radio_template,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) "radio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) dev->radio_dev.ctrl_handler = &dev->radio_ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) dev->radio_dev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) ret = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) radio_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) printk(KERN_INFO "%s: can't register radio device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) goto unreg_video;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) printk(KERN_INFO "%s: registered device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) dev->name, video_device_node_name(&dev->radio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) unreg_video:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) video_unregister_device(&dev->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) free_ctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) v4l2_ctrl_handler_free(&dev->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) int tm6000_v4l2_unregister(struct tm6000_core *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) video_unregister_device(&dev->vfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) /* if URB buffers are still allocated free them now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) tm6000_free_urb_buffers(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) video_unregister_device(&dev->radio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) int tm6000_v4l2_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) module_param(video_nr, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) MODULE_PARM_DESC(video_nr, "Allow changing video device number");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) module_param_named(debug, tm6000_debug, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) MODULE_PARM_DESC(debug, "activates debug info");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) module_param(vid_limit, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) module_param(keep_urb, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) MODULE_PARM_DESC(keep_urb, "Keep urb buffers allocated even when the device is closed by the user");