linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] cec fixes, vivid-cec improvements
@ 2017-08-20 11:53 Hans Verkuil
  2017-08-20 11:53 ` [PATCH 1/4] cec: replace pin->cur_value by adap->cec_pin_is_high Hans Verkuil
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Hans Verkuil @ 2017-08-20 11:53 UTC (permalink / raw)
  To: linux-media

From: Hans Verkuil <hans.verkuil@cisco.com>

The first two patches add support for CEC pin emulation in the
vivid driver. The third fixes a kernel logging bug in vivid.

The last patch is a bug fix: the CEC adapter was not explicitly
disabled when cec_delete_adapter was called. Normally this does not
cause any problems, but for the upcoming omap4 cec driver it does.

Regards,

	Hans

Hans Verkuil (4):
  cec: replace pin->cur_value by adap->cec_pin_is_high
  vivid: add CEC pin monitoring emulation
  vivid: fix incorrect HDMI input/output CEC logging
  cec: ensure that adap_enable(false) is called from
    cec_delete_adapter()

 drivers/media/cec/cec-adap.c              |  4 +-
 drivers/media/cec/cec-api.c               |  6 +--
 drivers/media/cec/cec-core.c              |  1 +
 drivers/media/cec/cec-pin.c               |  5 +--
 drivers/media/platform/vivid/vivid-cec.c  | 65 ++++++++++++++++++++++++++++++-
 drivers/media/platform/vivid/vivid-core.c |  8 ++--
 include/media/cec-pin.h                   |  1 -
 include/media/cec.h                       |  1 +
 8 files changed, 77 insertions(+), 14 deletions(-)

-- 
2.14.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] cec: replace pin->cur_value by adap->cec_pin_is_high
  2017-08-20 11:53 [PATCH 0/4] cec fixes, vivid-cec improvements Hans Verkuil
@ 2017-08-20 11:53 ` Hans Verkuil
  2017-08-20 11:53 ` [PATCH 2/4] vivid: add CEC pin monitoring emulation Hans Verkuil
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Hans Verkuil @ 2017-08-20 11:53 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The current CEC pin value (0 or 1) was part of the cec_pin struct,
but that assumes that CEC pin monitoring can only be used with
a driver that uses the low-level CEC pin framework.

But hardware that has both a high-level API and can monitor the
CEC pin at low-level at the same time does not need to depend on
the cec pin framework.

To support such devices remove the cur_value field from struct cec_pin
and add a cec_pin_is_high field to cec_adapter. This also makes it
possible to drop the '#ifdef CONFIG_CEC_PIN' in cec-api.c.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/cec/cec-api.c  | 6 ++----
 drivers/media/cec/cec-core.c | 1 +
 drivers/media/cec/cec-pin.c  | 5 ++---
 include/media/cec-pin.h      | 1 -
 include/media/cec.h          | 1 +
 5 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c
index 00d43d74020f..d1393a950c0d 100644
--- a/drivers/media/cec/cec-api.c
+++ b/drivers/media/cec/cec-api.c
@@ -444,15 +444,13 @@ static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
 	if (mode_follower == CEC_MODE_FOLLOWER)
 		adap->follower_cnt++;
 	if (mode_follower == CEC_MODE_MONITOR_PIN) {
-#ifdef CONFIG_CEC_PIN
 		struct cec_event ev = {
 			.flags = CEC_EVENT_FL_INITIAL_STATE,
 		};
 
-		ev.event = adap->pin->cur_value ? CEC_EVENT_PIN_HIGH :
-						  CEC_EVENT_PIN_LOW;
+		ev.event = adap->cec_pin_is_high ? CEC_EVENT_PIN_HIGH :
+						   CEC_EVENT_PIN_LOW;
 		cec_queue_event_fh(fh, &ev, 0);
-#endif
 		adap->monitor_pin_cnt++;
 	}
 	if (mode_follower == CEC_MODE_EXCL_FOLLOWER ||
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index 52f085ba104a..f344a2ddef7f 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -227,6 +227,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
 		return ERR_PTR(-ENOMEM);
 	strlcpy(adap->name, name, sizeof(adap->name));
 	adap->phys_addr = CEC_PHYS_ADDR_INVALID;
+	adap->cec_pin_is_high = true;
 	adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
 	adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
 	adap->capabilities = caps;
diff --git a/drivers/media/cec/cec-pin.c b/drivers/media/cec/cec-pin.c
index 03f800e5ec1f..589d4a640e8c 100644
--- a/drivers/media/cec/cec-pin.c
+++ b/drivers/media/cec/cec-pin.c
@@ -88,10 +88,10 @@ static const struct cec_state states[CEC_PIN_STATES] = {
 
 static void cec_pin_update(struct cec_pin *pin, bool v, bool force)
 {
-	if (!force && v == pin->cur_value)
+	if (!force && v == pin->adap->cec_pin_is_high)
 		return;
 
-	pin->cur_value = v;
+	pin->adap->cec_pin_is_high = v;
 	if (atomic_read(&pin->work_pin_events) < CEC_NUM_PIN_EVENTS) {
 		pin->work_pin_is_high[pin->work_pin_events_wr] = v;
 		pin->work_pin_ts[pin->work_pin_events_wr] = ktime_get();
@@ -772,7 +772,6 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops,
 	if (pin == NULL)
 		return ERR_PTR(-ENOMEM);
 	pin->ops = pin_ops;
-	pin->cur_value = true;
 	hrtimer_init(&pin->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	pin->timer.function = cec_pin_timer;
 	init_waitqueue_head(&pin->kthread_waitq);
diff --git a/include/media/cec-pin.h b/include/media/cec-pin.h
index 44b82d29d480..a60975d960ca 100644
--- a/include/media/cec-pin.h
+++ b/include/media/cec-pin.h
@@ -124,7 +124,6 @@ struct cec_pin {
 	u16				la_mask;
 	bool				enabled;
 	bool				monitor_all;
-	bool				cur_value;
 	bool				rx_eom;
 	bool				enable_irq_failed;
 	enum cec_pin_state		state;
diff --git a/include/media/cec.h b/include/media/cec.h
index 1bec7bde4792..63a2b8544f53 100644
--- a/include/media/cec.h
+++ b/include/media/cec.h
@@ -180,6 +180,7 @@ struct cec_adapter {
 	bool needs_hpd;
 	bool is_configuring;
 	bool is_configured;
+	bool cec_pin_is_high;
 	u32 monitor_all_cnt;
 	u32 monitor_pin_cnt;
 	u32 follower_cnt;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] vivid: add CEC pin monitoring emulation
  2017-08-20 11:53 [PATCH 0/4] cec fixes, vivid-cec improvements Hans Verkuil
  2017-08-20 11:53 ` [PATCH 1/4] cec: replace pin->cur_value by adap->cec_pin_is_high Hans Verkuil
@ 2017-08-20 11:53 ` Hans Verkuil
  2017-08-20 11:53 ` [PATCH 3/4] vivid: fix incorrect HDMI input/output CEC logging Hans Verkuil
  2017-08-20 11:53 ` [PATCH 4/4] cec: ensure that adap_enable(false) is called from cec_delete_adapter() Hans Verkuil
  3 siblings, 0 replies; 5+ messages in thread
From: Hans Verkuil @ 2017-08-20 11:53 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add support to emulate CEC pin monitoring. There are few hardware devices
that support this, so being able to emulate it here helps developing
software for this.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-cec.c | 65 +++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/vivid/vivid-cec.c b/drivers/media/platform/vivid/vivid-cec.c
index 43992fa92a88..643eeba79912 100644
--- a/drivers/media/platform/vivid/vivid-cec.c
+++ b/drivers/media/platform/vivid/vivid-cec.c
@@ -22,6 +22,15 @@
 #include "vivid-core.h"
 #include "vivid-cec.h"
 
+#define CEC_TIM_START_BIT_TOTAL		4500
+#define CEC_TIM_START_BIT_LOW		3700
+#define CEC_TIM_START_BIT_HIGH		800
+#define CEC_TIM_DATA_BIT_TOTAL		2400
+#define CEC_TIM_DATA_BIT_0_LOW		1500
+#define CEC_TIM_DATA_BIT_0_HIGH		900
+#define CEC_TIM_DATA_BIT_1_LOW		600
+#define CEC_TIM_DATA_BIT_1_HIGH		1800
+
 void vivid_cec_bus_free_work(struct vivid_dev *dev)
 {
 	spin_lock(&dev->cec_slock);
@@ -64,6 +73,58 @@ static bool vivid_cec_find_dest_adap(struct vivid_dev *dev,
 	return false;
 }
 
+static void vivid_cec_pin_adap_events(struct cec_adapter *adap, ktime_t ts,
+				      const struct cec_msg *msg, bool nacked)
+{
+	unsigned int len = nacked ? 1 : msg->len;
+	unsigned int i;
+	bool bit;
+
+	if (adap == NULL)
+		return;
+	ts = ktime_sub_us(ts, (CEC_TIM_START_BIT_TOTAL +
+			       len * 10 * CEC_TIM_DATA_BIT_TOTAL));
+	cec_queue_pin_event(adap, false, ts);
+	ts = ktime_add_us(ts, CEC_TIM_START_BIT_LOW);
+	cec_queue_pin_event(adap, true, ts);
+	ts = ktime_add_us(ts, CEC_TIM_START_BIT_HIGH);
+
+	for (i = 0; i < 10 * len; i++) {
+		switch (i % 10) {
+		case 0 ... 7:
+			bit = msg->msg[i / 10] & (0x80 >> (i % 10));
+			break;
+		case 8: /* EOM */
+			bit = i / 10 == msg->len - 1;
+			break;
+		case 9: /* ACK */
+			bit = cec_msg_is_broadcast(msg) ^ nacked;
+			break;
+		}
+		cec_queue_pin_event(adap, false, ts);
+		if (bit)
+			ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_LOW);
+		else
+			ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_LOW);
+		cec_queue_pin_event(adap, true, ts);
+		if (bit)
+			ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_1_HIGH);
+		else
+			ts = ktime_add_us(ts, CEC_TIM_DATA_BIT_0_HIGH);
+	}
+}
+
+static void vivid_cec_pin_events(struct vivid_dev *dev,
+				 const struct cec_msg *msg, bool nacked)
+{
+	ktime_t ts = ktime_get();
+	unsigned int i;
+
+	vivid_cec_pin_adap_events(dev->cec_rx_adap, ts, msg, nacked);
+	for (i = 0; i < MAX_OUTPUTS; i++)
+		vivid_cec_pin_adap_events(dev->cec_tx_adap[i], ts, msg, nacked);
+}
+
 static void vivid_cec_xfer_done_worker(struct work_struct *work)
 {
 	struct vivid_cec_work *cw =
@@ -84,6 +145,7 @@ static void vivid_cec_xfer_done_worker(struct work_struct *work)
 	dev->cec_xfer_start_jiffies = 0;
 	list_del(&cw->list);
 	spin_unlock(&dev->cec_slock);
+	vivid_cec_pin_events(dev, &cw->msg, !valid_dest);
 	cec_transmit_attempt_done(cw->adap, cw->tx_status);
 
 	/* Broadcast message */
@@ -118,6 +180,7 @@ static void vivid_cec_xfer_try_worker(struct work_struct *work)
 
 static int vivid_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
+	adap->cec_pin_is_high = true;
 	return 0;
 }
 
@@ -219,7 +282,7 @@ struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
 					 bool is_source)
 {
 	char name[sizeof(dev->vid_out_dev.name) + 2];
-	u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL;
+	u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN;
 
 	snprintf(name, sizeof(name), "%s%d",
 		 is_source ? dev->vid_out_dev.name : dev->vid_cap_dev.name,
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] vivid: fix incorrect HDMI input/output CEC logging
  2017-08-20 11:53 [PATCH 0/4] cec fixes, vivid-cec improvements Hans Verkuil
  2017-08-20 11:53 ` [PATCH 1/4] cec: replace pin->cur_value by adap->cec_pin_is_high Hans Verkuil
  2017-08-20 11:53 ` [PATCH 2/4] vivid: add CEC pin monitoring emulation Hans Verkuil
@ 2017-08-20 11:53 ` Hans Verkuil
  2017-08-20 11:53 ` [PATCH 4/4] cec: ensure that adap_enable(false) is called from cec_delete_adapter() Hans Verkuil
  3 siblings, 0 replies; 5+ messages in thread
From: Hans Verkuil @ 2017-08-20 11:53 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Only the first HDMI input has a CEC adapter, so just report 'HDMI 0' as
the HDMI input name.

For the HDMI outputs use bus_cnt instead of i as the output number.
The HDMI name now corresponds to what 'v4l2-ctl --list-outputs' reports.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-core.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index ef344b9a48af..5f316a5e38db 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -1201,8 +1201,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 				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);
+			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input 0\n",
+				  dev_name(&adap->devnode.dev));
 		}
 #endif
 
@@ -1255,13 +1255,13 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 				dev->cec_tx_adap[bus_cnt] = NULL;
 				goto unreg_dev;
 			}
+			v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n",
+				  dev_name(&adap->devnode.dev), bus_cnt);
 			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
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] cec: ensure that adap_enable(false) is called from cec_delete_adapter()
  2017-08-20 11:53 [PATCH 0/4] cec fixes, vivid-cec improvements Hans Verkuil
                   ` (2 preceding siblings ...)
  2017-08-20 11:53 ` [PATCH 3/4] vivid: fix incorrect HDMI input/output CEC logging Hans Verkuil
@ 2017-08-20 11:53 ` Hans Verkuil
  3 siblings, 0 replies; 5+ messages in thread
From: Hans Verkuil @ 2017-08-20 11:53 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

When the adapter is removed the cec_delete_adapter() call attempts
to set the physical address to INVALID by calling __cec_s_phys_addr()
and so disabling the adapter.

However, __cec_s_phys_addr checks if the device node was unregistered
and just returns in that case.

This means that the adap_enable callback is never called with 'false'
to disable the CEC adapter. Most drivers don't care, but some need
to do cleanup here.

Change the test so the adapter is correctly disabled, even when the
device node is unregistered.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Reported-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/media/cec/cec-adap.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
index 8ac39ddf892c..491f3665de22 100644
--- a/drivers/media/cec/cec-adap.c
+++ b/drivers/media/cec/cec-adap.c
@@ -1447,7 +1447,9 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
  */
 void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
 {
-	if (phys_addr == adap->phys_addr || adap->devnode.unregistered)
+	if (phys_addr == adap->phys_addr)
+		return;
+	if (phys_addr != CEC_PHYS_ADDR_INVALID && adap->devnode.unregistered)
 		return;
 
 	dprintk(1, "new physical address %x.%x.%x.%x\n",
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-08-20 11:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-20 11:53 [PATCH 0/4] cec fixes, vivid-cec improvements Hans Verkuil
2017-08-20 11:53 ` [PATCH 1/4] cec: replace pin->cur_value by adap->cec_pin_is_high Hans Verkuil
2017-08-20 11:53 ` [PATCH 2/4] vivid: add CEC pin monitoring emulation Hans Verkuil
2017-08-20 11:53 ` [PATCH 3/4] vivid: fix incorrect HDMI input/output CEC logging Hans Verkuil
2017-08-20 11:53 ` [PATCH 4/4] cec: ensure that adap_enable(false) is called from cec_delete_adapter() Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).