diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 09:12:38 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-13 09:12:38 -0800 |
commit | be4773e6a11a0cc1e63c9c32f000b870e51b8c01 (patch) | |
tree | b37b326da54cdbbf6ea31e6b0184c8dfdc113f78 /drivers | |
parent | f6d07dfcb15aad199d7351d3122eabd506968daf (diff) | |
parent | f20780f3e8feec0eebcf9fb41e1d90202fffaeff (diff) |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm sti driver updates from Dave Airlie:
"The sti driver had a requirement on some patches in Greg's tree, they
are in, so I see no problems just merging this one now"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux:
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
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/sti/Kconfig | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/Makefile | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_awg_utils.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_compositor.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_crtc.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_drv.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_drv.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_dvo.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_gdp.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hda.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hqvdp.c | 306 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_mixer.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_plane.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_tvout.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_vtac.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_vtg.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_vtg.h | 4 |
18 files changed, 283 insertions, 279 deletions
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index fbccc105819b..10c1b1926e6f 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig @@ -6,12 +6,6 @@ config DRM_STI select DRM_GEM_CMA_HELPER select DRM_KMS_CMA_HELPER select DRM_PANEL - select FW_LOADER_USER_HELPER_FALLBACK + select FW_LOADER help 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 diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile index e27490b492a5..b8057620b3b3 100644 --- a/drivers/gpu/drm/sti/Makefile +++ b/drivers/gpu/drm/sti/Makefile @@ -1,26 +1,23 @@ -sticompositor-y := \ +sti-drm-y := \ sti_mixer.o \ sti_gdp.o \ sti_vid.o \ sti_cursor.o \ sti_compositor.o \ sti_crtc.o \ - sti_plane.o - -stihdmi-y := sti_hdmi.o \ + sti_plane.o \ + sti_crtc.o \ + sti_plane.o \ + sti_hdmi.o \ sti_hdmi_tx3g0c55phy.o \ sti_hdmi_tx3g4c28phy.o \ - -stidvo-y := sti_dvo.o \ - sti_awg_utils.o - -obj-$(CONFIG_DRM_STI) = \ + sti_dvo.o \ + sti_awg_utils.o \ sti_vtg.o \ sti_vtac.o \ - stihdmi.o \ sti_hda.o \ sti_tvout.o \ - sticompositor.o \ sti_hqvdp.o \ - stidvo.o \ sti_drv.o + +obj-$(CONFIG_DRM_STI) = sti-drm.o diff --git a/drivers/gpu/drm/sti/sti_awg_utils.c b/drivers/gpu/drm/sti/sti_awg_utils.c index 6029a2e3db1d..00d0698be9d3 100644 --- a/drivers/gpu/drm/sti/sti_awg_utils.c +++ b/drivers/gpu/drm/sti/sti_awg_utils.c @@ -65,7 +65,6 @@ static int awg_generate_instr(enum opcode opcode, mux = 0; data_enable = 0; - arg = (arg << 22) >> 22; arg &= (0x3ff); break; case REPEAT: @@ -77,14 +76,12 @@ static int awg_generate_instr(enum opcode opcode, mux = 0; data_enable = 0; - arg = (arg << 22) >> 22; arg &= (0x3ff); break; case JUMP: mux = 0; data_enable = 0; arg |= 0x40; /* for jump instruction 7th bit is 1 */ - arg = (arg << 22) >> 22; arg &= 0x3ff; break; case STOP: @@ -94,7 +91,6 @@ static int awg_generate_instr(enum opcode opcode, case RPTSET: case RPLSET: case HOLD: - arg = (arg << 24) >> 24; arg &= (0x0ff); break; default: diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c index c652627b1bca..afed2171beb9 100644 --- a/drivers/gpu/drm/sti/sti_compositor.c +++ b/drivers/gpu/drm/sti/sti_compositor.c @@ -263,7 +263,7 @@ static int sti_compositor_remove(struct platform_device *pdev) return 0; } -static struct platform_driver sti_compositor_driver = { +struct platform_driver sti_compositor_driver = { .driver = { .name = "sti-compositor", .of_match_table = compositor_of_match, @@ -272,8 +272,6 @@ static struct platform_driver sti_compositor_driver = { .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"); diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index 493c4a3006ad..3ae09dcd4fd8 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c @@ -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, .disable = sti_crtc_disabling, .mode_fixup = sti_crtc_mode_fixup, @@ -254,15 +254,17 @@ static int sti_crtc_set_property(struct drm_crtc *crtc, int sti_crtc_vblank_cb(struct notifier_block *nb, unsigned long event, void *data) { - struct drm_device *drm_dev; struct sti_compositor *compo = container_of(nb, struct sti_compositor, vtg_vblank_nb); - int *crtc = data; + struct drm_crtc *crtc = data; + struct sti_mixer *mixer; unsigned long flags; struct sti_private *priv; + unsigned int pipe; - drm_dev = compo->mixer[*crtc]->drm_crtc.dev; - priv = drm_dev->dev_private; + priv = crtc->dev->dev_private; + pipe = drm_crtc_index(crtc); + mixer = compo->mixer[pipe]; if ((event != VTG_TOP_FIELD_EVENT) && (event != VTG_BOTTOM_FIELD_EVENT)) { @@ -270,30 +272,30 @@ int sti_crtc_vblank_cb(struct notifier_block *nb, return -EINVAL; } - drm_handle_vblank(drm_dev, *crtc); + drm_crtc_handle_vblank(crtc); - spin_lock_irqsave(&drm_dev->event_lock, flags); - if (compo->mixer[*crtc]->pending_event) { - drm_send_vblank_event(drm_dev, -1, - compo->mixer[*crtc]->pending_event); - drm_vblank_put(drm_dev, *crtc); - compo->mixer[*crtc]->pending_event = NULL; + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (mixer->pending_event) { + drm_crtc_send_vblank_event(crtc, mixer->pending_event); + drm_crtc_vblank_put(crtc); + mixer->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; /* Disable mixer only if all overlay planes (GDP and VDP) * 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); if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP) if (plane->status != STI_PLANE_DISABLED) return 0; } - sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc); + sti_crtc_disable(crtc); } return 0; @@ -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_compositor *compo = dev_priv->compo; struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; + struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc; DRM_DEBUG_DRIVER("\n"); if (sti_vtg_register_client(pipe == STI_MIXER_MAIN ? compo->vtg_main : compo->vtg_aux, - vtg_vblank_nb, pipe)) { + vtg_vblank_nb, crtc)) { DRM_ERROR("Cannot register VTG notifier\n"); return -EINVAL; } return 0; } -EXPORT_SYMBOL(sti_crtc_enable_vblank); void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe) { struct sti_private *priv = drm_dev->dev_private; struct sti_compositor *compo = priv->compo; struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; + struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc; DRM_DEBUG_DRIVER("\n"); @@ -332,13 +335,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe) /* free the resources of the pending requests */ if (compo->mixer[pipe]->pending_event) { - drm_vblank_put(drm_dev, pipe); + drm_crtc_vblank_put(crtc); 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, .page_flip = drm_atomic_helper_page_flip, .destroy = sti_crtc_destroy, @@ -357,7 +359,6 @@ bool sti_crtc_is_main(struct drm_crtc *crtc) return false; } -EXPORT_SYMBOL(sti_crtc_is_main); int sti_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_drv.c b/drivers/gpu/drm/sti/sti_drv.c index f8469967a0bf..1469987949d8 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -107,7 +107,7 @@ static int sti_atomic_commit(struct drm_device *drm, 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, .atomic_check = drm_atomic_helper_check, .atomic_commit = sti_atomic_commit, @@ -123,8 +123,8 @@ static void sti_mode_config_init(struct drm_device *dev) * this value would be used to check framebuffer size limitation * at drm_mode_addfb(). */ - dev->mode_config.max_width = STI_MAX_FB_HEIGHT; - dev->mode_config.max_height = STI_MAX_FB_WIDTH; + dev->mode_config.max_width = STI_MAX_FB_WIDTH; + dev->mode_config.max_height = STI_MAX_FB_HEIGHT; dev->mode_config.funcs = &sti_mode_config_funcs; } @@ -160,11 +160,10 @@ static int sti_load(struct drm_device *dev, unsigned long flags) drm_mode_config_reset(dev); -#ifdef CONFIG_DRM_STI_FBDEV drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc, dev->mode_config.num_connector); -#endif + return 0; } @@ -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_DESCRIPTION("STMicroelectronics SoC DRM driver"); diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h index 9372f69e1859..30ddc20841c3 100644 --- a/drivers/gpu/drm/sti/sti_drv.h +++ b/drivers/gpu/drm/sti/sti_drv.h @@ -32,4 +32,13 @@ struct sti_private { } 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 diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index d141d645bd13..45cbe2bf7dd6 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -329,7 +329,8 @@ struct drm_encoder *sti_dvo_best_encoder(struct drm_connector *connector) 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, .mode_valid = sti_dvo_connector_mode_valid, .best_encoder = sti_dvo_best_encoder, @@ -364,7 +365,7 @@ static void sti_dvo_connector_destroy(struct drm_connector *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, .fill_modes = drm_helper_probe_single_connector_modes, .detect = sti_dvo_connector_detect, @@ -557,8 +558,6 @@ struct platform_driver sti_dvo_driver = { .remove = sti_dvo_remove, }; -module_platform_driver(sti_dvo_driver); - MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 9365670427ad..c85dc7d6b005 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -492,7 +492,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, /* Register gdp callback */ if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ? compo->vtg_main : compo->vtg_aux, - &gdp->vtg_field_nb, mixer->id)) { + &gdp->vtg_field_nb, crtc)) { DRM_ERROR("Cannot register VTG notifier\n"); return; } diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index 598cd78b0b16..d735daccd458 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -589,7 +589,8 @@ struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector) 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, .mode_valid = sti_hda_connector_mode_valid, .best_encoder = sti_hda_best_encoder, @@ -611,7 +612,7 @@ static void sti_hda_connector_destroy(struct drm_connector *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, .fill_modes = drm_helper_probe_single_connector_modes, .detect = sti_hda_connector_detect, @@ -784,8 +785,6 @@ struct platform_driver sti_hda_driver = { .remove = sti_hda_remove, }; -module_platform_driver(sti_hda_driver); - MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 09e29e43423e..cd501563c0cc 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -628,7 +628,8 @@ struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector) 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, .mode_valid = sti_hdmi_connector_mode_valid, .best_encoder = sti_hdmi_best_encoder, @@ -663,7 +664,7 @@ static void sti_hdmi_connector_destroy(struct drm_connector *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, .fill_modes = drm_helper_probe_single_connector_modes, .detect = sti_hdmi_connector_detect, @@ -700,18 +701,17 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) encoder = sti_hdmi_find_encoder(drm_dev); if (!encoder) - goto err_adapt; + return -EINVAL; connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); if (!connector) - goto err_adapt; - + return -EINVAL; connector->hdmi = hdmi; bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); if (!bridge) - goto err_adapt; + return -EINVAL; bridge->driver_private = hdmi; bridge->funcs = &sti_hdmi_bridge_funcs; @@ -748,8 +748,7 @@ err_sysfs: drm_connector_unregister(drm_connector); err_connector: drm_connector_cleanup(drm_connector); -err_adapt: - put_device(&hdmi->ddc_adapt->dev); + return -EINVAL; } @@ -794,13 +793,10 @@ static int sti_hdmi_probe(struct platform_device *pdev) ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0); if (ddc) { - hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc); - if (!hdmi->ddc_adapt) { - of_node_put(ddc); - return -EPROBE_DEFER; - } - + hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc); of_node_put(ddc); + if (!hdmi->ddc_adapt) + return -EPROBE_DEFER; } hdmi->dev = pdev->dev; @@ -809,24 +805,29 @@ static int sti_hdmi_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg"); if (!res) { DRM_ERROR("Invalid hdmi resource\n"); - return -ENOMEM; + ret = -ENOMEM; + goto release_adapter; } hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!hdmi->regs) - return -ENOMEM; + if (!hdmi->regs) { + ret = -ENOMEM; + goto release_adapter; + } if (of_device_is_compatible(np, "st,stih416-hdmi")) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscfg"); if (!res) { DRM_ERROR("Invalid syscfg resource\n"); - return -ENOMEM; + ret = -ENOMEM; + goto release_adapter; } hdmi->syscfg = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!hdmi->syscfg) - return -ENOMEM; - + if (!hdmi->syscfg) { + ret = -ENOMEM; + goto release_adapter; + } } hdmi->phy_ops = (struct hdmi_phy_ops *) @@ -836,25 +837,29 @@ static int sti_hdmi_probe(struct platform_device *pdev) hdmi->clk_pix = devm_clk_get(dev, "pix"); if (IS_ERR(hdmi->clk_pix)) { 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"); if (IS_ERR(hdmi->clk_tmds)) { 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"); if (IS_ERR(hdmi->clk_phy)) { 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"); if (IS_ERR(hdmi->clk_audio)) { 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; @@ -867,7 +872,7 @@ static int sti_hdmi_probe(struct platform_device *pdev) hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi); if (ret) { DRM_ERROR("Failed to register HDMI interrupt\n"); - return ret; + goto release_adapter; } hdmi->reset = devm_reset_control_get(dev, "hdmi"); @@ -878,16 +883,20 @@ static int sti_hdmi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hdmi); 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) { struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); - if (hdmi->ddc_adapt) - put_device(&hdmi->ddc_adapt->dev); - + i2c_put_adapter(hdmi->ddc_adapt); component_del(&pdev->dev, &sti_hdmi_ops); + return 0; } @@ -901,8 +910,6 @@ struct platform_driver sti_hdmi_driver = { .remove = sti_hdmi_remove, }; -module_platform_driver(sti_hdmi_driver); - MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 7c8f9b8bfae1..ea0690bc77d5 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -628,6 +628,153 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp) 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, struct drm_plane_state *oldstate) { @@ -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); if (first_prepare) { + /* Start HQVDP XP70 coprocessor */ + sti_hqvdp_start_xp70(hqvdp); + /* Prevent VTG shutdown */ if (clk_prepare_enable(hqvdp->clk_pix_main)) { 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, /* Register VTG Vsync callback to handle bottom fields */ if (sti_vtg_register_client(hqvdp->vtg, &hqvdp->vtg_nb, - mixer->id)) { + crtc)) { DRM_ERROR("Cannot register VTG notifier\n"); return; } @@ -836,168 +986,16 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev, 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 |