diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c index 390d93e9a06c18971175c0bd6164d05f2b0bdbed..bbf8462879cef54596225dd7dbe28dfff79ad3d8 100644 --- a/drivers/gpu/drm/sti/sti_compositor.c +++ b/drivers/gpu/drm/sti/sti_compositor.c @@ -24,14 +24,15 @@ * 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++; diff --git a/drivers/gpu/drm/sti/sti_compositor.h b/drivers/gpu/drm/sti/sti_compositor.h index 3ea19db72e0f908feb6fe26b494699f4dabc2a82..019eb44c62cc4c51923dac410f67c158613ff6f4 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 { * @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; }; diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index 534cd2c810ec3c6ce5c1f39df0ad614da01e5d24..928b44fd3717e68445a06e4e3bd9be9d70e69f82 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) 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) diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 1b903ffb345bca28bee5bb36e99b1aa406de4c69..32448d1d1e8f264c4cccd160efacdb89472f8b99 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 { * * @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"); } } diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h index 750e1fd5a8ce5c60226206daa16c61a1bd80197e..b97282182908f0cf77589e3e39b94c5b977a9bed 100644 --- a/drivers/gpu/drm/sti/sti_mixer.h +++ b/drivers/gpu/drm/sti/sti_mixer.h @@ -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); diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index 604e574d726e47468ba55f43717cf73ea0777468..cb924aa2b321b3e0b499876770b86f76eb78a751 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c @@ -16,6 +16,8 @@ #include #include +#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,