aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sti
diff options
context:
space:
mode:
authorBenjamin Gaignard <benjamin.gaignard@linaro.org>2014-12-08 11:32:36 -0500
committerBenjamin Gaignard <benjamin.gaignard@linaro.org>2014-12-11 08:00:04 -0500
commit5e03abc52cd16c852552f9eaae497c9d6e55e5d0 (patch)
tree752885efb1af30670d79b1c878e1922026bf2860 /drivers/gpu/drm/sti
parent7f2d479c017473b655b68acdf1f7335e1fac7bc5 (diff)
drm: sti: enable auxiliary CRTC
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>
Diffstat (limited to 'drivers/gpu/drm/sti')
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c15
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.h2
-rw-r--r--drivers/gpu/drm/sti/sti_drm_crtc.c7
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c23
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.h2
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c12
6 files changed, 44 insertions, 17 deletions
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index 390d93e9a06c..bbf8462879ce 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -24,14 +24,15 @@
24 * stiH407 compositor properties 24 * stiH407 compositor properties
25 */ 25 */
26struct sti_compositor_data stih407_compositor_data = { 26struct sti_compositor_data stih407_compositor_data = {
27 .nb_subdev = 6, 27 .nb_subdev = 7,
28 .subdev_desc = { 28 .subdev_desc = {
29 {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100}, 29 {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
30 {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200}, 30 {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
31 {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300}, 31 {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
32 {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400}, 32 {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
33 {STI_VID_SUBDEV, (int)STI_VID_0, 0x700}, 33 {STI_VID_SUBDEV, (int)STI_VID_0, 0x700},
34 {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00} 34 {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00},
35 {STI_MIXER_AUX_SUBDEV, STI_MIXER_AUX, 0xD00},
35 }, 36 },
36}; 37};
37 38
@@ -102,21 +103,21 @@ static int sti_compositor_bind(struct device *dev, struct device *master,
102 enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK; 103 enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK;
103 enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY; 104 enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
104 105
105 if (compo->mixer[crtc]) 106 if (crtc < compo->nb_mixers)
106 plane_type = DRM_PLANE_TYPE_PRIMARY; 107 plane_type = DRM_PLANE_TYPE_PRIMARY;
107 108
108 switch (type) { 109 switch (type) {
109 case STI_CUR: 110 case STI_CUR:
110 cursor = sti_drm_plane_init(drm_dev, 111 cursor = sti_drm_plane_init(drm_dev,
111 compo->layer[i], 112 compo->layer[i],
112 (1 << crtc) - 1, 113 1, DRM_PLANE_TYPE_CURSOR);
113 DRM_PLANE_TYPE_CURSOR);
114 break; 114 break;
115 case STI_GDP: 115 case STI_GDP:
116 case STI_VID: 116 case STI_VID:
117 primary = sti_drm_plane_init(drm_dev, 117 primary = sti_drm_plane_init(drm_dev,
118 compo->layer[i], 118 compo->layer[i],
119 (1 << crtc) - 1, plane_type); 119 (1 << compo->nb_mixers) - 1,
120 plane_type);
120 plane++; 121 plane++;
121 break; 122 break;
122 case STI_BCK: 123 case STI_BCK:
@@ -124,7 +125,7 @@ static int sti_compositor_bind(struct device *dev, struct device *master,
124 } 125 }
125 126
126 /* The first planes are reserved for primary planes*/ 127 /* The first planes are reserved for primary planes*/
127 if (compo->mixer[crtc]) { 128 if (crtc < compo->nb_mixers) {
128 sti_drm_crtc_init(drm_dev, compo->mixer[crtc], 129 sti_drm_crtc_init(drm_dev, compo->mixer[crtc],
129 primary, cursor); 130 primary, cursor);
130 crtc++; 131 crtc++;
diff --git a/drivers/gpu/drm/sti/sti_compositor.h b/drivers/gpu/drm/sti/sti_compositor.h
index 3ea19db72e0f..019eb44c62cc 100644
--- a/drivers/gpu/drm/sti/sti_compositor.h
+++ b/drivers/gpu/drm/sti/sti_compositor.h
@@ -64,7 +64,6 @@ struct sti_compositor_data {
64 * @layer: array of layers 64 * @layer: array of layers
65 * @nb_mixers: number of mixers for this compositor 65 * @nb_mixers: number of mixers for this compositor
66 * @nb_layers: number of layers (GDP,VID,...) for this compositor 66 * @nb_layers: number of layers (GDP,VID,...) for this compositor
67 * @enable: true if compositor is enable else false
68 * @vtg_vblank_nb: callback for VTG VSYNC notification 67 * @vtg_vblank_nb: callback for VTG VSYNC notification
69 */ 68 */
70struct sti_compositor { 69struct sti_compositor {
@@ -83,7 +82,6 @@ struct sti_compositor {
83 struct sti_layer *layer[STI_MAX_LAYER]; 82 struct sti_layer *layer[STI_MAX_LAYER];
84 int nb_mixers; 83 int nb_mixers;
85 int nb_layers; 84 int nb_layers;
86 bool enable;
87 struct notifier_block vtg_vblank_nb; 85 struct notifier_block vtg_vblank_nb;
88}; 86};
89 87
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c
index 534cd2c810ec..928b44fd3717 100644
--- a/drivers/gpu/drm/sti/sti_drm_crtc.c
+++ b/drivers/gpu/drm/sti/sti_drm_crtc.c
@@ -28,7 +28,7 @@ static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
28 struct device *dev = mixer->dev; 28 struct device *dev = mixer->dev;
29 struct sti_compositor *compo = dev_get_drvdata(dev); 29 struct sti_compositor *compo = dev_get_drvdata(dev);
30 30
31 compo->enable = true; 31 mixer->enabled = true;
32 32
33 /* Prepare and enable the compo IP clock */ 33 /* Prepare and enable the compo IP clock */
34 if (mixer->id == STI_MIXER_MAIN) { 34 if (mixer->id == STI_MIXER_MAIN) {
@@ -200,7 +200,7 @@ static void sti_drm_crtc_disable(struct drm_crtc *crtc)
200 struct sti_compositor *compo = dev_get_drvdata(dev); 200 struct sti_compositor *compo = dev_get_drvdata(dev);
201 struct sti_layer *layer; 201 struct sti_layer *layer;
202 202
203 if (!compo->enable) 203 if (!mixer->enabled)
204 return; 204 return;
205 205
206 DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer)); 206 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)
237 clk_disable_unprepare(compo->clk_compo_aux); 237 clk_disable_unprepare(compo->clk_compo_aux);
238 } 238 }
239 239
240 compo->enable = false; 240 mixer->enabled = false;
241} 241}
242 242
243static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { 243static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
@@ -399,6 +399,7 @@ bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
399 399
400 return false; 400 return false;
401} 401}
402EXPORT_SYMBOL(sti_drm_crtc_is_main);
402 403
403int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer, 404int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
404 struct drm_plane *primary, struct drm_plane *cursor) 405 struct drm_plane *primary, struct drm_plane *cursor)
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 1b903ffb345b..32448d1d1e8f 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -83,6 +83,8 @@ struct sti_gdp_node_list {
83 * 83 *
84 * @layer: layer structure 84 * @layer: layer structure
85 * @clk_pix: pixel clock for the current gdp 85 * @clk_pix: pixel clock for the current gdp
86 * @clk_main_parent: gdp parent clock if main path used
87 * @clk_aux_parent: gdp parent clock if aux path used
86 * @vtg_field_nb: callback for VTG FIELD (top or bottom) notification 88 * @vtg_field_nb: callback for VTG FIELD (top or bottom) notification
87 * @is_curr_top: true if the current node processed is the top field 89 * @is_curr_top: true if the current node processed is the top field
88 * @node_list: array of node list 90 * @node_list: array of node list
@@ -90,6 +92,8 @@ struct sti_gdp_node_list {
90struct sti_gdp { 92struct sti_gdp {
91 struct sti_layer layer; 93 struct sti_layer layer;
92 struct clk *clk_pix; 94 struct clk *clk_pix;
95 struct clk *clk_main_parent;
96 struct clk *clk_aux_parent;
93 struct notifier_block vtg_field_nb; 97 struct notifier_block vtg_field_nb;
94 bool is_curr_top; 98 bool is_curr_top;
95 struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK]; 99 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)
307 311
308 /* Set and enable gdp clock */ 312 /* Set and enable gdp clock */
309 if (gdp->clk_pix) { 313 if (gdp->clk_pix) {
314 struct clk *clkp;
315 /* According to the mixer used, the gdp pixel clock
316 * should have a different parent clock. */
317 if (layer->mixer_id == STI_MIXER_MAIN)
318 clkp = gdp->clk_main_parent;
319 else
320 clkp = gdp->clk_aux_parent;
321
322 if (clkp)
323 clk_set_parent(gdp->clk_pix, clkp);
324
310 res = clk_set_rate(gdp->clk_pix, rate); 325 res = clk_set_rate(gdp->clk_pix, rate);
311 if (res < 0) { 326 if (res < 0) {
312 DRM_ERROR("Cannot set rate (%dHz) for gdp\n", 327 DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
@@ -521,6 +536,14 @@ static void sti_gdp_init(struct sti_layer *layer)
521 gdp->clk_pix = devm_clk_get(layer->dev, clk_name); 536 gdp->clk_pix = devm_clk_get(layer->dev, clk_name);
522 if (IS_ERR(gdp->clk_pix)) 537 if (IS_ERR(gdp->clk_pix))
523 DRM_ERROR("Cannot get %s clock\n", clk_name); 538 DRM_ERROR("Cannot get %s clock\n", clk_name);
539
540 gdp->clk_main_parent = devm_clk_get(layer->dev, "main_parent");
541 if (IS_ERR(gdp->clk_main_parent))
542 DRM_ERROR("Cannot get main_parent clock\n");
543
544 gdp->clk_aux_parent = devm_clk_get(layer->dev, "aux_parent");
545 if (IS_ERR(gdp->clk_aux_parent))
546 DRM_ERROR("Cannot get aux_parent clock\n");
524 } 547 }
525} 548}
526 549
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h
index 750e1fd5a8ce..b97282182908 100644
--- a/drivers/gpu/drm/sti/sti_mixer.h
+++ b/drivers/gpu/drm/sti/sti_mixer.h
@@ -23,6 +23,7 @@
23 * @id: id of the mixer 23 * @id: id of the mixer
24 * @drm_crtc: crtc object link to the mixer 24 * @drm_crtc: crtc object link to the mixer
25 * @pending_event: set if a flip event is pending on crtc 25 * @pending_event: set if a flip event is pending on crtc
26 * @enabled: to know if the mixer is active or not
26 */ 27 */
27struct sti_mixer { 28struct sti_mixer {
28 struct device *dev; 29 struct device *dev;
@@ -30,6 +31,7 @@ struct sti_mixer {
30 int id; 31 int id;
31 struct drm_crtc drm_crtc; 32 struct drm_crtc drm_crtc;
32 struct drm_pending_vblank_event *pending_event; 33 struct drm_pending_vblank_event *pending_event;
34 bool enabled;
33}; 35};
34 36
35const char *sti_mixer_to_str(struct sti_mixer *mixer); 37const char *sti_mixer_to_str(struct sti_mixer *mixer);
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index 604e574d726e..cb924aa2b321 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -16,6 +16,8 @@
16#include <drm/drmP.h> 16#include <drm/drmP.h>
17#include <drm/drm_crtc_helper.h> 17#include <drm/drm_crtc_helper.h>
18 18
19#include "sti_drm_crtc.h"
20
19/* glue registers */ 21/* glue registers */
20#define TVO_CSC_MAIN_M0 0x000 22#define TVO_CSC_MAIN_M0 0x000
21#define TVO_CSC_MAIN_M1 0x004 23#define TVO_CSC_MAIN_M1 0x004
@@ -96,7 +98,7 @@
96 98
97#define TVO_SYNC_HD_DCS_SHIFT 8 99#define TVO_SYNC_HD_DCS_SHIFT 8
98 100
99#define ENCODER_MAIN_CRTC_MASK BIT(0) 101#define ENCODER_CRTC_MASK (BIT(0) | BIT(1))
100 102
101/* enum listing the supported output data format */ 103/* enum listing the supported output data format */
102enum sti_tvout_video_out_type { 104enum sti_tvout_video_out_type {
@@ -404,7 +406,7 @@ static void sti_hda_encoder_commit(struct drm_encoder *encoder)
404{ 406{
405 struct sti_tvout *tvout = to_sti_tvout(encoder); 407 struct sti_tvout *tvout = to_sti_tvout(encoder);
406 408
407 tvout_hda_start(tvout, true); 409 tvout_hda_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
408} 410}
409 411
410static void sti_hda_encoder_disable(struct drm_encoder *encoder) 412static 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,
441 443
442 drm_encoder = (struct drm_encoder *) encoder; 444 drm_encoder = (struct drm_encoder *) encoder;
443 445
444 drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK; 446 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
445 drm_encoder->possible_clones = 1 << 0; 447 drm_encoder->possible_clones = 1 << 0;
446 448
447 drm_encoder_init(dev, drm_encoder, 449 drm_encoder_init(dev, drm_encoder,
@@ -456,7 +458,7 @@ static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
456{ 458{
457 struct sti_tvout *tvout = to_sti_tvout(encoder); 459 struct sti_tvout *tvout = to_sti_tvout(encoder);
458 460
459 tvout_hdmi_start(tvout, true); 461 tvout_hdmi_start(tvout, sti_drm_crtc_is_main(encoder->crtc));
460} 462}
461 463
462static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) 464static 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,
490 492
491 drm_encoder = (struct drm_encoder *) encoder; 493 drm_encoder = (struct drm_encoder *) encoder;
492 494
493 drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK; 495 drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
494 drm_encoder->possible_clones = 1 << 1; 496 drm_encoder->possible_clones = 1 << 1;
495 497
496 drm_encoder_init(dev, drm_encoder, 498 drm_encoder_init(dev, drm_encoder,