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

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
...@@ -1306,245 +1306,17 @@ static int vivid_create_queues(struct vivid_dev *dev) ...@@ -1306,245 +1306,17 @@ static int vivid_create_queues(struct vivid_dev *dev)
return 0; 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; struct video_device *vfd;
unsigned node_type = node_types[inst]; int ret, i;
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 */
if (dev->has_vid_cap) { if (dev->has_vid_cap) {
vfd = &dev->vid_cap_dev; vfd = &dev->vid_cap_dev;
snprintf(vfd->name, sizeof(vfd->name), snprintf(vfd->name, sizeof(vfd->name),
...@@ -1568,7 +1340,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1568,7 +1340,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK; dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_cap_pad); ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_cap_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
#ifdef CONFIG_VIDEO_VIVID_CEC #ifdef CONFIG_VIDEO_VIVID_CEC
...@@ -1577,7 +1349,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1577,7 +1349,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
if (ret < 0) { if (ret < 0) {
cec_delete_adapter(dev->cec_rx_adap); cec_delete_adapter(dev->cec_rx_adap);
dev->cec_rx_adap = NULL; dev->cec_rx_adap = NULL;
goto unreg_dev; return ret;
} }
cec_s_phys_addr(dev->cec_rx_adap, 0, false); cec_s_phys_addr(dev->cec_rx_adap, 0, false);
v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input 0\n", 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) ...@@ -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]); ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_cap_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n", v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
} }
...@@ -1616,7 +1388,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1616,7 +1388,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE; dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_out_pad); ret = media_entity_pads_init(&vfd->entity, 1, &dev->vid_out_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
#ifdef CONFIG_VIDEO_VIVID_CEC #ifdef CONFIG_VIDEO_VIVID_CEC
...@@ -1627,7 +1399,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1627,7 +1399,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
cec_delete_adapter(dev->cec_tx_adap[i]); cec_delete_adapter(dev->cec_tx_adap[i]);
dev->cec_tx_adap[i] = NULL; 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", v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n",
dev_name(&dev->cec_tx_adap[i]->devnode.dev), i); 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) ...@@ -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]); ret = video_register_device(vfd, VFL_TYPE_VIDEO, vid_out_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s\n", v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
} }
...@@ -1663,12 +1435,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1663,12 +1435,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK; dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_cap_pad); ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_cap_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_cap_nr[inst]); ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_cap_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s, supports %s VBI\n", v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s, supports %s VBI\n",
video_device_node_name(vfd), video_device_node_name(vfd),
(dev->has_raw_vbi_cap && dev->has_sliced_vbi_cap) ? (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) ...@@ -1695,12 +1467,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE; dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_out_pad); ret = media_entity_pads_init(&vfd->entity, 1, &dev->vbi_out_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_out_nr[inst]); ret = video_register_device(vfd, VFL_TYPE_VBI, vbi_out_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s, supports %s VBI\n", v4l2_info(&dev->v4l2_dev, "V4L2 output device registered as %s, supports %s VBI\n",
video_device_node_name(vfd), video_device_node_name(vfd),
(dev->has_raw_vbi_out && dev->has_sliced_vbi_out) ? (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) ...@@ -1725,12 +1497,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK; dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_pads_init(&vfd->entity, 1, &dev->sdr_cap_pad); ret = media_entity_pads_init(&vfd->entity, 1, &dev->sdr_cap_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
ret = video_register_device(vfd, VFL_TYPE_SDR, sdr_cap_nr[inst]); ret = video_register_device(vfd, VFL_TYPE_SDR, sdr_cap_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n", v4l2_info(&dev->v4l2_dev, "V4L2 capture device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
} }
...@@ -1749,7 +1521,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -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]); ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_rx_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, "V4L2 receiver device registered as %s\n", v4l2_info(&dev->v4l2_dev, "V4L2 receiver device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
} }
...@@ -1769,7 +1541,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -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]); ret = video_register_device(vfd, VFL_TYPE_RADIO, radio_tx_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, "V4L2 transmitter device registered as %s\n", v4l2_info(&dev->v4l2_dev, "V4L2 transmitter device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
} }
...@@ -1792,12 +1564,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1792,12 +1564,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
ret = media_entity_pads_init(&vfd->entity, 1, ret = media_entity_pads_init(&vfd->entity, 1,
&dev->meta_cap_pad); &dev->meta_cap_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
ret = video_register_device(vfd, VFL_TYPE_VIDEO, ret = video_register_device(vfd, VFL_TYPE_VIDEO,
meta_cap_nr[inst]); meta_cap_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, v4l2_info(&dev->v4l2_dev,
"V4L2 metadata capture device registered as %s\n", "V4L2 metadata capture device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
...@@ -1822,12 +1594,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1822,12 +1594,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
ret = media_entity_pads_init(&vfd->entity, 1, ret = media_entity_pads_init(&vfd->entity, 1,
&dev->meta_out_pad); &dev->meta_out_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
ret = video_register_device(vfd, VFL_TYPE_VIDEO, ret = video_register_device(vfd, VFL_TYPE_VIDEO,
meta_out_nr[inst]); meta_out_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, v4l2_info(&dev->v4l2_dev,
"V4L2 metadata output device registered as %s\n", "V4L2 metadata output device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
...@@ -1851,12 +1623,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1851,12 +1623,12 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
ret = media_entity_pads_init(&vfd->entity, 1, ret = media_entity_pads_init(&vfd->entity, 1,
&dev->touch_cap_pad); &dev->touch_cap_pad);
if (ret) if (ret)
goto unreg_dev; return ret;
#endif #endif
ret = video_register_device(vfd, VFL_TYPE_TOUCH, ret = video_register_device(vfd, VFL_TYPE_TOUCH,
touch_cap_nr[inst]); touch_cap_nr[inst]);
if (ret < 0) if (ret < 0)
goto unreg_dev; return ret;
v4l2_info(&dev->v4l2_dev, v4l2_info(&dev->v4l2_dev,
"V4L2 touch capture device registered as %s\n", "V4L2 touch capture device registered as %s\n",
video_device_node_name(vfd)); video_device_node_name(vfd));
...@@ -1868,10 +1640,256 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) ...@@ -1868,10 +1640,256 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
if (ret) { if (ret) {
dev_err(dev->mdev.dev, dev_err(dev->mdev.dev,
"media device register failed (err=%d)\n", ret); "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; 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 #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 */ /* Now that everything is fine, let's add it to device list */
vivid_devs[inst] = dev; vivid_devs[inst] = dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment