drm/nv50/display: expose color vibrance control
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 21 Jan 2012 22:13:26 +0000 (23:13 +0100)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 13 Mar 2012 07:14:56 +0000 (17:14 +1000)
Signed-off-by: Christoph Bumiller <e0425955@student.tuwien.ac.at>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_crtc.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_evo.h

index cdae563be5bde8177741acb8886306c308c30dc7..9f9d50dbca7f7fb368dc497580be060ebee735d7 100644 (file)
@@ -519,6 +519,19 @@ nouveau_connector_set_property(struct drm_connector *connector,
                return nv_crtc->set_dither(nv_crtc, true);
        }
 
+       if (nv_crtc && nv_crtc->set_color_vibrance) {
+               /* Hue */
+               if (property == disp->vibrant_hue_property) {
+                       nv_crtc->vibrant_hue = value - 90;
+                       return nv_crtc->set_color_vibrance(nv_crtc, true);
+               }
+               /* Saturation */
+               if (property == disp->color_vibrance_property) {
+                       nv_crtc->color_vibrance = value - 100;
+                       return nv_crtc->set_color_vibrance(nv_crtc, true);
+               }
+       }
+
        if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV)
                return get_slave_funcs(encoder)->set_property(
                        encoder, connector, property, value);
@@ -1018,6 +1031,16 @@ nouveau_connector_create(struct drm_device *dev, int index)
                                              0);
        }
 
+       /* Add hue and saturation options */
+       if (disp->vibrant_hue_property)
+               drm_connector_attach_property(connector,
+                                             disp->vibrant_hue_property,
+                                             90);
+       if (disp->color_vibrance_property)
+               drm_connector_attach_property(connector,
+                                             disp->color_vibrance_property,
+                                             150);
+
        switch (nv_connector->type) {
        case DCB_CONNECTOR_VGA:
                if (dev_priv->card_type >= NV_50) {
index 686f6b4a1da344a01f42181c5e49413c6ebb1a7a..e6d0d1eb0133d888a6fe209bb81dfa404398b201 100644 (file)
@@ -35,6 +35,8 @@ struct nouveau_crtc {
        uint32_t dpms_saved_fp_control;
        uint32_t fp_users;
        int saturation;
+       int color_vibrance;
+       int vibrant_hue;
        int sharpness;
        int last_dpms;
 
@@ -67,6 +69,7 @@ struct nouveau_crtc {
 
        int (*set_dither)(struct nouveau_crtc *crtc, bool update);
        int (*set_scale)(struct nouveau_crtc *crtc, bool update);
+       int (*set_color_vibrance)(struct nouveau_crtc *crtc, bool update);
 };
 
 static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc)
index 5565e5056ba17cc53c3ed18dfd38b03ac0994a84..35acc92f647b5a2a6eed220697f0f61e0720dc30 100644 (file)
@@ -286,6 +286,20 @@ nouveau_display_create(struct drm_device *dev)
        disp->underscan_vborder_property =
                drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
 
+       if (gen == 1) {
+               disp->vibrant_hue_property =
+                       drm_property_create(dev, DRM_MODE_PROP_RANGE,
+                                           "vibrant hue", 2);
+               disp->vibrant_hue_property->values[0] = 0;
+               disp->vibrant_hue_property->values[1] = 180; /* -90..+90 */
+
+               disp->color_vibrance_property =
+                       drm_property_create(dev, DRM_MODE_PROP_RANGE,
+                                           "color vibrance", 2);
+               disp->color_vibrance_property->values[0] = 0;
+               disp->color_vibrance_property->values[1] = 200; /* -100..+100 */
+       }
+
        dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
        dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
 
index 3a69a4aabd3598acbb50d4f597ec9fa20023ddf1..4bb6aeec91f665c26aa3cdb19789cf6ec9f67a9e 100644 (file)
@@ -406,6 +406,9 @@ struct nouveau_display_engine {
        struct drm_property *underscan_property;
        struct drm_property *underscan_hborder_property;
        struct drm_property *underscan_vborder_property;
+       /* not really hue and saturation: */
+       struct drm_property *vibrant_hue_property;
+       struct drm_property *color_vibrance_property;
 };
 
 struct nouveau_gpio_engine {
index 8f6c2ace3adf5c48b40863b34b240ceca88082ea..701b927998bfbe2d10dd9931036c67213153c486 100644 (file)
@@ -170,6 +170,41 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
        return ret;
 }
 
+static int
+nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
+{
+       struct drm_device *dev = nv_crtc->base.dev;
+       struct nouveau_channel *evo = nv50_display(dev)->master;
+       int ret;
+       int adj;
+       u32 hue, vib;
+
+       NV_DEBUG_KMS(dev, "vibrance = %i, hue = %i\n",
+                    nv_crtc->color_vibrance, nv_crtc->vibrant_hue);
+
+       ret = RING_SPACE(evo, 2 + (update ? 2 : 0));
+       if (ret) {
+               NV_ERROR(dev, "no space while setting color vibrance\n");
+               return ret;
+       }
+
+       adj = (nv_crtc->color_vibrance > 0) ? 50 : 0;
+       vib = ((nv_crtc->color_vibrance * 2047 + adj) / 100) & 0xfff;
+
+       hue = ((nv_crtc->vibrant_hue * 2047) / 100) & 0xfff;
+
+       BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
+       OUT_RING  (evo, (hue << 20) | (vib << 8));
+
+       if (update) {
+               BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+               OUT_RING  (evo, 0);
+               FIRE_RING (evo);
+       }
+
+       return 0;
+}
+
 struct nouveau_connector *
 nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
 {
@@ -577,8 +612,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
        OUT_RING  (evo, fb->base.depth == 8 ?
                   NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
 
-       BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
-       OUT_RING  (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
        BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1);
        OUT_RING  (evo, (y << 16) | x);
 
@@ -661,6 +694,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
 
        nv_crtc->set_dither(nv_crtc, false);
        nv_crtc->set_scale(nv_crtc, false);
+       nv_crtc->set_color_vibrance(nv_crtc, false);
 
        return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
 }
@@ -721,6 +755,9 @@ nv50_crtc_create(struct drm_device *dev, int index)
        if (!nv_crtc)
                return -ENOMEM;
 
+       nv_crtc->color_vibrance = 50;
+       nv_crtc->vibrant_hue = 0;
+
        /* Default CLUT parameters, will be activated on the hw upon
         * first mode set.
         */
@@ -751,6 +788,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
        /* set function pointers */
        nv_crtc->set_dither = nv50_crtc_set_dither;
        nv_crtc->set_scale = nv50_crtc_set_scale;
+       nv_crtc->set_color_vibrance = nv50_crtc_set_color_vibrance;
 
        drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs);
        drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
index 3860ca62cb19f27acc062f7e0d8e8d9555647835..771d879bc834c9125194fb8c55eb12c3343222bb 100644 (file)
 #define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE                            0x00000000
 #define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE                              0x00000009
 #define NV50_EVO_CRTC_COLOR_CTRL                                     0x000008a8
-#define NV50_EVO_CRTC_COLOR_CTRL_COLOR                               0x00040000
+#define NV50_EVO_CRTC_COLOR_CTRL_VIBRANCE                            0x000fff00
+#define NV50_EVO_CRTC_COLOR_CTRL_HUE                                 0xfff00000
 #define NV50_EVO_CRTC_FB_POS                                         0x000008c0
 #define NV50_EVO_CRTC_REAL_RES                                       0x000008c8
 #define NV50_EVO_CRTC_SCALE_CENTER_OFFSET                            0x000008d4