drm: sti: enable auxiliary CRTC
authorBenjamin Gaignard <benjamin.gaignard@linaro.org>
Mon, 8 Dec 2014 16:32:36 +0000 (17:32 +0100)
committerBenjamin Gaignard <benjamin.gaignard@linaro.org>
Thu, 11 Dec 2014 13:00:04 +0000 (14:00 +0100)
For stih407 SoC enable the second mixer to get two CRTC.
Allow GPD planes and encoders to be connected to this new CRTC.
Cursor plane can only be set on first CRTC.
GPD clocks needed change the parent clock depending on which
CRTC GPD are used.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
drivers/gpu/drm/sti/sti_compositor.c
drivers/gpu/drm/sti/sti_compositor.h
drivers/gpu/drm/sti/sti_drm_crtc.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sti/sti_mixer.h
drivers/gpu/drm/sti/sti_tvout.c

index 390d93e9a06c18971175c0bd6164d05f2b0bdbed..bbf8462879cef54596225dd7dbe28dfff79ad3d8 100644 (file)
  * stiH407 compositor properties
  */
 struct sti_compositor_data stih407_compositor_data = {
-       .nb_subdev = 6,
+       .nb_subdev = 7,
        .subdev_desc = {
                        {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
                        {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
                        {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
                        {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
                        {STI_VID_SUBDEV, (int)STI_VID_0, 0x700},
-                       {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00}
+                       {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00},
+                       {STI_MIXER_AUX_SUBDEV, STI_MIXER_AUX, 0xD00},
        },
 };
 
@@ -102,21 +103,21 @@ static int sti_compositor_bind(struct device *dev, struct device *master,
                        enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK;
                        enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
 
-                       if (compo->mixer[crtc])
+                       if (crtc < compo->nb_mixers)
                                plane_type = DRM_PLANE_TYPE_PRIMARY;
 
                        switch (type) {
                        case STI_CUR:
                                cursor = sti_drm_plane_init(drm_dev,
                                                compo->layer[i],
-                                               (1 << crtc) - 1,
-                                               DRM_PLANE_TYPE_CURSOR);
+                                               1, DRM_PLANE_TYPE_CURSOR);
                                break;
                        case STI_GDP:
                        case STI_VID:
                                primary = sti_drm_plane_init(drm_dev,
                                                compo->layer[i],
-                                               (1 << crtc) - 1, plane_type);
+                                               (1 << compo->nb_mixers) - 1,
+                                               plane_type);
                                plane++;
                                break;
                        case STI_BCK:
@@ -124,7 +125,7 @@ static int sti_compositor_bind(struct device *dev, struct device *master,
                        }
 
                        /* The first planes are reserved for primary planes*/
-                       if (compo->mixer[crtc]) {
+                       if (crtc < compo->nb_mixers) {
                                sti_drm_crtc_init(drm_dev, compo->mixer[crtc],
                                                primary, cursor);
                                crtc++;
index 3ea19db72e0f908feb6fe26b494699f4dabc2a82..019eb44c62cc4c51923dac410f67c158613ff6f4 100644 (file)
@@ -64,7 +64,6 @@ struct sti_compositor_data {
  * @layer: array of layers
  * @nb_mixers: number of mixers for this compositor
  * @nb_layers: number of layers (GDP,VID,...) for this compositor
- * @enable: true if compositor is enable else false
  * @vtg_vblank_nb: callback for VTG VSYNC notification
  */
 struct sti_compositor {
@@ -83,7 +82,6 @@ struct sti_compositor {
        struct sti_layer *layer[STI_MAX_LAYER];
        int nb_mixers;
        int nb_layers;
-       bool enable;
        struct notifier_block vtg_vblank_nb;
 };
 
index 534cd2c810ec3c6ce5c1f39df0ad614da01e5d24..928b44fd3717e68445a06e4e3bd9be9d70e69f82 100644 (file)
@@ -28,7 +28,7 @@ static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
        struct device *dev = mixer->dev;
        struct sti_compositor *compo = dev_get_drvdata(dev);
 
-       compo->enable = true;
+       mixer->enabled = true;
 
        /* Prepare and enable the compo IP clock */
        if (mixer->id == STI_MIXER_MAIN) {
@@ -200,7 +200,7 @@ static void sti_drm_crtc_disable(struct drm_crtc *crtc)
        struct sti_compositor *compo = dev_get_drvdata(dev);
        struct sti_layer *layer;
 
-       if (!compo->enable)
+       if (!mixer->enabled)
                return;
 
        DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
@@ -237,7 +237,7 @@ static void sti_drm_crtc_disable(struct drm_crtc *crtc)
                clk_disable_unprepare(compo->clk_compo_aux);
        }
 
-       compo->enable = false;
+       mixer->enabled = false;
 }
 
 static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
@@ -399,6 +399,7 @@ bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
 
        return false;
 }
+EXPORT_SYMBOL(sti_drm_crtc_is_main);
 
 int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
                struct drm_plane *primary, struct drm_plane *cursor)
index 1b903ffb345bca28bee5bb36e99b1aa406de4c69..32448d1d1e8f264c4cccd160efacdb89472f8b99 100644 (file)
@@ -83,6 +83,8 @@ struct sti_gdp_node_list {
  *
  * @layer:             layer structure
  * @clk_pix:            pixel clock for the current gdp
+ * @clk_main_parent:    gdp parent clock if main path used
+ * @clk_aux_parent:     gdp parent clock if aux path used
  * @vtg_field_nb:       callback for VTG FIELD (top or bottom) notification
  * @is_curr_top:        true if the current node processed is the top field
  * @node_list:         array of node list
@@ -90,6 +92,8 @@ struct sti_gdp_node_list {
 struct sti_gdp {
        struct sti_layer layer;
        struct clk *clk_pix;
+       struct clk *clk_main_parent;
+       struct clk *clk_aux_parent;
        struct notifier_block vtg_field_nb;
        bool is_curr_top;
        struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK];
@@ -307,6 +311,17 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
 
                /* Set and enable gdp clock */
                if (gdp->clk_pix) {
+                       struct clk *clkp;
+                       /* According to the mixer used, the gdp pixel clock
+                        * should have a different parent clock. */
+                       if (layer->mixer_id == STI_MIXER_MAIN)
+                               clkp = gdp->clk_main_parent;
+                       else
+                               clkp = gdp->clk_aux_parent;
+
+                       if (clkp)
+                               clk_set_parent(gdp->clk_pix, clkp);
+
                        res = clk_set_rate(gdp->clk_pix, rate);
                        if (res < 0) {
                                DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
@@ -521,6 +536,14 @@ static void sti_gdp_init(struct sti_layer *layer)
                gdp->clk_pix = devm_clk_get(layer->dev, clk_name);
                if (IS_ERR(gdp->clk_pix))
                        DRM_ERROR("Cannot get %s clock\n", clk_name);
+
+               gdp->clk_main_parent = devm_clk_get(layer->dev, "main_parent");
+               if (IS_ERR(gdp->clk_main_parent))
+                       DRM_ERROR("Cannot get main_parent clock\n");
+
+               gdp->clk_aux_parent = devm_clk_get(layer->dev, "aux_parent");
+               if (IS_ERR(gdp->clk_aux_parent))
+                       DRM_ERROR("Cannot get aux_parent clock\n");
        }
 }
 
index 750e1fd5a8ce5c60226206daa16c61a1bd80197e..b97282182908f0cf77589e3e39b94c5b977a9bed 100644 (file)
@@ -23,6 +23,7 @@
  * @id: id of the mixer
  * @drm_crtc: crtc object link to the mixer
  * @pending_event: set if a flip event is pending on crtc
+ * @enabled: to know if the mixer is active or not
  */
 struct sti_mixer {
        struct device *dev;
@@ -30,6 +31,7 @@ struct sti_mixer {
        int id;
        struct drm_crtc drm_crtc;
        struct drm_pending_vblank_event *pending_event;
+       bool enabled;
 };
 
 const char *sti_mixer_to_str(struct sti_mixer *mixer);
index 604e574d726e47468ba55f43717cf73ea0777468..cb924aa2b321b3e0b499876770b86f76eb78a751 100644 (file)
@@ -16,6 +16,8 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
+#include "sti_drm_crtc.h"
+
 /* glue registers */
 #define TVO_CSC_MAIN_M0                  0x000
 #define TVO_CSC_MAIN_M1                  0x004
@@ -96,7 +98,7 @@
 
 #define TVO_SYNC_HD_DCS_SHIFT            8
 
-#define ENCODER_MAIN_CRTC_MASK           BIT(0)
+#define ENCODER_CRTC_MASK                (BIT(0) | BIT(1))
 
 /* enum listing the supported output data format */
 enum sti_tvout_video_out_type {
@@ -404,7 +406,7 @@ static void sti_hda_encoder_commit(struct drm_encoder *encoder)
 {
        struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-       tvout_hda_start(tvout, true);
+       tvout_hda_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
 }
 
 static void sti_hda_encoder_disable(struct drm_encoder *encoder)
@@ -441,7 +443,7 @@ static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev,
 
        drm_encoder = (struct drm_encoder *) encoder;
 
-       drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK;
+       drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
        drm_encoder->possible_clones = 1 << 0;
 
        drm_encoder_init(dev, drm_encoder,
@@ -456,7 +458,7 @@ static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
 {
        struct sti_tvout *tvout = to_sti_tvout(encoder);
 
-       tvout_hdmi_start(tvout, true);
+       tvout_hdmi_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
 }
 
 static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
@@ -490,7 +492,7 @@ static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev,
 
        drm_encoder = (struct drm_encoder *) encoder;
 
-       drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK;
+       drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
        drm_encoder->possible_clones = 1 << 1;
 
        drm_encoder_init(dev, drm_encoder,