forked from Minki/linux
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>
This commit is contained in:
parent
7f2d479c01
commit
5e03abc52c
@ -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++;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user