diff options
| author | Clarence Ip <cip@codeaurora.org> | 2016-07-15 16:02:26 -0400 |
|---|---|---|
| committer | Dhaval Patel <pdhaval@codeaurora.org> | 2016-08-01 12:35:46 -0700 |
| commit | bc79a7ccd350e433c5f47542b4b98cd9e154aff7 (patch) | |
| tree | 6bc3b6aad91517f63a1769252320ddf8d9953e11 /drivers/gpu | |
| parent | 1af16b75729c333f399d471f1520b5b0e284090d (diff) | |
drm/msm/dsi-staging: use sde connector for dsi
Update the display manager and dsi driver to make use of the sde's
generic connector infrastructure. Replace DISPLAY_TYPE property
with a generic SDE_INFO property that contains one or more key+value
pairs.
Change-Id: I366ea44e2e03211424b9cfa7b713178f5d01490d
Signed-off-by: Clarence Ip <cip@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/msm/display-manager/display_manager.c | 49 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/display-manager/display_manager.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_display.c | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_display.h | 12 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_drm.c | 249 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/dsi-staging/dsi_drm.h | 77 |
6 files changed, 144 insertions, 269 deletions
diff --git a/drivers/gpu/drm/msm/display-manager/display_manager.c b/drivers/gpu/drm/msm/display-manager/display_manager.c index af891dcd0ca8..236550ad9b41 100644 --- a/drivers/gpu/drm/msm/display-manager/display_manager.c +++ b/drivers/gpu/drm/msm/display-manager/display_manager.c @@ -22,8 +22,11 @@ #include "msm_drv.h" #include "msm_kms.h" #include "msm_gpu.h" -#include "display_manager.h" +#include "sde_connector.h" + #include "dsi_display.h" +#include "dsi_drm.h" +#include "display_manager.h" static u32 dm_get_num_of_displays(struct display_manager *disp_m) { @@ -97,21 +100,26 @@ static int disp_manager_comp_ops_bind(struct device *dev, struct device *master, void *data) { - int rc = 0; - struct drm_device *drm = dev_get_drvdata(master); - struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm; struct msm_drm_private *priv; struct display_manager *disp_m; struct dsi_display *dsi_display; - int i; + int i, rc = -EINVAL; + + if (master && dev) { + drm = dev_get_drvdata(master); + disp_m = platform_get_drvdata(to_platform_device(dev)); + if (drm && drm->dev_private && disp_m) + rc = 0; + } - if (!master || !dev || !drm->dev_private) { + if (rc) { pr_err("Invalid params\n"); return -EINVAL; } priv = drm->dev_private; - disp_m = platform_get_drvdata(pdev); + disp_m->drm_dev = drm; /* DSI displays */ for (i = 0; i < disp_m->dsi_display_count; i++) { @@ -363,9 +371,16 @@ int display_manager_drm_init_by_index(struct display_manager *disp_m, u32 display_index, struct drm_encoder *encoder) { - int rc = 0; + static const struct sde_connector_ops dsi_ops = { + .post_init = dsi_conn_post_init, + .detect = dsi_conn_detect, + .get_modes = dsi_connector_get_modes, + .mode_valid = dsi_conn_mode_valid + }; + int rc = -EINVAL; int i; struct dsi_display *display; + struct drm_connector *connector; if (!disp_m || !encoder) { pr_err("Invalid params\n"); @@ -379,7 +394,21 @@ int display_manager_drm_init_by_index(struct display_manager *disp_m, if (!display || !dsi_display_is_active(display)) continue; - dsi_display_drm_init(display, encoder); + rc = dsi_display_drm_bridge_init(display, encoder); + if (rc) + continue; + + connector = sde_connector_init(disp_m->drm_dev, + encoder, + 0, + display, + &dsi_ops, + DRM_CONNECTOR_POLL_HPD, + DRM_MODE_CONNECTOR_DSI); + if (!connector) + rc = -ENOMEM; + else if (IS_ERR(connector)) + rc = PTR_ERR(connector); break; } @@ -407,7 +436,7 @@ int display_manager_drm_deinit_by_index(struct display_manager *disp_m, if (!display || !dsi_display_is_active(display)) continue; - dsi_display_drm_deinit(display); + dsi_display_drm_bridge_deinit(display); break; } diff --git a/drivers/gpu/drm/msm/display-manager/display_manager.h b/drivers/gpu/drm/msm/display-manager/display_manager.h index c1484243d946..7e44573f2458 100644 --- a/drivers/gpu/drm/msm/display-manager/display_manager.h +++ b/drivers/gpu/drm/msm/display-manager/display_manager.h @@ -87,6 +87,7 @@ struct display_info { }; struct display_manager { + struct drm_device *drm_dev; struct platform_device *pdev; const char *name; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c index 1e90d46c1950..a531c7f3141f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c @@ -1897,11 +1897,11 @@ int dsi_display_unbind(struct dsi_display *display) return rc; } -int dsi_display_drm_init(struct dsi_display *display, struct drm_encoder *enc) +int dsi_display_drm_bridge_init(struct dsi_display *display, + struct drm_encoder *enc) { int rc = 0; struct dsi_bridge *bridge; - struct dsi_connector *connector; struct msm_drm_private *priv = NULL; if (!display || !enc) { @@ -1918,7 +1918,7 @@ int dsi_display_drm_init(struct dsi_display *display, struct drm_encoder *enc) goto error; } - if (display->connector || display->bridge) { + if (display->bridge) { pr_err("display is already initialize\n"); goto error; } @@ -1930,28 +1930,15 @@ int dsi_display_drm_init(struct dsi_display *display, struct drm_encoder *enc) goto error; } - connector = dsi_drm_connector_init(display, display->drm_dev, bridge); - if (IS_ERR_OR_NULL(connector)) { - rc = PTR_ERR(connector); - pr_err("[%s] connector init failed, rc=%d\n", display->name, - rc); - goto error_bridge_deinit; - } - - display->connector = connector; - priv->connectors[priv->num_connectors++] = &connector->base; display->bridge = bridge; priv->bridges[priv->num_bridges++] = &bridge->base; - goto error; -error_bridge_deinit: - dsi_drm_bridge_cleanup(bridge); error: mutex_unlock(&display->display_lock); return rc; } -int dsi_display_drm_deinit(struct dsi_display *display) +int dsi_display_drm_bridge_deinit(struct dsi_display *display) { int rc = 0; @@ -1962,9 +1949,7 @@ int dsi_display_drm_deinit(struct dsi_display *display) mutex_lock(&display->display_lock); - dsi_drm_connector_cleanup(display->connector); dsi_drm_bridge_cleanup(display->bridge); - display->connector = NULL; display->bridge = NULL; mutex_unlock(&display->display_lock); @@ -2003,8 +1988,6 @@ int dsi_display_get_info(struct dsi_display *display, info->width_mm = phy_props.panel_width_mm; info->height_mm = phy_props.panel_height_mm; - strlcpy(info->display_type, display->display_type, - sizeof(display->display_type)); info->op_mode = display->panel->mode.panel_mode; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h index 0631bac5cd9e..88f396f99af6 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h @@ -55,7 +55,6 @@ enum dsi_display_type { /** * struct dsi_display_info - defines dsi display properties - * @display_type: Display type as defined by device tree. * @type: Type of panel connected to DSI interface. * @num_of_h_tiles: In case of split panels, number of h tiles indicates the * number of dsi interfaces used. For single DSI panels this @@ -70,7 +69,6 @@ enum dsi_display_type { * @dsi_op_mode: dsi operation mode, video or cmd mode */ struct dsi_display_info { - char display_type[20]; enum dsi_display_type type; /* Split DSI properties */ @@ -185,7 +183,6 @@ struct dsi_display { bool is_tpg_enabled; struct mipi_dsi_host host; - struct dsi_connector *connector; struct dsi_bridge *bridge; u32 cmd_engine_refcount; @@ -284,22 +281,23 @@ int dsi_display_bind(struct dsi_display *display, struct drm_device *dev); int dsi_display_unbind(struct dsi_display *display); /** - * dsi_display_drm_init() - initializes DRM objects for the display device. + * dsi_display_drm_bridge_init() - initializes DRM bridge object for DSI * @display: Handle to the display. * @encoder: Pointer to the encoder object which is connected to the * display. * * Return: error code. */ -int dsi_display_drm_init(struct dsi_display *display, struct drm_encoder *enc); +int dsi_display_drm_bridge_init(struct dsi_display *display, + struct drm_encoder *enc); /** - * dsi_display_drm_deinit() - destroys DRM objects assosciated with the display + * dsi_display_drm_bridge_deinit() - destroys DRM bridge for the display * @display: Handle to the display. * * Return: error code. */ -int dsi_display_drm_deinit(struct dsi_display *display); +int dsi_display_drm_bridge_deinit(struct dsi_display *display); /** * dsi_display_get_info() - returns the display properties diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c index 8f5e6664621f..7ffcfa7f962b 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c @@ -17,11 +17,11 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic.h> -#include "dsi_drm.h" #include "msm_kms.h" +#include "sde_connector.h" +#include "dsi_drm.h" #define to_dsi_bridge(x) container_of((x), struct dsi_bridge, base) -#define to_dsi_connector(x) container_of((x), struct dsi_connector, base) #define to_dsi_state(x) container_of((x), struct dsi_connector_state, base) static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode, @@ -265,101 +265,59 @@ static const struct drm_bridge_funcs dsi_bridge_ops = { .mode_set = dsi_bridge_mode_set, }; -static enum drm_connector_status dsi_conn_detect(struct drm_connector *conn, - bool force) +int dsi_conn_post_init(struct drm_connector *connector, + void *info, + void *display) { - int rc = 0; - enum drm_connector_status status = connector_status_connected; - struct dsi_connector *c_conn = to_dsi_connector(conn); - struct dsi_display_info info; - struct drm_property_blob *blob; - size_t len; - - memset(&info, 0x0, sizeof(info)); - rc = dsi_display_get_info(c_conn->display, &info); - if (rc) { - pr_err("[%d] failed to get display info, rc=%d\n", - c_conn->id, rc); - status = connector_status_disconnected; - goto error; - } - - if (info.is_hot_pluggable) { - status = (info.is_connected ? connector_status_connected : - connector_status_disconnected); - } - - conn->display_info.width_mm = info.width_mm; - conn->display_info.height_mm = info.height_mm; - - len = strnlen(info.display_type, sizeof(info.display_type)); - - blob = drm_property_create_blob(conn->dev, - len, - info.display_type); - if (IS_ERR_OR_NULL(blob)) { - rc = PTR_ERR(blob); - pr_err("failed to create blob, rc=%d\n", rc); - status = connector_status_connected; - goto error; - } - - rc = drm_object_property_set_value(&conn->base, - c_conn->display_type, - blob->base.id); - if (rc) { - pr_err("failed to update display_type prop, rc=%d\n", rc); - status = connector_status_disconnected; - drm_property_unreference_blob(blob); - goto error; - } + if (info) + sde_kms_info_add_keystr(info, + "DISPLAY_TYPE", + ((struct dsi_display *)display)->display_type); - c_conn->display_type_blob = blob; -error: - return status; + return 0; } -static void dsi_connector_destroy(struct drm_connector *connector) +enum drm_connector_status dsi_conn_detect(struct drm_connector *conn, + bool force, + void *display) { - struct dsi_connector *c_conn = to_dsi_connector(connector); - - drm_connector_unregister(connector); - drm_connector_cleanup(connector); - kfree(c_conn); -} + enum drm_connector_status status = connector_status_unknown; + struct dsi_display_info dsi_info; + int rc; -static struct drm_connector_state * -dsi_connector_atomic_dup_state(struct drm_connector *connector) -{ - struct dsi_connector_state *state = to_dsi_state(connector->state); - struct dsi_connector_state *duplicate; + if (!conn || !display) + return status; - duplicate = kmemdup(state, sizeof(*state), GFP_KERNEL); - if (!duplicate) - return NULL; + /* get display dsi_info */ + memset(&dsi_info, 0x0, sizeof(dsi_info)); + rc = dsi_display_get_info(display, &dsi_info); + if (rc) { + pr_err("failed to get display dsi_info, rc=%d\n", rc); + return connector_status_disconnected; + } - return &duplicate->base; -} + if (dsi_info.is_hot_pluggable) + status = (dsi_info.is_connected ? connector_status_connected : + connector_status_disconnected); + else + status = connector_status_connected; -static void dsi_connector_atomic_destroy_state(struct drm_connector *conn, - struct drm_connector_state *state) -{ - struct dsi_connector_state *c_state = to_dsi_state(state); + conn->display_info.width_mm = dsi_info.width_mm; + conn->display_info.height_mm = dsi_info.height_mm; - kfree(c_state); + return status; } -static int dsi_connector_get_modes(struct drm_connector *connector) +int dsi_connector_get_modes(struct drm_connector *connector, + void *display) { - int rc = 0; u32 count = 0; u32 size = 0; - int i = 0; - struct dsi_connector *c_conn = to_dsi_connector(connector); struct dsi_display_mode *modes; struct drm_display_mode drm_mode; + int rc, i; - if (c_conn->panel) { + if (sde_connector_get_panel(connector)) { /* * TODO: If drm_panel is attached, query modes from the panel. * This is complicated in split dsi cases because panel is not @@ -367,11 +325,9 @@ static int dsi_connector_get_modes(struct drm_connector *connector) */ goto end; } - - rc = dsi_display_get_modes(c_conn->display, NULL, &count); + rc = dsi_display_get_modes(display, NULL, &count); if (rc) { - pr_err("[%d] failed to get num of modes, rc=%d\n", - c_conn->id, rc); + pr_err("failed to get num of modes, rc=%d\n", rc); goto error; } @@ -382,10 +338,9 @@ static int dsi_connector_get_modes(struct drm_connector *connector) goto end; } - rc = dsi_display_get_modes(c_conn->display, modes, &count); + rc = dsi_display_get_modes(display, modes, &count); if (rc) { - pr_err("[%d] failed to get modes, rc=%d\n", - c_conn->id, rc); + pr_err("failed to get modes, rc=%d\n", rc); count = 0; goto error; } @@ -397,8 +352,8 @@ static int dsi_connector_get_modes(struct drm_connector *connector) convert_to_drm_mode(&modes[i], &drm_mode); m = drm_mode_duplicate(connector->dev, &drm_mode); if (!m) { - pr_err("[%d] failed to add mode %ux%u\n", - c_conn->id, drm_mode.hdisplay, + pr_err("failed to add mode %ux%u\n", + drm_mode.hdisplay, drm_mode.vdisplay); count = -ENOMEM; goto error; @@ -414,12 +369,12 @@ end: return count; } -static enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode, + void *display) { - int rc = 0; struct dsi_display_mode dsi_mode; - struct dsi_connector *c_conn = to_dsi_connector(connector); + int rc; if (!connector || !mode) { pr_err("Invalid params\n"); @@ -428,122 +383,16 @@ static enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector, convert_to_dsi_mode(mode, &dsi_mode); - rc = dsi_display_validate_mode(c_conn->display, &dsi_mode, + rc = dsi_display_validate_mode(display, &dsi_mode, DSI_VALIDATE_FLAG_ALLOW_ADJUST); if (rc) { - pr_err("[%d] mode not supported, rc=%d\n", c_conn->id, rc); + pr_err("mode not supported, rc=%d\n", rc); return MODE_BAD; } return MODE_OK; } -static struct drm_encoder *dsi_conn_best_encoder(struct drm_connector *conn) -{ - struct dsi_connector *connector = to_dsi_connector(conn); - /* - * This is true for now, revisit this code when multiple encoders are - * supported. - */ - return connector->encoder; -} - - -static const struct drm_connector_funcs dsi_conn_ops = { - .dpms = drm_atomic_helper_connector_dpms, - .reset = drm_atomic_helper_connector_reset, - - .detect = dsi_conn_detect, - .destroy = dsi_connector_destroy, - .fill_modes = drm_helper_probe_single_connector_modes, - .atomic_duplicate_state = dsi_connector_atomic_dup_state, - .atomic_destroy_state = dsi_connector_atomic_destroy_state, -}; - -static const struct dsi_connector_helper_funcs dsi_conn_helper_ops = { - .base = { - .get_modes = dsi_connector_get_modes, - .mode_valid = dsi_conn_mode_valid, - .best_encoder = dsi_conn_best_encoder, - }, -}; - -struct dsi_connector *dsi_drm_connector_init(struct dsi_display *display, - struct drm_device *dev, - struct dsi_bridge *bridge) -{ - int rc = 0; - struct dsi_connector *conn; - struct drm_property *blob; - - conn = kzalloc(sizeof(*conn), GFP_KERNEL); - if (!conn) { - rc = -ENOMEM; - goto error; - } - - conn->display = display; - - rc = drm_connector_init(dev, - &conn->base, - &dsi_conn_ops, - DRM_MODE_CONNECTOR_DSI); - if (rc) { - pr_err("failed to initialize drm connector, rc=%d\n", rc); - goto error_free_conn; - } - - conn->base.helper_private = &dsi_conn_helper_ops; - - conn->base.polled = DRM_CONNECTOR_POLL_HPD; - conn->base.interlace_allowed = 0; - conn->base.doublescan_allowed = 0; - - rc = drm_connector_register(&conn->base); - if (rc) { - pr_err("failed to register drm connector, rc=%d\n", rc); - goto error_cleanup_conn; - } - - rc = drm_mode_connector_attach_encoder(&conn->base, - bridge->base.encoder); - if (rc) { - pr_err("failed to attach encoder to connector, rc=%d\n", rc); - goto error_unregister_conn; - } - - conn->encoder = bridge->base.encoder; - - blob = drm_property_create(dev, - DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, - "DISPLAY_TYPE", 0); - if (!blob) { - pr_err("failed to create DISPLAY_TYPE property\n"); - goto error_unregister_conn; - } - - drm_object_attach_property(&conn->base.base, blob, 0); - conn->display_type = blob; - - return conn; - -error_unregister_conn: - drm_connector_unregister(&conn->base); -error_cleanup_conn: - drm_connector_cleanup(&conn->base); -error_free_conn: - kfree(conn); -error: - return ERR_PTR(rc); -} - -void dsi_drm_connector_cleanup(struct dsi_connector *conn) -{ - drm_connector_unregister(&conn->base); - drm_connector_cleanup(&conn->base); - kfree(conn); -} - struct dsi_bridge *dsi_drm_bridge_init(struct dsi_display *display, struct drm_device *dev, struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h index 0fdf2665c079..934899bd2068 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h @@ -20,32 +20,9 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include "dsi_display.h" - -struct dsi_connector_state { - struct drm_connector_state base; -}; - -struct dsi_connector_helper_funcs { - struct drm_connector_helper_funcs base; -}; - -struct dsi_connector { - struct drm_connector base; - u32 id; - - struct dsi_display *display; - struct drm_panel *panel; - struct drm_encoder *encoder; - - struct drm_property *display_type; - struct drm_property_blob *display_type_blob; +#include "msm_drv.h" - enum dsi_display_type type; - bool has_tile; - u32 h_tile_id; - bool is_master; -}; +#include "dsi_display.h" struct dsi_bridge { struct drm_bridge base; @@ -55,14 +32,52 @@ struct dsi_bridge { struct dsi_display_mode dsi_mode; }; -struct dsi_connector *dsi_drm_connector_init(struct dsi_display *display, - struct drm_device *dev, - struct dsi_bridge *bridge); -void dsi_drm_connector_cleanup(struct dsi_connector *conn); +/** + * dsi_conn_post_init - callback to perform additional initialization steps + * @connector: Pointer to drm connector structure + * @info: Pointer to sde connector info structure + * @display: Pointer to private display handle + * Returns: Zero on success + */ +int dsi_conn_post_init(struct drm_connector *connector, + void *info, + void *display); + +/** + * dsi_conn_detect - callback to determine if connector is connected + * @connector: Pointer to drm connector structure + * @force: Force detect setting from drm framework + * @display: Pointer to private display handle + * Returns: Connector 'is connected' status + */ +enum drm_connector_status dsi_conn_detect(struct drm_connector *conn, + bool force, + void *display); + +/** + * dsi_connector_get_modes - callback to add drm modes via drm_mode_probed_add() + * @connector: Pointer to drm connector structure + * @display: Pointer to private display handle + * Returns: Number of modes added + */ +int dsi_connector_get_modes(struct drm_connector *connector, + void *display); + +/** + * dsi_conn_mode_valid - callback to determine if specified mode is valid + * @connector: Pointer to drm connector structure + * @mode: Pointer to drm mode structure + * @display: Pointer to private display handle + * Returns: Validity status for specified mode + */ +enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode, + void *display); struct dsi_bridge *dsi_drm_bridge_init(struct dsi_display *display, - struct drm_device *dev, - struct drm_encoder *encoder); + struct drm_device *dev, + struct drm_encoder *encoder); void dsi_drm_bridge_cleanup(struct dsi_bridge *bridge); + #endif /* _DSI_DRM_H_ */ |
