NV50: Implement DPMS.
parent
d88616555d
commit
701011224c
|
@ -96,6 +96,43 @@ static int nv50_dac_set_clock_mode(struct nv50_output *output)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nv50_dac_set_power_mode(struct nv50_output *output, int mode)
|
||||||
|
{
|
||||||
|
struct drm_nouveau_private *dev_priv = output->dev->dev_private;
|
||||||
|
uint32_t val;
|
||||||
|
int or = nv50_output_or_offset(output);
|
||||||
|
|
||||||
|
NV50_DEBUG("or %d\n", or);
|
||||||
|
|
||||||
|
/* wait for it to be done */
|
||||||
|
while (NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)) & NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING);
|
||||||
|
|
||||||
|
val = NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)) & ~0x7F;
|
||||||
|
|
||||||
|
if (mode != DPMSModeOn)
|
||||||
|
val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_BLANKED;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case DPMSModeStandby:
|
||||||
|
val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_HSYNC_OFF;
|
||||||
|
break;
|
||||||
|
case DPMSModeSuspend:
|
||||||
|
val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_VSYNC_OFF;
|
||||||
|
break;
|
||||||
|
case DPMSModeOff:
|
||||||
|
val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_OFF;
|
||||||
|
val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_HSYNC_OFF;
|
||||||
|
val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_VSYNC_OFF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NV_WRITE(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or), val | NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int nv50_dac_destroy(struct nv50_output *output)
|
static int nv50_dac_destroy(struct nv50_output *output)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = output->dev;
|
struct drm_device *dev = output->dev;
|
||||||
|
@ -172,6 +209,7 @@ int nv50_dac_create(struct drm_device *dev, int dcb_entry)
|
||||||
output->validate_mode = nv50_dac_validate_mode;
|
output->validate_mode = nv50_dac_validate_mode;
|
||||||
output->execute_mode = nv50_dac_execute_mode;
|
output->execute_mode = nv50_dac_execute_mode;
|
||||||
output->set_clock_mode = nv50_dac_set_clock_mode;
|
output->set_clock_mode = nv50_dac_set_clock_mode;
|
||||||
|
output->set_power_mode = nv50_dac_set_power_mode;
|
||||||
output->detect = NULL; /* TODO */
|
output->detect = NULL; /* TODO */
|
||||||
output->destroy = nv50_dac_destroy;
|
output->destroy = nv50_dac_destroy;
|
||||||
|
|
||||||
|
|
|
@ -640,6 +640,18 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
|
||||||
/* next line changes crtc, so putting it here is important */
|
/* next line changes crtc, so putting it here is important */
|
||||||
display->last_crtc = crtc->index;
|
display->last_crtc = crtc->index;
|
||||||
|
|
||||||
|
/* this is executed immediately */
|
||||||
|
list_for_each_entry(output, &display->outputs, head) {
|
||||||
|
if (output->crtc != crtc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rval = output->set_power_mode(output, DPMSModeOn);
|
||||||
|
if (rval != 0) {
|
||||||
|
DRM_ERROR("output set power mode failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* blank any unused crtcs */
|
/* blank any unused crtcs */
|
||||||
list_for_each_entry(crtc, &display->crtcs, head) {
|
list_for_each_entry(crtc, &display->crtcs, head) {
|
||||||
if (!(crtc_mask & (1 << crtc->index)))
|
if (!(crtc_mask & (1 << crtc->index)))
|
||||||
|
@ -654,9 +666,6 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (display)
|
|
||||||
display->update(display);
|
|
||||||
|
|
||||||
kfree(hw_mode);
|
kfree(hw_mode);
|
||||||
|
|
||||||
if (rval != 0)
|
if (rval != 0)
|
||||||
|
@ -938,12 +947,31 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool nv50_kms_connector_set_property(struct drm_connector *connector,
|
||||||
|
struct drm_property *property,
|
||||||
|
uint64_t value)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
|
|
||||||
|
if (property == dev->mode_config.dpms_property && connector->encoder) {
|
||||||
|
struct nv50_output *output = to_nv50_output(connector->encoder);
|
||||||
|
|
||||||
|
if (!output->set_power_mode(output, (int) value))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct drm_connector_funcs nv50_kms_connector_funcs = {
|
static const struct drm_connector_funcs nv50_kms_connector_funcs = {
|
||||||
.save = NULL,
|
.save = NULL,
|
||||||
.restore = NULL,
|
.restore = NULL,
|
||||||
.detect = nv50_kms_connector_detect,
|
.detect = nv50_kms_connector_detect,
|
||||||
.destroy = nv50_kms_connector_destroy,
|
.destroy = nv50_kms_connector_destroy,
|
||||||
.fill_modes = nv50_kms_connector_fill_modes,
|
.fill_modes = nv50_kms_connector_fill_modes,
|
||||||
|
.set_property = nv50_kms_connector_set_property
|
||||||
};
|
};
|
||||||
|
|
||||||
static int nv50_kms_connectors_init(struct drm_device *dev)
|
static int nv50_kms_connectors_init(struct drm_device *dev)
|
||||||
|
|
|
@ -49,6 +49,8 @@ struct nv50_output {
|
||||||
int (*validate_mode) (struct nv50_output *output, struct nouveau_hw_mode *mode);
|
int (*validate_mode) (struct nv50_output *output, struct nouveau_hw_mode *mode);
|
||||||
int (*execute_mode) (struct nv50_output *output, bool disconnect);
|
int (*execute_mode) (struct nv50_output *output, bool disconnect);
|
||||||
int (*set_clock_mode) (struct nv50_output *output);
|
int (*set_clock_mode) (struct nv50_output *output);
|
||||||
|
/* this is not a normal modeset call, it is a direct register write, so it's executed immediately */
|
||||||
|
int (*set_power_mode) (struct nv50_output *output, int mode);
|
||||||
bool (*detect) (struct nv50_output *output);
|
bool (*detect) (struct nv50_output *output);
|
||||||
int (*destroy) (struct nv50_output *output);
|
int (*destroy) (struct nv50_output *output);
|
||||||
};
|
};
|
||||||
|
|
|
@ -114,6 +114,29 @@ static int nv50_sor_set_clock_mode(struct nv50_output *output)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nv50_sor_set_power_mode(struct nv50_output *output, int mode)
|
||||||
|
{
|
||||||
|
struct drm_nouveau_private *dev_priv = output->dev->dev_private;
|
||||||
|
uint32_t val;
|
||||||
|
int or = nv50_output_or_offset(output);
|
||||||
|
|
||||||
|
NV50_DEBUG("or %d\n", nv50_output_or_offset(output));
|
||||||
|
|
||||||
|
/* wait for it to be done */
|
||||||
|
while (NV_READ(NV50_PDISPLAY_SOR_REGS_DPMS_CTRL(or)) & NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_PENDING);
|
||||||
|
|
||||||
|
val = NV_READ(NV50_PDISPLAY_SOR_REGS_DPMS_CTRL(or));
|
||||||
|
|
||||||
|
if (mode == DPMSModeOn)
|
||||||
|
val |= NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_ON;
|
||||||
|
else
|
||||||
|
val &= ~NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_ON;
|
||||||
|
|
||||||
|
NV_WRITE(NV50_PDISPLAY_SOR_REGS_DPMS_CTRL(or), val | NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_PENDING);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int nv50_sor_destroy(struct nv50_output *output)
|
static int nv50_sor_destroy(struct nv50_output *output)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = output->dev;
|
struct drm_device *dev = output->dev;
|
||||||
|
@ -194,6 +217,7 @@ int nv50_sor_create(struct drm_device *dev, int dcb_entry)
|
||||||
output->validate_mode = nv50_sor_validate_mode;
|
output->validate_mode = nv50_sor_validate_mode;
|
||||||
output->execute_mode = nv50_sor_execute_mode;
|
output->execute_mode = nv50_sor_execute_mode;
|
||||||
output->set_clock_mode = nv50_sor_set_clock_mode;
|
output->set_clock_mode = nv50_sor_set_clock_mode;
|
||||||
|
output->set_power_mode = nv50_sor_set_power_mode;
|
||||||
output->detect = NULL;
|
output->detect = NULL;
|
||||||
output->destroy = nv50_sor_destroy;
|
output->destroy = nv50_sor_destroy;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue