-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/lin…
…ux into drm-next 1) support for "stolen mem" for splash-screen take-over 2) additional hdmi pixel clks 3) various pipe flush related fixes 4) support for snapdragon 410 (8x16) 5) support for DSI and dual-DSI It includes one small patch to export tile-group functions (which was ack'd by you), as these are used to explain to userspace dual-dsi configurations (with left and right tile). * 'msm-next' of git://people.freedesktop.org/~robclark/linux: (24 commits) drm/msm/mdp5: Enable DSI connector in msm drm driver drm/msm: Initial add DSI connector support drm/msm: Add split display interface drm/msm/mdp5: Move *_modeset_init out of construct_encoder function drm: export tile-group functions drm/msm/mdp5: Remove CTL flush dummy bits drm/msm/mdp5: Update headers (add CTL flush bits) drm/msm/mdp5: Add hardware configuration for msm8x16 drm/msm/mdp5: Get SMP client list from mdp5_cfg drm/msm/mdp5: Update headers (remove enum mdp5_client_id) drm/msm/mdp5: Separate MDP5 domain from MDSS domain drm/msm/mdp5: Update headers (introduce MDP5 domain) drm/msm/dsi: Update generated DSI header file drm/msm/mdp5: Fix PIPE source image size settings drm/msm/mdp5: Update generated mdp5 header file with DSI support drm/msm/mdp5: Add pingpong entry to mdp5 config table drm/msm/mdp5: Make the intf connection in config module drm/msm/mdp5: Add START signal to kick off certain pipelines drm/msm/mdp5: Enhance operation mode for pipeline configuration drm/msm/mdp5: Update generated header files ...
- Loading branch information
Showing
29 changed files
with
5,327 additions
and
478 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
#ifndef __DSI_CONNECTOR_H__ | ||
#define __DSI_CONNECTOR_H__ | ||
|
||
#include <linux/platform_device.h> | ||
|
||
#include "drm_crtc.h" | ||
#include "drm_mipi_dsi.h" | ||
#include "drm_panel.h" | ||
|
||
#include "msm_drv.h" | ||
|
||
#define DSI_0 0 | ||
#define DSI_1 1 | ||
#define DSI_MAX 2 | ||
|
||
#define DSI_CLOCK_MASTER DSI_0 | ||
#define DSI_CLOCK_SLAVE DSI_1 | ||
|
||
#define DSI_LEFT DSI_0 | ||
#define DSI_RIGHT DSI_1 | ||
|
||
/* According to the current drm framework sequence, take the encoder of | ||
* DSI_1 as master encoder | ||
*/ | ||
#define DSI_ENCODER_MASTER DSI_1 | ||
#define DSI_ENCODER_SLAVE DSI_0 | ||
|
||
struct msm_dsi { | ||
struct drm_device *dev; | ||
struct platform_device *pdev; | ||
|
||
struct drm_connector *connector; | ||
struct drm_bridge *bridge; | ||
|
||
struct mipi_dsi_host *host; | ||
struct msm_dsi_phy *phy; | ||
struct drm_panel *panel; | ||
unsigned long panel_flags; | ||
bool phy_enabled; | ||
|
||
/* the encoders we are hooked to (outside of dsi block) */ | ||
struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]; | ||
|
||
int id; | ||
}; | ||
|
||
/* dsi manager */ | ||
struct drm_bridge *msm_dsi_manager_bridge_init(u8 id); | ||
void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge); | ||
struct drm_connector *msm_dsi_manager_connector_init(u8 id); | ||
int msm_dsi_manager_phy_enable(int id, | ||
const unsigned long bit_rate, const unsigned long esc_rate, | ||
u32 *clk_pre, u32 *clk_post); | ||
void msm_dsi_manager_phy_disable(int id); | ||
int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); | ||
bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len); | ||
int msm_dsi_manager_register(struct msm_dsi *msm_dsi); | ||
void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); | ||
|
||
/* msm dsi */ | ||
struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); | ||
|
||
/* dsi host */ | ||
int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, | ||
const struct mipi_dsi_msg *msg); | ||
void msm_dsi_host_xfer_restore(struct mipi_dsi_host *host, | ||
const struct mipi_dsi_msg *msg); | ||
int msm_dsi_host_cmd_tx(struct mipi_dsi_host *host, | ||
const struct mipi_dsi_msg *msg); | ||
int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host, | ||
const struct mipi_dsi_msg *msg); | ||
void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, | ||
u32 iova, u32 len); | ||
int msm_dsi_host_enable(struct mipi_dsi_host *host); | ||
int msm_dsi_host_disable(struct mipi_dsi_host *host); | ||
int msm_dsi_host_power_on(struct mipi_dsi_host *host); | ||
int msm_dsi_host_power_off(struct mipi_dsi_host *host); | ||
int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, | ||
struct drm_display_mode *mode); | ||
struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host, | ||
unsigned long *panel_flags); | ||
int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); | ||
void msm_dsi_host_unregister(struct mipi_dsi_host *host); | ||
void msm_dsi_host_destroy(struct mipi_dsi_host *host); | ||
int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, | ||
struct drm_device *dev); | ||
int msm_dsi_host_init(struct msm_dsi *msm_dsi); | ||
|
||
/* dsi phy */ | ||
struct msm_dsi_phy; | ||
enum msm_dsi_phy_type { | ||
MSM_DSI_PHY_UNKNOWN, | ||
MSM_DSI_PHY_28NM, | ||
MSM_DSI_PHY_MAX | ||
}; | ||
struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, | ||
enum msm_dsi_phy_type type, int id); | ||
int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, | ||
const unsigned long bit_rate, const unsigned long esc_rate); | ||
int msm_dsi_phy_disable(struct msm_dsi_phy *phy); | ||
void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, | ||
u32 *clk_pre, u32 *clk_post); | ||
#endif /* __DSI_CONNECTOR_H__ */ | ||
|
Oops, something went wrong.