^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2005 Mike Isely <isely@pobox.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "pvrusb2-context.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "pvrusb2-hdw.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "pvrusb2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "pvrusb2-debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "pvrusb2-v4l2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "pvrusb2-ioread.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <media/v4l2-dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <media/v4l2-fh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <media/v4l2-common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <media/v4l2-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct pvr2_v4l2_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct pvr2_v4l2_fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct pvr2_v4l2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct pvr2_v4l2_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct video_device devbase; /* MUST be first! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct pvr2_v4l2 *v4lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct pvr2_context_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* Information about this device: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) enum pvr2_config config; /* Expected stream format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int v4l_type; /* V4L defined type for this device node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct pvr2_v4l2_fh {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct v4l2_fh fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct pvr2_channel channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct pvr2_v4l2_dev *pdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct pvr2_ioread *rhp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct file *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) wait_queue_head_t wait_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int fw_mode_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Map contiguous ordinal value to input id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned char *input_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned int input_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct pvr2_v4l2 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct pvr2_channel channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* streams - Note that these must be separately, individually,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * allocated pointers. This is because the v4l core is going to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * manage their deletion - separately, individually... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct pvr2_v4l2_dev *dev_video;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct pvr2_v4l2_dev *dev_radio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) module_param_array(video_nr, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) module_param_array(radio_nr, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) module_param_array(vbi_nr, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define PVR_FORMAT_PIX 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define PVR_FORMAT_VBI 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static struct v4l2_format pvr_format [] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) [PVR_FORMAT_PIX] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .fmt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .pix = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .width = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .height = 576,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .pixelformat = V4L2_PIX_FMT_MPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .field = V4L2_FIELD_INTERLACED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* FIXME : Don't know what to put here... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .sizeimage = 32 * 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) [PVR_FORMAT_VBI] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .type = V4L2_BUF_TYPE_VBI_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .fmt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .vbi = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .sampling_rate = 27000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .offset = 248,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .samples_per_line = 1443,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .sample_format = V4L2_PIX_FMT_GREY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .start = { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .count = { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^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) * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) strscpy(cap->driver, "pvrusb2", sizeof(cap->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) strscpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) sizeof(cap->bus_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) strscpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ret = pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *std = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ret = pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *std = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct pvr2_ctrl *cptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct v4l2_input tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) memset(&tmp, 0, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) tmp.index = vi->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (vi->index >= fh->input_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) val = fh->input_map[vi->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case PVR2_CVAL_INPUT_TV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) case PVR2_CVAL_INPUT_DTV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) case PVR2_CVAL_INPUT_RADIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) tmp.type = V4L2_INPUT_TYPE_TUNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) case PVR2_CVAL_INPUT_SVIDEO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) case PVR2_CVAL_INPUT_COMPOSITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) tmp.type = V4L2_INPUT_TYPE_CAMERA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) pvr2_ctrl_get_valname(cptr, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) tmp.name, sizeof(tmp.name) - 1, &cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) tmp.name[cnt] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* Don't bother with audioset, since this driver currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) always switches the audio whenever the video is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) switched. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* Handling std is a tougher problem. It doesn't make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) sense in cases where a device might be multi-standard.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) We could just copy out the current value for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) standard, but it can change over time. For now just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) leave it zero. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *vi = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct pvr2_ctrl *cptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ret = pvr2_ctrl_get_value(cptr, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) *i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) for (idx = 0; idx < fh->input_cnt; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (fh->input_map[idx] == val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) *i = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (inp >= fh->input_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) fh->input_map[inp]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* pkt: FIXME: We are returning one "fake" input here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) which could very well be called "whatever_we_like".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) This is for apps that want to see an audio input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) just to feel comfortable, as well as to test if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) it can do stereo or sth. There is actually no guarantee
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) that the actual audio input cannot change behind the app's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) back, but most applications should not mind that either.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) Hopefully, mplayer people will work with us on this (this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) whole mess is to support mplayer pvr://), or Hans will come
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) up with a more standard way to say "we have inputs but we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) don 't want you to change them independent of video" which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) will sort this mess.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (vin->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) strscpy(vin->name, "PVRUSB2 Audio", sizeof(vin->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) vin->capability = V4L2_AUDCAP_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) vin->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) strscpy(vin->name, "PVRUSB2 Audio", sizeof(vin->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) vin->capability = V4L2_AUDCAP_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (vout->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^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 int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (vt->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return -EINVAL; /* Only answer for the 1st tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pvr2_hdw_execute_tuner_poll(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return pvr2_hdw_get_tuner_status(hdw, vt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (vt->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) vt->audmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) unsigned long fv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct v4l2_tuner vt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) int cur_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct pvr2_ctrl *ctrlp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = pvr2_hdw_get_tuner_status(hdw, &vt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (vf->type == V4L2_TUNER_RADIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (cur_input != PVR2_CVAL_INPUT_RADIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (cur_input == PVR2_CVAL_INPUT_RADIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) fv = vf->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (vt.capability & V4L2_TUNER_CAP_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) fv = (fv * 125) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) fv = fv * 62500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int cur_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct v4l2_tuner vt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ret = pvr2_hdw_get_tuner_status(hdw, &vt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ret = pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) &cur_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (cur_input == PVR2_CVAL_INPUT_RADIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) vf->type = V4L2_TUNER_RADIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) vf->type = V4L2_TUNER_ANALOG_TV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (vt.capability & V4L2_TUNER_CAP_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) val = (val * 2) / 125;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) val /= 62500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) vf->frequency = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* Only one format is supported: MPEG. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (fd->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) fd->pixelformat = V4L2_PIX_FMT_MPEG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) vf->fmt.pix.width = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) vf->fmt.pix.height = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int lmin, lmax, ldef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct pvr2_ctrl *hcp, *vcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) int h = vf->fmt.pix.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int w = vf->fmt.pix.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) lmin = pvr2_ctrl_get_min(hcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) lmax = pvr2_ctrl_get_max(hcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pvr2_ctrl_get_def(hcp, &ldef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (w == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) w = ldef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) else if (w < lmin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) w = lmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) else if (w > lmax)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) w = lmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) lmin = pvr2_ctrl_get_min(vcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) lmax = pvr2_ctrl_get_max(vcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) pvr2_ctrl_get_def(vcp, &ldef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (h == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) h = ldef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) else if (h < lmin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) h = lmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) else if (h > lmax)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) h = lmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) sizeof(struct v4l2_format));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) vf->fmt.pix.width = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) vf->fmt.pix.height = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct pvr2_ctrl *hcp, *vcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return 0;
^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) static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct pvr2_v4l2_dev *pdi = fh->pdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (!fh->pdi->stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* No stream defined for this node. This means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) that we're not currently allowed to stream from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) this node. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return pvr2_hdw_set_streaming(hdw, !0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (!fh->pdi->stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* No stream defined for this node. This means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) that we're not currently allowed to stream from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) this node. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return pvr2_hdw_set_streaming(hdw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) static int pvr2_queryctrl(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct v4l2_queryctrl *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct pvr2_ctrl *cptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) cptr = pvr2_hdw_get_ctrl_nextv4l(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (cptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) vc->id = pvr2_ctrl_get_v4lid(cptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (!cptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) pvr2_trace(PVR2_TRACE_V4LIOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) "QUERYCTRL id=0x%x not implemented here",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) vc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) pvr2_trace(PVR2_TRACE_V4LIOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) "QUERYCTRL id=0x%x mapping name=%s (%s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) vc->id, pvr2_ctrl_get_name(cptr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) pvr2_ctrl_get_desc(cptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) strscpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) vc->flags = pvr2_ctrl_get_v4lflags(cptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) pvr2_ctrl_get_def(cptr, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) vc->default_value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) switch (pvr2_ctrl_get_type(cptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case pvr2_ctl_enum:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) vc->type = V4L2_CTRL_TYPE_MENU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) vc->minimum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) vc->step = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) case pvr2_ctl_bool:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) vc->type = V4L2_CTRL_TYPE_BOOLEAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) vc->minimum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) vc->maximum = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) vc->step = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) case pvr2_ctl_int:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) vc->type = V4L2_CTRL_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) vc->minimum = pvr2_ctrl_get_min(cptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) vc->maximum = pvr2_ctrl_get_max(cptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) vc->step = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) pvr2_trace(PVR2_TRACE_V4LIOCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) "QUERYCTRL id=0x%x name=%s not mappable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) vc->id, pvr2_ctrl_get_name(cptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) unsigned int cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) vm->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) vm->name, sizeof(vm->name) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) &cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) vm->name[cnt] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) vc->value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) vc->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static int pvr2_g_ext_ctrls(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct v4l2_ext_controls *ctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct v4l2_ext_control *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct pvr2_ctrl *cptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) for (idx = 0; idx < ctls->count; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ctrl = ctls->controls + idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) cptr = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (cptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) pvr2_ctrl_get_def(cptr, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ret = pvr2_ctrl_get_value(cptr, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) ctls->error_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /* Ensure that if read as a 64 bit value, the user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) will still get a hopefully sane value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ctrl->value64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) ctrl->value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static int pvr2_s_ext_ctrls(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct v4l2_ext_controls *ctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) struct v4l2_ext_control *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /* Default value cannot be changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) for (idx = 0; idx < ctls->count; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ctrl = ctls->controls + idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ctrl->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ctls->error_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) goto commit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) commit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return ret;
^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) static int pvr2_try_ext_ctrls(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct v4l2_ext_controls *ctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct v4l2_ext_control *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct pvr2_ctrl *pctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* For the moment just validate that the requested control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) actually exists. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) for (idx = 0; idx < ctls->count; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) ctrl = ctls->controls + idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (!pctl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ctls->error_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static int pvr2_g_pixelaspect(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) int type, struct v4l2_fract *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct v4l2_cropcap cap = { .type = type };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ret = pvr2_hdw_get_cropcap(hdw, &cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) *f = cap.pixelaspect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static int pvr2_g_selection(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct v4l2_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct v4l2_cropcap cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) switch (sel->target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case V4L2_SEL_TGT_CROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ret = pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) sel->r.left = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ret = pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) sel->r.top = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ret = pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) sel->r.width = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ret = pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) sel->r.height = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) case V4L2_SEL_TGT_CROP_DEFAULT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) ret = pvr2_hdw_get_cropcap(hdw, &cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) sel->r = cap.defrect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) case V4L2_SEL_TGT_CROP_BOUNDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ret = pvr2_hdw_get_cropcap(hdw, &cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) sel->r = cap.bounds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) static int pvr2_s_selection(struct file *file, void *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct v4l2_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) sel->r.left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) goto commit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) sel->r.top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) goto commit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) sel->r.width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) goto commit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) ret = pvr2_ctrl_set_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) sel->r.height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) commit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) pvr2_hdw_commit_ctl(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) static int pvr2_log_status(struct file *file, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) pvr2_hdw_trigger_module_log(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .vidioc_querycap = pvr2_querycap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .vidioc_s_audio = pvr2_s_audio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .vidioc_g_audio = pvr2_g_audio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .vidioc_enumaudio = pvr2_enumaudio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .vidioc_enum_input = pvr2_enum_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .vidioc_g_pixelaspect = pvr2_g_pixelaspect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) .vidioc_s_selection = pvr2_s_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .vidioc_g_selection = pvr2_g_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .vidioc_g_input = pvr2_g_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .vidioc_s_input = pvr2_s_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .vidioc_g_frequency = pvr2_g_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .vidioc_s_frequency = pvr2_s_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .vidioc_s_tuner = pvr2_s_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .vidioc_g_tuner = pvr2_g_tuner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .vidioc_g_std = pvr2_g_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .vidioc_s_std = pvr2_s_std,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .vidioc_querystd = pvr2_querystd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) .vidioc_log_status = pvr2_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .vidioc_streamon = pvr2_streamon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) .vidioc_streamoff = pvr2_streamoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) .vidioc_queryctrl = pvr2_queryctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .vidioc_querymenu = pvr2_querymenu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .vidioc_g_ctrl = pvr2_g_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .vidioc_s_ctrl = pvr2_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) enum pvr2_config cfg = dip->config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) char msg[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) unsigned int mcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* Construct the unregistration message *before* we actually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) perform the unregistration step. By doing it this way we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) have to worry about potentially touching deleted resources. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mcnt = scnprintf(msg, sizeof(msg) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) "pvrusb2: unregistered device %s [%s]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) video_device_node_name(&dip->devbase),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) pvr2_config_get_name(cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) msg[mcnt] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* Paranoia */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) dip->v4lp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) dip->stream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /* Actual deallocation happens later when all internal references
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) are gone. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) video_unregister_device(&dip->devbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) pr_info("%s\n", msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^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) static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (!dip) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (!dip->devbase.v4l2_dev->dev) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) dip->devbase.v4l2_dev->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (vp->dev_video) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) pvr2_v4l2_dev_destroy(vp->dev_video);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) vp->dev_video = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (vp->dev_radio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) pvr2_v4l2_dev_destroy(vp->dev_radio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) vp->dev_radio = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) pvr2_channel_done(&vp->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) kfree(vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static void pvr2_video_device_release(struct video_device *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct pvr2_v4l2_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) kfree(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct pvr2_v4l2 *vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) vp = container_of(chp,struct pvr2_v4l2,channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (!vp->channel.mc_head->disconnect_flag) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (!list_empty(&vp->dev_video->devbase.fh_list) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) (vp->dev_radio &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) !list_empty(&vp->dev_radio->devbase.fh_list))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) pvr2_trace(PVR2_TRACE_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) "pvr2_v4l2 internal_check exit-empty id=%p", vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) pvr2_v4l2_destroy_no_lock(vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static int pvr2_v4l2_release(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct pvr2_v4l2_fh *fhp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) struct pvr2_v4l2 *vp = fhp->pdi->v4lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (fhp->rhp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct pvr2_stream *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) pvr2_hdw_set_streaming(hdw,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) sp = pvr2_ioread_get_stream(fhp->rhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) pvr2_ioread_destroy(fhp->rhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) fhp->rhp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) v4l2_fh_del(&fhp->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) v4l2_fh_exit(&fhp->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) file->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) pvr2_channel_done(&fhp->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) pvr2_trace(PVR2_TRACE_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) "Destroying pvr_v4l2_fh id=%p",fhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (fhp->input_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) kfree(fhp->input_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) fhp->input_map = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) kfree(fhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (vp->channel.mc_head->disconnect_flag &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) list_empty(&vp->dev_video->devbase.fh_list) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) (!vp->dev_radio ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) list_empty(&vp->dev_radio->devbase.fh_list))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) pvr2_v4l2_destroy_no_lock(vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static int pvr2_v4l2_open(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) struct pvr2_v4l2_dev *dip; /* Our own context pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct pvr2_v4l2_fh *fhp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct pvr2_v4l2 *vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) struct pvr2_hdw *hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) unsigned int input_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) unsigned int input_cnt,idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) vp = dip->v4lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) hdw = vp->channel.hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (!pvr2_hdw_dev_ok(hdw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) "pvr2_v4l2_open: hardware not ready");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (!fhp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) v4l2_fh_init(&fhp->fh, &dip->devbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) init_waitqueue_head(&fhp->wait_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) fhp->pdi = dip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (dip->v4l_type == VFL_TYPE_RADIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* Opening device as a radio, legal input selection subset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) is just the radio. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) /* Opening the main V4L device, legal input selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) subset includes all analog inputs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) (1 << PVR2_CVAL_INPUT_TV) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) (1 << PVR2_CVAL_INPUT_COMPOSITE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) (1 << PVR2_CVAL_INPUT_SVIDEO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) pvr2_channel_done(&fhp->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) pvr2_trace(PVR2_TRACE_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) "Destroying pvr_v4l2_fh id=%p (input mask error)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) fhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) v4l2_fh_exit(&fhp->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) kfree(fhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) input_mask &= pvr2_hdw_get_input_available(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) input_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (input_mask & (1UL << idx)) input_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) fhp->input_cnt = input_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (!fhp->input_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) pvr2_channel_done(&fhp->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) pvr2_trace(PVR2_TRACE_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) "Destroying pvr_v4l2_fh id=%p (input map failure)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) fhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) v4l2_fh_exit(&fhp->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) kfree(fhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) input_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (!(input_mask & (1UL << idx))) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) fhp->input_map[input_cnt++] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) fhp->file = file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) file->private_data = fhp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) v4l2_fh_add(&fhp->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) wake_up(&fhp->wait_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct pvr2_stream *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct pvr2_hdw *hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (fh->rhp) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (!fh->pdi->stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* No stream defined for this node. This means that we're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) not currently allowed to stream from this node. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* First read() attempt. Try to claim the stream and start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) it... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if ((ret = pvr2_channel_claim_stream(&fh->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) fh->pdi->stream)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* Someone else must already have it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!fh->rhp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) pvr2_channel_claim_stream(&fh->channel,NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) sp = fh->pdi->stream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return pvr2_ioread_set_enabled(fh->rhp,!0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) static ssize_t pvr2_v4l2_read(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) char __user *buff, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (fh->fw_mode_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) char *tbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) int c1,c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) int tcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) unsigned int offs = *ppos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (!tbuf) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) while (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) c1 = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (c2 < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) tcnt = c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!c2) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (copy_to_user(buff,tbuf,c2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) tcnt = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) offs += c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) tcnt += c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) buff += c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) count -= c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) *ppos += c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) kfree(tbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return tcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (!fh->rhp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) ret = pvr2_v4l2_iosetup(fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ret = pvr2_ioread_read(fh->rhp,buff,count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (ret >= 0) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (ret != -EAGAIN) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (file->f_flags & O_NONBLOCK) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /* Doing blocking I/O. Wait here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ret = wait_event_interruptible(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) fh->wait_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) pvr2_ioread_avail(fh->rhp) >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (ret < 0) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static __poll_t pvr2_v4l2_poll(struct file *file, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) __poll_t mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) struct pvr2_v4l2_fh *fh = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (fh->fw_mode_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) mask |= EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (!fh->rhp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) ret = pvr2_v4l2_iosetup(fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (ret) return EPOLLERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) poll_wait(file,&fh->wait_data,wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (pvr2_ioread_avail(fh->rhp) >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) mask |= EPOLLIN | EPOLLRDNORM;
^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) return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static const struct v4l2_file_operations vdev_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) .open = pvr2_v4l2_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .release = pvr2_v4l2_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) .read = pvr2_v4l2_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) .unlocked_ioctl = video_ioctl2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) .poll = pvr2_v4l2_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) static const struct video_device vdev_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .fops = &vdev_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) struct pvr2_v4l2 *vp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) int v4l_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) int mindevnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) int unit_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct pvr2_hdw *hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) int *nr_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) u32 caps = V4L2_CAP_TUNER | V4L2_CAP_READWRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) dip->v4lp = vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) hdw = vp->channel.mc_head->hdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) dip->v4l_type = v4l_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) switch (v4l_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) case VFL_TYPE_VIDEO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dip->stream = &vp->channel.mc_head->video_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) dip->config = pvr2_config_mpeg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) dip->minor_type = pvr2_v4l_type_video;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) nr_ptr = video_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) caps |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (!dip->stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) pr_err(KBUILD_MODNAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) ": Failed to set up pvrusb2 v4l video dev due to missing stream instance\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) case VFL_TYPE_VBI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) dip->config = pvr2_config_vbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) dip->minor_type = pvr2_v4l_type_vbi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) nr_ptr = vbi_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) caps |= V4L2_CAP_VBI_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) case VFL_TYPE_RADIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) dip->stream = &vp->channel.mc_head->video_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) dip->config = pvr2_config_mpeg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) dip->minor_type = pvr2_v4l_type_radio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) nr_ptr = radio_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) caps |= V4L2_CAP_RADIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* Bail out (this should be impossible) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev due to unrecognized config\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) dip->devbase = vdev_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) dip->devbase.release = pvr2_video_device_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) dip->devbase.device_caps = caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) pvr2_ctrl_get_value(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) pvr2_hdw_get_ctrl_by_id(hdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) PVR2_CID_STDAVAIL), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) dip->devbase.tvnorms = (v4l2_std_id)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) mindevnum = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) unit_number = pvr2_hdw_get_unit_number(hdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) mindevnum = nr_ptr[unit_number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if ((video_register_device(&dip->devbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) dip->v4l_type, mindevnum) < 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) (video_register_device(&dip->devbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) dip->v4l_type, -1) < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) pr_err(KBUILD_MODNAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) ": Failed to register pvrusb2 v4l device\n");
^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) pr_info("pvrusb2: registered device %s [%s]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) video_device_node_name(&dip->devbase),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) pvr2_config_get_name(dip->config));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) pvr2_hdw_v4l_store_minor_number(hdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) dip->minor_type,dip->devbase.minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) struct pvr2_v4l2 *vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) vp = kzalloc(sizeof(*vp),GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (!vp) return vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) pvr2_channel_init(&vp->channel,mnp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) vp->channel.check_func = pvr2_v4l2_internal_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) /* register streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (!vp->dev_video) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_VIDEO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) (1 << PVR2_CVAL_INPUT_RADIO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (!vp->dev_radio) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) return vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) pvr2_v4l2_destroy_no_lock(vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }