Commit 62c6b4c9 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

media: vivid: move the devnode creation logic to a separate function



In order to reduce even further the size of the big
vivid_create_instance() function, let's place the part of the
logic which creates the device nodes into a separate function.

    With this and the past patches, those warnings finally
    vanishes:

            drivers/media/test-drivers/vivid/vivid-core.c: drivers/media/test-drivers/vivid/vivid-core.c:1189 vivid_create_instance() parse error: turning off implications after 60 seconds
            drivers/media/test-drivers/vivid/vivid-core.c: drivers/media/test-drivers/vivid/vivid-core.c:1257 vivid_create_instance() parse error: __split_smt: function too hairy.  Giving up after 303 seconds

The init code also seems more organized after breaking the long
function into a smaller set.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent faf21f28
Loading
Loading
Loading
Loading
+274 −256
Original line number Diff line number Diff line
@@ -1306,245 +1306,17 @@ static int vivid_create_queues(struct vivid_dev *dev)
	return 0;
}

static int vivid_create_instance(struct platform_device *pdev, int inst)
static int vivid_create_devnodes(struct platform_device *pdev,
				 struct vivid_dev *dev, int inst,
				 unsigned int cec_tx_bus_cnt,
				 v4l2_std_id tvnorms_cap,
				 v4l2_std_id tvnorms_out,
				 unsigned in_type_counter[4],
				 unsigned out_type_counter[4])
{
	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;

	ret = vivid_detect_feature_set(dev, inst, node_type,
				       &has_tuner, &has_modulator,
				       &ccs_cap, &ccs_out,
				       in_type_counter, out_type_counter);
	if (ret) {
		kfree(dev);
		return ret;
	}

	vivid_set_capabilities(dev);

	ret = -ENOMEM;
	/* initialize the test pattern generator */
	tpg_init(&dev->tpg, 640, 360);
	if (tpg_alloc(&dev->tpg, array_size(MAX_WIDTH, MAX_ZOOM)))
		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(array_size(256, 128));
	if (!dev->edid)
		goto free_dev;

	ret = vivid_init_dv_timings(dev);
	if (ret < 0)
		goto free_dev;

	vivid_disable_unused_ioctls(dev, has_tuner, has_modulator,
				    in_type_counter, out_type_counter);

	/* 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));

	ret = vivid_create_queues(dev);
	if (ret)
		goto unreg_dev;

#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);
	int ret, i;

	/* finally start creating the device nodes */
	if (dev->has_vid_cap) {
		vfd = &dev->vid_cap_dev;
		snprintf(vfd->name, sizeof(vfd->name),
@@ -1568,7 +1340,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		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;
			return ret;
#endif

#ifdef CONFIG_VIDEO_VIVID_CEC
@@ -1577,7 +1349,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
			if (ret < 0) {
				cec_delete_adapter(dev->cec_rx_adap);
				dev->cec_rx_adap = NULL;
				goto unreg_dev;
				return ret;
			}
			cec_s_phys_addr(dev->cec_rx_adap, 0, false);
			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input 0\n",
@@ -1587,7 +1359,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)

		ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
					  video_device_node_name(vfd));
	}
@@ -1616,7 +1388,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		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;
			return ret;
#endif

#ifdef CONFIG_VIDEO_VIVID_CEC
@@ -1627,7 +1399,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
					cec_delete_adapter(dev->cec_tx_adap[i]);
					dev->cec_tx_adap[i] = NULL;
				}
				goto unreg_dev;
				return ret;
			}
			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n",
				  dev_name(&dev->cec_tx_adap[i]->devnode.dev), i);
@@ -1640,7 +1412,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)

		ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_out_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s\n",
					  video_device_node_name(vfd));
	}
@@ -1663,12 +1435,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		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;
			return ret;
#endif

		ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		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) ?
@@ -1695,12 +1467,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		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;
			return ret;
#endif

		ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_out_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		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) ?
@@ -1725,12 +1497,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		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;
			return ret;
#endif

		ret = video_register_device(vfd, VFL_TYPE_SDR, sdr_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
					  video_device_node_name(vfd));
	}
@@ -1749,7 +1521,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)

		ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_rx_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev, "V4L2 receiver device registered as %s\n",
					  video_device_node_name(vfd));
	}
@@ -1769,7 +1541,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)

		ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_tx_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev, "V4L2 transmitter device registered as %s\n",
					  video_device_node_name(vfd));
	}
@@ -1792,12 +1564,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		ret = media_entity_pads_init(&vfd->entity, 1,
					     &dev->meta_cap_pad);
		if (ret)
			goto unreg_dev;
			return ret;
#endif
		ret = video_register_device(vfd, VFL_TYPE_VIDEO,
					    meta_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev,
			  "V4L2 metadata capture device registered as %s\n",
			  video_device_node_name(vfd));
@@ -1822,12 +1594,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		ret = media_entity_pads_init(&vfd->entity, 1,
					     &dev->meta_out_pad);
		if (ret)
			goto unreg_dev;
			return ret;
#endif
		ret = video_register_device(vfd, VFL_TYPE_VIDEO,
					    meta_out_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev,
			  "V4L2 metadata output device registered as %s\n",
			  video_device_node_name(vfd));
@@ -1851,12 +1623,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
		ret = media_entity_pads_init(&vfd->entity, 1,
					     &dev->touch_cap_pad);
		if (ret)
			goto unreg_dev;
			return ret;
#endif
		ret = video_register_device(vfd, VFL_TYPE_TOUCH,
					    touch_cap_nr[inst]);
		if (ret < 0)
			goto unreg_dev;
			return ret;
		v4l2_info(&dev->v4l2_dev,
			  "V4L2 touch capture device registered as %s\n",
			  video_device_node_name(vfd));
@@ -1868,10 +1640,256 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
	if (ret) {
		dev_err(dev->mdev.dev,
			"media device register failed (err=%d)\n", ret);
		return ret;
	}
#endif
	return 0;
}

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;
	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;

	ret = vivid_detect_feature_set(dev, inst, node_type,
				       &has_tuner, &has_modulator,
				       &ccs_cap, &ccs_out,
				       in_type_counter, out_type_counter);
	if (ret) {
		kfree(dev);
		return ret;
	}

	vivid_set_capabilities(dev);

	ret = -ENOMEM;
	/* initialize the test pattern generator */
	tpg_init(&dev->tpg, 640, 360);
	if (tpg_alloc(&dev->tpg, array_size(MAX_WIDTH, MAX_ZOOM)))
		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(array_size(256, 128));
	if (!dev->edid)
		goto free_dev;

	ret = vivid_init_dv_timings(dev);
	if (ret < 0)
		goto free_dev;

	vivid_disable_unused_ioctls(dev, has_tuner, has_modulator,
				    in_type_counter, out_type_counter);

	/* 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));

	ret = vivid_create_queues(dev);
	if (ret)
		goto unreg_dev;

#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 */
	ret = vivid_create_devnodes(pdev, dev, inst, cec_tx_bus_cnt,
				    tvnorms_cap, tvnorms_out,
				    in_type_counter, out_type_counter);
	if (ret)
		goto unreg_dev;

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