On Tue, Jul 28, 2015 at 03:59:45PM +0200, Takashi Iwai wrote:
FWIW, we're currently discussing about extending the i915/hda component binding so that the audio driver gets a notification and queries the ELD via callbacks instead of the flaky hardware access.
It'd be best if we have a common infrastructure for that, of course. But currently it's a start, just a bit step forward there.
Okay, so it sounds like i915/hda also needs this.
I think in addition to what I said above, we need whatever provides the notification system to generate state notifications for new "listeners" that would otherwise be unaware of the current state.
I'm thinking at the moment that something along these lines to go into drivers/video/hdmi.c / include/linux/hdmi.h:
struct hdmi_state { struct mutex mutex; struct raw_notifier_head head; bool connected; bool edid_valid; u8 edid[MAX_EDID_SIZE]; };
enum { HDMI_CONNECTED, HDMI_DISCONNECTED, HDMI_NEW_EDID, };
int hdmi_register_notifier(struct notifier_block *nb) { struct hdmi_state *state = ...; int ret;
mutex_lock(&state->mutex); if (state->connected) { nb->notifier_call(nb, HDMI_CONNECTED, NULL); if (state->edid_valid) nb->notifier_call(nb, HDMI_NEW_EDID, state->edid); } else { nb->notifier_call(nb, HDMI_DISCONNECTED, NULL); } ret = raw_notifier_chain_register(&state->head, nb); mutex_unlock(&state->mutex);
return ret; }
int hdmi_unregister_notifier(struct notifier_block *nb) { struct hdmi_state *state = ...; int ret;
mutex_lock(&state->mutex); ret = raw_notifier_chain_unregister(&state->head, nb); mutex_unlock(&state->mutex);
return ret; }
void hdmi_event_connect(struct device *dev) { struct hdmi_state *state = lookup_state_from_dev(dev);
mutex_lock(&state->mutex); state->connected = true; raw_notifier_call_chain(&state->head, HDMI_CONNECTED, NULL); mutex_unlock(&state->mutex); }
void hdmi_event_disconnect(struct device *dev) { struct hdmi_state *state = lookup_state_from_dev(dev);
mutex_lock(&state->mutex); state->connected = false; state->valid_edid = false; raw_notifier_call_chain(&state->head, HDMI_DISCONNECTED, NULL); mutex_unlock(&state->mutex); }
int hdmi_event_new_edid(struct device *dev, const void *edid, size_t size) { struct hdmi_state *state = lookup_state_from_dev(dev);
if (size > sizeof(state->edid)) return -EINVAL;
mutex_lock(&state->mutex); state->valid_edid = true; memcpy(state->edid, edid, size); raw_notifier_call_chain(&state->head, HDMI_NEW_EDID, state->edid); mutex_unlock(&state->mutex);
return 0; }
The problems here are: how to go from a struct device to the state (iow, the implementation of lookup_state_from_dev()) and how to convey on the client side which 'state' to attach to. I'd rather not involve DT at this level: DT is not the world's only firmware system, we have to cater for x86 too here, so we need something that is firmware agnostic.
This is something I've just banged out in this email...