[PATCH 03/14] drm/amd/display: Engage PSR synchronously
Bindu R
bindu.r at amd.com
Fri Nov 6 23:16:59 UTC 2020
From: Krunoslav Kovac <Krunoslav.Kovac at amd.com>
[Why & How]
The intended use is to force PSR into active state and ignore all
events until explicit EXIT.
A new event force_static is added to power module. It is then sent
to FW.
Signed-off-by: Krunoslav Kovac <Krunoslav.Kovac at amd.com>
Acked-by: Bindu Ramamurthy<Bindu.R at amd.com>
Acked-by: Bindu Ramamurthy <bindu.r at amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +-
.../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 6 +-
.../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 5 +-
drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +-
drivers/gpu/drm/amd/display/dc/core/dc_link.c | 18 ++-
.../gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +-
drivers/gpu/drm/amd/display/dc/dc_link.h | 5 +-
drivers/gpu/drm/amd/display/dc/dc_types.h | 19 +++
drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 24 ++--
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 111 +++++++++++-------
drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 3 +-
drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 2 +-
12 files changed, 129 insertions(+), 76 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 84f11c05f12c..88893c9711cb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9738,7 +9738,7 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
&stream, 1,
¶ms);
- return dc_link_set_psr_allow_active(link, true, false);
+ return dc_link_set_psr_allow_active(link, true, false, false);
}
/*
@@ -9752,7 +9752,7 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
DRM_DEBUG_DRIVER("Disabling psr...\n");
- return dc_link_set_psr_allow_active(stream->link, false, true);
+ return dc_link_set_psr_allow_active(stream->link, false, true, false);
}
/*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index d31380ea57dc..11459fb09a37 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -2333,11 +2333,11 @@ static int psr_get(void *data, u64 *val)
{
struct amdgpu_dm_connector *connector = data;
struct dc_link *link = connector->dc_link;
- uint32_t psr_state = 0;
+ enum dc_psr_state state = PSR_STATE0;
- dc_link_get_psr_state(link, &psr_state);
+ dc_link_get_psr_state(link, &state);
- *val = psr_state;
+ *val = state;
return 0;
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
index 19d97ed6beb8..710b54e065fa 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
@@ -98,7 +98,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
if (edp_link) {
clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
- dc_link_set_psr_allow_active(edp_link, false, false);
+ dc_link_set_psr_allow_active(edp_link, false, false, false);
}
}
@@ -108,7 +108,8 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
struct dc_link *edp_link = get_edp_link(dc);
if (edp_link)
- dc_link_set_psr_allow_active(edp_link, clk_mgr->psr_allow_active_cache, false);
+ dc_link_set_psr_allow_active(edp_link,
+ clk_mgr->psr_allow_active_cache, false, false);
if (dc->hwss.optimize_pwr_state)
dc->hwss.optimize_pwr_state(dc, dc->current_state);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 34e76fdc1334..6b6127f3a82c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3058,9 +3058,9 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable)
if (link->psr_settings.psr_feature_enabled) {
if (enable && !link->psr_settings.psr_allow_active)
- return dc_link_set_psr_allow_active(link, true, false);
+ return dc_link_set_psr_allow_active(link, true, false, false);
else if (!enable && link->psr_settings.psr_allow_active)
- return dc_link_set_psr_allow_active(link, false, true);
+ return dc_link_set_psr_allow_active(link, false, true, false);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 09b51fca3d44..46d415e183ff 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -2565,17 +2565,23 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
return true;
}
-bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool wait)
+bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,
+ bool wait, bool force_static)
{
struct dc *dc = link->ctx->dc;
struct dmcu *dmcu = dc->res_pool->dmcu;
struct dmub_psr *psr = dc->res_pool->psr;
+ if (psr == NULL && force_static)
+ return false;
+
link->psr_settings.psr_allow_active = allow_active;
- if (psr != NULL && link->psr_settings.psr_feature_enabled)
+ if (psr != NULL && link->psr_settings.psr_feature_enabled) {
+ if (force_static && psr->funcs->psr_force_static)
+ psr->funcs->psr_force_static(psr);
psr->funcs->psr_enable(psr, allow_active, wait);
- else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
+ } else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
else
return false;
@@ -2583,16 +2589,16 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool
return true;
}
-bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state)
+bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
{
struct dc *dc = link->ctx->dc;
struct dmcu *dmcu = dc->res_pool->dmcu;
struct dmub_psr *psr = dc->res_pool->psr;
if (psr != NULL && link->psr_settings.psr_feature_enabled)
- psr->funcs->psr_get_state(psr, psr_state);
+ psr->funcs->psr_get_state(psr, state);
else if (dmcu != NULL && link->psr_settings.psr_feature_enabled)
- dmcu->funcs->get_psr_state(dmcu, psr_state);
+ dmcu->funcs->get_psr_state(dmcu, state);
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 8a7c4de49a4b..6c60c1fdebdc 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -2575,8 +2575,8 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
sizeof(psr_error_status.raw));
/* PSR error, disable and re-enable PSR */
- dc_link_set_psr_allow_active(link, false, true);
- dc_link_set_psr_allow_active(link, true, true);
+ dc_link_set_psr_allow_active(link, false, true, false);
+ dc_link_set_psr_allow_active(link, true, true, false);
return true;
} else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
index 266b93a705d5..39277aaa3e62 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
@@ -219,9 +219,10 @@ int dc_link_get_backlight_level(const struct dc_link *dc_link);
int dc_link_get_target_backlight_pwm(const struct dc_link *link);
-bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable, bool wait);
+bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable,
+ bool wait, bool force_static);
-bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state);
+bool dc_link_get_psr_state(const struct dc_link *dc_link, enum dc_psr_state *state);
bool dc_link_setup_psr(struct dc_link *dc_link,
const struct dc_stream_state *stream, struct psr_config *psr_config,
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 7ff8676daec9..bfb98fd36bf8 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -676,6 +676,25 @@ struct dc_plane_flip_time {
unsigned int prev_update_time_in_us;
};
+enum dc_psr_state {
+ PSR_STATE0 = 0x0,
+ PSR_STATE1,
+ PSR_STATE1a,
+ PSR_STATE2,
+ PSR_STATE2a,
+ PSR_STATE3,
+ PSR_STATE3Init,
+ PSR_STATE4,
+ PSR_STATE4a,
+ PSR_STATE4b,
+ PSR_STATE4c,
+ PSR_STATE4d,
+ PSR_STATE5,
+ PSR_STATE5a,
+ PSR_STATE5b,
+ PSR_STATE5c
+};
+
struct psr_config {
unsigned char psr_version;
unsigned int psr_rfb_setup_time;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index f0cebe721bcc..f3ed8b619caf 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -99,7 +99,7 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu,
return true;
}
-static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
+static void dce_get_dmcu_psr_state(struct dmcu *dmcu, enum dc_psr_state *state)
{
struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
@@ -114,7 +114,7 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset);
/* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
- *psr_state = REG_READ(DMCU_IRAM_RD_DATA);
+ *state = (enum dc_psr_state)REG_READ(DMCU_IRAM_RD_DATA);
/* Disable write access to IRAM after finished using IRAM
* in order to allow dynamic sleep state
@@ -129,7 +129,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
unsigned int dmcu_wait_reg_ready_interval = 100;
unsigned int retryCount;
- uint32_t psr_state = 0;
+ enum dc_psr_state state = PSR_STATE0;
/* waitDMCUReadyForCmd */
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
@@ -148,12 +148,12 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
if (wait == true) {
for (retryCount = 0; retryCount <= 100; retryCount++) {
- dce_get_dmcu_psr_state(dmcu, &psr_state);
+ dce_get_dmcu_psr_state(dmcu, &state);
if (enable) {
- if (psr_state != 0)
+ if (state != PSR_STATE0)
break;
} else {
- if (psr_state == 0)
+ if (state == PSR_STATE0)
break;
}
udelay(10);
@@ -513,7 +513,7 @@ static bool dcn10_dmcu_load_iram(struct dmcu *dmcu,
return true;
}
-static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
+static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, enum dc_psr_state *state)
{
struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
@@ -532,7 +532,7 @@ static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
REG_WRITE(DMCU_IRAM_RD_CTRL, psr_state_offset);
/* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
- *psr_state = REG_READ(DMCU_IRAM_RD_DATA);
+ *state = (enum dc_psr_state)REG_READ(DMCU_IRAM_RD_DATA);
/* Disable write access to IRAM after finished using IRAM
* in order to allow dynamic sleep state
@@ -547,7 +547,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
unsigned int dmcu_wait_reg_ready_interval = 100;
unsigned int retryCount;
- uint32_t psr_state = 0;
+ enum dc_psr_state state = PSR_STATE0;
/* If microcontroller is not running, do nothing */
if (dmcu->dmcu_state != DMCU_RUNNING)
@@ -575,12 +575,12 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait)
*/
if (wait == true) {
for (retryCount = 0; retryCount <= 1000; retryCount++) {
- dcn10_get_dmcu_psr_state(dmcu, &psr_state);
+ dcn10_get_dmcu_psr_state(dmcu, &state);
if (enable) {
- if (psr_state != 0)
+ if (state != PSR_STATE0)
break;
} else {
- if (psr_state == 0)
+ if (state == PSR_STATE0)
break;
}
udelay(500);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
index 67af67ef2865..df3879c713c5 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
@@ -34,55 +34,60 @@
/**
* Convert dmcub psr state to dmcu psr state.
*/
-static void convert_psr_state(uint32_t *psr_state)
+static enum dc_psr_state convert_psr_state(uint32_t raw_state)
{
- if (*psr_state == 0)
- *psr_state = 0;
- else if (*psr_state == 0x10)
- *psr_state = 1;
- else if (*psr_state == 0x11)
- *psr_state = 2;
- else if (*psr_state == 0x20)
- *psr_state = 3;
- else if (*psr_state == 0x21)
- *psr_state = 4;
- else if (*psr_state == 0x30)
- *psr_state = 5;
- else if (*psr_state == 0x31)
- *psr_state = 6;
- else if (*psr_state == 0x40)
- *psr_state = 7;
- else if (*psr_state == 0x41)
- *psr_state = 8;
- else if (*psr_state == 0x42)
- *psr_state = 9;
- else if (*psr_state == 0x43)
- *psr_state = 10;
- else if (*psr_state == 0x44)
- *psr_state = 11;
- else if (*psr_state == 0x50)
- *psr_state = 12;
- else if (*psr_state == 0x51)
- *psr_state = 13;
- else if (*psr_state == 0x52)
- *psr_state = 14;
- else if (*psr_state == 0x53)
- *psr_state = 15;
+ enum dc_psr_state state = PSR_STATE0;
+
+ if (raw_state == 0)
+ state = PSR_STATE0;
+ else if (raw_state == 0x10)
+ state = PSR_STATE1;
+ else if (raw_state == 0x11)
+ state = PSR_STATE1a;
+ else if (raw_state == 0x20)
+ state = PSR_STATE2;
+ else if (raw_state == 0x21)
+ state = PSR_STATE2a;
+ else if (raw_state == 0x30)
+ state = PSR_STATE3;
+ else if (raw_state == 0x31)
+ state = PSR_STATE3Init;
+ else if (raw_state == 0x40)
+ state = PSR_STATE4;
+ else if (raw_state == 0x41)
+ state = PSR_STATE4a;
+ else if (raw_state == 0x42)
+ state = PSR_STATE4b;
+ else if (raw_state == 0x43)
+ state = PSR_STATE4c;
+ else if (raw_state == 0x44)
+ state = PSR_STATE4d;
+ else if (raw_state == 0x50)
+ state = PSR_STATE5;
+ else if (raw_state == 0x51)
+ state = PSR_STATE5a;
+ else if (raw_state == 0x52)
+ state = PSR_STATE5b;
+ else if (raw_state == 0x53)
+ state = PSR_STATE5c;
+
+ return state;
}
/**
* Get PSR state from firmware.
*/
-static void dmub_psr_get_state(struct dmub_psr *dmub, uint32_t *psr_state)
+static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state)
{
struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
+ uint32_t raw_state;
// Send gpint command and wait for ack
dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30);
- dmub_srv_get_gpint_response(srv, psr_state);
+ dmub_srv_get_gpint_response(srv, &raw_state);
- convert_psr_state(psr_state);
+ *state = convert_psr_state(raw_state);
}
/**
@@ -123,7 +128,9 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
- uint32_t retry_count, psr_state = 0;
+ uint32_t retry_count;
+ enum dc_psr_state state = PSR_STATE0;
+
cmd.psr_enable.header.type = DMUB_CMD__PSR;
@@ -144,13 +151,13 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
*/
if (wait) {
for (retry_count = 0; retry_count <= 1000; retry_count++) {
- dmub_psr_get_state(dmub, &psr_state);
+ dmub_psr_get_state(dmub, &state);
if (enable) {
- if (psr_state != 0)
+ if (state != PSR_STATE0)
break;
} else {
- if (psr_state == 0)
+ if (state == PSR_STATE0)
break;
}
@@ -169,12 +176,12 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level)
{
union dmub_rb_cmd cmd;
- uint32_t psr_state = 0;
+ enum dc_psr_state state = PSR_STATE0;
struct dc_context *dc = dmub->ctx;
- dmub_psr_get_state(dmub, &psr_state);
+ dmub_psr_get_state(dmub, &state);
- if (psr_state == 0)
+ if (state == PSR_STATE0)
return;
cmd.psr_set_level.header.type = DMUB_CMD__PSR;
@@ -269,11 +276,29 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
return true;
}
+/**
+ * Send command to PSR to force static ENTER and ignore all state changes until exit
+ */
+static void dmub_psr_force_static(struct dmub_psr *dmub)
+{
+ union dmub_rb_cmd cmd;
+ struct dc_context *dc = dmub->ctx;
+
+ cmd.psr_force_static.header.type = DMUB_CMD__PSR;
+ cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
+ cmd.psr_enable.header.payload_bytes = 0;
+
+ dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
+ dc_dmub_srv_cmd_execute(dc->dmub_srv);
+ dc_dmub_srv_wait_idle(dc->dmub_srv);
+}
+
static const struct dmub_psr_funcs psr_funcs = {
.psr_copy_settings = dmub_psr_copy_settings,
.psr_enable = dmub_psr_enable,
.psr_get_state = dmub_psr_get_state,
.psr_set_level = dmub_psr_set_level,
+ .psr_force_static = dmub_psr_force_static,
};
/**
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h
index dc121ed92d2e..4e113ac5a56b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h
@@ -37,8 +37,9 @@ struct dmub_psr {
struct dmub_psr_funcs {
bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context);
void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait);
- void (*psr_get_state)(struct dmub_psr *dmub, uint32_t *psr_state);
+ void (*psr_get_state)(struct dmub_psr *dmub, enum dc_psr_state *dc_psr_state);
void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level);
+ void (*psr_force_static)(struct dmub_psr *dmub);
};
struct dmub_psr *dmub_psr_create(struct dc_context *ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
index 5315f1f86b21..69d9fbfb4bec 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
@@ -66,7 +66,7 @@ struct dmcu_funcs {
bool (*setup_psr)(struct dmcu *dmcu,
struct dc_link *link,
struct psr_context *psr_context);
- void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state);
+ void (*get_psr_state)(struct dmcu *dmcu, enum dc_psr_state *dc_psr_state);
void (*set_psr_wait_loop)(struct dmcu *dmcu,
unsigned int wait_loop_number);
void (*get_psr_wait_loop)(struct dmcu *dmcu,
--
2.25.1
More information about the amd-gfx
mailing list