static int vivid_create_instance()

in drivers/media/platform/vivid/vivid-core.c [826:1841]


static int vivid_create_instance(struct platform_device *pdev, int inst)
{
	static const struct v4l2_dv_timings def_dv_timings =
					V4L2_DV_BT_CEA_1280X720P60;
	unsigned in_type_counter[4] = { 0, 0, 0, 0 };
	unsigned out_type_counter[4] = { 0, 0, 0, 0 };
	int ccs_cap = ccs_cap_mode[inst];
	int ccs_out = ccs_out_mode[inst];
	bool has_tuner;
	bool has_modulator;
	struct vivid_dev *dev;
	struct video_device *vfd;
	unsigned node_type = node_types[inst];
	v4l2_std_id tvnorms_cap = 0, tvnorms_out = 0;
	int ret;
	int i;
#ifdef CONFIG_VIDEO_VIVID_CEC
	unsigned int cec_tx_bus_cnt = 0;
#endif

	/* allocate main vivid state structure */
	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;

	dev->inst = inst;

#ifdef CONFIG_MEDIA_CONTROLLER
	dev->v4l2_dev.mdev = &dev->mdev;

	/* Initialize media device */
	strscpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
	snprintf(dev->mdev.bus_info, sizeof(dev->mdev.bus_info),
		 "platform:%s-%03d", VIVID_MODULE_NAME, inst);
	dev->mdev.dev = &pdev->dev;
	media_device_init(&dev->mdev);
	dev->mdev.ops = &vivid_media_ops;
#endif

	/* register v4l2_device */
	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
			"%s-%03d", VIVID_MODULE_NAME, inst);
	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
	if (ret) {
		kfree(dev);
		return ret;
	}
	dev->v4l2_dev.release = vivid_dev_release;

	/* start detecting feature set */

	/* do we use single- or multi-planar? */
	dev->multiplanar = multiplanar[inst] > 1;
	v4l2_info(&dev->v4l2_dev, "using %splanar format API\n",
			dev->multiplanar ? "multi" : "single ");

	/* how many inputs do we have and of what type? */
	dev->num_inputs = num_inputs[inst];
	if (dev->num_inputs < 1)
		dev->num_inputs = 1;
	if (dev->num_inputs >= MAX_INPUTS)
		dev->num_inputs = MAX_INPUTS;
	for (i = 0; i < dev->num_inputs; i++) {
		dev->input_type[i] = (input_types[inst] >> (i * 2)) & 0x3;
		dev->input_name_counter[i] = in_type_counter[dev->input_type[i]]++;
	}
	dev->has_audio_inputs = in_type_counter[TV] && in_type_counter[SVID];
	if (in_type_counter[HDMI] == 16) {
		/* The CEC physical address only allows for max 15 inputs */
		in_type_counter[HDMI]--;
		dev->num_inputs--;
	}
	dev->num_hdmi_inputs = in_type_counter[HDMI];

	/* how many outputs do we have and of what type? */
	dev->num_outputs = num_outputs[inst];
	if (dev->num_outputs < 1)
		dev->num_outputs = 1;
	if (dev->num_outputs >= MAX_OUTPUTS)
		dev->num_outputs = MAX_OUTPUTS;
	for (i = 0; i < dev->num_outputs; i++) {
		dev->output_type[i] = ((output_types[inst] >> i) & 1) ? HDMI : SVID;
		dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++;
		dev->display_present[i] = true;
	}
	dev->has_audio_outputs = out_type_counter[SVID];
	if (out_type_counter[HDMI] == 16) {
		/*
		 * The CEC physical address only allows for max 15 inputs,
		 * so outputs are also limited to 15 to allow for easy
		 * CEC output to input mapping.
		 */
		out_type_counter[HDMI]--;
		dev->num_outputs--;
	}
	dev->num_hdmi_outputs = out_type_counter[HDMI];

	/* do we create a video capture device? */
	dev->has_vid_cap = node_type & 0x0001;

	/* do we create a vbi capture device? */
	if (in_type_counter[TV] || in_type_counter[SVID]) {
		dev->has_raw_vbi_cap = node_type & 0x0004;
		dev->has_sliced_vbi_cap = node_type & 0x0008;
		dev->has_vbi_cap = dev->has_raw_vbi_cap | dev->has_sliced_vbi_cap;
	}

	/* do we create a meta capture device */
	dev->has_meta_cap = node_type & 0x20000;

	/* sanity checks */
	if ((in_type_counter[WEBCAM] || in_type_counter[HDMI]) &&
	    !dev->has_vid_cap && !dev->has_meta_cap) {
		v4l2_warn(&dev->v4l2_dev,
			  "Webcam or HDMI input without video or metadata nodes\n");
		kfree(dev);
		return -EINVAL;
	}
	if ((in_type_counter[TV] || in_type_counter[SVID]) &&
	    !dev->has_vid_cap && !dev->has_vbi_cap && !dev->has_meta_cap) {
		v4l2_warn(&dev->v4l2_dev,
			  "TV or S-Video input without video, VBI or metadata nodes\n");
		kfree(dev);
		return -EINVAL;
	}

	/* do we create a video output device? */
	dev->has_vid_out = node_type & 0x0100;

	/* do we create a vbi output device? */
	if (out_type_counter[SVID]) {
		dev->has_raw_vbi_out = node_type & 0x0400;
		dev->has_sliced_vbi_out = node_type & 0x0800;
		dev->has_vbi_out = dev->has_raw_vbi_out | dev->has_sliced_vbi_out;
	}

	/* do we create a metadata output device */
	dev->has_meta_out = node_type & 0x40000;

	/* sanity checks */
	if (out_type_counter[SVID] &&
	    !dev->has_vid_out && !dev->has_vbi_out && !dev->has_meta_out) {
		v4l2_warn(&dev->v4l2_dev,
			  "S-Video output without video, VBI or metadata nodes\n");
		kfree(dev);
		return -EINVAL;
	}
	if (out_type_counter[HDMI] && !dev->has_vid_out && !dev->has_meta_out) {
		v4l2_warn(&dev->v4l2_dev,
			  "HDMI output without video or metadata nodes\n");
		kfree(dev);
		return -EINVAL;
	}

	/* do we create a radio receiver device? */
	dev->has_radio_rx = node_type & 0x0010;

	/* do we create a radio transmitter device? */
	dev->has_radio_tx = node_type & 0x1000;

	/* do we create a software defined radio capture device? */
	dev->has_sdr_cap = node_type & 0x0020;

	/* do we have a TV tuner? */
	dev->has_tv_tuner = in_type_counter[TV];

	/* do we have a tuner? */
	has_tuner = ((dev->has_vid_cap || dev->has_vbi_cap) && in_type_counter[TV]) ||
		    dev->has_radio_rx || dev->has_sdr_cap;

	/* do we have a modulator? */
	has_modulator = dev->has_radio_tx;

	if (dev->has_vid_cap)
		/* do we have a framebuffer for overlay testing? */
		dev->has_fb = node_type & 0x10000;

	/* can we do crop/compose/scaling while capturing? */
	if (no_error_inj && ccs_cap == -1)
		ccs_cap = 7;

	/* if ccs_cap == -1, then the user can select it using controls */
	if (ccs_cap != -1) {
		dev->has_crop_cap = ccs_cap & 1;
		dev->has_compose_cap = ccs_cap & 2;
		dev->has_scaler_cap = ccs_cap & 4;
		v4l2_info(&dev->v4l2_dev, "Capture Crop: %c Compose: %c Scaler: %c\n",
			dev->has_crop_cap ? 'Y' : 'N',
			dev->has_compose_cap ? 'Y' : 'N',
			dev->has_scaler_cap ? 'Y' : 'N');
	}

	/* can we do crop/compose/scaling with video output? */
	if (no_error_inj && ccs_out == -1)
		ccs_out = 7;

	/* if ccs_out == -1, then the user can select it using controls */
	if (ccs_out != -1) {
		dev->has_crop_out = ccs_out & 1;
		dev->has_compose_out = ccs_out & 2;
		dev->has_scaler_out = ccs_out & 4;
		v4l2_info(&dev->v4l2_dev, "Output Crop: %c Compose: %c Scaler: %c\n",
			dev->has_crop_out ? 'Y' : 'N',
			dev->has_compose_out ? 'Y' : 'N',
			dev->has_scaler_out ? 'Y' : 'N');
	}

	/* do we create a touch capture device */
	dev->has_touch_cap = node_type & 0x80000;

	/* end detecting feature set */

	if (dev->has_vid_cap) {
		/* set up the capabilities of the video capture device */
		dev->vid_cap_caps = dev->multiplanar ?
			V4L2_CAP_VIDEO_CAPTURE_MPLANE :
			V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY;
		dev->vid_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
		if (dev->has_audio_inputs)
			dev->vid_cap_caps |= V4L2_CAP_AUDIO;
		if (dev->has_tv_tuner)
			dev->vid_cap_caps |= V4L2_CAP_TUNER;
	}
	if (dev->has_vid_out) {
		/* set up the capabilities of the video output device */
		dev->vid_out_caps = dev->multiplanar ?
			V4L2_CAP_VIDEO_OUTPUT_MPLANE :
			V4L2_CAP_VIDEO_OUTPUT;
		if (dev->has_fb)
			dev->vid_out_caps |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
		dev->vid_out_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
		if (dev->has_audio_outputs)
			dev->vid_out_caps |= V4L2_CAP_AUDIO;
	}
	if (dev->has_vbi_cap) {
		/* set up the capabilities of the vbi capture device */
		dev->vbi_cap_caps = (dev->has_raw_vbi_cap ? V4L2_CAP_VBI_CAPTURE : 0) |
				    (dev->has_sliced_vbi_cap ? V4L2_CAP_SLICED_VBI_CAPTURE : 0);
		dev->vbi_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
		if (dev->has_audio_inputs)
			dev->vbi_cap_caps |= V4L2_CAP_AUDIO;
		if (dev->has_tv_tuner)
			dev->vbi_cap_caps |= V4L2_CAP_TUNER;
	}
	if (dev->has_vbi_out) {
		/* set up the capabilities of the vbi output device */
		dev->vbi_out_caps = (dev->has_raw_vbi_out ? V4L2_CAP_VBI_OUTPUT : 0) |
				    (dev->has_sliced_vbi_out ? V4L2_CAP_SLICED_VBI_OUTPUT : 0);
		dev->vbi_out_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
		if (dev->has_audio_outputs)
			dev->vbi_out_caps |= V4L2_CAP_AUDIO;
	}
	if (dev->has_sdr_cap) {
		/* set up the capabilities of the sdr capture device */
		dev->sdr_cap_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER;
		dev->sdr_cap_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
	}
	/* set up the capabilities of the radio receiver device */
	if (dev->has_radio_rx)
		dev->radio_rx_caps = V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE |
				     V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
				     V4L2_CAP_READWRITE;
	/* set up the capabilities of the radio transmitter device */
	if (dev->has_radio_tx)
		dev->radio_tx_caps = V4L2_CAP_RDS_OUTPUT | V4L2_CAP_MODULATOR |
				     V4L2_CAP_READWRITE;

	/* set up the capabilities of meta capture device */
	if (dev->has_meta_cap) {
		dev->meta_cap_caps = V4L2_CAP_META_CAPTURE |
				     V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
		if (dev->has_audio_inputs)
			dev->meta_cap_caps |= V4L2_CAP_AUDIO;
		if (dev->has_tv_tuner)
			dev->meta_cap_caps |= V4L2_CAP_TUNER;
	}
	/* set up the capabilities of meta output device */
	if (dev->has_meta_out) {
		dev->meta_out_caps = V4L2_CAP_META_OUTPUT |
				     V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
		if (dev->has_audio_outputs)
			dev->meta_out_caps |= V4L2_CAP_AUDIO;
	}
	/* set up the capabilities of the touch capture device */
	if (dev->has_touch_cap) {
		dev->touch_cap_caps = V4L2_CAP_TOUCH | V4L2_CAP_STREAMING |
				      V4L2_CAP_READWRITE;
		dev->touch_cap_caps |= dev->multiplanar ?
			V4L2_CAP_VIDEO_CAPTURE_MPLANE : V4L2_CAP_VIDEO_CAPTURE;
	}

	ret = -ENOMEM;
	/* initialize the test pattern generator */
	tpg_init(&dev->tpg, 640, 360);
	if (tpg_alloc(&dev->tpg, MAX_ZOOM * MAX_WIDTH))
		goto free_dev;
	dev->scaled_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
	if (!dev->scaled_line)
		goto free_dev;
	dev->blended_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
	if (!dev->blended_line)
		goto free_dev;

	/* load the edid */
	dev->edid = vmalloc(256 * 128);
	if (!dev->edid)
		goto free_dev;

	while (v4l2_dv_timings_presets[dev->query_dv_timings_size].bt.width)
		dev->query_dv_timings_size++;

	/*
	 * Create a char pointer array that points to the names of all the
	 * preset timings
	 */
	dev->query_dv_timings_qmenu = kmalloc_array(dev->query_dv_timings_size,
						    sizeof(char *), GFP_KERNEL);
	/*
	 * Create a string array containing the names of all the preset
	 * timings. Each name is max 31 chars long (+ terminating 0).
	 */
	dev->query_dv_timings_qmenu_strings =
		kmalloc_array(dev->query_dv_timings_size, 32, GFP_KERNEL);

	if (!dev->query_dv_timings_qmenu ||
	    !dev->query_dv_timings_qmenu_strings)
		goto free_dev;

	for (i = 0; i < dev->query_dv_timings_size; i++) {
		const struct v4l2_bt_timings *bt = &v4l2_dv_timings_presets[i].bt;
		char *p = dev->query_dv_timings_qmenu_strings + i * 32;
		u32 htot, vtot;

		dev->query_dv_timings_qmenu[i] = p;

		htot = V4L2_DV_BT_FRAME_WIDTH(bt);
		vtot = V4L2_DV_BT_FRAME_HEIGHT(bt);
		snprintf(p, 32, "%ux%u%s%u",
			bt->width, bt->height, bt->interlaced ? "i" : "p",
			(u32)bt->pixelclock / (htot * vtot));
	}

	/* disable invalid ioctls based on the feature set */
	if (!dev->has_audio_inputs) {
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_AUDIO);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_AUDIO);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUMAUDIO);
		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_AUDIO);
		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_AUDIO);
		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_ENUMAUDIO);
		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_AUDIO);
		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_AUDIO);
		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_ENUMAUDIO);
	}
	if (!dev->has_audio_outputs) {
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_AUDOUT);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_AUDOUT);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUMAUDOUT);
		v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_AUDOUT);
		v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_AUDOUT);
		v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_ENUMAUDOUT);
		v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_AUDOUT);
		v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_AUDOUT);
		v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_ENUMAUDOUT);
	}
	if (!in_type_counter[TV] && !in_type_counter[SVID]) {
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_STD);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_STD);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUMSTD);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_QUERYSTD);
	}
	if (!out_type_counter[SVID]) {
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_STD);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_STD);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUMSTD);
	}
	if (!has_tuner && !has_modulator) {
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_FREQUENCY);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_FREQUENCY);
		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_FREQUENCY);
		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_FREQUENCY);
		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_FREQUENCY);
		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_FREQUENCY);
	}
	if (!has_tuner) {
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_TUNER);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_TUNER);
		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_TUNER);
		v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_G_TUNER);
		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_TUNER);
		v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_G_TUNER);
	}
	if (in_type_counter[HDMI] == 0) {
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_EDID);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_EDID);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_DV_TIMINGS_CAP);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_G_DV_TIMINGS);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_DV_TIMINGS);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_ENUM_DV_TIMINGS);
		v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_QUERY_DV_TIMINGS);
	}
	if (out_type_counter[HDMI] == 0) {
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_EDID);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_DV_TIMINGS_CAP);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_DV_TIMINGS);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_DV_TIMINGS);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_DV_TIMINGS);
	}
	if (!dev->has_fb) {
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_FBUF);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_FBUF);
		v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_OVERLAY);
	}
	v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
	v4l2_disable_ioctl(&dev->vbi_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
	v4l2_disable_ioctl(&dev->sdr_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
	v4l2_disable_ioctl(&dev->meta_cap_dev, VIDIOC_S_HW_FREQ_SEEK);
	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_S_FREQUENCY);
	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_G_FREQUENCY);
	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_FRAMESIZES);
	v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_FRAMEINTERVALS);
	v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_FREQUENCY);
	v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_FREQUENCY);
	v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_FREQUENCY);
	v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_FREQUENCY);
	v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_S_PARM);
	v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_ENUM_FRAMESIZES);
	v4l2_disable_ioctl(&dev->touch_cap_dev, VIDIOC_ENUM_FRAMEINTERVALS);

	/* configure internal data */
	dev->fmt_cap = &vivid_formats[0];
	dev->fmt_out = &vivid_formats[0];
	if (!dev->multiplanar)
		vivid_formats[0].data_offset[0] = 0;
	dev->webcam_size_idx = 1;
	dev->webcam_ival_idx = 3;
	tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
	dev->std_out = V4L2_STD_PAL;
	if (dev->input_type[0] == TV || dev->input_type[0] == SVID)
		tvnorms_cap = V4L2_STD_ALL;
	if (dev->output_type[0] == SVID)
		tvnorms_out = V4L2_STD_ALL;
	for (i = 0; i < MAX_INPUTS; i++) {
		dev->dv_timings_cap[i] = def_dv_timings;
		dev->std_cap[i] = V4L2_STD_PAL;
	}
	dev->dv_timings_out = def_dv_timings;
	dev->tv_freq = 2804 /* 175.25 * 16 */;
	dev->tv_audmode = V4L2_TUNER_MODE_STEREO;
	dev->tv_field_cap = V4L2_FIELD_INTERLACED;
	dev->tv_field_out = V4L2_FIELD_INTERLACED;
	dev->radio_rx_freq = 95000 * 16;
	dev->radio_rx_audmode = V4L2_TUNER_MODE_STEREO;
	if (dev->has_radio_tx) {
		dev->radio_tx_freq = 95500 * 16;
		dev->radio_rds_loop = false;
	}
	dev->radio_tx_subchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS;
	dev->sdr_adc_freq = 300000;
	dev->sdr_fm_freq = 50000000;
	dev->sdr_pixelformat = V4L2_SDR_FMT_CU8;
	dev->sdr_buffersize = SDR_CAP_SAMPLES_PER_BUF * 2;

	dev->edid_max_blocks = dev->edid_blocks = 2;
	memcpy(dev->edid, vivid_hdmi_edid, sizeof(vivid_hdmi_edid));
	dev->radio_rds_init_time = ktime_get();

	/* create all controls */
	ret = vivid_create_controls(dev, ccs_cap == -1, ccs_out == -1, no_error_inj,
			in_type_counter[TV] || in_type_counter[SVID] ||
			out_type_counter[SVID],
			in_type_counter[HDMI] || out_type_counter[HDMI]);
	if (ret)
		goto unreg_dev;

	/* enable/disable interface specific controls */
	if (dev->num_outputs && dev->output_type[0] != HDMI)
		v4l2_ctrl_activate(dev->ctrl_display_present, false);
	if (dev->num_inputs && dev->input_type[0] != HDMI) {
		v4l2_ctrl_activate(dev->ctrl_dv_timings_signal_mode, false);
		v4l2_ctrl_activate(dev->ctrl_dv_timings, false);
	} else if (dev->num_inputs && dev->input_type[0] == HDMI) {
		v4l2_ctrl_activate(dev->ctrl_std_signal_mode, false);
		v4l2_ctrl_activate(dev->ctrl_standard, false);
	}

	/*
	 * update the capture and output formats to do a proper initial
	 * configuration.
	 */
	vivid_update_format_cap(dev, false);
	vivid_update_format_out(dev);

	/* initialize overlay */
	dev->fb_cap.fmt.width = dev->src_rect.width;
	dev->fb_cap.fmt.height = dev->src_rect.height;
	dev->fb_cap.fmt.pixelformat = dev->fmt_cap->fourcc;
	dev->fb_cap.fmt.bytesperline = dev->src_rect.width * tpg_g_twopixelsize(&dev->tpg, 0) / 2;
	dev->fb_cap.fmt.sizeimage = dev->src_rect.height * dev->fb_cap.fmt.bytesperline;

	/* update touch configuration */
	dev->timeperframe_tch_cap.numerator = 1;
	dev->timeperframe_tch_cap.denominator = 10;
	vivid_set_touch(dev, 0);

	/* initialize locks */
	spin_lock_init(&dev->slock);
	mutex_init(&dev->mutex);

	/* init dma queues */
	INIT_LIST_HEAD(&dev->vid_cap_active);
	INIT_LIST_HEAD(&dev->vid_out_active);
	INIT_LIST_HEAD(&dev->vbi_cap_active);
	INIT_LIST_HEAD(&dev->vbi_out_active);
	INIT_LIST_HEAD(&dev->sdr_cap_active);
	INIT_LIST_HEAD(&dev->meta_cap_active);
	INIT_LIST_HEAD(&dev->meta_out_active);
	INIT_LIST_HEAD(&dev->touch_cap_active);

	INIT_LIST_HEAD(&dev->cec_work_list);
	spin_lock_init(&dev->cec_slock);
	/*
	 * Same as create_singlethread_workqueue, but now I can use the
	 * string formatting of alloc_ordered_workqueue.
	 */
	dev->cec_workqueue =
		alloc_ordered_workqueue("vivid-%03d-cec", WQ_MEM_RECLAIM, inst);
	if (!dev->cec_workqueue) {
		ret = -ENOMEM;
		goto unreg_dev;
	}

	if (allocators[inst] == 1)
		dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));

	/* start creating the vb2 queues */
	if (dev->has_vid_cap) {
		/* initialize vid_cap queue */
		ret = vivid_create_queue(dev, &dev->vb_vid_cap_q,
					 V4L2_BUF_TYPE_VIDEO_CAPTURE, 2,
					 &vivid_vid_cap_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_vid_out) {
		/* initialize vid_out queue */
		ret = vivid_create_queue(dev, &dev->vb_vid_out_q,
					 V4L2_BUF_TYPE_VIDEO_OUTPUT, 2,
					 &vivid_vid_out_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_vbi_cap) {
		/* initialize vbi_cap queue */
		ret = vivid_create_queue(dev, &dev->vb_vbi_cap_q,
					 V4L2_BUF_TYPE_VBI_CAPTURE, 2,
					 &vivid_vbi_cap_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_vbi_out) {
		/* initialize vbi_out queue */
		ret = vivid_create_queue(dev, &dev->vb_vbi_out_q,
					 V4L2_BUF_TYPE_VBI_OUTPUT, 2,
					 &vivid_vbi_out_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_sdr_cap) {
		/* initialize sdr_cap queue */
		ret = vivid_create_queue(dev, &dev->vb_sdr_cap_q,
					 V4L2_BUF_TYPE_SDR_CAPTURE, 8,
					 &vivid_sdr_cap_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_meta_cap) {
		/* initialize meta_cap queue */
		ret = vivid_create_queue(dev, &dev->vb_meta_cap_q,
					 V4L2_BUF_TYPE_META_CAPTURE, 2,
					 &vivid_meta_cap_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_meta_out) {
		/* initialize meta_out queue */
		ret = vivid_create_queue(dev, &dev->vb_meta_out_q,
					 V4L2_BUF_TYPE_META_OUTPUT, 1,
					 &vivid_meta_out_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_touch_cap) {
		/* initialize touch_cap queue */
		ret = vivid_create_queue(dev, &dev->vb_touch_cap_q,
					 V4L2_BUF_TYPE_VIDEO_CAPTURE, 1,
					 &vivid_touch_cap_qops);
		if (ret)
			goto unreg_dev;
	}

	if (dev->has_fb) {
		/* Create framebuffer for testing capture/output overlay */
		ret = vivid_fb_init(dev);
		if (ret)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "Framebuffer device registered as fb%d\n",
			  dev->fb_info.node);
	}

#ifdef CONFIG_VIDEO_VIVID_CEC
	if (dev->has_vid_cap && in_type_counter[HDMI]) {
		struct cec_adapter *adap;

		adap = vivid_cec_alloc_adap(dev, 0, false);
		ret = PTR_ERR_OR_ZERO(adap);
		if (ret < 0)
			goto unreg_dev;
		dev->cec_rx_adap = adap;
	}

	if (dev->has_vid_out) {
		for (i = 0; i < dev->num_outputs; i++) {
			struct cec_adapter *adap;

			if (dev->output_type[i] != HDMI)
				continue;

			dev->cec_output2bus_map[i] = cec_tx_bus_cnt;
			adap = vivid_cec_alloc_adap(dev, cec_tx_bus_cnt, true);
			ret = PTR_ERR_OR_ZERO(adap);
			if (ret < 0) {
				for (i = 0; i < dev->num_outputs; i++)
					cec_delete_adapter(dev->cec_tx_adap[i]);
				goto unreg_dev;
			}

			dev->cec_tx_adap[cec_tx_bus_cnt] = adap;
			cec_tx_bus_cnt++;
		}
	}
#endif

	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_cap);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_out);
	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_touch_cap);

	/* finally start creating the device nodes */
	if (dev->has_vid_cap) {
		vfd = &dev->vid_cap_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-vid-cap", inst);
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->vid_cap_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_vid_cap_q;
		vfd->tvnorms = tvnorms_cap;

		/*
		 * Provide a mutex to v4l2 core. It will be used to protect
		 * all fops and v4l2 ioctls.
		 */
		vfd->lock = &dev->mutex;
		video_set_drvdata(vfd, dev);

#ifdef CONFIG_MEDIA_CONTROLLER
		dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_cap_pad);
		if (ret)
			goto unreg_dev;
#endif

#ifdef CONFIG_VIDEO_VIVID_CEC
		if (in_type_counter[HDMI]) {
			ret = cec_register_adapter(dev->cec_rx_adap, &pdev->dev);
			if (ret < 0) {
				cec_delete_adapter(dev->cec_rx_adap);
				dev->cec_rx_adap = NULL;
				goto unreg_dev;
			}
			cec_s_phys_addr(dev->cec_rx_adap, 0, false);
			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input 0\n",
				  dev_name(&dev->cec_rx_adap->devnode.dev));
		}
#endif

		ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
					  video_device_node_name(vfd));
	}

	if (dev->has_vid_out) {
		vfd = &dev->vid_out_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-vid-out", inst);
		vfd->vfl_dir = VFL_DIR_TX;
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->vid_out_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_vid_out_q;
		vfd->tvnorms = tvnorms_out;

		/*
		 * Provide a mutex to v4l2 core. It will be used to protect
		 * all fops and v4l2 ioctls.
		 */
		vfd->lock = &dev->mutex;
		video_set_drvdata(vfd, dev);

#ifdef CONFIG_MEDIA_CONTROLLER
		dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_out_pad);
		if (ret)
			goto unreg_dev;
#endif

#ifdef CONFIG_VIDEO_VIVID_CEC
		for (i = 0; i < cec_tx_bus_cnt; i++) {
			ret = cec_register_adapter(dev->cec_tx_adap[i], &pdev->dev);
			if (ret < 0) {
				for (; i < cec_tx_bus_cnt; i++) {
					cec_delete_adapter(dev->cec_tx_adap[i]);
					dev->cec_tx_adap[i] = NULL;
				}
				goto unreg_dev;
			}
			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n",
				  dev_name(&dev->cec_tx_adap[i]->devnode.dev), i);
			if (i <= out_type_counter[HDMI])
				cec_s_phys_addr(dev->cec_tx_adap[i], i << 12, false);
			else
				cec_s_phys_addr(dev->cec_tx_adap[i], 0x1000, false);
		}
#endif

		ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_out_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s\n",
					  video_device_node_name(vfd));
	}

	if (dev->has_vbi_cap) {
		vfd = &dev->vbi_cap_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-vbi-cap", inst);
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->vbi_cap_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_vbi_cap_q;
		vfd->lock = &dev->mutex;
		vfd->tvnorms = tvnorms_cap;
		video_set_drvdata(vfd, dev);

#ifdef CONFIG_MEDIA_CONTROLLER
		dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK;
		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_cap_pad);
		if (ret)
			goto unreg_dev;
#endif

		ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s, supports %s VBI\n",
					  video_device_node_name(vfd),
					  (dev->has_raw_vbi_cap && dev->has_sliced_vbi_cap) ?
					  "raw and sliced" :
					  (dev->has_raw_vbi_cap ? "raw" : "sliced"));
	}

	if (dev->has_vbi_out) {
		vfd = &dev->vbi_out_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-vbi-out", inst);
		vfd->vfl_dir = VFL_DIR_TX;
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->vbi_out_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_vbi_out_q;
		vfd->lock = &dev->mutex;
		vfd->tvnorms = tvnorms_out;
		video_set_drvdata(vfd, dev);

#ifdef CONFIG_MEDIA_CONTROLLER
		dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE;
		ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_out_pad);
		if (ret)
			goto unreg_dev;
#endif

		ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_out_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s, supports %s VBI\n",
					  video_device_node_name(vfd),
					  (dev->has_raw_vbi_out && dev->has_sliced_vbi_out) ?
					  "raw and sliced" :
					  (dev->has_raw_vbi_out ? "raw" : "sliced"));
	}

	if (dev->has_sdr_cap) {
		vfd = &dev->sdr_cap_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-sdr-cap", inst);
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->sdr_cap_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_sdr_cap_q;
		vfd->lock = &dev->mutex;
		video_set_drvdata(vfd, dev);

#ifdef CONFIG_MEDIA_CONTROLLER
		dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
		ret = media_entity_pads_init(&vfd->entity, 1, &dev->sdr_cap_pad);
		if (ret)
			goto unreg_dev;
#endif

		ret = video_register_device(vfd, VFL_TYPE_SDR, sdr_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
					  video_device_node_name(vfd));
	}

	if (dev->has_radio_rx) {
		vfd = &dev->radio_rx_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-rad-rx", inst);
		vfd->fops = &vivid_radio_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->radio_rx_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->lock = &dev->mutex;
		video_set_drvdata(vfd, dev);

		ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_rx_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "V4L2 receiver device registered as %s\n",
					  video_device_node_name(vfd));
	}

	if (dev->has_radio_tx) {
		vfd = &dev->radio_tx_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-rad-tx", inst);
		vfd->vfl_dir = VFL_DIR_TX;
		vfd->fops = &vivid_radio_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->radio_tx_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->lock = &dev->mutex;
		video_set_drvdata(vfd, dev);

		ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_tx_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev, "V4L2 transmitter device registered as %s\n",
					  video_device_node_name(vfd));
	}

	if (dev->has_meta_cap) {
		vfd = &dev->meta_cap_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-meta-cap", inst);
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->meta_cap_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_meta_cap_q;
		vfd->lock = &dev->mutex;
		vfd->tvnorms = tvnorms_cap;
		video_set_drvdata(vfd, dev);
#ifdef CONFIG_MEDIA_CONTROLLER
		dev->meta_cap_pad.flags = MEDIA_PAD_FL_SINK;
		ret = media_entity_pads_init(&vfd->entity, 1,
					     &dev->meta_cap_pad);
		if (ret)
			goto unreg_dev;
#endif
		ret = video_register_device(vfd, VFL_TYPE_GRABBER,
					    meta_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev,
			  "V4L2 metadata capture device registered as %s\n",
			  video_device_node_name(vfd));
	}

	if (dev->has_meta_out) {
		vfd = &dev->meta_out_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-meta-out", inst);
		vfd->vfl_dir = VFL_DIR_TX;
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->meta_out_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_meta_out_q;
		vfd->lock = &dev->mutex;
		vfd->tvnorms = tvnorms_out;
		video_set_drvdata(vfd, dev);
#ifdef CONFIG_MEDIA_CONTROLLER
		dev->meta_out_pad.flags = MEDIA_PAD_FL_SOURCE;
		ret = media_entity_pads_init(&vfd->entity, 1,
					     &dev->meta_out_pad);
		if (ret)
			goto unreg_dev;
#endif
		ret = video_register_device(vfd, VFL_TYPE_GRABBER,
					    meta_out_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev,
			  "V4L2 metadata output device registered as %s\n",
			  video_device_node_name(vfd));
	}

	if (dev->has_touch_cap) {
		vfd = &dev->touch_cap_dev;
		snprintf(vfd->name, sizeof(vfd->name),
			 "vivid-%03d-touch-cap", inst);
		vfd->fops = &vivid_fops;
		vfd->ioctl_ops = &vivid_ioctl_ops;
		vfd->device_caps = dev->touch_cap_caps;
		vfd->release = video_device_release_empty;
		vfd->v4l2_dev = &dev->v4l2_dev;
		vfd->queue = &dev->vb_touch_cap_q;
		vfd->tvnorms = tvnorms_cap;
		vfd->lock = &dev->mutex;
		video_set_drvdata(vfd, dev);
#ifdef CONFIG_MEDIA_CONTROLLER
		dev->touch_cap_pad.flags = MEDIA_PAD_FL_SINK;
		ret = media_entity_pads_init(&vfd->entity, 1,
					     &dev->touch_cap_pad);
		if (ret)
			goto unreg_dev;
#endif
		ret = video_register_device(vfd, VFL_TYPE_TOUCH,
					    touch_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
		v4l2_info(&dev->v4l2_dev,
			  "V4L2 touch capture device registered as %s\n",
			  video_device_node_name(vfd));
	}

#ifdef CONFIG_MEDIA_CONTROLLER
	/* Register the media device */
	ret = media_device_register(&dev->mdev);
	if (ret) {
		dev_err(dev->mdev.dev,
			"media device register failed (err=%d)\n", ret);
		goto unreg_dev;
	}
#endif

	/* Now that everything is fine, let's add it to device list */
	vivid_devs[inst] = dev;

	return 0;

unreg_dev:
	video_unregister_device(&dev->touch_cap_dev);
	video_unregister_device(&dev->meta_out_dev);
	video_unregister_device(&dev->meta_cap_dev);
	video_unregister_device(&dev->radio_tx_dev);
	video_unregister_device(&dev->radio_rx_dev);
	video_unregister_device(&dev->sdr_cap_dev);
	video_unregister_device(&dev->vbi_out_dev);
	video_unregister_device(&dev->vbi_cap_dev);
	video_unregister_device(&dev->vid_out_dev);
	video_unregister_device(&dev->vid_cap_dev);
	cec_unregister_adapter(dev->cec_rx_adap);
	for (i = 0; i < MAX_OUTPUTS; i++)
		cec_unregister_adapter(dev->cec_tx_adap[i]);
	if (dev->cec_workqueue) {
		vivid_cec_bus_free_work(dev);
		destroy_workqueue(dev->cec_workqueue);
	}
free_dev:
	v4l2_device_put(&dev->v4l2_dev);
	return ret;
}