diff options
Diffstat (limited to 'drivers/media/platform/vivid/vivid-core.c')
-rw-r--r-- | drivers/media/platform/vivid/vivid-core.c | 118 |
1 files changed, 109 insertions, 9 deletions
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index c14da84af..7f937136c 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -46,6 +46,7 @@ #include "vivid-vbi-cap.h" #include "vivid-vbi-out.h" #include "vivid-osd.h" +#include "vivid-cec.h" #include "vivid-ctrls.h" #define VIVID_MODULE_NAME "vivid" @@ -684,6 +685,11 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) 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--; + } /* how many outputs do we have and of what type? */ dev->num_outputs = num_outputs[inst]; @@ -696,6 +702,15 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++; } 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--; + } /* do we create a video capture device? */ dev->has_vid_cap = node_type & 0x0001; @@ -1010,6 +1025,17 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) INIT_LIST_HEAD(&dev->vbi_out_active); INIT_LIST_HEAD(&dev->sdr_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) + goto unreg_dev; + /* start creating the vb2 queues */ if (dev->has_vid_cap) { /* initialize vid_cap queue */ @@ -1117,7 +1143,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) /* finally start creating the device nodes */ if (dev->has_vid_cap) { vfd = &dev->vid_cap_dev; - strlcpy(vfd->name, "vivid-vid-cap", sizeof(vfd->name)); + 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; @@ -1133,6 +1160,27 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) vfd->lock = &dev->mutex; video_set_drvdata(vfd, dev); +#ifdef CONFIG_VIDEO_VIVID_CEC + if (in_type_counter[HDMI]) { + struct cec_adapter *adap; + + adap = vivid_cec_alloc_adap(dev, 0, &pdev->dev, false); + ret = PTR_ERR_OR_ZERO(adap); + if (ret < 0) + goto unreg_dev; + dev->cec_rx_adap = adap; + ret = cec_register_adapter(adap); + if (ret < 0) { + cec_delete_adapter(adap); + dev->cec_rx_adap = NULL; + goto unreg_dev; + } + cec_s_phys_addr(adap, 0, false); + v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input %d\n", + dev_name(&adap->devnode.dev), i); + } +#endif + ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]); if (ret < 0) goto unreg_dev; @@ -1141,8 +1189,13 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) } if (dev->has_vid_out) { +#ifdef CONFIG_VIDEO_VIVID_CEC + unsigned int bus_cnt = 0; +#endif + vfd = &dev->vid_out_dev; - strlcpy(vfd->name, "vivid-vid-out", sizeof(vfd->name)); + 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; @@ -1159,6 +1212,35 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) vfd->lock = &dev->mutex; video_set_drvdata(vfd, dev); +#ifdef CONFIG_VIDEO_VIVID_CEC + for (i = 0; i < dev->num_outputs; i++) { + struct cec_adapter *adap; + + if (dev->output_type[i] != HDMI) + continue; + dev->cec_output2bus_map[i] = bus_cnt; + adap = vivid_cec_alloc_adap(dev, bus_cnt, + &pdev->dev, true); + ret = PTR_ERR_OR_ZERO(adap); + if (ret < 0) + goto unreg_dev; + dev->cec_tx_adap[bus_cnt] = adap; + ret = cec_register_adapter(adap); + if (ret < 0) { + cec_delete_adapter(adap); + dev->cec_tx_adap[bus_cnt] = NULL; + goto unreg_dev; + } + bus_cnt++; + if (bus_cnt <= out_type_counter[HDMI]) + cec_s_phys_addr(adap, bus_cnt << 12, false); + else + cec_s_phys_addr(adap, 0x1000, false); + v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n", + dev_name(&adap->devnode.dev), i); + } +#endif + ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_out_nr[inst]); if (ret < 0) goto unreg_dev; @@ -1168,7 +1250,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (dev->has_vbi_cap) { vfd = &dev->vbi_cap_dev; - strlcpy(vfd->name, "vivid-vbi-cap", sizeof(vfd->name)); + 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; @@ -1191,7 +1274,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (dev->has_vbi_out) { vfd = &dev->vbi_out_dev; - strlcpy(vfd->name, "vivid-vbi-out", sizeof(vfd->name)); + 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; @@ -1215,7 +1299,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (dev->has_sdr_cap) { vfd = &dev->sdr_cap_dev; - strlcpy(vfd->name, "vivid-sdr-cap", sizeof(vfd->name)); + 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; @@ -1234,7 +1319,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (dev->has_radio_rx) { vfd = &dev->radio_rx_dev; - strlcpy(vfd->name, "vivid-rad-rx", sizeof(vfd->name)); + 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; @@ -1252,7 +1338,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (dev->has_radio_tx) { vfd = &dev->radio_tx_dev; - strlcpy(vfd->name, "vivid-rad-tx", sizeof(vfd->name)); + 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; @@ -1282,6 +1369,13 @@ unreg_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; @@ -1331,8 +1425,7 @@ static int vivid_probe(struct platform_device *pdev) static int vivid_remove(struct platform_device *pdev) { struct vivid_dev *dev; - unsigned i; - + unsigned int i, j; for (i = 0; i < n_devs; i++) { dev = vivid_devs[i]; @@ -1380,6 +1473,13 @@ static int vivid_remove(struct platform_device *pdev) unregister_framebuffer(&dev->fb_info); vivid_fb_release_buffers(dev); } + cec_unregister_adapter(dev->cec_rx_adap); + for (j = 0; j < MAX_OUTPUTS; j++) + cec_unregister_adapter(dev->cec_tx_adap[j]); + if (dev->cec_workqueue) { + vivid_cec_bus_free_work(dev); + destroy_workqueue(dev->cec_workqueue); + } v4l2_device_put(&dev->v4l2_dev); vivid_devs[i] = NULL; } |