Skip to content

Commit

Permalink
Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/lin…
Browse files Browse the repository at this point in the history
…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
Dave Airlie committed Apr 8, 2015
2 parents a08aad5 + d5af49c commit fa37a8c
Show file tree
Hide file tree
Showing 29 changed files with 5,327 additions and 478 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5599,6 +5599,7 @@ struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
mutex_unlock(&dev->mode_config.idr_mutex);
return NULL;
}
EXPORT_SYMBOL(drm_mode_get_tile_group);

/**
* drm_mode_create_tile_group - create a tile group from a displayid description
Expand Down Expand Up @@ -5637,3 +5638,4 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
mutex_unlock(&dev->mode_config.idr_mutex);
return tg;
}
EXPORT_SYMBOL(drm_mode_create_tile_group);
11 changes: 11 additions & 0 deletions drivers/gpu/drm/msm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,14 @@ config DRM_MSM_REGISTER_LOGGING
Compile in support for logging register reads/writes in a format
that can be parsed by envytools demsm tool. If enabled, register
logging can be switched on via msm.reglog=y module param.

config DRM_MSM_DSI
bool "Enable DSI support in MSM DRM driver"
depends on DRM_MSM
select DRM_PANEL
select DRM_MIPI_DSI
default y
help
Choose this option if you have a need for MIPI DSI connector
support.

5 changes: 5 additions & 0 deletions drivers/gpu/drm/msm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,10 @@ msm-y := \

msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
dsi/dsi_host.o \
dsi/dsi_manager.o \
dsi/dsi_phy.o \
mdp/mdp5/mdp5_cmd_encoder.o

obj-$(CONFIG_DRM_MSM) += msm.o
212 changes: 212 additions & 0 deletions drivers/gpu/drm/msm/dsi/dsi.c
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;
}

117 changes: 117 additions & 0 deletions drivers/gpu/drm/msm/dsi/dsi.h
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__ */

Loading

0 comments on commit fa37a8c

Please sign in to comment.