^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) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // DVB USB compliant linux driver for Conexant USB reference design -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // (analog part).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Copyright (C) 2011, 2017, 2018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // Maciej S. Szmigiero (mail@maciej.szmigiero.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // In case there are new analog / DVB-T hybrid devices released in the market
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // using the same general design as Medion MD95700: a CX25840 video decoder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // outputting a BT.656 stream to a USB bridge chip which then forwards it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) // the host in isochronous USB packets this code should be made generic, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) // board specific bits implemented via separate card structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) // This is, however, unlikely as the Medion model was released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) // years ago (in 2005).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) // TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) // * audio support,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) // * finish radio support (requires audio of course),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) // * VBI support,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) // * controls support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <media/drv-intf/cx25840.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <media/tuner.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <media/v4l2-fh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <media/videobuf2-vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include "cxusb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int cxusb_medion_v_queue_setup(struct vb2_queue *q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned int *num_buffers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned int *num_planes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned int sizes[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct device *alloc_devs[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct dvb_usb_device *dvbdev = vb2_get_drv_priv(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned int size = cxdev->width * cxdev->height * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (*num_planes > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (*num_planes != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (sizes[0] < size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *num_planes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) sizes[0] = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int cxusb_medion_v_buf_init(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct dvb_usb_device *dvbdev = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) cxusb_vprintk(dvbdev, OPS, "buffer init\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (vb2_plane_size(vb, 0) < cxdev->width * cxdev->height * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) cxusb_vprintk(dvbdev, OPS, "buffer OK\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 0;
^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) static void cxusb_auxbuf_init(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u8 *buf, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) cxusb_vprintk(dvbdev, AUXB, "initializing auxbuf of len %u\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) auxbuf->buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) auxbuf->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) auxbuf->paylen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static void cxusb_auxbuf_head_trim(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (pos == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (WARN_ON(pos > auxbuf->paylen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) cxusb_vprintk(dvbdev, AUXB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) "trimming auxbuf len by %u to %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pos, auxbuf->paylen - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) memmove(auxbuf->buf, auxbuf->buf + pos, auxbuf->paylen - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) auxbuf->paylen -= pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static unsigned int cxusb_auxbuf_paylen(struct cxusb_medion_auxbuf *auxbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return auxbuf->paylen;
^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) static bool cxusb_auxbuf_make_space(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int howmuch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int freespace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (WARN_ON(howmuch >= auxbuf->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) howmuch = auxbuf->len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) freespace = auxbuf->len - cxusb_auxbuf_paylen(auxbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) cxusb_vprintk(dvbdev, AUXB, "freespace is %u\n", freespace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (freespace >= howmuch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) howmuch -= freespace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) cxusb_vprintk(dvbdev, AUXB, "will overwrite %u bytes of buffer\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) howmuch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) cxusb_auxbuf_head_trim(dvbdev, auxbuf, howmuch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* returns false if some data was overwritten */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static bool cxusb_auxbuf_append_urb(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned long len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) for (i = 0, len = 0; i < urb->number_of_packets; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) len += urb->iso_frame_desc[i].actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ret = cxusb_auxbuf_make_space(dvbdev, auxbuf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) for (i = 0; i < urb->number_of_packets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned int to_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) to_copy = urb->iso_frame_desc[i].actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) memcpy(auxbuf->buf + auxbuf->paylen, urb->transfer_buffer +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) urb->iso_frame_desc[i].offset, to_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) auxbuf->paylen += to_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static bool cxusb_auxbuf_copy(struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int pos, unsigned char *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (pos + len > auxbuf->paylen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) memcpy(dest, auxbuf->buf + pos, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static bool cxusb_medion_cf_refc_fld_chg(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) bool firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned int maxlines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned int maxlinesamples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) unsigned char buf[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) bool firstfield_code = (buf[3] & CXUSB_BT656_FIELD_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) CXUSB_BT656_FIELD_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) unsigned int remlines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (bt656->line == 0 || firstfield == firstfield_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (bt656->fmode == LINE_SAMPLES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unsigned int remsamples = maxlinesamples -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) bt656->linesamples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) cxusb_vprintk(dvbdev, BT656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) "field %c after line %u field change\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) firstfield ? '1' : '2', bt656->line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (bt656->buf && remsamples > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) memset(bt656->buf, 0, remsamples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) bt656->buf += remsamples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) cxusb_vprintk(dvbdev, BT656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "field %c line %u %u samples still remaining (of %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) firstfield ? '1' : '2',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) bt656->line, remsamples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) maxlinesamples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) bt656->line++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) remlines = maxlines - bt656->line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (bt656->buf && remlines > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) memset(bt656->buf, 0, remlines * maxlinesamples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bt656->buf += remlines * maxlinesamples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) cxusb_vprintk(dvbdev, BT656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "field %c %u lines still remaining (of %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) firstfield ? '1' : '2', remlines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) maxlines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static void cxusb_medion_cf_refc_start_sch(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) bool firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) unsigned char buf[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) bool firstfield_code = (buf[3] & CXUSB_BT656_FIELD_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) CXUSB_BT656_FIELD_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) bool sav_code = (buf[3] & CXUSB_BT656_SEAV_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) CXUSB_BT656_SEAV_SAV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) bool vbi_code = (buf[3] & CXUSB_BT656_VBI_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) CXUSB_BT656_VBI_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!sav_code || firstfield != firstfield_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!vbi_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) cxusb_vprintk(dvbdev, BT656, "line start @ pos %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) bt656->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) bt656->linesamples = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) bt656->fmode = LINE_SAMPLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) cxusb_vprintk(dvbdev, BT656, "VBI start @ pos %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) bt656->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) bt656->fmode = VBI_SAMPLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static void cxusb_medion_cf_refc_line_smpl(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) bool firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned int maxlinesamples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) unsigned char buf[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) bool sav_code = (buf[3] & CXUSB_BT656_SEAV_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) CXUSB_BT656_SEAV_SAV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) unsigned int remsamples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (sav_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) cxusb_vprintk(dvbdev, BT656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) "SAV in line samples @ line %u, pos %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) bt656->line, bt656->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) remsamples = maxlinesamples - bt656->linesamples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (bt656->buf && remsamples > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) memset(bt656->buf, 0, remsamples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) bt656->buf += remsamples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) cxusb_vprintk(dvbdev, BT656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) "field %c line %u %u samples still remaining (of %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) firstfield ? '1' : '2', bt656->line, remsamples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) maxlinesamples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) bt656->fmode = START_SEARCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) bt656->line++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static void cxusb_medion_cf_refc_vbi_smpl(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) unsigned char buf[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) bool sav_code = (buf[3] & CXUSB_BT656_SEAV_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) CXUSB_BT656_SEAV_SAV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (sav_code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) cxusb_vprintk(dvbdev, BT656, "SAV in VBI samples @ pos %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) bt656->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) bt656->fmode = START_SEARCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* returns whether the whole 4-byte code should be skipped in the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static bool cxusb_medion_cf_ref_code(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) bool firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) unsigned int maxlines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned int maxlinesamples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned char buf[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (bt656->fmode == START_SEARCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) cxusb_medion_cf_refc_start_sch(dvbdev, bt656, firstfield, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) } else if (bt656->fmode == LINE_SAMPLES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) cxusb_medion_cf_refc_line_smpl(dvbdev, bt656, firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) maxlinesamples, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } else if (bt656->fmode == VBI_SAMPLES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) cxusb_medion_cf_refc_vbi_smpl(dvbdev, bt656, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return false;
^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) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static bool cxusb_medion_cs_start_sch(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) unsigned int maxlinesamples)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) unsigned char buf[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) unsigned int tocheck = clamp_t(size_t, maxlinesamples / 4, 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (!cxusb_auxbuf_copy(auxbuf, bt656->pos + 1, buf, tocheck))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) for (idx = 0; idx <= tocheck - 3; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (memcmp(buf + idx, CXUSB_BT656_PREAMBLE, 3) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) bt656->pos += (1 + idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) cxusb_vprintk(dvbdev, BT656, "line %u early start, pos %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) bt656->line, bt656->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) bt656->linesamples = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) bt656->fmode = LINE_SAMPLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static void cxusb_medion_cs_line_smpl(struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) unsigned int maxlinesamples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (bt656->buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) *(bt656->buf++) = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) bt656->linesamples++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) bt656->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (bt656->linesamples >= maxlinesamples) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) bt656->fmode = START_SEARCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) bt656->line++;
^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) static bool cxusb_medion_copy_samples(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unsigned int maxlinesamples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (bt656->fmode == START_SEARCH && bt656->line > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return cxusb_medion_cs_start_sch(dvbdev, auxbuf, bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) maxlinesamples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) else if (bt656->fmode == LINE_SAMPLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) cxusb_medion_cs_line_smpl(bt656, maxlinesamples, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) else /* TODO: copy VBI samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) bt656->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static bool cxusb_medion_copy_field(struct dvb_usb_device *dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct cxusb_medion_auxbuf *auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct cxusb_bt656_params *bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) bool firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) unsigned int maxlines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) unsigned int maxlinesmpls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) while (bt656->line < maxlines) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (!cxusb_auxbuf_copy(auxbuf, bt656->pos, &val, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (val == CXUSB_BT656_PREAMBLE[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) unsigned char buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) buf[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!cxusb_auxbuf_copy(auxbuf, bt656->pos + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) buf + 1, 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (buf[1] == CXUSB_BT656_PREAMBLE[1] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) buf[2] == CXUSB_BT656_PREAMBLE[2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * is this a field change?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * if so, terminate copying the current field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (cxusb_medion_cf_refc_fld_chg(dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) maxlines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) maxlinesmpls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (cxusb_medion_cf_ref_code(dvbdev, bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) firstfield,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) maxlines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) maxlinesmpls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) bt656->pos += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!cxusb_medion_copy_samples(dvbdev, auxbuf, bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) maxlinesmpls, val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (bt656->line < maxlines) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) cxusb_vprintk(dvbdev, BT656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) "end of buffer pos = %u, line = %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) bt656->pos, bt656->line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static bool cxusb_medion_v_process_auxbuf(struct cxusb_medion_dev *cxdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) bool reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct dvb_usb_device *dvbdev = cxdev->dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct cxusb_bt656_params *bt656 = &cxdev->bt656;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * if this is a new frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * fetch a buffer from list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (bt656->mode == NEW_FRAME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (!list_empty(&cxdev->buflist)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) cxdev->vbuf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) list_first_entry(&cxdev->buflist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct cxusb_medion_vbuffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) list_del(&cxdev->vbuf->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) dev_warn(&dvbdev->udev->dev, "no free buffers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (bt656->mode == NEW_FRAME || reset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) cxusb_vprintk(dvbdev, URB, "will copy field 1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) bt656->pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) bt656->mode = FIRST_FIELD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) bt656->fmode = START_SEARCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) bt656->line = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (cxdev->vbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) cxdev->vbuf->vb2.vb2_buf.timestamp = ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) bt656->buf = vb2_plane_vaddr(&cxdev->vbuf->vb2.vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (bt656->mode == FIRST_FIELD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (!cxusb_medion_copy_field(dvbdev, &cxdev->auxbuf, bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) true, cxdev->height / 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) cxdev->width * 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * do not trim buffer there in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * we need to reset the search later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) cxusb_vprintk(dvbdev, URB, "will copy field 2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) bt656->mode = SECOND_FIELD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) bt656->fmode = START_SEARCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) bt656->line = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (bt656->mode == SECOND_FIELD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (!cxusb_medion_copy_field(dvbdev, &cxdev->auxbuf, bt656,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) false, cxdev->height / 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) cxdev->width * 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) cxusb_auxbuf_head_trim(dvbdev, &cxdev->auxbuf, bt656->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) bt656->mode = NEW_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (cxdev->vbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) vb2_set_plane_payload(&cxdev->vbuf->vb2.vb2_buf, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) cxdev->width * cxdev->height * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) cxdev->vbuf->vb2.field = cxdev->field_order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) cxdev->vbuf->vb2.sequence = cxdev->vbuf_sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) vb2_buffer_done(&cxdev->vbuf->vb2.vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) VB2_BUF_STATE_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) cxdev->vbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cxdev->bt656.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) cxusb_vprintk(dvbdev, URB, "frame done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) cxusb_vprintk(dvbdev, URB, "frame skipped\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) cxdev->vbuf_sequence++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static bool cxusb_medion_v_complete_handle_urb(struct cxusb_medion_dev *cxdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) bool *auxbuf_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct dvb_usb_device *dvbdev = cxdev->dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) unsigned int urbn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct urb *urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) *auxbuf_reset = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) urbn = cxdev->nexturb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!test_bit(urbn, &cxdev->urbcomplete))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) clear_bit(urbn, &cxdev->urbcomplete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) cxdev->nexturb++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) cxdev->nexturb %= CXUSB_VIDEO_URBS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) urb = cxdev->streamurbs[cxdev->nexturb];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) } while (!urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) urb = cxdev->streamurbs[urbn];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) cxusb_vprintk(dvbdev, URB, "URB %u status = %d\n", urbn, urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (urb->status == 0 || urb->status == -EXDEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) unsigned long len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) for (i = 0, len = 0; i < urb->number_of_packets; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) len += urb->iso_frame_desc[i].actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) cxusb_vprintk(dvbdev, URB, "URB %u data len = %lu\n", urbn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) cxusb_vprintk(dvbdev, URB, "appending URB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * append new data to auxbuf while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * overwriting old data if necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * if any overwrite happens then we can no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * longer rely on consistency of the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * data so let's start again the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * auxbuf frame assembling process from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * the beginning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) *auxbuf_reset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) !cxusb_auxbuf_append_urb(dvbdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) &cxdev->auxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) cxusb_vprintk(dvbdev, URB, "URB %u resubmit\n", urbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ret = usb_submit_urb(urb, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) "unable to resubmit URB %u (%d), you'll have to restart streaming\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) urbn, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* next URB is complete already? reschedule us then to handle it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return test_bit(cxdev->nexturb, &cxdev->urbcomplete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static void cxusb_medion_v_complete_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct cxusb_medion_dev *cxdev = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct cxusb_medion_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) urbwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct dvb_usb_device *dvbdev = cxdev->dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) bool auxbuf_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) bool reschedule;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) mutex_lock(cxdev->videodev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) cxusb_vprintk(dvbdev, URB, "worker called, stop_streaming = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) (int)cxdev->stop_streaming);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (cxdev->stop_streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) reschedule = cxusb_medion_v_complete_handle_urb(cxdev, &auxbuf_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (cxusb_medion_v_process_auxbuf(cxdev, auxbuf_reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /* reschedule us until auxbuf no longer can produce any frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) reschedule = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (reschedule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) cxusb_vprintk(dvbdev, URB, "rescheduling worker\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) schedule_work(&cxdev->urbwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) mutex_unlock(cxdev->videodev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static void cxusb_medion_v_complete(struct urb *u)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct dvb_usb_device *dvbdev = u->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) for (i = 0; i < CXUSB_VIDEO_URBS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (cxdev->streamurbs[i] == u)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (i >= CXUSB_VIDEO_URBS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) "complete on unknown URB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) cxusb_vprintk(dvbdev, URB, "URB %u complete\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) set_bit(i, &cxdev->urbcomplete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) schedule_work(&cxdev->urbwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static void cxusb_medion_urbs_free(struct cxusb_medion_dev *cxdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) for (i = 0; i < CXUSB_VIDEO_URBS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (cxdev->streamurbs[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) kfree(cxdev->streamurbs[i]->transfer_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) usb_free_urb(cxdev->streamurbs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) cxdev->streamurbs[i] = NULL;
^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) static void cxusb_medion_return_buffers(struct cxusb_medion_dev *cxdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) bool requeue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct cxusb_medion_vbuffer *vbuf, *vbuf_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) list_for_each_entry_safe(vbuf, vbuf_tmp, &cxdev->buflist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) list_del(&vbuf->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) vb2_buffer_done(&vbuf->vb2.vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) requeue ? VB2_BUF_STATE_QUEUED :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (cxdev->vbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) vb2_buffer_done(&cxdev->vbuf->vb2.vb2_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) requeue ? VB2_BUF_STATE_QUEUED :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) VB2_BUF_STATE_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) cxdev->vbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) cxdev->bt656.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static int cxusb_medion_v_ss_auxbuf_alloc(struct cxusb_medion_dev *cxdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) int *npackets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct dvb_usb_device *dvbdev = cxdev->dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) unsigned int framelen, urblen, auxbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) framelen = (cxdev->width * 2 + 4 + 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) (cxdev->height + 50 /* VBI lines */);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * try to fit a whole frame into each URB, as long as doing so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * does not require very high order memory allocations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) BUILD_BUG_ON(CXUSB_VIDEO_URB_MAX_SIZE / CXUSB_VIDEO_PKT_SIZE >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) CXUSB_VIDEO_MAX_FRAME_PKTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) *npackets = min_t(int, (framelen + CXUSB_VIDEO_PKT_SIZE - 1) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) CXUSB_VIDEO_PKT_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) CXUSB_VIDEO_URB_MAX_SIZE / CXUSB_VIDEO_PKT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) urblen = *npackets * CXUSB_VIDEO_PKT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) cxusb_vprintk(dvbdev, URB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) "each URB will have %d packets for total of %u bytes (%u x %u @ %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) *npackets, urblen, (unsigned int)cxdev->width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) (unsigned int)cxdev->height, framelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) auxbuflen = framelen + urblen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) buf = vmalloc(auxbuflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) cxusb_auxbuf_init(dvbdev, &cxdev->auxbuf, buf, auxbuflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static u32 cxusb_medion_norm2field_order(v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) bool is625 = norm & V4L2_STD_625_50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) bool is525 = norm & V4L2_STD_525_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (!is625 && !is525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (is625 && is525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (is625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return V4L2_FIELD_SEQ_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) else /* is525 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return V4L2_FIELD_SEQ_BT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static u32 cxusb_medion_field_order(struct cxusb_medion_dev *cxdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct dvb_usb_device *dvbdev = cxdev->dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) u32 field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) v4l2_std_id norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* TV tuner is PAL-only so it is always TB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (cxdev->input == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return V4L2_FIELD_SEQ_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) field = cxusb_medion_norm2field_order(cxdev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (field != V4L2_FIELD_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) ret = v4l2_subdev_call(cxdev->cx25840, video, g_std, &norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) cxusb_vprintk(dvbdev, OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) "cannot get current standard for input %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) (unsigned int)cxdev->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) field = cxusb_medion_norm2field_order(norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (field != V4L2_FIELD_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) dev_warn(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) "cannot determine field order for the current standard setup and received signal, using TB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return V4L2_FIELD_SEQ_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) static int cxusb_medion_v_start_streaming(struct vb2_queue *q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct dvb_usb_device *dvbdev = vb2_get_drv_priv(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) u8 streamon_params[2] = { 0x03, 0x00 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) int npackets, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) cxusb_vprintk(dvbdev, OPS, "should start streaming\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (cxdev->stop_streaming) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* stream is being stopped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) goto ret_retbufs;
^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) cxdev->field_order = cxusb_medion_field_order(cxdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) ret = v4l2_subdev_call(cxdev->cx25840, video, s_stream, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) "unable to start stream (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) goto ret_retbufs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) ret = cxusb_ctrl_msg(dvbdev, CMD_STREAMING_ON, streamon_params, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) "unable to start streaming (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) goto ret_unstream_cx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) ret = cxusb_medion_v_ss_auxbuf_alloc(cxdev, &npackets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) goto ret_unstream_md;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) for (i = 0; i < CXUSB_VIDEO_URBS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) int framen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) u8 *streambuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct urb *surb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * TODO: change this to an array of single pages to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * doing a large continuous allocation when (if)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * s-g isochronous USB transfers are supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) streambuf = kmalloc(npackets * CXUSB_VIDEO_PKT_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (!streambuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (i < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) goto ret_freeab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) surb = usb_alloc_urb(npackets, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (!surb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) kfree(streambuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) goto ret_freeu;
^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) cxdev->streamurbs[i] = surb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) surb->dev = dvbdev->udev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) surb->context = dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) surb->pipe = usb_rcvisocpipe(dvbdev->udev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) surb->interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) surb->transfer_flags = URB_ISO_ASAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) surb->transfer_buffer = streambuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) surb->complete = cxusb_medion_v_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) surb->number_of_packets = npackets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) surb->transfer_buffer_length = npackets * CXUSB_VIDEO_PKT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) for (framen = 0; framen < npackets; framen++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) surb->iso_frame_desc[framen].offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) CXUSB_VIDEO_PKT_SIZE * framen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) surb->iso_frame_desc[framen].length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) CXUSB_VIDEO_PKT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) cxdev->urbcomplete = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) cxdev->nexturb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) cxdev->vbuf_sequence = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) cxdev->vbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) cxdev->bt656.mode = NEW_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) cxdev->bt656.buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) for (i = 0; i < CXUSB_VIDEO_URBS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (cxdev->streamurbs[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ret = usb_submit_urb(cxdev->streamurbs[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) "URB %d submission failed (%d)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) ret_freeu:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) cxusb_medion_urbs_free(cxdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) ret_freeab:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) vfree(cxdev->auxbuf.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ret_unstream_md:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) cxusb_ctrl_msg(dvbdev, CMD_STREAMING_OFF, NULL, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) ret_unstream_cx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) v4l2_subdev_call(cxdev->cx25840, video, s_stream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ret_retbufs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) cxusb_medion_return_buffers(cxdev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static void cxusb_medion_v_stop_streaming(struct vb2_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct dvb_usb_device *dvbdev = vb2_get_drv_priv(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) cxusb_vprintk(dvbdev, OPS, "should stop streaming\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (WARN_ON(cxdev->stop_streaming))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) cxdev->stop_streaming = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) cxusb_ctrl_msg(dvbdev, CMD_STREAMING_OFF, NULL, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) ret = v4l2_subdev_call(cxdev->cx25840, video, s_stream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) dev_err(&dvbdev->udev->dev, "unable to stop stream (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* let URB completion run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) mutex_unlock(cxdev->videodev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) for (i = 0; i < CXUSB_VIDEO_URBS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (cxdev->streamurbs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) usb_kill_urb(cxdev->streamurbs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) flush_work(&cxdev->urbwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) mutex_lock(cxdev->videodev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) /* free transfer buffer and URB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) vfree(cxdev->auxbuf.buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) cxusb_medion_urbs_free(cxdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) cxusb_medion_return_buffers(cxdev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) cxdev->stop_streaming = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static void cxusub_medion_v_buf_queue(struct vb2_buffer *vb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct vb2_v4l2_buffer *v4l2buf = to_vb2_v4l2_buffer(vb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct cxusb_medion_vbuffer *vbuf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) container_of(v4l2buf, struct cxusb_medion_vbuffer, vb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct dvb_usb_device *dvbdev = vb2_get_drv_priv(vb->vb2_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* cxusb_vprintk(dvbdev, OPS, "mmmm.. a fresh buffer...\n"); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) list_add_tail(&vbuf->list, &cxdev->buflist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static const struct vb2_ops cxdev_video_qops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) .queue_setup = cxusb_medion_v_queue_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) .buf_init = cxusb_medion_v_buf_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) .start_streaming = cxusb_medion_v_start_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) .stop_streaming = cxusb_medion_v_stop_streaming,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) .buf_queue = cxusub_medion_v_buf_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) .wait_prepare = vb2_ops_wait_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .wait_finish = vb2_ops_wait_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static const __u32 videocaps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static const __u32 radiocaps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) static int cxusb_medion_v_querycap(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) strscpy(cap->driver, dvbdev->udev->dev.driver->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) strscpy(cap->card, "Medion 95700", sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) usb_make_path(dvbdev->udev, cap->bus_info, sizeof(cap->bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) cap->capabilities = videocaps | radiocaps | V4L2_CAP_DEVICE_CAPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return 0;
^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 cxusb_medion_v_enum_fmt_vid_cap(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) struct v4l2_fmtdesc *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (f->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) f->pixelformat = V4L2_PIX_FMT_UYVY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static int cxusb_medion_g_fmt_vid_cap(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) f->fmt.pix.width = cxdev->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) f->fmt.pix.height = cxdev->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) f->fmt.pix.field = vb2_start_streaming_called(&cxdev->videoqueue) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) cxdev->field_order : cxusb_medion_field_order(cxdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) f->fmt.pix.bytesperline = cxdev->width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) static int cxusb_medion_try_s_fmt_vid_cap(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct v4l2_format *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) bool isset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct v4l2_subdev_format subfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) u32 field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (isset && vb2_is_busy(&cxdev->videoqueue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) field = vb2_start_streaming_called(&cxdev->videoqueue) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) cxdev->field_order : cxusb_medion_field_order(cxdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) memset(&subfmt, 0, sizeof(subfmt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) subfmt.which = isset ? V4L2_SUBDEV_FORMAT_ACTIVE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) V4L2_SUBDEV_FORMAT_TRY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) subfmt.format.width = f->fmt.pix.width & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) subfmt.format.height = f->fmt.pix.height & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) subfmt.format.code = MEDIA_BUS_FMT_FIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) subfmt.format.field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) subfmt.format.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) ret = v4l2_subdev_call(cxdev->cx25840, pad, set_fmt, NULL, &subfmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) f->fmt.pix.width = subfmt.format.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) f->fmt.pix.height = subfmt.format.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) f->fmt.pix.field = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (isset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) cxdev->width = f->fmt.pix.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) cxdev->height = f->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static int cxusb_medion_try_fmt_vid_cap(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return cxusb_medion_try_s_fmt_vid_cap(file, f, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static int cxusb_medion_s_fmt_vid_cap(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct v4l2_format *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return cxusb_medion_try_s_fmt_vid_cap(file, f, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct v4l2_input input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) u32 inputcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) } cxusb_medion_inputs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) { .input = { .name = "TV tuner", .type = V4L2_INPUT_TYPE_TUNER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) .tuner = 0, .std = V4L2_STD_PAL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) .inputcfg = CX25840_COMPOSITE2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) { .input = { .name = "Composite", .type = V4L2_INPUT_TYPE_CAMERA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) .std = V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) .inputcfg = CX25840_COMPOSITE1, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) { .input = { .name = "S-Video", .type = V4L2_INPUT_TYPE_CAMERA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) .std = V4L2_STD_ALL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) .inputcfg = CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) #define CXUSB_INPUT_CNT ARRAY_SIZE(cxusb_medion_inputs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static int cxusb_medion_enum_input(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct v4l2_input *inp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) u32 index = inp->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (index >= CXUSB_INPUT_CNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) *inp = cxusb_medion_inputs[index].input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) inp->index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) inp->capabilities |= V4L2_IN_CAP_STD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (index == cxdev->input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) u32 status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) ret = v4l2_subdev_call(cxdev->cx25840, video, g_input_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) dev_warn(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) "cx25840 input status query failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) inp->status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static int cxusb_medion_g_input(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) unsigned int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) *i = cxdev->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) static int cxusb_medion_set_norm(struct cxusb_medion_dev *cxdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct dvb_usb_device *dvbdev = cxdev->dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) cxusb_vprintk(dvbdev, OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) "trying to set standard for input %u to %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) (unsigned int)cxdev->input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) (unsigned long)norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /* no autodetection support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (norm == V4L2_STD_UNKNOWN)
^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) /* on composite or S-Video any std is acceptable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (cxdev->input != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) ret = v4l2_subdev_call(cxdev->cx25840, video, s_std, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) goto ret_savenorm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /* TV tuner is only able to demodulate PAL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if ((norm & ~V4L2_STD_PAL) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) ret = v4l2_subdev_call(cxdev->tda9887, video, s_std, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) "tda9887 norm setup failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) ret = v4l2_subdev_call(cxdev->tuner, video, s_std, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) "tuner norm setup failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) ret = v4l2_subdev_call(cxdev->cx25840, video, s_std, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) "cx25840 norm setup failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) ret_savenorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) cxdev->norm = norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) static int cxusb_medion_s_input(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) v4l2_std_id norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (i >= CXUSB_INPUT_CNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) ret = v4l2_subdev_call(cxdev->cx25840, video, s_routing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) cxusb_medion_inputs[i].inputcfg, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) cxdev->input = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) cxdev->videodev->tvnorms = cxusb_medion_inputs[i].input.std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) norm = cxdev->norm & cxusb_medion_inputs[i].input.std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (norm == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) norm = cxusb_medion_inputs[i].input.std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) cxusb_medion_set_norm(cxdev, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) static int cxusb_medion_g_tuner(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct v4l2_tuner *tuner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) struct video_device *vdev = video_devdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (tuner->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (vdev->vfl_type == VFL_TYPE_VIDEO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) tuner->type = V4L2_TUNER_ANALOG_TV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) tuner->type = V4L2_TUNER_RADIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) tuner->capability = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) tuner->afc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) * fills:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * always: capability (static), rangelow (static), rangehigh (static)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * radio mode: afc (may fail silently), rxsubchans (static), audmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) ret = v4l2_subdev_call(cxdev->tda9887, tuner, g_tuner, tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * fills:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * always: capability (static), rangelow (static), rangehigh (static)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * radio mode: rxsubchans (always stereo), audmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * signal (might be wrong)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) ret = v4l2_subdev_call(cxdev->tuner, tuner, g_tuner, tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) tuner->signal = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * fills: TV mode: capability, rxsubchans, audmode, signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) ret = v4l2_subdev_call(cxdev->cx25840, tuner, g_tuner, tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (vdev->vfl_type == VFL_TYPE_VIDEO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) strscpy(tuner->name, "TV tuner", sizeof(tuner->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) strscpy(tuner->name, "Radio tuner", sizeof(tuner->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) memset(tuner->reserved, 0, sizeof(tuner->reserved));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static int cxusb_medion_s_tuner(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) const struct v4l2_tuner *tuner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct video_device *vdev = video_devdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (tuner->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) ret = v4l2_subdev_call(cxdev->tda9887, tuner, s_tuner, tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) ret = v4l2_subdev_call(cxdev->tuner, tuner, s_tuner, tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) * make sure that cx25840 is in a correct TV / radio mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) * since calls above may have changed it for tuner / IF demod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) if (vdev->vfl_type == VFL_TYPE_VIDEO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) v4l2_subdev_call(cxdev->cx25840, video, s_std, cxdev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) v4l2_subdev_call(cxdev->cx25840, tuner, s_radio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) return v4l2_subdev_call(cxdev->cx25840, tuner, s_tuner, tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) static int cxusb_medion_g_frequency(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) struct v4l2_frequency *freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (freq->tuner != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return v4l2_subdev_call(cxdev->tuner, tuner, g_frequency, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) static int cxusb_medion_s_frequency(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) const struct v4l2_frequency *freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) struct video_device *vdev = video_devdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (freq->tuner != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) ret = v4l2_subdev_call(cxdev->tda9887, tuner, s_frequency, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) ret = v4l2_subdev_call(cxdev->tuner, tuner, s_frequency, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * make sure that cx25840 is in a correct TV / radio mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * since calls above may have changed it for tuner / IF demod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (vdev->vfl_type == VFL_TYPE_VIDEO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) v4l2_subdev_call(cxdev->cx25840, video, s_std, cxdev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) v4l2_subdev_call(cxdev->cx25840, tuner, s_radio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return v4l2_subdev_call(cxdev->cx25840, tuner, s_frequency, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static int cxusb_medion_g_std(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) v4l2_std_id *norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) *norm = cxdev->norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (*norm == V4L2_STD_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return 0;
^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) static int cxusb_medion_s_std(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) v4l2_std_id norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return cxusb_medion_set_norm(cxdev, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) static int cxusb_medion_querystd(struct file *file, void *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) v4l2_std_id *norm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) v4l2_std_id norm_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * make sure we don't have improper std bits set for the TV tuner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * (could happen when no signal was present yet after reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (cxdev->input == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) norm_mask = V4L2_STD_PAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) norm_mask = V4L2_STD_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) ret = v4l2_subdev_call(cxdev->cx25840, video, querystd, norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) cxusb_vprintk(dvbdev, OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) "cannot get detected standard for input %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) (unsigned int)cxdev->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) cxusb_vprintk(dvbdev, OPS, "input %u detected standard is %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) (unsigned int)cxdev->input, (unsigned long)*norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) *norm &= norm_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) static int cxusb_medion_log_status(struct file *file, void *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) struct dvb_usb_device *dvbdev = video_drvdata(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) v4l2_device_call_all(&cxdev->v4l2dev, 0, core, log_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) static const struct v4l2_ioctl_ops cxusb_video_ioctl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) .vidioc_querycap = cxusb_medion_v_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) .vidioc_enum_fmt_vid_cap = cxusb_medion_v_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) .vidioc_g_fmt_vid_cap = cxusb_medion_g_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) .vidioc_s_fmt_vid_cap = cxusb_medion_s_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) .vidioc_try_fmt_vid_cap = cxusb_medion_try_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) .vidioc_enum_input = cxusb_medion_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) .vidioc_g_input = cxusb_medion_g_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) .vidioc_s_input = cxusb_medion_s_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) .vidioc_g_tuner = cxusb_medion_g_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) .vidioc_s_tuner = cxusb_medion_s_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) .vidioc_g_frequency = cxusb_medion_g_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) .vidioc_s_frequency = cxusb_medion_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) .vidioc_g_std = cxusb_medion_g_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) .vidioc_s_std = cxusb_medion_s_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) .vidioc_querystd = cxusb_medion_querystd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) .vidioc_log_status = cxusb_medion_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) .vidioc_reqbufs = vb2_ioctl_reqbufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) .vidioc_querybuf = vb2_ioctl_querybuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) .vidioc_qbuf = vb2_ioctl_qbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) .vidioc_dqbuf = vb2_ioctl_dqbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) .vidioc_create_bufs = vb2_ioctl_create_bufs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) .vidioc_streamon = vb2_ioctl_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) .vidioc_streamoff = vb2_ioctl_streamoff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) static const struct v4l2_ioctl_ops cxusb_radio_ioctl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) .vidioc_querycap = cxusb_medion_v_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) .vidioc_g_tuner = cxusb_medion_g_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) .vidioc_s_tuner = cxusb_medion_s_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) .vidioc_g_frequency = cxusb_medion_g_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) .vidioc_s_frequency = cxusb_medion_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) .vidioc_log_status = cxusb_medion_log_status
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * in principle, this should be const, but s_io_pin_config is declared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * to take non-const, and gcc complains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) static struct v4l2_subdev_io_pin_config cxusub_medion_pin_config[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) { .pin = CX25840_PIN_DVALID_PRGM0, .function = CX25840_PAD_DEFAULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) .strength = CX25840_PIN_DRIVE_MEDIUM },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) { .pin = CX25840_PIN_PLL_CLK_PRGM7, .function = CX25840_PAD_AUX_PLL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) { .pin = CX25840_PIN_HRESET_PRGM2, .function = CX25840_PAD_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) .strength = CX25840_PIN_DRIVE_MEDIUM }
^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) int cxusb_medion_analog_init(struct dvb_usb_device *dvbdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) u8 tuner_analog_msg_data[] = { 0x9c, 0x60, 0x85, 0x54 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) struct i2c_msg tuner_analog_msg = { .addr = 0x61, .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) .buf = tuner_analog_msg_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) .len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) sizeof(tuner_analog_msg_data) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) struct v4l2_subdev_format subfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /* switch tuner to analog mode so IF demod will become accessible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) ret = i2c_transfer(&dvbdev->i2c_adap, &tuner_analog_msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) dev_warn(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) "tuner analog switch failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) * cx25840 might have lost power during mode switching so we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) * to set it again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) ret = v4l2_subdev_call(cxdev->cx25840, core, reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) dev_warn(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) "cx25840 reset failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) ret = v4l2_subdev_call(cxdev->cx25840, video, s_routing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) CX25840_COMPOSITE1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) dev_warn(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) "cx25840 initial input setting failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) /* composite */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) cxdev->input = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) cxdev->videodev->tvnorms = V4L2_STD_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) cxdev->norm = V4L2_STD_PAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) /* TODO: setup audio samples insertion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) ret = v4l2_subdev_call(cxdev->cx25840, core, s_io_pin_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) ARRAY_SIZE(cxusub_medion_pin_config),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) cxusub_medion_pin_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) dev_warn(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) "cx25840 pin config failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) /* make sure that we aren't in radio mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) v4l2_subdev_call(cxdev->tda9887, video, s_std, cxdev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) v4l2_subdev_call(cxdev->tuner, video, s_std, cxdev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) v4l2_subdev_call(cxdev->cx25840, video, s_std, cxdev->norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) memset(&subfmt, 0, sizeof(subfmt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) subfmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) subfmt.format.width = cxdev->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) subfmt.format.height = cxdev->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) subfmt.format.code = MEDIA_BUS_FMT_FIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) subfmt.format.field = V4L2_FIELD_SEQ_TB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) subfmt.format.colorspace = V4L2_COLORSPACE_SMPTE170M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) ret = v4l2_subdev_call(cxdev->cx25840, pad, set_fmt, NULL, &subfmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) dev_warn(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) "cx25840 format set failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) cxdev->width = subfmt.format.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) cxdev->height = subfmt.format.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) static int cxusb_videoradio_open(struct file *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) struct dvb_usb_device *dvbdev = video_drvdata(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * no locking needed since this call only modifies analog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * state if there are no other analog handles currenly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * opened so ops done via them cannot create a conflict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) ret = cxusb_medion_get(dvbdev, CXUSB_OPEN_ANALOG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) ret = v4l2_fh_open(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) goto ret_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) cxusb_vprintk(dvbdev, OPS, "got open\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) ret_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) cxusb_medion_put(dvbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) static int cxusb_videoradio_release(struct file *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) struct video_device *vdev = video_devdata(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct dvb_usb_device *dvbdev = video_drvdata(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) cxusb_vprintk(dvbdev, OPS, "got release\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (vdev->vfl_type == VFL_TYPE_VIDEO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) ret = vb2_fop_release(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) ret = v4l2_fh_release(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) cxusb_medion_put(dvbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static const struct v4l2_file_operations cxusb_video_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) .read = vb2_fop_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) .poll = vb2_fop_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) .mmap = vb2_fop_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) .open = cxusb_videoradio_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) .release = cxusb_videoradio_release
^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 const struct v4l2_file_operations cxusb_radio_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) .open = cxusb_videoradio_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) .release = cxusb_videoradio_release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) static void cxusb_medion_v4l2_release(struct v4l2_device *v4l2_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) struct cxusb_medion_dev *cxdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) container_of(v4l2_dev, struct cxusb_medion_dev, v4l2dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) struct dvb_usb_device *dvbdev = cxdev->dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) cxusb_vprintk(dvbdev, OPS, "v4l2 device release\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) v4l2_device_unregister(&cxdev->v4l2dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) mutex_destroy(&cxdev->dev_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) while (completion_done(&cxdev->v4l2_release))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) complete(&cxdev->v4l2_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) static void cxusb_medion_videodev_release(struct video_device *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) struct dvb_usb_device *dvbdev = video_get_drvdata(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) cxusb_vprintk(dvbdev, OPS, "video device release\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) video_device_release(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) static int cxusb_medion_register_analog_video(struct dvb_usb_device *dvbdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) cxdev->videoqueue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) cxdev->videoqueue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) VB2_DMABUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) cxdev->videoqueue.ops = &cxdev_video_qops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) cxdev->videoqueue.mem_ops = &vb2_vmalloc_memops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) cxdev->videoqueue.drv_priv = dvbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) cxdev->videoqueue.buf_struct_size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) sizeof(struct cxusb_medion_vbuffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) cxdev->videoqueue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) cxdev->videoqueue.min_buffers_needed = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) cxdev->videoqueue.lock = &cxdev->dev_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) ret = vb2_queue_init(&cxdev->videoqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) "video queue init failed, ret = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) cxdev->videodev = video_device_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if (!cxdev->videodev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) dev_err(&dvbdev->udev->dev, "video device alloc failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) cxdev->videodev->device_caps = videocaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) cxdev->videodev->fops = &cxusb_video_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) cxdev->videodev->v4l2_dev = &cxdev->v4l2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) cxdev->videodev->queue = &cxdev->videoqueue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) strscpy(cxdev->videodev->name, "cxusb", sizeof(cxdev->videodev->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) cxdev->videodev->vfl_dir = VFL_DIR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) cxdev->videodev->ioctl_ops = &cxusb_video_ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) cxdev->videodev->tvnorms = V4L2_STD_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) cxdev->videodev->release = cxusb_medion_videodev_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) cxdev->videodev->lock = &cxdev->dev_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) video_set_drvdata(cxdev->videodev, dvbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) ret = video_register_device(cxdev->videodev, VFL_TYPE_VIDEO, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) "video device register failed, ret = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) goto ret_vrelease;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) ret_vrelease:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) video_device_release(cxdev->videodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) static int cxusb_medion_register_analog_radio(struct dvb_usb_device *dvbdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) cxdev->radiodev = video_device_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) if (!cxdev->radiodev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) dev_err(&dvbdev->udev->dev, "radio device alloc failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) cxdev->radiodev->device_caps = radiocaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) cxdev->radiodev->fops = &cxusb_radio_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) cxdev->radiodev->v4l2_dev = &cxdev->v4l2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) strscpy(cxdev->radiodev->name, "cxusb", sizeof(cxdev->radiodev->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) cxdev->radiodev->vfl_dir = VFL_DIR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) cxdev->radiodev->ioctl_ops = &cxusb_radio_ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) cxdev->radiodev->release = video_device_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) cxdev->radiodev->lock = &cxdev->dev_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) video_set_drvdata(cxdev->radiodev, dvbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) ret = video_register_device(cxdev->radiodev, VFL_TYPE_RADIO, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) "radio device register failed, ret = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) video_device_release(cxdev->radiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) static int cxusb_medion_register_analog_subdevs(struct dvb_usb_device *dvbdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) struct tuner_setup tun_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) /* attach cx25840 capture chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) cxdev->cx25840 = v4l2_i2c_new_subdev(&cxdev->v4l2dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) &dvbdev->i2c_adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) "cx25840", 0x44, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) if (!cxdev->cx25840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) dev_err(&dvbdev->udev->dev, "cx25840 not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) * Initialize cx25840 chip by calling its subdevice init core op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) * This switches it into the generic mode that disables some of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) * ivtv-related hacks in the cx25840 driver while allowing setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) * of the chip video output configuration (passed in the call below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) * as the last argument).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) ret = v4l2_subdev_call(cxdev->cx25840, core, init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) CX25840_VCONFIG_FMT_BT656 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) CX25840_VCONFIG_RES_8BIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) CX25840_VCONFIG_VBIRAW_DISABLED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) CX25840_VCONFIG_ANCDATA_DISABLED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) CX25840_VCONFIG_ACTIVE_COMPOSITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) CX25840_VCONFIG_VALID_ANDACTIVE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) CX25840_VCONFIG_HRESETW_NORMAL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) CX25840_VCONFIG_CLKGATE_NONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) CX25840_VCONFIG_DCMODE_DWORDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) "cx25840 init failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) /* attach analog tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) cxdev->tuner = v4l2_i2c_new_subdev(&cxdev->v4l2dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) &dvbdev->i2c_adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) "tuner", 0x61, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) if (!cxdev->tuner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) dev_err(&dvbdev->udev->dev, "tuner not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) /* configure it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) memset(&tun_setup, 0, sizeof(tun_setup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) tun_setup.addr = 0x61;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) tun_setup.type = TUNER_PHILIPS_FMD1216ME_MK3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) tun_setup.mode_mask = T_RADIO | T_ANALOG_TV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) v4l2_subdev_call(cxdev->tuner, tuner, s_type_addr, &tun_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) /* attach IF demod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) cxdev->tda9887 = v4l2_i2c_new_subdev(&cxdev->v4l2dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) &dvbdev->i2c_adap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) "tuner", 0x43, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) if (!cxdev->tda9887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) dev_err(&dvbdev->udev->dev, "tda9887 not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) int cxusb_medion_register_analog(struct dvb_usb_device *dvbdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) mutex_init(&cxdev->dev_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) init_completion(&cxdev->v4l2_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) cxdev->v4l2dev.release = cxusb_medion_v4l2_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) ret = v4l2_device_register(&dvbdev->udev->dev, &cxdev->v4l2dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) dev_err(&dvbdev->udev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) "V4L2 device registration failed, ret = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) mutex_destroy(&cxdev->dev_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) ret = cxusb_medion_register_analog_subdevs(dvbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) goto ret_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) INIT_WORK(&cxdev->urbwork, cxusb_medion_v_complete_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) INIT_LIST_HEAD(&cxdev->buflist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) cxdev->width = 320;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) cxdev->height = 240;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) ret = cxusb_medion_register_analog_video(dvbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) goto ret_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) ret = cxusb_medion_register_analog_radio(dvbdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) goto ret_vunreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) ret_vunreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) vb2_video_unregister_device(cxdev->videodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) ret_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) v4l2_device_put(&cxdev->v4l2dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) wait_for_completion(&cxdev->v4l2_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) void cxusb_medion_unregister_analog(struct dvb_usb_device *dvbdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) struct cxusb_medion_dev *cxdev = dvbdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) cxusb_vprintk(dvbdev, OPS, "unregistering analog\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) video_unregister_device(cxdev->radiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) vb2_video_unregister_device(cxdev->videodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) v4l2_device_put(&cxdev->v4l2dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) wait_for_completion(&cxdev->v4l2_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) cxusb_vprintk(dvbdev, OPS, "analog unregistered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) }