提交 f20780f3 编写于 作者: D Dave Airlie

Merge branch 'drm-sti-next-2015-11-03' of...

Merge branch 'drm-sti-next-2015-11-03' of http://git.linaro.org/people/benjamin.gaignard/kernel into drm-next

sti/drm changes

Add better support for firmware loading
lots of fixes.

* 'drm-sti-next-2015-11-03' of http://git.linaro.org/people/benjamin.gaignard/kernel:
  drm/sti: load HQVDP firmware the first time HQVDP's plane is used
  drm/sti: fix typo issue in sti_mode_config_init
  drm/sti: set mixer background color through module param
  drm/sti: Remove local fbdev emulation Kconfig option
  drm/sti: remove redundant sign extensions
  drm/sti: hdmi use of_get_i2c_adapter_by_node interface
  drm/sti: hdmi fix i2c adapter device refcounting
  drm/sti: Do not export symbols
  drm/sti: Build monolithic driver
  drm/sti: Use drm_crtc_vblank_*() API
  drm/sti: Store correct CRTC index in events
  drm/sti: Select FW_LOADER
  drm/sti: Constify function pointer structs
...@@ -6,12 +6,6 @@ config DRM_STI ...@@ -6,12 +6,6 @@ config DRM_STI
select DRM_GEM_CMA_HELPER select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER select DRM_KMS_CMA_HELPER
select DRM_PANEL select DRM_PANEL
select FW_LOADER_USER_HELPER_FALLBACK select FW_LOADER
help help
Choose this option to enable DRM on STM stiH41x chipset Choose this option to enable DRM on STM stiH41x chipset
config DRM_STI_FBDEV
bool "DRM frame buffer device for STMicroelectronics SoC stiH41x Serie"
depends on DRM_STI
help
Choose this option to enable FBDEV on top of DRM for STM stiH41x chipset
sticompositor-y := \ sti-drm-y := \
sti_mixer.o \ sti_mixer.o \
sti_gdp.o \ sti_gdp.o \
sti_vid.o \ sti_vid.o \
sti_cursor.o \ sti_cursor.o \
sti_compositor.o \ sti_compositor.o \
sti_crtc.o \ sti_crtc.o \
sti_plane.o sti_plane.o \
sti_crtc.o \
stihdmi-y := sti_hdmi.o \ sti_plane.o \
sti_hdmi.o \
sti_hdmi_tx3g0c55phy.o \ sti_hdmi_tx3g0c55phy.o \
sti_hdmi_tx3g4c28phy.o \ sti_hdmi_tx3g4c28phy.o \
sti_dvo.o \
stidvo-y := sti_dvo.o \ sti_awg_utils.o \
sti_awg_utils.o
obj-$(CONFIG_DRM_STI) = \
sti_vtg.o \ sti_vtg.o \
sti_vtac.o \ sti_vtac.o \
stihdmi.o \
sti_hda.o \ sti_hda.o \
sti_tvout.o \ sti_tvout.o \
sticompositor.o \
sti_hqvdp.o \ sti_hqvdp.o \
stidvo.o \
sti_drv.o sti_drv.o
obj-$(CONFIG_DRM_STI) = sti-drm.o
...@@ -65,7 +65,6 @@ static int awg_generate_instr(enum opcode opcode, ...@@ -65,7 +65,6 @@ static int awg_generate_instr(enum opcode opcode,
mux = 0; mux = 0;
data_enable = 0; data_enable = 0;
arg = (arg << 22) >> 22;
arg &= (0x3ff); arg &= (0x3ff);
break; break;
case REPEAT: case REPEAT:
...@@ -77,14 +76,12 @@ static int awg_generate_instr(enum opcode opcode, ...@@ -77,14 +76,12 @@ static int awg_generate_instr(enum opcode opcode,
mux = 0; mux = 0;
data_enable = 0; data_enable = 0;
arg = (arg << 22) >> 22;
arg &= (0x3ff); arg &= (0x3ff);
break; break;
case JUMP: case JUMP:
mux = 0; mux = 0;
data_enable = 0; data_enable = 0;
arg |= 0x40; /* for jump instruction 7th bit is 1 */ arg |= 0x40; /* for jump instruction 7th bit is 1 */
arg = (arg << 22) >> 22;
arg &= 0x3ff; arg &= 0x3ff;
break; break;
case STOP: case STOP:
...@@ -94,7 +91,6 @@ static int awg_generate_instr(enum opcode opcode, ...@@ -94,7 +91,6 @@ static int awg_generate_instr(enum opcode opcode,
case RPTSET: case RPTSET:
case RPLSET: case RPLSET:
case HOLD: case HOLD:
arg = (arg << 24) >> 24;
arg &= (0x0ff); arg &= (0x0ff);
break; break;
default: default:
......
...@@ -263,7 +263,7 @@ static int sti_compositor_remove(struct platform_device *pdev) ...@@ -263,7 +263,7 @@ static int sti_compositor_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct platform_driver sti_compositor_driver = { struct platform_driver sti_compositor_driver = {
.driver = { .driver = {
.name = "sti-compositor", .name = "sti-compositor",
.of_match_table = compositor_of_match, .of_match_table = compositor_of_match,
...@@ -272,8 +272,6 @@ static struct platform_driver sti_compositor_driver = { ...@@ -272,8 +272,6 @@ static struct platform_driver sti_compositor_driver = {
.remove = sti_compositor_remove, .remove = sti_compositor_remove,
}; };
module_platform_driver(sti_compositor_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -226,7 +226,7 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, ...@@ -226,7 +226,7 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
} }
} }
static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
.enable = sti_crtc_enable, .enable = sti_crtc_enable,
.disable = sti_crtc_disabling, .disable = sti_crtc_disabling,
.mode_fixup = sti_crtc_mode_fixup, .mode_fixup = sti_crtc_mode_fixup,
...@@ -254,15 +254,17 @@ static int sti_crtc_set_property(struct drm_crtc *crtc, ...@@ -254,15 +254,17 @@ static int sti_crtc_set_property(struct drm_crtc *crtc,
int sti_crtc_vblank_cb(struct notifier_block *nb, int sti_crtc_vblank_cb(struct notifier_block *nb,
unsigned long event, void *data) unsigned long event, void *data)
{ {
struct drm_device *drm_dev;
struct sti_compositor *compo = struct sti_compositor *compo =
container_of(nb, struct sti_compositor, vtg_vblank_nb); container_of(nb, struct sti_compositor, vtg_vblank_nb);
int *crtc = data; struct drm_crtc *crtc = data;
struct sti_mixer *mixer;
unsigned long flags; unsigned long flags;
struct sti_private *priv; struct sti_private *priv;
unsigned int pipe;
drm_dev = compo->mixer[*crtc]->drm_crtc.dev; priv = crtc->dev->dev_private;
priv = drm_dev->dev_private; pipe = drm_crtc_index(crtc);
mixer = compo->mixer[pipe];
if ((event != VTG_TOP_FIELD_EVENT) && if ((event != VTG_TOP_FIELD_EVENT) &&
(event != VTG_BOTTOM_FIELD_EVENT)) { (event != VTG_BOTTOM_FIELD_EVENT)) {
...@@ -270,30 +272,30 @@ int sti_crtc_vblank_cb(struct notifier_block *nb, ...@@ -270,30 +272,30 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
return -EINVAL; return -EINVAL;
} }
drm_handle_vblank(drm_dev, *crtc); drm_crtc_handle_vblank(crtc);
spin_lock_irqsave(&drm_dev->event_lock, flags); spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (compo->mixer[*crtc]->pending_event) { if (mixer->pending_event) {
drm_send_vblank_event(drm_dev, -1, drm_crtc_send_vblank_event(crtc, mixer->pending_event);
compo->mixer[*crtc]->pending_event); drm_crtc_vblank_put(crtc);
drm_vblank_put(drm_dev, *crtc); mixer->pending_event = NULL;
compo->mixer[*crtc]->pending_event = NULL;
} }
spin_unlock_irqrestore(&drm_dev->event_lock, flags); spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
if (compo->mixer[*crtc]->status == STI_MIXER_DISABLING) { if (mixer->status == STI_MIXER_DISABLING) {
struct drm_plane *p; struct drm_plane *p;
/* Disable mixer only if all overlay planes (GDP and VDP) /* Disable mixer only if all overlay planes (GDP and VDP)
* are disabled */ * are disabled */
list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) { list_for_each_entry(p, &crtc->dev->mode_config.plane_list,
head) {
struct sti_plane *plane = to_sti_plane(p); struct sti_plane *plane = to_sti_plane(p);
if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP) if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
if (plane->status != STI_PLANE_DISABLED) if (plane->status != STI_PLANE_DISABLED)
return 0; return 0;
} }
sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc); sti_crtc_disable(crtc);
} }
return 0; return 0;
...@@ -304,25 +306,26 @@ int sti_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe) ...@@ -304,25 +306,26 @@ int sti_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
struct sti_private *dev_priv = dev->dev_private; struct sti_private *dev_priv = dev->dev_private;
struct sti_compositor *compo = dev_priv->compo; struct sti_compositor *compo = dev_priv->compo;
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
if (sti_vtg_register_client(pipe == STI_MIXER_MAIN ? if (sti_vtg_register_client(pipe == STI_MIXER_MAIN ?
compo->vtg_main : compo->vtg_aux, compo->vtg_main : compo->vtg_aux,
vtg_vblank_nb, pipe)) { vtg_vblank_nb, crtc)) {
DRM_ERROR("Cannot register VTG notifier\n"); DRM_ERROR("Cannot register VTG notifier\n");
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
EXPORT_SYMBOL(sti_crtc_enable_vblank);
void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe) void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
{ {
struct sti_private *priv = drm_dev->dev_private; struct sti_private *priv = drm_dev->dev_private;
struct sti_compositor *compo = priv->compo; struct sti_compositor *compo = priv->compo;
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
...@@ -332,13 +335,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe) ...@@ -332,13 +335,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
/* free the resources of the pending requests */ /* free the resources of the pending requests */
if (compo->mixer[pipe]->pending_event) { if (compo->mixer[pipe]->pending_event) {
drm_vblank_put(drm_dev, pipe); drm_crtc_vblank_put(crtc);
compo->mixer[pipe]->pending_event = NULL; compo->mixer[pipe]->pending_event = NULL;
} }
} }
EXPORT_SYMBOL(sti_crtc_disable_vblank);
static struct drm_crtc_funcs sti_crtc_funcs = { static const struct drm_crtc_funcs sti_crtc_funcs = {
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip, .page_flip = drm_atomic_helper_page_flip,
.destroy = sti_crtc_destroy, .destroy = sti_crtc_destroy,
...@@ -357,7 +359,6 @@ bool sti_crtc_is_main(struct drm_crtc *crtc) ...@@ -357,7 +359,6 @@ bool sti_crtc_is_main(struct drm_crtc *crtc)
return false; return false;
} }
EXPORT_SYMBOL(sti_crtc_is_main);
int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer, int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
struct drm_plane *primary, struct drm_plane *cursor) struct drm_plane *primary, struct drm_plane *cursor)
......
...@@ -107,7 +107,7 @@ static int sti_atomic_commit(struct drm_device *drm, ...@@ -107,7 +107,7 @@ static int sti_atomic_commit(struct drm_device *drm,
return 0; return 0;
} }
static struct drm_mode_config_funcs sti_mode_config_funcs = { static const struct drm_mode_config_funcs sti_mode_config_funcs = {
.fb_create = drm_fb_cma_create, .fb_create = drm_fb_cma_create,
.atomic_check = drm_atomic_helper_check, .atomic_check = drm_atomic_helper_check,
.atomic_commit = sti_atomic_commit, .atomic_commit = sti_atomic_commit,
...@@ -123,8 +123,8 @@ static void sti_mode_config_init(struct drm_device *dev) ...@@ -123,8 +123,8 @@ static void sti_mode_config_init(struct drm_device *dev)
* this value would be used to check framebuffer size limitation * this value would be used to check framebuffer size limitation
* at drm_mode_addfb(). * at drm_mode_addfb().
*/ */
dev->mode_config.max_width = STI_MAX_FB_HEIGHT; dev->mode_config.max_width = STI_MAX_FB_WIDTH;
dev->mode_config.max_height = STI_MAX_FB_WIDTH; dev->mode_config.max_height = STI_MAX_FB_HEIGHT;
dev->mode_config.funcs = &sti_mode_config_funcs; dev->mode_config.funcs = &sti_mode_config_funcs;
} }
...@@ -160,11 +160,10 @@ static int sti_load(struct drm_device *dev, unsigned long flags) ...@@ -160,11 +160,10 @@ static int sti_load(struct drm_device *dev, unsigned long flags)
drm_mode_config_reset(dev); drm_mode_config_reset(dev);
#ifdef CONFIG_DRM_STI_FBDEV
drm_fbdev_cma_init(dev, 32, drm_fbdev_cma_init(dev, 32,
dev->mode_config.num_crtc, dev->mode_config.num_crtc,
dev->mode_config.num_connector); dev->mode_config.num_connector);
#endif
return 0; return 0;
} }
...@@ -287,7 +286,29 @@ static struct platform_driver sti_platform_driver = { ...@@ -287,7 +286,29 @@ static struct platform_driver sti_platform_driver = {
}, },
}; };
module_platform_driver(sti_platform_driver); static struct platform_driver * const drivers[] = {
&sti_tvout_driver,
&sti_vtac_driver,
&sti_hqvdp_driver,
&sti_hdmi_driver,
&sti_hda_driver,
&sti_dvo_driver,
&sti_vtg_driver,
&sti_compositor_driver,
&sti_platform_driver,
};
static int sti_drm_init(void)
{
return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
module_init(sti_drm_init);
static void sti_drm_exit(void)
{
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
}
module_exit(sti_drm_exit);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
......
...@@ -32,4 +32,13 @@ struct sti_private { ...@@ -32,4 +32,13 @@ struct sti_private {
} commit; } commit;
}; };
extern struct platform_driver sti_tvout_driver;
extern struct platform_driver sti_vtac_driver;
extern struct platform_driver sti_hqvdp_driver;
extern struct platform_driver sti_hdmi_driver;
extern struct platform_driver sti_hda_driver;
extern struct platform_driver sti_dvo_driver;
extern struct platform_driver sti_vtg_driver;
extern struct platform_driver sti_compositor_driver;
#endif #endif
...@@ -329,7 +329,8 @@ struct drm_encoder *sti_dvo_best_encoder(struct drm_connector *connector) ...@@ -329,7 +329,8 @@ struct drm_encoder *sti_dvo_best_encoder(struct drm_connector *connector)
return dvo_connector->encoder; return dvo_connector->encoder;
} }
static struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = { static const
struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = {
.get_modes = sti_dvo_connector_get_modes, .get_modes = sti_dvo_connector_get_modes,
.mode_valid = sti_dvo_connector_mode_valid, .mode_valid = sti_dvo_connector_mode_valid,
.best_encoder = sti_dvo_best_encoder, .best_encoder = sti_dvo_best_encoder,
...@@ -364,7 +365,7 @@ static void sti_dvo_connector_destroy(struct drm_connector *connector) ...@@ -364,7 +365,7 @@ static void sti_dvo_connector_destroy(struct drm_connector *connector)
kfree(dvo_connector); kfree(dvo_connector);
} }
static struct drm_connector_funcs sti_dvo_connector_funcs = { static const struct drm_connector_funcs sti_dvo_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = sti_dvo_connector_detect, .detect = sti_dvo_connector_detect,
...@@ -557,8 +558,6 @@ struct platform_driver sti_dvo_driver = { ...@@ -557,8 +558,6 @@ struct platform_driver sti_dvo_driver = {
.remove = sti_dvo_remove, .remove = sti_dvo_remove,
}; };
module_platform_driver(sti_dvo_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -492,7 +492,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, ...@@ -492,7 +492,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
/* Register gdp callback */ /* Register gdp callback */
if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ? if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ?
compo->vtg_main : compo->vtg_aux, compo->vtg_main : compo->vtg_aux,
&gdp->vtg_field_nb, mixer->id)) { &gdp->vtg_field_nb, crtc)) {
DRM_ERROR("Cannot register VTG notifier\n"); DRM_ERROR("Cannot register VTG notifier\n");
return; return;
} }
......
...@@ -589,7 +589,8 @@ struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector) ...@@ -589,7 +589,8 @@ struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector)
return hda_connector->encoder; return hda_connector->encoder;
} }
static struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = { static const
struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
.get_modes = sti_hda_connector_get_modes, .get_modes = sti_hda_connector_get_modes,
.mode_valid = sti_hda_connector_mode_valid, .mode_valid = sti_hda_connector_mode_valid,
.best_encoder = sti_hda_best_encoder, .best_encoder = sti_hda_best_encoder,
...@@ -611,7 +612,7 @@ static void sti_hda_connector_destroy(struct drm_connector *connector) ...@@ -611,7 +612,7 @@ static void sti_hda_connector_destroy(struct drm_connector *connector)
kfree(hda_connector); kfree(hda_connector);
} }
static struct drm_connector_funcs sti_hda_connector_funcs = { static const struct drm_connector_funcs sti_hda_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = sti_hda_connector_detect, .detect = sti_hda_connector_detect,
...@@ -784,8 +785,6 @@ struct platform_driver sti_hda_driver = { ...@@ -784,8 +785,6 @@ struct platform_driver sti_hda_driver = {
.remove = sti_hda_remove, .remove = sti_hda_remove,
}; };
module_platform_driver(sti_hda_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -628,7 +628,8 @@ struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector) ...@@ -628,7 +628,8 @@ struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
return hdmi_connector->encoder; return hdmi_connector->encoder;
} }
static struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = { static const
struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
.get_modes = sti_hdmi_connector_get_modes, .get_modes = sti_hdmi_connector_get_modes,
.mode_valid = sti_hdmi_connector_mode_valid, .mode_valid = sti_hdmi_connector_mode_valid,
.best_encoder = sti_hdmi_best_encoder, .best_encoder = sti_hdmi_best_encoder,
...@@ -663,7 +664,7 @@ static void sti_hdmi_connector_destroy(struct drm_connector *connector) ...@@ -663,7 +664,7 @@ static void sti_hdmi_connector_destroy(struct drm_connector *connector)
kfree(hdmi_connector); kfree(hdmi_connector);
} }
static struct drm_connector_funcs sti_hdmi_connector_funcs = { static const struct drm_connector_funcs sti_hdmi_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = sti_hdmi_connector_detect, .detect = sti_hdmi_connector_detect,
...@@ -700,18 +701,17 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) ...@@ -700,18 +701,17 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
encoder = sti_hdmi_find_encoder(drm_dev); encoder = sti_hdmi_find_encoder(drm_dev);
if (!encoder) if (!encoder)
goto err_adapt; return -EINVAL;
connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
if (!connector) if (!connector)
goto err_adapt; return -EINVAL;
connector->hdmi = hdmi; connector->hdmi = hdmi;
bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
if (!bridge) if (!bridge)
goto err_adapt; return -EINVAL;
bridge->driver_private = hdmi; bridge->driver_private = hdmi;
bridge->funcs = &sti_hdmi_bridge_funcs; bridge->funcs = &sti_hdmi_bridge_funcs;
...@@ -748,8 +748,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) ...@@ -748,8 +748,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
drm_connector_unregister(drm_connector); drm_connector_unregister(drm_connector);
err_connector: err_connector:
drm_connector_cleanup(drm_connector); drm_connector_cleanup(drm_connector);
err_adapt:
put_device(&hdmi->ddc_adapt->dev);
return -EINVAL; return -EINVAL;
} }
...@@ -794,13 +793,10 @@ static int sti_hdmi_probe(struct platform_device *pdev) ...@@ -794,13 +793,10 @@ static int sti_hdmi_probe(struct platform_device *pdev)
ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0); ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0);
if (ddc) { if (ddc) {
hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc); hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc);
if (!hdmi->ddc_adapt) {
of_node_put(ddc);
return -EPROBE_DEFER;
}
of_node_put(ddc); of_node_put(ddc);
if (!hdmi->ddc_adapt)
return -EPROBE_DEFER;
} }
hdmi->dev = pdev->dev; hdmi->dev = pdev->dev;
...@@ -809,24 +805,29 @@ static int sti_hdmi_probe(struct platform_device *pdev) ...@@ -809,24 +805,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
if (!res) { if (!res) {
DRM_ERROR("Invalid hdmi resource\n"); DRM_ERROR("Invalid hdmi resource\n");
return -ENOMEM; ret = -ENOMEM;
goto release_adapter;
} }
hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!hdmi->regs) if (!hdmi->regs) {
return -ENOMEM; ret = -ENOMEM;
goto release_adapter;
}
if (of_device_is_compatible(np, "st,stih416-hdmi")) { if (of_device_is_compatible(np, "st,stih416-hdmi")) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"syscfg"); "syscfg");
if (!res) { if (!res) {
DRM_ERROR("Invalid syscfg resource\n"); DRM_ERROR("Invalid syscfg resource\n");
return -ENOMEM; ret = -ENOMEM;
goto release_adapter;
} }
hdmi->syscfg = devm_ioremap_nocache(dev, res->start, hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
resource_size(res)); resource_size(res));
if (!hdmi->syscfg) if (!hdmi->syscfg) {
return -ENOMEM; ret = -ENOMEM;
goto release_adapter;
}
} }
hdmi->phy_ops = (struct hdmi_phy_ops *) hdmi->phy_ops = (struct hdmi_phy_ops *)
...@@ -836,25 +837,29 @@ static int sti_hdmi_probe(struct platform_device *pdev) ...@@ -836,25 +837,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
hdmi->clk_pix = devm_clk_get(dev, "pix"); hdmi->clk_pix = devm_clk_get(dev, "pix");
if (IS_ERR(hdmi->clk_pix)) { if (IS_ERR(hdmi->clk_pix)) {
DRM_ERROR("Cannot get hdmi_pix clock\n"); DRM_ERROR("Cannot get hdmi_pix clock\n");
return PTR_ERR(hdmi->clk_pix); ret = PTR_ERR(hdmi->clk_pix);
goto release_adapter;
} }
hdmi->clk_tmds = devm_clk_get(dev, "tmds"); hdmi->clk_tmds = devm_clk_get(dev, "tmds");
if (IS_ERR(hdmi->clk_tmds)) { if (IS_ERR(hdmi->clk_tmds)) {
DRM_ERROR("Cannot get hdmi_tmds clock\n"); DRM_ERROR("Cannot get hdmi_tmds clock\n");
return PTR_ERR(hdmi->clk_tmds); ret = PTR_ERR(hdmi->clk_tmds);
goto release_adapter;
} }
hdmi->clk_phy = devm_clk_get(dev, "phy"); hdmi->clk_phy = devm_clk_get(dev, "phy");
if (IS_ERR(hdmi->clk_phy)) { if (IS_ERR(hdmi->clk_phy)) {
DRM_ERROR("Cannot get hdmi_phy clock\n"); DRM_ERROR("Cannot get hdmi_phy clock\n");
return PTR_ERR(hdmi->clk_phy); ret = PTR_ERR(hdmi->clk_phy);
goto release_adapter;
} }
hdmi->clk_audio = devm_clk_get(dev, "audio"); hdmi->clk_audio = devm_clk_get(dev, "audio");
if (IS_ERR(hdmi->clk_audio)) { if (IS_ERR(hdmi->clk_audio)) {
DRM_ERROR("Cannot get hdmi_audio clock\n"); DRM_ERROR("Cannot get hdmi_audio clock\n");
return PTR_ERR(hdmi->clk_audio); ret = PTR_ERR(hdmi->clk_audio);
goto release_adapter;
} }
hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG; hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
...@@ -867,7 +872,7 @@ static int sti_hdmi_probe(struct platform_device *pdev) ...@@ -867,7 +872,7 @@ static int sti_hdmi_probe(struct platform_device *pdev)
hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi); hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
if (ret) { if (ret) {
DRM_ERROR("Failed to register HDMI interrupt\n"); DRM_ERROR("Failed to register HDMI interrupt\n");
return ret; goto release_adapter;
} }
hdmi->reset = devm_reset_control_get(dev, "hdmi"); hdmi->reset = devm_reset_control_get(dev, "hdmi");
...@@ -878,16 +883,20 @@ static int sti_hdmi_probe(struct platform_device *pdev) ...@@ -878,16 +883,20 @@ static int sti_hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hdmi); platform_set_drvdata(pdev, hdmi);
return component_add(&pdev->dev, &sti_hdmi_ops); return component_add(&pdev->dev, &sti_hdmi_ops);
release_adapter:
i2c_put_adapter(hdmi->ddc_adapt);
return ret;
} }
static int sti_hdmi_remove(struct platform_device *pdev) static int sti_hdmi_remove(struct platform_device *pdev)
{ {
struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
if (hdmi->ddc_adapt) i2c_put_adapter(hdmi->ddc_adapt);
put_device(&hdmi->ddc_adapt->dev);
component_del(&pdev->dev, &sti_hdmi_ops); component_del(&pdev->dev, &sti_hdmi_ops);
return 0; return 0;
} }
...@@ -901,8 +910,6 @@ struct platform_driver sti_hdmi_driver = { ...@@ -901,8 +910,6 @@ struct platform_driver sti_hdmi_driver = {
.remove = sti_hdmi_remove, .remove = sti_hdmi_remove,
}; };
module_platform_driver(sti_hdmi_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -628,6 +628,153 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp) ...@@ -628,6 +628,153 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
memset(hqvdp->hqvdp_cmd, 0, size); memset(hqvdp->hqvdp_cmd, 0, size);
} }
static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
{
/* Configure Plugs (same for RD & WR) */
writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
}
/**
* sti_hqvdp_start_xp70
* @hqvdp: hqvdp pointer
*
* Run the xP70 initialization sequence
*/
static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp)
{
const struct firmware *firmware;
u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
u8 *data;
int i;
struct fw_header {
int rd_size;
int wr_size;
int pmem_size;
int dmem_size;
} *header;
DRM_DEBUG_DRIVER("\n");
if (hqvdp->xp70_initialized) {
DRM_INFO("HQVDP XP70 already initialized\n");
return;
}
/* Request firmware */
if (request_firmware(&firmware, HQVDP_FMW_NAME, hqvdp->dev)) {
DRM_ERROR("Can't get HQVDP firmware\n");
return;
}
/* Check firmware parts */
if (!firmware) {
DRM_ERROR("Firmware not available\n");
return;
}
header = (struct fw_header *)firmware->data;
if (firmware->size < sizeof(*header)) {
DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
goto out;
}
if ((sizeof(*header) + header->rd_size + header->wr_size +
header->pmem_size + header->dmem_size) != firmware->size) {
DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
sizeof(*header), header->rd_size, header->wr_size,
header->pmem_size, header->dmem_size,
firmware->size);
goto out;
}
data = (u8 *)firmware->data;
data += sizeof(*header);
fw_rd_plug = (void *)data;
data += header->rd_size;
fw_wr_plug = (void *)data;
data += header->wr_size;
fw_pmem = (void *)data;
data += header->pmem_size;
fw_dmem = (void *)data;
/* Enable clock */
if (clk_prepare_enable(hqvdp->clk))
DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
/* Reset */
writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
& STARTUP_CTRL1_RST_DONE)
break;
msleep(POLL_DELAY_MS);
}
if (i == POLL_MAX_ATTEMPT) {
DRM_ERROR("Could not reset\n");
goto out;
}
/* Init Read & Write plugs */
for (i = 0; i < header->rd_size / 4; i++)
writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
for (i = 0; i < header->wr_size / 4; i++)
writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
sti_hqvdp_init_plugs(hqvdp);
/* Authorize Idle Mode */
writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
/* Prevent VTG interruption during the boot */
writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
/* Download PMEM & DMEM */
for (i = 0; i < header->pmem_size / 4; i++)
writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
for (i = 0; i < header->dmem_size / 4; i++)
writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
/* Enable fetch */
writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
/* Wait end of boot */
for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
& INFO_XP70_FW_READY)
break;
msleep(POLL_DELAY_MS);
}
if (i == POLL_MAX_ATTEMPT) {
DRM_ERROR("Could not boot\n");
goto out;
}
/* Launch Vsync */
writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
DRM_INFO("HQVDP XP70 initialized\n");
hqvdp->xp70_initialized = true;
out:
release_firmware(firmware);
}
static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
struct drm_plane_state *oldstate) struct drm_plane_state *oldstate)
{ {
...@@ -754,6 +901,9 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, ...@@ -754,6 +901,9 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc); sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
if (first_prepare) { if (first_prepare) {
/* Start HQVDP XP70 coprocessor */
sti_hqvdp_start_xp70(hqvdp);
/* Prevent VTG shutdown */ /* Prevent VTG shutdown */
if (clk_prepare_enable(hqvdp->clk_pix_main)) { if (clk_prepare_enable(hqvdp->clk_pix_main)) {
DRM_ERROR("Failed to prepare/enable pix main clk\n"); DRM_ERROR("Failed to prepare/enable pix main clk\n");
...@@ -763,7 +913,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, ...@@ -763,7 +913,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
/* Register VTG Vsync callback to handle bottom fields */ /* Register VTG Vsync callback to handle bottom fields */
if (sti_vtg_register_client(hqvdp->vtg, if (sti_vtg_register_client(hqvdp->vtg,
&hqvdp->vtg_nb, &hqvdp->vtg_nb,
mixer->id)) { crtc)) {
DRM_ERROR("Cannot register VTG notifier\n"); DRM_ERROR("Cannot register VTG notifier\n");
return; return;
} }
...@@ -836,168 +986,16 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev, ...@@ -836,168 +986,16 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
return &hqvdp->plane.drm_plane; return &hqvdp->plane.drm_plane;
} }
static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
{
/* Configure Plugs (same for RD & WR) */
writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
}
/**
* sti_hqvdp_start_xp70
* @firmware: firmware found
* @ctxt: hqvdp structure
*
* Run the xP70 initialization sequence
*/
static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
{
struct sti_hqvdp *hqvdp = ctxt;
u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
u8 *data;
int i;
struct fw_header {
int rd_size;
int wr_size;
int pmem_size;
int dmem_size;
} *header;
DRM_DEBUG_DRIVER("\n");
if (hqvdp->xp70_initialized) {
DRM_INFO("HQVDP XP70 already initialized\n");
return;
}
/* Check firmware parts */
if (!firmware) {
DRM_ERROR("Firmware not available\n");
return;
}
header = (struct fw_header *) firmware->data;
if (firmware->size < sizeof(*header)) {
DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
goto out;
}
if ((sizeof(*header) + header->rd_size + header->wr_size +
header->pmem_size + header->dmem_size) != firmware->size) {
DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
sizeof(*header), header->rd_size, header->wr_size,
header->pmem_size, header->dmem_size,
firmware->size);
goto out;
}
data = (u8 *) firmware->data;
data += sizeof(*header);
fw_rd_plug = (void *) data;
data += header->rd_size;
fw_wr_plug = (void *) data;
data += header->wr_size;
fw_pmem = (void *) data;
data += header->pmem_size;
fw_dmem = (void *) data;
/* Enable clock */
if (clk_prepare_enable(hqvdp->clk))
DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
/* Reset */
writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
& STARTUP_CTRL1_RST_DONE)
break;
msleep(POLL_DELAY_MS);
}
if (i == POLL_MAX_ATTEMPT) {
DRM_ERROR("Could not reset\n");
goto out;
}
/* Init Read & Write plugs */
for (i = 0; i < header->rd_size / 4; i++)
writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
for (i = 0; i < header->wr_size / 4; i++)
writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
sti_hqvdp_init_plugs(hqvdp);
/* Authorize Idle Mode */
writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
/* Prevent VTG interruption during the boot */
writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
/* Download PMEM & DMEM */
for (i = 0; i < header->pmem_size / 4; i++)
writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
for (i = 0; i < header->dmem_size / 4; i++)
writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
/* Enable fetch */
writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
/* Wait end of boot */
for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
& INFO_XP70_FW_READY)
break;
msleep(POLL_DELAY_MS);
}
if (i == POLL_MAX_ATTEMPT) {
DRM_ERROR("Could not boot\n");
goto out;
}
/* Launch Vsync */
writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
DRM_INFO("HQVDP XP70 initialized\n");
hqvdp->xp70_initialized = true;
out:
release_firmware(firmware);
}
int sti_hqvdp_bind(struct device *dev, struct device *master, void *data) int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
{ {
struct sti_hqvdp *hqvdp = dev_get_drvdata(dev); struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
struct drm_plane *plane; struct drm_plane *plane;
int err;
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
hqvdp->drm_dev = drm_dev; hqvdp->drm_dev = drm_dev;
/* Request for firmware */
err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
HQVDP_FMW_NAME, hqvdp->dev,
GFP_KERNEL, hqvdp, sti_hqvdp_start_xp70);
if (err) {
DRM_ERROR("Can't get HQVDP firmware\n");
return err;
}
/* Create HQVDP plane once xp70 is initialized */ /* Create HQVDP plane once xp70 is initialized */
plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0); plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0);
if (!plane) if (!plane)
...@@ -1090,8 +1088,6 @@ struct platform_driver sti_hqvdp_driver = { ...@@ -1090,8 +1088,6 @@ struct platform_driver sti_hqvdp_driver = {
.remove = sti_hqvdp_remove, .remove = sti_hqvdp_remove,
}; };
module_platform_driver(sti_hqvdp_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -10,6 +10,11 @@ ...@@ -10,6 +10,11 @@
#include "sti_mixer.h" #include "sti_mixer.h"
#include "sti_vtg.h" #include "sti_vtg.h"
/* Module parameter to set the background color of the mixer */
static unsigned int bkg_color = 0x000000;
MODULE_PARM_DESC(bkgcolor, "Value of the background color 0xRRGGBB");
module_param_named(bkgcolor, bkg_color, int, 0644);
/* Identity: G=Y , B=Cb , R=Cr */ /* Identity: G=Y , B=Cb , R=Cr */
static const u32 mixerColorSpaceMatIdentity[] = { static const u32 mixerColorSpaceMatIdentity[] = {
0x10000000, 0x00000000, 0x10000000, 0x00001000, 0x10000000, 0x00000000, 0x10000000, 0x00001000,
...@@ -58,7 +63,6 @@ const char *sti_mixer_to_str(struct sti_mixer *mixer) ...@@ -58,7 +63,6 @@ const char *sti_mixer_to_str(struct sti_mixer *mixer)
return "<UNKNOWN MIXER>"; return "<UNKNOWN MIXER>";
} }
} }
EXPORT_SYMBOL(sti_mixer_to_str);
static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id) static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
{ {
...@@ -81,11 +85,9 @@ void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable) ...@@ -81,11 +85,9 @@ void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)
} }
static void sti_mixer_set_background_color(struct sti_mixer *mixer, static void sti_mixer_set_background_color(struct sti_mixer *mixer,
u8 red, u8 green, u8 blue) unsigned int rgb)
{ {
u32 val = (red << 16) | (green << 8) | blue; sti_mixer_reg_write(mixer, GAM_MIXER_BKC, rgb);
sti_mixer_reg_write(mixer, GAM_MIXER_BKC, val);
} }
static void sti_mixer_set_background_area(struct sti_mixer *mixer, static void sti_mixer_set_background_area(struct sti_mixer *mixer,
...@@ -175,7 +177,7 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer, ...@@ -175,7 +177,7 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer,
sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo); sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds); sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);
sti_mixer_set_background_color(mixer, 0xFF, 0, 0); sti_mixer_set_background_color(mixer, bkg_color);
sti_mixer_set_background_area(mixer, mode); sti_mixer_set_background_area(mixer, mode);
sti_mixer_set_background_status(mixer, true); sti_mixer_set_background_status(mixer, true);
......
...@@ -42,7 +42,6 @@ const char *sti_plane_to_str(struct sti_plane *plane) ...@@ -42,7 +42,6 @@ const char *sti_plane_to_str(struct sti_plane *plane)
return "<UNKNOWN PLANE>"; return "<UNKNOWN PLANE>";
} }
} }
EXPORT_SYMBOL(sti_plane_to_str);
static void sti_plane_destroy(struct drm_plane *drm_plane) static void sti_plane_destroy(struct drm_plane *drm_plane)
{ {
...@@ -108,7 +107,6 @@ void sti_plane_init_property(struct sti_plane *plane, ...@@ -108,7 +107,6 @@ void sti_plane_init_property(struct sti_plane *plane,
plane->drm_plane.base.id, plane->drm_plane.base.id,
sti_plane_to_str(plane), plane->zorder); sti_plane_to_str(plane), plane->zorder);
} }
EXPORT_SYMBOL(sti_plane_init_property);
struct drm_plane_funcs sti_plane_helpers_funcs = { struct drm_plane_funcs sti_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane, .update_plane = drm_atomic_helper_update_plane,
...@@ -119,4 +117,3 @@ struct drm_plane_funcs sti_plane_helpers_funcs = { ...@@ -119,4 +117,3 @@ struct drm_plane_funcs sti_plane_helpers_funcs = {
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
}; };
EXPORT_SYMBOL(sti_plane_helpers_funcs);
...@@ -735,8 +735,6 @@ struct platform_driver sti_tvout_driver = { ...@@ -735,8 +735,6 @@ struct platform_driver sti_tvout_driver = {
.remove = sti_tvout_remove, .remove = sti_tvout_remove,
}; };
module_platform_driver(sti_tvout_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -216,8 +216,6 @@ struct platform_driver sti_vtac_driver = { ...@@ -216,8 +216,6 @@ struct platform_driver sti_vtac_driver = {
.remove = sti_vtac_remove, .remove = sti_vtac_remove,
}; };
module_platform_driver(sti_vtac_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -79,7 +79,7 @@ LIST_HEAD(vtg_lookup); ...@@ -79,7 +79,7 @@ LIST_HEAD(vtg_lookup);
* @irq: VTG irq * @irq: VTG irq
* @type: VTG type (main or aux) * @type: VTG type (main or aux)
* @notifier_list: notifier callback * @notifier_list: notifier callback
* @crtc_id: the crtc id for vblank event * @crtc: the CRTC for vblank event
* @slave: slave vtg * @slave: slave vtg
* @link: List node to link the structure in lookup list * @link: List node to link the structure in lookup list
*/ */
...@@ -90,7 +90,7 @@ struct sti_vtg { ...@@ -90,7 +90,7 @@ struct sti_vtg {
int irq; int irq;
u32 irq_status; u32 irq_status;
struct raw_notifier_head notifier_list; struct raw_notifier_head notifier_list;
int crtc_id; struct drm_crtc *crtc;
struct sti_vtg *slave; struct sti_vtg *slave;
struct list_head link; struct list_head link;
}; };
...@@ -110,7 +110,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np) ...@@ -110,7 +110,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np)
} }
return NULL; return NULL;
} }
EXPORT_SYMBOL(of_vtg_find);
static void vtg_reset(struct sti_vtg *vtg) static void vtg_reset(struct sti_vtg *vtg)
{ {
...@@ -242,7 +241,6 @@ void sti_vtg_set_config(struct sti_vtg *vtg, ...@@ -242,7 +241,6 @@ void sti_vtg_set_config(struct sti_vtg *vtg,
else else
vtg_enable_irq(vtg); vtg_enable_irq(vtg);
} }
EXPORT_SYMBOL(sti_vtg_set_config);
/** /**
* sti_vtg_get_line_number * sti_vtg_get_line_number
...@@ -265,7 +263,6 @@ u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y) ...@@ -265,7 +263,6 @@ u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y)
return start_line + y; return start_line + y;
} }
EXPORT_SYMBOL(sti_vtg_get_line_number);
/** /**
* sti_vtg_get_pixel_number * sti_vtg_get_pixel_number
...@@ -281,18 +278,16 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x) ...@@ -281,18 +278,16 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x)
{ {
return mode.htotal - mode.hsync_start + x; return mode.htotal - mode.hsync_start + x;
} }
EXPORT_SYMBOL(sti_vtg_get_pixel_number);
int sti_vtg_register_client(struct sti_vtg *vtg, int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
struct notifier_block *nb, int crtc_id) struct drm_crtc *crtc)
{ {
if (vtg->slave) if (vtg->slave)
return sti_vtg_register_client(vtg->slave, nb, crtc_id); return sti_vtg_register_client(vtg->slave, nb, crtc);
vtg->crtc_id = crtc_id; vtg->crtc = crtc;
return raw_notifier_chain_register(&vtg->notifier_list, nb); return raw_notifier_chain_register(&vtg->notifier_list, nb);
} }
EXPORT_SYMBOL(sti_vtg_register_client);
int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb) int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
{ {
...@@ -301,7 +296,6 @@ int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb) ...@@ -301,7 +296,6 @@ int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
return raw_notifier_chain_unregister(&vtg->notifier_list, nb); return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
} }
EXPORT_SYMBOL(sti_vtg_unregister_client);
static irqreturn_t vtg_irq_thread(int irq, void *arg) static irqreturn_t vtg_irq_thread(int irq, void *arg)
{ {
...@@ -311,7 +305,7 @@ static irqreturn_t vtg_irq_thread(int irq, void *arg) ...@@ -311,7 +305,7 @@ static irqreturn_t vtg_irq_thread(int irq, void *arg)
event = (vtg->irq_status & VTG_IRQ_TOP) ? event = (vtg->irq_status & VTG_IRQ_TOP) ?
VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT; VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT;
raw_notifier_call_chain(&vtg->notifier_list, event, &vtg->crtc_id); raw_notifier_call_chain(&vtg->notifier_list, event, vtg->crtc);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -406,8 +400,6 @@ struct platform_driver sti_vtg_driver = { ...@@ -406,8 +400,6 @@ struct platform_driver sti_vtg_driver = {
.remove = vtg_remove, .remove = vtg_remove,
}; };
module_platform_driver(sti_vtg_driver);
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -17,8 +17,8 @@ struct notifier_block; ...@@ -17,8 +17,8 @@ struct notifier_block;
struct sti_vtg *of_vtg_find(struct device_node *np); struct sti_vtg *of_vtg_find(struct device_node *np);
void sti_vtg_set_config(struct sti_vtg *vtg, void sti_vtg_set_config(struct sti_vtg *vtg,
const struct drm_display_mode *mode); const struct drm_display_mode *mode);
int sti_vtg_register_client(struct sti_vtg *vtg, int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
struct notifier_block *nb, int crtc_id); struct drm_crtc *crtc);
int sti_vtg_unregister_client(struct sti_vtg *vtg, int sti_vtg_unregister_client(struct sti_vtg *vtg,
struct notifier_block *nb); struct notifier_block *nb);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册