Loading drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c +64 −8 Original line number Diff line number Diff line Loading @@ -26,21 +26,73 @@ #include "outpdp.h" #include "conn.h" #include "dport.h" static int nvkm_output_dp_service(void *data, u32 type, int index) static void nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool present) { struct nvkm_output_dp *outp = data; DBG("IRQ: %d\n", type); return NVKM_EVENT_KEEP; struct nouveau_i2c_port *port = outp->base.edid; if (present) { if (!outp->present) { nouveau_i2c(port)->acquire_pad(port, 0); DBG("aux power -> always\n"); outp->present = true; } } else { if (outp->present) { nouveau_i2c(port)->release_pad(port); DBG("aux power -> demand\n"); outp->present = false; } } } static void nvkm_output_dp_detect(struct nvkm_output_dp *outp) { struct nouveau_i2c_port *port = outp->base.edid; int ret = nouveau_i2c(port)->acquire_pad(port, 0); if (ret == 0) { ret = nv_rdaux(outp->base.edid, DPCD_RC00_DPCD_REV, outp->dpcd, sizeof(outp->dpcd)); nvkm_output_dp_enable(outp, ret == 0); nouveau_i2c(port)->release_pad(port); } } static void nvkm_output_dp_service_work(struct work_struct *work) { struct nvkm_output_dp *outp = container_of(work, typeof(*outp), work); struct nouveau_disp *disp = nouveau_disp(outp); int type = atomic_xchg(&outp->pending, 0); u32 send = 0; if (type & (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG)) { nvkm_output_dp_detect(outp); if (type & NVKM_I2C_UNPLUG) send |= NVKM_HPD_UNPLUG; if (type & NVKM_I2C_PLUG) send |= NVKM_HPD_PLUG; nouveau_event_get(outp->base.conn->hpd.event); } if (type & NVKM_I2C_IRQ) { nouveau_event_get(outp->irq); send |= NVKM_HPD_IRQ; } nouveau_event_trigger(disp->hpd, send, outp->base.info.connector); } static int nvkm_output_dp_hotplug(void *data, u32 type, int index) nvkm_output_dp_service(void *data, u32 type, int index) { struct nvkm_output_dp *outp = data; DBG("HPD: %d\n", type); return NVKM_EVENT_KEEP; atomic_or(type, &outp->pending); schedule_work(&outp->work); return NVKM_EVENT_DROP; } int Loading @@ -48,6 +100,7 @@ _nvkm_output_dp_fini(struct nouveau_object *object, bool suspend) { struct nvkm_output_dp *outp = (void *)object; nouveau_event_put(outp->irq); nvkm_output_dp_enable(outp, false); return nvkm_output_fini(&outp->base, suspend); } Loading @@ -55,6 +108,7 @@ int _nvkm_output_dp_init(struct nouveau_object *object) { struct nvkm_output_dp *outp = (void *)object; nvkm_output_dp_detect(outp); return nvkm_output_init(&outp->base); } Loading Loading @@ -113,10 +167,12 @@ nvkm_output_dp_create_(struct nouveau_object *parent, return ret; } INIT_WORK(&outp->work, nvkm_output_dp_service_work); /* hotplug detect, replaces gpio-based mechanism with aux events */ ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_PLUG | NVKM_I2C_UNPLUG, outp->base.edid->index, nvkm_output_dp_hotplug, outp, nvkm_output_dp_service, outp, &outp->base.conn->hpd.event); if (ret) { ERR("error monitoring aux hpd events: %d\n", ret); Loading drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h +4 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ struct nvkm_output_dp { struct nouveau_eventh *irq; struct nouveau_eventh *hpd; struct work_struct work; atomic_t pending; bool present; u8 dpcd[16]; }; #define nvkm_output_dp_create(p,e,c,b,i,d) \ Loading Loading
drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c +64 −8 Original line number Diff line number Diff line Loading @@ -26,21 +26,73 @@ #include "outpdp.h" #include "conn.h" #include "dport.h" static int nvkm_output_dp_service(void *data, u32 type, int index) static void nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool present) { struct nvkm_output_dp *outp = data; DBG("IRQ: %d\n", type); return NVKM_EVENT_KEEP; struct nouveau_i2c_port *port = outp->base.edid; if (present) { if (!outp->present) { nouveau_i2c(port)->acquire_pad(port, 0); DBG("aux power -> always\n"); outp->present = true; } } else { if (outp->present) { nouveau_i2c(port)->release_pad(port); DBG("aux power -> demand\n"); outp->present = false; } } } static void nvkm_output_dp_detect(struct nvkm_output_dp *outp) { struct nouveau_i2c_port *port = outp->base.edid; int ret = nouveau_i2c(port)->acquire_pad(port, 0); if (ret == 0) { ret = nv_rdaux(outp->base.edid, DPCD_RC00_DPCD_REV, outp->dpcd, sizeof(outp->dpcd)); nvkm_output_dp_enable(outp, ret == 0); nouveau_i2c(port)->release_pad(port); } } static void nvkm_output_dp_service_work(struct work_struct *work) { struct nvkm_output_dp *outp = container_of(work, typeof(*outp), work); struct nouveau_disp *disp = nouveau_disp(outp); int type = atomic_xchg(&outp->pending, 0); u32 send = 0; if (type & (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG)) { nvkm_output_dp_detect(outp); if (type & NVKM_I2C_UNPLUG) send |= NVKM_HPD_UNPLUG; if (type & NVKM_I2C_PLUG) send |= NVKM_HPD_PLUG; nouveau_event_get(outp->base.conn->hpd.event); } if (type & NVKM_I2C_IRQ) { nouveau_event_get(outp->irq); send |= NVKM_HPD_IRQ; } nouveau_event_trigger(disp->hpd, send, outp->base.info.connector); } static int nvkm_output_dp_hotplug(void *data, u32 type, int index) nvkm_output_dp_service(void *data, u32 type, int index) { struct nvkm_output_dp *outp = data; DBG("HPD: %d\n", type); return NVKM_EVENT_KEEP; atomic_or(type, &outp->pending); schedule_work(&outp->work); return NVKM_EVENT_DROP; } int Loading @@ -48,6 +100,7 @@ _nvkm_output_dp_fini(struct nouveau_object *object, bool suspend) { struct nvkm_output_dp *outp = (void *)object; nouveau_event_put(outp->irq); nvkm_output_dp_enable(outp, false); return nvkm_output_fini(&outp->base, suspend); } Loading @@ -55,6 +108,7 @@ int _nvkm_output_dp_init(struct nouveau_object *object) { struct nvkm_output_dp *outp = (void *)object; nvkm_output_dp_detect(outp); return nvkm_output_init(&outp->base); } Loading Loading @@ -113,10 +167,12 @@ nvkm_output_dp_create_(struct nouveau_object *parent, return ret; } INIT_WORK(&outp->work, nvkm_output_dp_service_work); /* hotplug detect, replaces gpio-based mechanism with aux events */ ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_PLUG | NVKM_I2C_UNPLUG, outp->base.edid->index, nvkm_output_dp_hotplug, outp, nvkm_output_dp_service, outp, &outp->base.conn->hpd.event); if (ret) { ERR("error monitoring aux hpd events: %d\n", ret); Loading
drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h +4 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ struct nvkm_output_dp { struct nouveau_eventh *irq; struct nouveau_eventh *hpd; struct work_struct work; atomic_t pending; bool present; u8 dpcd[16]; }; #define nvkm_output_dp_create(p,e,c,b,i,d) \ Loading