summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/dsi/dsi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-20 14:06:06 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-20 14:06:06 -0700
commit14aa02449064541217836b9f3d3295e241d5ae9c (patch)
tree3456d1c397041cf86579cd2aed18de99f3240c81 /drivers/gpu/drm/msm/dsi/dsi.c
parent79319a052cb0ae862954fe9f6e606417f1698ddb (diff)
parent2c33ce009ca2389dbf0535d0672214d09738e35e (diff)
downloadlinux-stable-14aa02449064541217836b9f3d3295e241d5ae9c.tar.gz
linux-stable-14aa02449064541217836b9f3d3295e241d5ae9c.tar.bz2
linux-stable-14aa02449064541217836b9f3d3295e241d5ae9c.zip
Merge branch 'drm-next-merged' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "Highlights: Core: - Virtual GEM layer merged, this has been around for a long time, and it provides a software backed device that allows userspace to use it as a GEM shared memory handler. This makes it a lot easier to do certain things when you have no GPU but still have to deal with DRI expectations. - atomic helper updates. - framebuffer modifier interface added. - i2c over auxch displayport fixes. - fb width/height confusion fixes. - new driver for ps8622/ps8625 bridge chips - lots of new panels i915: - more plane atomic conversion - vGPU guest support for XenGT - Skylake workarounds and fixes - Y-tiling support - work on dynamic pagetable allocation - EU count report param for gen9+ - CHV fixes (no longer prelim) - remove ilk rc6 - frontbuffer tracking for fbc - Displayport link rate refactoring - sprite colorkey refactor radeon: - Displayport MST support (not enabled by default) - non-ATOM native hw auxch support (DCE5+) - output csc support - new queries for userspace debug support - new VCE packet nouveau: - gk20a iommu support - gm107 graphics support - more gm20x bringup (waiting on signed nvidia fw). amdkfd: - multiple kgd instance support - use 64-bit time accessors msm: - stolen memory support - DSI and dual-DSI support - snapdragon 410 support exynos: - cleanups for atomic and pageflip imx-drm: - more media-bus formats - TV output prep - drm panel support tegra: - hw vblank counter using host1x syncpoints omap: - universal plane support - prep work for atomic modesetting rcar-du: - ported to atomic modesetting atmel-hlcdc: - ported to atomic modesetting - added suspend/resume support sti: - ported to atomic modesetting dwhdmi: - more compliant audio support - update rockchip phy support tda998x: - DT probing for attached crtcs - simplified EDID reading rockchip: - fixes adv7511: - fixes" * 'drm-next-merged' of git://people.freedesktop.org/~airlied/linux: (689 commits) media-bus: Fixup RGB444_1X12, RGB565_1X16, and YUV8_1X24 media bus format drm/i915: Dont enable CS_PARSER_ERROR interrupts at all drm/i915: Move drm_framebuffer_unreference out of struct_mutex for takeover drm: fix trivial typo mistake drm: Make integer overflow checking cover universal cursor updates (v2) drm/nouveau/bios: fix fetching from acpi on certain systems drm/nouveau/gr/gm206: initial init+ctx code drm/nouveau/ce/gm206: enable support via gm204 code drm/nouveau/fifo/gm206: enable support via gm204 code drm/nouveau/gr/gm204: initial init+ctx code drm/nouveau: support for buffer moves via MaxwellDmaCopyA drm/nouveau/ce/gm204: initial support drm/nouveau: add support for gm20x fifo channels drm/nouveau/fifo/gm204: initial support drm/nouveau/gr/gk104-: prevent reading non-existent regs in intr handler drm/nouveau/gr/gm107: very slightly demagic part of attrib cb setup drm/nouveau/gr/gk104-: correct crop/zrop num_active_fbps setting drm/nouveau/gr/gf100-: add symbolic names for classes drm/nouveau/gr/gm107: support tpc "strand" ctxsw in gpccs ucode drm/nouveau/gr/gf100-: support mmio access with gpc offset from gpccs ucode ...
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi.c')
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
new file mode 100644
index 000000000000..28d1f95a90cc
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "dsi.h"
+
+struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
+{
+ if (!msm_dsi || !msm_dsi->panel)
+ return NULL;
+
+ return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ?
+ msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] :
+ msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
+}
+
+static void dsi_destroy(struct msm_dsi *msm_dsi)
+{
+ if (!msm_dsi)
+ return;
+
+ msm_dsi_manager_unregister(msm_dsi);
+ if (msm_dsi->host) {
+ msm_dsi_host_destroy(msm_dsi->host);
+ msm_dsi->host = NULL;
+ }
+
+ platform_set_drvdata(msm_dsi->pdev, NULL);
+}
+
+static struct msm_dsi *dsi_init(struct platform_device *pdev)
+{
+ struct msm_dsi *msm_dsi = NULL;
+ int ret;
+
+ if (!pdev) {
+ dev_err(&pdev->dev, "no dsi device\n");
+ ret = -ENXIO;
+ goto fail;
+ }
+
+ msm_dsi = devm_kzalloc(&pdev->dev, sizeof(*msm_dsi), GFP_KERNEL);
+ if (!msm_dsi) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ DBG("dsi probed=%p", msm_dsi);
+
+ msm_dsi->pdev = pdev;
+ platform_set_drvdata(pdev, msm_dsi);
+
+ /* Init dsi host */
+ ret = msm_dsi_host_init(msm_dsi);
+ if (ret)
+ goto fail;
+
+ /* Register to dsi manager */
+ ret = msm_dsi_manager_register(msm_dsi);
+ if (ret)
+ goto fail;
+
+ return msm_dsi;
+
+fail:
+ if (msm_dsi)
+ dsi_destroy(msm_dsi);
+
+ return ERR_PTR(ret);
+}
+
+static int dsi_bind(struct device *dev, struct device *master, void *data)
+{
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct msm_drm_private *priv = drm->dev_private;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct msm_dsi *msm_dsi;
+
+ DBG("");
+ msm_dsi = dsi_init(pdev);
+ if (IS_ERR(msm_dsi))
+ return PTR_ERR(msm_dsi);
+
+ priv->dsi[msm_dsi->id] = msm_dsi;
+
+ return 0;
+}
+
+static void dsi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct drm_device *drm = dev_get_drvdata(master);
+ struct msm_drm_private *priv = drm->dev_private;
+ struct msm_dsi *msm_dsi = dev_get_drvdata(dev);
+ int id = msm_dsi->id;
+
+ if (priv->dsi[id]) {
+ dsi_destroy(msm_dsi);
+ priv->dsi[id] = NULL;
+ }
+}
+
+static const struct component_ops dsi_ops = {
+ .bind = dsi_bind,
+ .unbind = dsi_unbind,
+};
+
+static int dsi_dev_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &dsi_ops);
+}
+
+static int dsi_dev_remove(struct platform_device *pdev)
+{
+ DBG("");
+ component_del(&pdev->dev, &dsi_ops);
+ return 0;
+}
+
+static const struct of_device_id dt_match[] = {
+ { .compatible = "qcom,mdss-dsi-ctrl" },
+ {}
+};
+
+static struct platform_driver dsi_driver = {
+ .probe = dsi_dev_probe,
+ .remove = dsi_dev_remove,
+ .driver = {
+ .name = "msm_dsi",
+ .of_match_table = dt_match,
+ },
+};
+
+void __init msm_dsi_register(void)
+{
+ DBG("");
+ platform_driver_register(&dsi_driver);
+}
+
+void __exit msm_dsi_unregister(void)
+{
+ DBG("");
+ platform_driver_unregister(&dsi_driver);
+}
+
+int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
+ struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM])
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ int ret, i;
+
+ if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] ||
+ !encoders[MSM_DSI_CMD_ENCODER_ID]))
+ return -EINVAL;
+
+ msm_dsi->dev = dev;
+
+ ret = msm_dsi_host_modeset_init(msm_dsi->host, dev);
+ if (ret) {
+ dev_err(dev->dev, "failed to modeset init host: %d\n", ret);
+ goto fail;
+ }
+
+ msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id);
+ if (IS_ERR(msm_dsi->bridge)) {
+ ret = PTR_ERR(msm_dsi->bridge);
+ dev_err(dev->dev, "failed to create dsi bridge: %d\n", ret);
+ msm_dsi->bridge = NULL;
+ goto fail;
+ }
+
+ msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);
+ if (IS_ERR(msm_dsi->connector)) {
+ ret = PTR_ERR(msm_dsi->connector);
+ dev_err(dev->dev, "failed to create dsi connector: %d\n", ret);
+ msm_dsi->connector = NULL;
+ goto fail;
+ }
+
+ for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) {
+ encoders[i]->bridge = msm_dsi->bridge;
+ msm_dsi->encoders[i] = encoders[i];
+ }
+
+ priv->bridges[priv->num_bridges++] = msm_dsi->bridge;
+ priv->connectors[priv->num_connectors++] = msm_dsi->connector;
+
+ return 0;
+fail:
+ if (msm_dsi) {
+ /* bridge/connector are normally destroyed by drm: */
+ if (msm_dsi->bridge) {
+ msm_dsi_manager_bridge_destroy(msm_dsi->bridge);
+ msm_dsi->bridge = NULL;
+ }
+ if (msm_dsi->connector) {
+ msm_dsi->connector->funcs->destroy(msm_dsi->connector);
+ msm_dsi->connector = NULL;
+ }
+ }
+
+ return ret;
+}
+