diff options
author | Dave Airlie <airlied@redhat.com> | 2017-06-16 09:33:43 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-06-16 09:33:43 +1000 |
commit | bfda9aa15317838ddb259406027ef9911a1dffbc (patch) | |
tree | 82ca374d4cd7a0c33c9a251bfdc3baf08a3e0163 /drivers/gpu/drm/vc4 | |
parent | 3ee45a3b533a20ed9fcc11ddb880fc4b30d28f51 (diff) | |
parent | ac7c748317f515f426f48e72964c71142506f7a6 (diff) |
Merge tag 'drm-misc-next-2017-06-15' of git://anongit.freedesktop.org/git/drm-misc into drm-next
Cross-subsystem Changes:
- dt-bindings: add vendor prefix for NLT Technologies, Ltd. (Lucas)
- dt-bindings: Add support for samsung s6e3hf2 panel (Hoegeun)
Core Changes:
- Add drm_panel_bridge to avoid connector boilerplate in drivers (Eric)
- Trival fixes for dupe forward decl and reduce scope of variable (Dawid)
Driver Changes:
- dw-hdmi: Use mode_valid hook on bridge instead of connector (Jose)
- vc4,atmel-hlcdc: Use drm_panel_bridge where appropriate (Eric)
- panel: Add Innolux P079ZCA panel driver (Chris)
- panel-simple: Add NL12880B20-05, NL192108AC18-02D, P320HVN03 panels (Lucas)
- panel-samsung-s6e3ha2: Add s6e3hf2 panel support (Hoegeun)
- zte,vc4,pl111,panel,mxsfb: Miscellaneous fixes
Cc: Jose Abreu <Jose.Abreu@synopsys.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: Chris Zhong <zyw@rock-chips.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Cc: Dawid Kurek <dawikur@gmail.com>
* tag 'drm-misc-next-2017-06-15' of git://anongit.freedesktop.org/git/drm-misc: (26 commits)
drm: Reduce scope of 'state' variable
drm: mxsfb_crtc: Reset the eLCDIF controller
drm: Remove duplicate forward declaration
drm/panel: s6e3ha2: Add support for s6e3hf2 panel on TM2e board
dt-bindings: Add support for samsung s6e3hf2 panel
drm/panel: add backlight dependency for sitronix-st7789v
drm/panel: S6E3HA2 needs backlight code
drm/panel: simple: add support for AUO P320HVN03
drm/panel: simple: add support for NLT NL192108AC18-02D
dt-bindings: add vendor prefix for NLT Technologies, Ltd.
drm/panel: simple: add support for NEC NL12880B20-05
drm/panel: add Innolux P079ZCA panel driver
dt-bindings: Add INNOLUX P079ZCA panel bindings
drm/vc4: Fix resource leak in 'vc4_get_hang_state_ioctl()' in error handling path
drm/vc4/vc4_bo.c: always set bo->resv
drm: Add const to name field declaration in struct drm_prop_enum_list
drm/pl111: Fix offset calculation for the primary plane.
drm/atmel-hlcdc: Fix panel registration
drm/bridge: Build the panel wrapper in drm_kms_helper
drm/atmel-hlcdc: Replace the panel usage with drm_panel_bridge.
...
Diffstat (limited to 'drivers/gpu/drm/vc4')
-rw-r--r-- | drivers/gpu/drm/vc4/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_bo.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_dpi.c | 164 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_dsi.c | 154 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_gem.c | 13 |
5 files changed, 63 insertions, 282 deletions
diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig index b16aefe4a8d3..4361bdcfd28a 100644 --- a/drivers/gpu/drm/vc4/Kconfig +++ b/drivers/gpu/drm/vc4/Kconfig @@ -7,7 +7,7 @@ config DRM_VC4 select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DRM_GEM_CMA_HELPER - select DRM_PANEL + select DRM_PANEL_BRIDGE select SND_PCM select SND_PCM_ELD select SND_SOC_GENERIC_DMAENGINE_PCM diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 80b2f9e55c5c..590c0912afc1 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -91,8 +91,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo) vc4->bo_stats.num_allocated--; vc4->bo_stats.size_allocated -= obj->size; - if (bo->resv == &bo->_resv) - reservation_object_fini(bo->resv); + reservation_object_fini(&bo->_resv); drm_gem_cma_free_object(obj); } @@ -212,6 +211,8 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) vc4->bo_stats.num_allocated++; vc4->bo_stats.size_allocated += size; mutex_unlock(&vc4->bo_lock); + bo->resv = &bo->_resv; + reservation_object_init(bo->resv); return &bo->base.base; } @@ -250,12 +251,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, return ERR_PTR(-ENOMEM); } } - bo = to_vc4_bo(&cma_obj->base); - - bo->resv = &bo->_resv; - reservation_object_init(bo->resv); - - return bo; + return to_vc4_bo(&cma_obj->base); } int vc4_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c index 39d68080873c..2e0fe46aeb2e 100644 --- a/drivers/gpu/drm/vc4/vc4_dpi.c +++ b/drivers/gpu/drm/vc4/vc4_dpi.c @@ -23,8 +23,10 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_edid.h> +#include <drm/drm_of.h> #include <drm/drm_panel.h> #include <linux/clk.h> #include <linux/component.h> @@ -95,7 +97,8 @@ struct vc4_dpi { struct drm_encoder *encoder; struct drm_connector *connector; - struct drm_panel *panel; + struct drm_bridge *bridge; + bool is_panel_bridge; void __iomem *regs; @@ -118,24 +121,6 @@ to_vc4_dpi_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_dpi_encoder, base.base); } -/* VC4 DPI connector KMS struct */ -struct vc4_dpi_connector { - struct drm_connector base; - struct vc4_dpi *dpi; - - /* Since the connector is attached to just the one encoder, - * this is the reference to it so we can do the best_encoder() - * hook. - */ - struct drm_encoder *encoder; -}; - -static inline struct vc4_dpi_connector * -to_vc4_dpi_connector(struct drm_connector *connector) -{ - return container_of(connector, struct vc4_dpi_connector, base); -} - #define DPI_REG(reg) { reg, #reg } static const struct { u32 reg; @@ -167,80 +152,6 @@ int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused) } #endif -static enum drm_connector_status -vc4_dpi_connector_detect(struct drm_connector *connector, bool force) -{ - struct vc4_dpi_connector *vc4_connector = - to_vc4_dpi_connector(connector); - struct vc4_dpi *dpi = vc4_connector->dpi; - - if (dpi->panel) - return connector_status_connected; - else - return connector_status_disconnected; -} - -static void vc4_dpi_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - -static int vc4_dpi_connector_get_modes(struct drm_connector *connector) -{ - struct vc4_dpi_connector *vc4_connector = - to_vc4_dpi_connector(connector); - struct vc4_dpi *dpi = vc4_connector->dpi; - - if (dpi->panel) - return drm_panel_get_modes(dpi->panel); - - return 0; -} - -static const struct drm_connector_funcs vc4_dpi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .detect = vc4_dpi_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_dpi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static const struct drm_connector_helper_funcs vc4_dpi_connector_helper_funcs = { - .get_modes = vc4_dpi_connector_get_modes, -}; - -static struct drm_connector *vc4_dpi_connector_init(struct drm_device *dev, - struct vc4_dpi *dpi) -{ - struct drm_connector *connector = NULL; - struct vc4_dpi_connector *dpi_connector; - - dpi_connector = devm_kzalloc(dev->dev, sizeof(*dpi_connector), - GFP_KERNEL); - if (!dpi_connector) - return ERR_PTR(-ENOMEM); - - connector = &dpi_connector->base; - - dpi_connector->encoder = dpi->encoder; - dpi_connector->dpi = dpi; - - drm_connector_init(dev, connector, &vc4_dpi_connector_funcs, - DRM_MODE_CONNECTOR_DPI); - drm_connector_helper_add(connector, &vc4_dpi_connector_helper_funcs); - - connector->polled = 0; - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - drm_mode_connector_attach_encoder(connector, dpi->encoder); - - return connector; -} - static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = { .destroy = drm_encoder_cleanup, }; @@ -250,11 +161,7 @@ static void vc4_dpi_encoder_disable(struct drm_encoder *encoder) struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder); struct vc4_dpi *dpi = vc4_encoder->dpi; - drm_panel_disable(dpi->panel); - clk_disable_unprepare(dpi->pixel_clock); - - drm_panel_unprepare(dpi->panel); } static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) @@ -265,12 +172,6 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE; int ret; - ret = drm_panel_prepare(dpi->panel); - if (ret) { - DRM_ERROR("Panel failed to prepare\n"); - return; - } - if (dpi->connector->display_info.num_bus_formats) { u32 bus_format = dpi->connector->display_info.bus_formats[0]; @@ -321,13 +222,6 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) ret = clk_prepare_enable(dpi->pixel_clock); if (ret) DRM_ERROR("Failed to set clock rate: %d\n", ret); - - ret = drm_panel_enable(dpi->panel); - if (ret) { - DRM_ERROR("Panel failed to enable\n"); - drm_panel_unprepare(dpi->panel); - return; - } } static bool vc4_dpi_encoder_mode_fixup(struct drm_encoder *encoder, @@ -351,24 +245,34 @@ static const struct of_device_id vc4_dpi_dt_match[] = { {} }; -/* Walks the OF graph to find the panel node and then asks DRM to look - * up the panel. +/* Sets up the next link in the display chain, whether it's a panel or + * a bridge. */ -static struct drm_panel *vc4_dpi_get_panel(struct device *dev) +static int vc4_dpi_init_bridge(struct vc4_dpi *dpi) { - struct device_node *panel_node; - struct device_node *np = dev->of_node; + struct device *dev = &dpi->pdev->dev; struct drm_panel *panel; + int ret; - /* don't proceed if we have an endpoint but no panel_node tied to it */ - panel_node = of_graph_get_remote_node(np, 0, 0); - if (!panel_node) - return NULL; + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, + &panel, &dpi->bridge); + if (ret) { + /* If nothing was connected in the DT, that's not an + * error. + */ + if (ret == -ENODEV) + return 0; + else + return ret; + } - panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); + if (panel) { + dpi->bridge = drm_panel_bridge_add(panel, + DRM_MODE_CONNECTOR_DPI); + dpi->is_panel_bridge = true; + } - return panel; + return drm_bridge_attach(dpi->encoder, dpi->bridge, NULL); } static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) @@ -422,20 +326,13 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data) if (ret) DRM_ERROR("Failed to turn on core clock: %d\n", ret); - dpi->panel = vc4_dpi_get_panel(dev); - drm_encoder_init(drm, dpi->encoder, &vc4_dpi_encoder_funcs, DRM_MODE_ENCODER_DPI, NULL); drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs); - dpi->connector = vc4_dpi_connector_init(drm, dpi); - if (IS_ERR(dpi->connector)) { - ret = PTR_ERR(dpi->connector); + ret = vc4_dpi_init_bridge(dpi); + if (ret) goto err_destroy_encoder; - } - - if (dpi->panel) - drm_panel_attach(dpi->panel, dpi->connector); dev_set_drvdata(dev, dpi); @@ -456,10 +353,9 @@ static void vc4_dpi_unbind(struct device *dev, struct device *master, struct vc4_dev *vc4 = to_vc4_dev(drm); struct vc4_dpi *dpi = dev_get_drvdata(dev); - if (dpi->panel) - drm_panel_detach(dpi->panel); + if (dpi->is_panel_bridge) + drm_panel_bridge_remove(dpi->bridge); - vc4_dpi_connector_destroy(dpi->connector); drm_encoder_cleanup(dpi->encoder); clk_disable_unprepare(dpi->core_clock); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 0ef41df3915f..5e8b81eaa168 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -503,8 +503,8 @@ struct vc4_dsi { struct mipi_dsi_host dsi_host; struct drm_encoder *encoder; - struct drm_connector *connector; - struct drm_panel *panel; + struct drm_bridge *bridge; + bool is_panel_bridge; void __iomem *regs; @@ -605,18 +605,6 @@ to_vc4_dsi_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_dsi_encoder, base.base); } -/* VC4 DSI connector KMS struct */ -struct vc4_dsi_connector { - struct drm_connector base; - struct vc4_dsi *dsi; -}; - -static inline struct vc4_dsi_connector * -to_vc4_dsi_connector(struct drm_connector *connector) -{ - return container_of(connector, struct vc4_dsi_connector, base); -} - #define DSI_REG(reg) { reg, #reg } static const struct { u32 reg; @@ -724,79 +712,6 @@ int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused) } #endif -static enum drm_connector_status -vc4_dsi_connector_detect(struct drm_connector *connector, bool force) -{ - struct vc4_dsi_connector *vc4_connector = - to_vc4_dsi_connector(connector); - struct vc4_dsi *dsi = vc4_connector->dsi; - - if (dsi->panel) - return connector_status_connected; - else - return connector_status_disconnected; -} - -static void vc4_dsi_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - -static int vc4_dsi_connector_get_modes(struct drm_connector *connector) -{ - struct vc4_dsi_connector *vc4_connector = - to_vc4_dsi_connector(connector); - struct vc4_dsi *dsi = vc4_connector->dsi; - - if (dsi->panel) - return drm_panel_get_modes(dsi->panel); - - return 0; -} - -static const struct drm_connector_funcs vc4_dsi_connector_funcs = { - .dpms = drm_atomic_helper_connector_dpms, - .detect = vc4_dsi_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = vc4_dsi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static const struct drm_connector_helper_funcs vc4_dsi_connector_helper_funcs = { - .get_modes = vc4_dsi_connector_get_modes, -}; - -static struct drm_connector *vc4_dsi_connector_init(struct drm_device *dev, - struct vc4_dsi *dsi) -{ - struct drm_connector *connector; - struct vc4_dsi_connector *dsi_connector; - - dsi_connector = devm_kzalloc(dev->dev, sizeof(*dsi_connector), - GFP_KERNEL); - if (!dsi_connector) - return ERR_PTR(-ENOMEM); - - connector = &dsi_connector->base; - - dsi_connector->dsi = dsi; - - drm_connector_init(dev, connector, &vc4_dsi_connector_funcs, - DRM_MODE_CONNECTOR_DSI); - drm_connector_helper_add(connector, &vc4_dsi_connector_helper_funcs); - - connector->polled = 0; - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - drm_mode_connector_attach_encoder(connector, dsi->encoder); - - return connector; -} - static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder) { drm_encoder_cleanup(encoder); @@ -894,12 +809,8 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) struct vc4_dsi *dsi = vc4_encoder->dsi; struct device *dev = &dsi->pdev->dev; - drm_panel_disable(dsi->panel); - vc4_dsi_ulps(dsi, true); - drm_panel_unprepare(dsi->panel); - clk_disable_unprepare(dsi->pll_phy_clock); clk_disable_unprepare(dsi->escape_clock); clk_disable_unprepare(dsi->pixel_clock); @@ -984,12 +895,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) return; } - ret = drm_panel_prepare(dsi->panel); - if (ret) { - DRM_ERROR("Panel failed to prepare\n"); - return; - } - if (debug_dump_regs) { DRM_INFO("DSI regs before:\n"); vc4_dsi_dump_regs(dsi); @@ -1211,13 +1116,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) DRM_INFO("DSI regs after:\n"); vc4_dsi_dump_regs(dsi); } - - ret = drm_panel_enable(dsi->panel); - if (ret) { - DRM_ERROR("Panel failed to enable\n"); - drm_panel_unprepare(dsi->panel); - return; - } } static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, @@ -1415,17 +1313,22 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host, return 0; } - dsi->panel = of_drm_find_panel(device->dev.of_node); - if (!dsi->panel) - return 0; - - ret = drm_panel_attach(dsi->panel, dsi->connector); - if (ret != 0) - return ret; + dsi->bridge = of_drm_find_bridge(device->dev.of_node); + if (!dsi->bridge) { + struct drm_panel *panel = + of_drm_find_panel(device->dev.of_node); - drm_helper_hpd_irq_event(dsi->connector->dev); + dsi->bridge = drm_panel_bridge_add(panel, + DRM_MODE_CONNECTOR_DSI); + if (IS_ERR(dsi->bridge)) { + ret = PTR_ERR(dsi->bridge); + dsi->bridge = NULL; + return ret; + } + dsi->is_panel_bridge = true; + } - return 0; + return drm_bridge_attach(dsi->encoder, dsi->bridge, NULL); } static int vc4_dsi_host_detach(struct mipi_dsi_host *host, @@ -1433,15 +1336,9 @@ static int vc4_dsi_host_detach(struct mipi_dsi_host *host, { struct vc4_dsi *dsi = host_to_dsi(host); - if (dsi->panel) { - int ret = drm_panel_detach(dsi->panel); - - if (ret) - return ret; - - dsi->panel = NULL; - - drm_helper_hpd_irq_event(dsi->connector->dev); + if (dsi->is_panel_bridge) { + drm_panel_bridge_remove(dsi->bridge); + dsi->bridge = NULL; } return 0; @@ -1708,12 +1605,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) DRM_MODE_ENCODER_DSI, NULL); drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); - dsi->connector = vc4_dsi_connector_init(drm, dsi); - if (IS_ERR(dsi->connector)) { - ret = PTR_ERR(dsi->connector); - goto err_destroy_encoder; - } - dsi->dsi_host.ops = &vc4_dsi_host_ops; dsi->dsi_host.dev = dev; @@ -1724,11 +1615,6 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) pm_runtime_enable(dev); return 0; - -err_destroy_encoder: - vc4_dsi_encoder_destroy(dsi->encoder); - - return ret; } static void vc4_dsi_unbind(struct device *dev, struct device *master, @@ -1740,7 +1626,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master, pm_runtime_disable(dev); - vc4_dsi_connector_destroy(dsi->connector); + drm_bridge_remove(dsi->bridge); vc4_dsi_encoder_destroy(dsi->encoder); mipi_dsi_host_unregister(&dsi->dsi_host); diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 9dc7646d49ed..d5b821ad06af 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -111,8 +111,8 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, &handle); if (ret) { - state->bo_count = i - 1; - goto err; + state->bo_count = i; + goto err_delete_handle; } bo_state[i].handle = handle; bo_state[i].paddr = vc4_bo->base.paddr; @@ -124,13 +124,16 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data, state->bo_count * sizeof(*bo_state))) ret = -EFAULT; - kfree(bo_state); +err_delete_handle: + if (ret) { + for (i = 0; i < state->bo_count; i++) + drm_gem_handle_delete(file_priv, bo_state[i].handle); + } err_free: - vc4_free_hang_state(dev, kernel_state); + kfree(bo_state); -err: return ret; } |