signed-off-by: Maxim Levitsky <[email protected]>
---
 drivers/gpu/drm/nouveau/nv50_dac.c     |   47 +++++++++++++++++++++++++++-----
 drivers/gpu/drm/nouveau/nv50_display.c |    2 +-
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c 
b/drivers/gpu/drm/nouveau/nv50_dac.c
index a0f2beb..5cc0fb2 100644
--- a/drivers/gpu/drm/nouveau/nv50_dac.c
+++ b/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -70,10 +70,12 @@ nv50_dac_detect(struct drm_encoder *encoder, struct 
drm_connector *connector)
        struct drm_device *dev = encoder->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        enum drm_connector_status status = connector_status_disconnected;
-       uint32_t dpms_state, load_pattern, load_state;
+       uint32_t dpms_state, load_pattern, load_state, clk;
        int or = nv_encoder->or;
 
-       nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001);
+       clk = nv_rd32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or));
+       nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x01);
+
        dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or));
 
        nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
@@ -115,6 +117,8 @@ nv50_dac_detect(struct drm_encoder *encoder, struct 
drm_connector *connector)
        else
                NV_DEBUG_KMS(dev, "Load was not detected on output with or 
%d\n", or);
 
+       nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), clk);
+
        return status;
 }
 
@@ -123,7 +127,7 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
        struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-       uint32_t val;
+       uint32_t val, clk;
        int or = nv_encoder->or;
 
        NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
@@ -138,9 +142,13 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode)
        }
 
        val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F;
+       clk = nv_rd32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or));
 
-       if (mode != DRM_MODE_DPMS_ON)
+       if (mode != DRM_MODE_DPMS_ON) {
                val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED;
+               clk |= 0x02;
+       } else
+               clk &= ~0x02;
 
        switch (mode) {
        case DRM_MODE_DPMS_STANDBY:
@@ -160,6 +168,9 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode)
 
        nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val |
                NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
+
+       nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), clk);
+
 }
 
 static void
@@ -292,6 +303,29 @@ nv50_dac_create(struct drm_connector *connector, struct 
dcb_entry *entry)
 {
        struct nouveau_encoder *nv_encoder;
        struct drm_encoder *encoder;
+       int type, or;
+
+       switch (entry->type) {
+       case OUTPUT_ANALOG:
+               type = DRM_MODE_ENCODER_DAC;
+               break;
+       case OUTPUT_TV:
+               type = DRM_MODE_ENCODER_TVDAC;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       or = ffs(entry->or) - 1;
+
+       if (type == DRM_MODE_ENCODER_DAC)
+               nv_wr32(connector->dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 
0x00000003);
+       else
+               nv_wr32(connector->dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 
0x80000002);
+
+       /* FIXME: add support for TV-out */
+       if (type != DRM_MODE_ENCODER_DAC)
+               return -EINVAL;
 
        nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
        if (!nv_encoder)
@@ -299,10 +333,9 @@ nv50_dac_create(struct drm_connector *connector, struct 
dcb_entry *entry)
        encoder = to_drm_encoder(nv_encoder);
 
        nv_encoder->dcb = entry;
-       nv_encoder->or = ffs(entry->or) - 1;
+       nv_encoder->or = or;
 
-       drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs,
-                        DRM_MODE_ENCODER_DAC);
+       drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs, 
type);
        drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);
 
        encoder->possible_crtcs = entry->heads;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c 
b/drivers/gpu/drm/nouveau/nv50_display.c
index 7ba28e0..c1806cb 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -185,7 +185,6 @@ nv50_display_init(struct drm_device *dev)
        for (i = 0; i < 3; i++) {
                nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 |
                        NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
-               nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001);
        }
 
        /* The precise purpose is unknown, i suspect it has something to do
@@ -359,6 +358,7 @@ nv50_display_create(struct drm_device *dev)
                        nv50_sor_create(connector, entry);
                        break;
                case OUTPUT_ANALOG:
+               case OUTPUT_TV:
                        nv50_dac_create(connector, entry);
                        break;
                default:
-- 
1.7.5.4

_______________________________________________
Nouveau mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to