kfree(pin);
 }
 
+static int cec_pin_received(struct cec_adapter *adap, struct cec_msg *msg)
+{
+       struct cec_pin *pin = adap->pin;
+
+       if (pin->ops->received)
+               return pin->ops->received(adap, msg);
+       return -ENOMSG;
+}
+
 void cec_pin_changed(struct cec_adapter *adap, bool value)
 {
        struct cec_pin *pin = adap->pin;
        .error_inj_parse_line = cec_pin_error_inj_parse_line,
        .error_inj_show = cec_pin_error_inj_show,
 #endif
+       .received = cec_pin_received,
 };
 
 struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops,
 
  *             an error if negative. If NULL or -ENOTTY is returned,
  *             then this is not supported.
  *
- * These operations are used by the cec pin framework to manipulate
- * the CEC pin.
+ * @received:  optional. High-level CEC message callback. Allows the driver
+ *             to process CEC messages.
+ *
+ * These operations (except for the @received op) are used by the
+ * cec pin framework to manipulate the CEC pin.
  */
 struct cec_pin_ops {
        bool (*read)(struct cec_adapter *adap);
        void (*status)(struct cec_adapter *adap, struct seq_file *file);
        int  (*read_hpd)(struct cec_adapter *adap);
        int  (*read_5v)(struct cec_adapter *adap);
+
+       /* High-level CEC message callback */
+       int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
 };
 
 /**