-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Compositor control all the input sub-device (VID, GDP) and the mixer(s). It is the main entry point for composition. Layer interface is used to control the abstracted layers. Add debug in mixer and GDP. Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Reviewed-by: Rob Clark <robdclark@gmail.com>
- Loading branch information
Benjamin Gaignard
committed
Jul 30, 2014
1 parent
e21e219
commit d219673
Showing
7 changed files
with
566 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
config DRM_STI | ||
tristate "DRM Support for STMicroelectronics SoC stiH41x Series" | ||
depends on DRM && (SOC_STIH415 || SOC_STIH416 || ARCH_MULTIPLATFORM) | ||
select DRM_KMS_CMA_HELPER | ||
help | ||
Choose this option to enable DRM on STM stiH41x chipset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
/* | ||
* Copyright (C) STMicroelectronics SA 2014 | ||
* Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | ||
* Fabien Dessenne <fabien.dessenne@st.com> | ||
* for STMicroelectronics. | ||
* License terms: GNU General Public License (GPL), version 2 | ||
*/ | ||
|
||
#include <linux/component.h> | ||
#include <linux/module.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/reset.h> | ||
|
||
#include <drm/drmP.h> | ||
|
||
#include "sti_compositor.h" | ||
#include "sti_gdp.h" | ||
#include "sti_vtg.h" | ||
|
||
/* | ||
* stiH407 compositor properties | ||
*/ | ||
struct sti_compositor_data stih407_compositor_data = { | ||
.nb_subdev = 6, | ||
.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} | ||
}, | ||
}; | ||
|
||
/* | ||
* stiH416 compositor properties | ||
* Note: | ||
* on stih416 MIXER_AUX has a different base address from MIXER_MAIN | ||
* Moreover, GDPx is different for Main and Aux Mixer. So this subdev map does | ||
* not fit for stiH416 if we want to enable the MIXER_AUX. | ||
*/ | ||
struct sti_compositor_data stih416_compositor_data = { | ||
.nb_subdev = 3, | ||
.subdev_desc = { | ||
{STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100}, | ||
{STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200}, | ||
{STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00} | ||
}, | ||
}; | ||
|
||
static int sti_compositor_init_subdev(struct sti_compositor *compo, | ||
struct sti_compositor_subdev_descriptor *desc, | ||
unsigned int array_size) | ||
{ | ||
unsigned int i, mixer_id = 0, layer_id = 0; | ||
|
||
for (i = 0; i < array_size; i++) { | ||
switch (desc[i].type) { | ||
case STI_MIXER_MAIN_SUBDEV: | ||
case STI_MIXER_AUX_SUBDEV: | ||
compo->mixer[mixer_id++] = | ||
sti_mixer_create(compo->dev, desc[i].id, | ||
compo->regs + desc[i].offset); | ||
break; | ||
case STI_GPD_SUBDEV: | ||
case STI_VID_SUBDEV: | ||
compo->layer[layer_id++] = | ||
sti_layer_create(compo->dev, desc[i].id, | ||
compo->regs + desc[i].offset); | ||
break; | ||
/* case STI_CURSOR_SUBDEV : TODO */ | ||
default: | ||
DRM_ERROR("Unknow subdev compoment type\n"); | ||
return 1; | ||
} | ||
|
||
} | ||
compo->nb_mixers = mixer_id; | ||
compo->nb_layers = layer_id; | ||
|
||
return 0; | ||
} | ||
|
||
static int sti_compositor_bind(struct device *dev, struct device *master, | ||
void *data) | ||
{ | ||
struct sti_compositor *compo = dev_get_drvdata(dev); | ||
struct drm_device *drm_dev = data; | ||
unsigned int i, crtc = 0, plane = 0; | ||
|
||
drm_vblank_init(drm_dev, crtc); | ||
/* Allow usage of vblank without having to call drm_irq_install */ | ||
drm_dev->irq_enabled = 1; | ||
|
||
|
||
DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n", | ||
crtc, plane); | ||
DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n"); | ||
|
||
return 0; | ||
} | ||
|
||
static void sti_compositor_unbind(struct device *dev, struct device *master, | ||
void *data) | ||
{ | ||
/* do nothing */ | ||
} | ||
|
||
static const struct component_ops sti_compositor_ops = { | ||
.bind = sti_compositor_bind, | ||
.unbind = sti_compositor_unbind, | ||
}; | ||
|
||
static const struct of_device_id compositor_of_match[] = { | ||
{ | ||
.compatible = "st,stih416-compositor", | ||
.data = &stih416_compositor_data, | ||
}, { | ||
.compatible = "st,stih407-compositor", | ||
.data = &stih407_compositor_data, | ||
}, { | ||
/* end node */ | ||
} | ||
}; | ||
MODULE_DEVICE_TABLE(of, compositor_of_match); | ||
|
||
static int sti_compositor_probe(struct platform_device *pdev) | ||
{ | ||
struct device *dev = &pdev->dev; | ||
struct device_node *np = dev->of_node; | ||
struct device_node *vtg_np; | ||
struct sti_compositor *compo; | ||
struct resource *res; | ||
int err; | ||
|
||
compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL); | ||
if (!compo) { | ||
DRM_ERROR("Failed to allocate compositor context\n"); | ||
return -ENOMEM; | ||
} | ||
compo->dev = dev; | ||
|
||
/* populate data structure depending on compatibility */ | ||
BUG_ON(!of_match_node(compositor_of_match, np)->data); | ||
|
||
memcpy(&compo->data, of_match_node(compositor_of_match, np)->data, | ||
sizeof(struct sti_compositor_data)); | ||
|
||
/* Get Memory ressources */ | ||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
if (res == NULL) { | ||
DRM_ERROR("Get memory resource failed\n"); | ||
return -ENXIO; | ||
} | ||
compo->regs = devm_ioremap(dev, res->start, resource_size(res)); | ||
if (compo->regs == NULL) { | ||
DRM_ERROR("Register mapping failed\n"); | ||
return -ENXIO; | ||
} | ||
|
||
/* Get clock resources */ | ||
compo->clk_compo_main = devm_clk_get(dev, "compo_main"); | ||
if (IS_ERR(compo->clk_compo_main)) { | ||
DRM_ERROR("Cannot get compo_main clock\n"); | ||
return PTR_ERR(compo->clk_compo_main); | ||
} | ||
|
||
compo->clk_compo_aux = devm_clk_get(dev, "compo_aux"); | ||
if (IS_ERR(compo->clk_compo_aux)) { | ||
DRM_ERROR("Cannot get compo_aux clock\n"); | ||
return PTR_ERR(compo->clk_compo_aux); | ||
} | ||
|
||
compo->clk_pix_main = devm_clk_get(dev, "pix_main"); | ||
if (IS_ERR(compo->clk_pix_main)) { | ||
DRM_ERROR("Cannot get pix_main clock\n"); | ||
return PTR_ERR(compo->clk_pix_main); | ||
} | ||
|
||
compo->clk_pix_aux = devm_clk_get(dev, "pix_aux"); | ||
if (IS_ERR(compo->clk_pix_aux)) { | ||
DRM_ERROR("Cannot get pix_aux clock\n"); | ||
return PTR_ERR(compo->clk_pix_aux); | ||
} | ||
|
||
/* Get reset resources */ | ||
compo->rst_main = devm_reset_control_get(dev, "compo-main"); | ||
/* Take compo main out of reset */ | ||
if (!IS_ERR(compo->rst_main)) | ||
reset_control_deassert(compo->rst_main); | ||
|
||
compo->rst_aux = devm_reset_control_get(dev, "compo-aux"); | ||
/* Take compo aux out of reset */ | ||
if (!IS_ERR(compo->rst_aux)) | ||
reset_control_deassert(compo->rst_aux); | ||
|
||
vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0); | ||
if (vtg_np) | ||
compo->vtg_main = of_vtg_find(vtg_np); | ||
|
||
vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1); | ||
if (vtg_np) | ||
compo->vtg_aux = of_vtg_find(vtg_np); | ||
|
||
/* Initialize compositor subdevices */ | ||
err = sti_compositor_init_subdev(compo, compo->data.subdev_desc, | ||
compo->data.nb_subdev); | ||
if (err) | ||
return err; | ||
|
||
platform_set_drvdata(pdev, compo); | ||
|
||
return component_add(&pdev->dev, &sti_compositor_ops); | ||
} | ||
|
||
static int sti_compositor_remove(struct platform_device *pdev) | ||
{ | ||
component_del(&pdev->dev, &sti_compositor_ops); | ||
return 0; | ||
} | ||
|
||
static struct platform_driver sti_compositor_driver = { | ||
.driver = { | ||
.name = "sti-compositor", | ||
.owner = THIS_MODULE, | ||
.of_match_table = compositor_of_match, | ||
}, | ||
.probe = sti_compositor_probe, | ||
.remove = sti_compositor_remove, | ||
}; | ||
|
||
module_platform_driver(sti_compositor_driver); | ||
|
||
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); | ||
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Copyright (C) STMicroelectronics SA 2014 | ||
* Authors: Benjamin Gaignard <benjamin.gaignard@st.com> | ||
* Fabien Dessenne <fabien.dessenne@st.com> | ||
* for STMicroelectronics. | ||
* License terms: GNU General Public License (GPL), version 2 | ||
*/ | ||
|
||
#ifndef _STI_COMPOSITOR_H_ | ||
#define _STI_COMPOSITOR_H_ | ||
|
||
#include <linux/clk.h> | ||
#include <linux/kernel.h> | ||
|
||
#include "sti_layer.h" | ||
#include "sti_mixer.h" | ||
|
||
#define WAIT_NEXT_VSYNC_MS 50 /*ms*/ | ||
|
||
#define STI_MAX_LAYER 8 | ||
#define STI_MAX_MIXER 2 | ||
|
||
enum sti_compositor_subdev_type { | ||
STI_MIXER_MAIN_SUBDEV, | ||
STI_MIXER_AUX_SUBDEV, | ||
STI_GPD_SUBDEV, | ||
STI_VID_SUBDEV, | ||
STI_CURSOR_SUBDEV, | ||
}; | ||
|
||
struct sti_compositor_subdev_descriptor { | ||
enum sti_compositor_subdev_type type; | ||
int id; | ||
unsigned int offset; | ||
}; | ||
|
||
/** | ||
* STI Compositor data structure | ||
* | ||
* @nb_subdev: number of subdevices supported by the compositor | ||
* @subdev_desc: subdev list description | ||
*/ | ||
#define MAX_SUBDEV 9 | ||
struct sti_compositor_data { | ||
unsigned int nb_subdev; | ||
struct sti_compositor_subdev_descriptor subdev_desc[MAX_SUBDEV]; | ||
}; | ||
|
||
/** | ||
* STI Compositor structure | ||
* | ||
* @dev: driver device | ||
* @regs: registers (main) | ||
* @data: device data | ||
* @clk_compo_main: clock for main compo | ||
* @clk_compo_aux: clock for aux compo | ||
* @clk_pix_main: pixel clock for main path | ||
* @clk_pix_aux: pixel clock for aux path | ||
* @rst_main: reset control of the main path | ||
* @rst_aux: reset control of the aux path | ||
* @mixer: array of mixers | ||
* @vtg_main: vtg for main data path | ||
* @vtg_aux: vtg for auxillary data path | ||
* @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 { | ||
struct device *dev; | ||
void __iomem *regs; | ||
struct sti_compositor_data data; | ||
struct clk *clk_compo_main; | ||
struct clk *clk_compo_aux; | ||
struct clk *clk_pix_main; | ||
struct clk *clk_pix_aux; | ||
struct reset_control *rst_main; | ||
struct reset_control *rst_aux; | ||
struct sti_mixer *mixer[STI_MAX_MIXER]; | ||
struct sti_vtg *vtg_main; | ||
struct sti_vtg *vtg_aux; | ||
struct sti_layer *layer[STI_MAX_LAYER]; | ||
int nb_mixers; | ||
int nb_layers; | ||
bool enable; | ||
struct notifier_block vtg_vblank_nb; | ||
}; | ||
|
||
#endif |
Oops, something went wrong.