media: vivid: add CEC support to display present ctrl
authorJohan Korsnes <johan.korsnes@gmail.com>
Tue, 18 Jun 2019 07:37:25 +0000 (03:37 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Fri, 21 Jun 2019 21:34:44 +0000 (17:34 -0400)
Set/invalidate physical addresses based on the configuration of the
display present control. This is relevant not only when the display
present control is modified, but also when the Vivid instance EDID is
set/cleared.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/vivid/vivid-ctrls.c
drivers/media/platform/vivid/vivid-vid-cap.c
drivers/media/platform/vivid/vivid-vid-common.c

index ed80ba51441ed495b825353fe525e4adc6bd2465..3e916c8befb7170e7c247e3dffc364432e10254b 100644 (file)
@@ -18,6 +18,7 @@
 #include "vivid-radio-common.h"
 #include "vivid-osd.h"
 #include "vivid-ctrls.h"
+#include "vivid-cec.h"
 
 #define VIVID_CID_CUSTOM_BASE          (V4L2_CID_USER_BASE | 0xf000)
 #define VIVID_CID_BUTTON               (VIVID_CID_CUSTOM_BASE + 0)
@@ -925,7 +926,7 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
        struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
        struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
        u32 display_present = 0;
-       unsigned int i, j;
+       unsigned int i, j, bus_idx;
 
        switch (ctrl->id) {
        case VIVID_CID_HAS_CROP_OUT:
@@ -964,15 +965,31 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
                        break;
 
                dev->display_present[dev->output] = ctrl->val;
-
                for (i = 0, j = 0; i < dev->num_outputs; i++)
                        if (dev->output_type[i] == HDMI)
                                display_present |=
                                        dev->display_present[i] << j++;
 
-               __v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, display_present);
                __v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
-               __v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, display_present);
+
+               if (dev->edid_blocks) {
+                       __v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
+                                          display_present);
+                       __v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
+                                          display_present);
+               }
+
+               bus_idx = dev->cec_output2bus_map[dev->output];
+               if (!dev->cec_tx_adap[bus_idx])
+                       break;
+
+               if (ctrl->val && dev->edid_blocks)
+                       cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
+                                       dev->cec_tx_adap[bus_idx]->phys_addr,
+                                       false);
+               else
+                       cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
+
                break;
        }
        return 0;
index 6edb0325f25f05f25bcc5258ec73b8e191d3b1cc..8cbaa0c998eddb8928613fd3d68b400b4d6b50c5 100644 (file)
@@ -1748,7 +1748,8 @@ int vidioc_s_edid(struct file *file, void *_fh,
 {
        struct vivid_dev *dev = video_drvdata(file);
        u16 phys_addr;
-       unsigned int i;
+       u32 display_present = 0;
+       unsigned int i, j;
        int ret;
 
        memset(edid->reserved, 0, sizeof(edid->reserved));
@@ -1758,6 +1759,8 @@ int vidioc_s_edid(struct file *file, void *_fh,
                return -EINVAL;
        if (edid->blocks == 0) {
                dev->edid_blocks = 0;
+               v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, 0);
+               v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, 0);
                phys_addr = CEC_PHYS_ADDR_INVALID;
                goto set_phys_addr;
        }
@@ -1776,13 +1779,23 @@ int vidioc_s_edid(struct file *file, void *_fh,
        dev->edid_blocks = edid->blocks;
        memcpy(dev->edid, edid->edid, edid->blocks * 128);
 
+       for (i = 0, j = 0; i < dev->num_outputs; i++)
+               if (dev->output_type[i] == HDMI)
+                       display_present |=
+                               dev->display_present[i] << j++;
+
+       v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, display_present);
+       v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, display_present);
+
 set_phys_addr:
        /* TODO: a proper hotplug detect cycle should be emulated here */
        cec_s_phys_addr(dev->cec_rx_adap, phys_addr, false);
 
        for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
                cec_s_phys_addr(dev->cec_tx_adap[i],
-                               v4l2_phys_addr_for_input(phys_addr, i + 1),
+                               dev->display_present[i] ?
+                               v4l2_phys_addr_for_input(phys_addr, i + 1) :
+                               CEC_PHYS_ADDR_INVALID,
                                false);
        return 0;
 }
index 10a344c29a1a3d387d68af11c60cc13dc3c7f061..1f33eb1a76b68ae8be26027ee9e1b2af7f0a10d9 100644 (file)
@@ -887,6 +887,8 @@ int vidioc_g_edid(struct file *file, void *_fh,
                        return -EINVAL;
                if (dev->output_type[edid->pad] != HDMI)
                        return -EINVAL;
+               if (!dev->display_present[edid->pad])
+                       return -ENODATA;
                bus_idx = dev->cec_output2bus_map[edid->pad];
                adap = dev->cec_tx_adap[bus_idx];
        }