From fc903ebd50d0396b5de1ff614a009c2ddcb3222c Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 12 Feb 2016 14:48:30 +0530 Subject: drm/dsi: Check for CONFIG_OF when defining of_mipi_dsi_device_add() of_mipi_dsi_device_add() is used only when CONFIG_OF is enabled. It currently works if OF support is disabled, but this will change when we add more functionality to it. Define the original function if CONFIG_OF is enabled and a dummy function otherwise. Signed-off-by: Archit Taneja Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_mipi_dsi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 6e6a9c58d404..4f2a70471e05 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -129,6 +129,7 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi) return device_add(&dsi->dev); } +#if IS_ENABLED(CONFIG_OF) static struct mipi_dsi_device * of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) { @@ -170,6 +171,13 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) return dsi; } +#else +static struct mipi_dsi_device * +of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) +{ + return ERR_PTR(-ENODEV); +} +#endif int mipi_dsi_host_register(struct mipi_dsi_host *host) { -- cgit v1.2.3 From c63ae8a9686bb8c87154a31dc5ebadbda778a8e5 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 12 Feb 2016 14:48:31 +0530 Subject: drm/dsi: Use mipi_dsi_device_register_full() for DSI device creation Use mipi_dsi_device_register_full() for device creation. This takes in a struct mipi_dsi_device_info as a template to populate the DSI device information. The reason to introduce this is to have a way to create DSI devices not available via DT. Drivers that want to create a DSI device can populate a struct mipi_dsi_device_info and call this function. For DSI devices available via DT, of_mipi_dsi_device_add() is used as before, but this now calls mipi_dsi_device_register_full() internally. Signed-off-by: Archit Taneja Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_mipi_dsi.c | 64 +++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 4f2a70471e05..5d7243da2323 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -133,8 +133,8 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi) static struct mipi_dsi_device * of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) { - struct mipi_dsi_device *dsi; struct device *dev = host->dev; + struct mipi_dsi_device_info info = { }; int ret; u32 reg; @@ -145,39 +145,69 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) return ERR_PTR(-EINVAL); } - if (reg > 3) { - dev_err(dev, "device node %s has invalid reg property: %u\n", - node->full_name, reg); + info.channel = reg; + info.node = of_node_get(node); + + return mipi_dsi_device_register_full(host, &info); +} +#else +static struct mipi_dsi_device * +of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) +{ + return ERR_PTR(-ENODEV); +} +#endif + +/** + * mipi_dsi_device_register_full - create a MIPI DSI device + * @host: DSI host to which this device is connected + * @info: pointer to template containing DSI device information + * + * Create a MIPI DSI device by using the device information provided by + * mipi_dsi_device_info template + * + * Returns: + * A pointer to the newly created MIPI DSI device, or, a pointer encoded + * with an error + */ +struct mipi_dsi_device * +mipi_dsi_device_register_full(struct mipi_dsi_host *host, + const struct mipi_dsi_device_info *info) +{ + struct mipi_dsi_device *dsi; + struct device *dev = host->dev; + int ret; + + if (!info) { + dev_err(dev, "invalid mipi_dsi_device_info pointer\n"); + return ERR_PTR(-EINVAL); + } + + if (info->channel > 3) { + dev_err(dev, "invalid virtual channel: %u\n", info->channel); return ERR_PTR(-EINVAL); } dsi = mipi_dsi_device_alloc(host); if (IS_ERR(dsi)) { - dev_err(dev, "failed to allocate DSI device %s: %ld\n", - node->full_name, PTR_ERR(dsi)); + dev_err(dev, "failed to allocate DSI device %ld\n", + PTR_ERR(dsi)); return dsi; } - dsi->dev.of_node = of_node_get(node); - dsi->channel = reg; + dsi->dev.of_node = info->node; + dsi->channel = info->channel; ret = mipi_dsi_device_add(dsi); if (ret) { - dev_err(dev, "failed to add DSI device %s: %d\n", - node->full_name, ret); + dev_err(dev, "failed to add DSI device %d\n", ret); kfree(dsi); return ERR_PTR(ret); } return dsi; } -#else -static struct mipi_dsi_device * -of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) -{ - return ERR_PTR(-ENODEV); -} -#endif +EXPORT_SYMBOL(mipi_dsi_device_register_full); int mipi_dsi_host_register(struct mipi_dsi_host *host) { -- cgit v1.2.3 From bf4363ce3a67ba06042351f40841ef4da9b30787 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 12 Feb 2016 14:48:32 +0530 Subject: drm/dsi: Try to match non-DT DSI devices Add a device name field in struct mipi_dsi_device. This name is not the same as the device name (which is of the format "hostname.reg"). When the device is created via DT, this name is set to the modalias string. In the non-DT case, the driver creating the DSI device provides the name by populating a field in struct mipi_dsi_device_info. Matching for DT case would be as it was before. For the non-DT case, we compare the device and driver names. Other buses (like I2C/SPI) perform a non-DT match by comparing the device name and entries in the driver's id_table. Such a mechanism isn't used for the DSI bus. Reviewed-by: Andrzej Hajda Signed-off-by: Archit Taneja Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_mipi_dsi.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 5d7243da2323..42a7aacf7a2f 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -47,7 +47,17 @@ static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv) { - return of_driver_match_device(dev, drv); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); + + /* attempt OF style match */ + if (of_driver_match_device(dev, drv)) + return 1; + + /* compare DSI device and driver names */ + if (!strcmp(dsi->name, drv->name)) + return 1; + + return 0; } static const struct dev_pm_ops mipi_dsi_device_pm_ops = { @@ -138,6 +148,11 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) int ret; u32 reg; + if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { + dev_err(dev, "modalias failure on %s\n", node->full_name); + return ERR_PTR(-EINVAL); + } + ret = of_property_read_u32(node, "reg", ®); if (ret) { dev_err(dev, "device node %s has no valid reg property: %d\n", @@ -197,6 +212,7 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host, dsi->dev.of_node = info->node; dsi->channel = info->channel; + strlcpy(dsi->name, info->type, sizeof(dsi->name)); ret = mipi_dsi_device_add(dsi); if (ret) { -- cgit v1.2.3 From 509e42ce0441df39d5241150c1bec32cf6347b6c Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 12 Feb 2016 14:48:33 +0530 Subject: drm/dsi: Add routine to unregister a DSI device A driver calling mipi_dsi_device_register_full() might want to remove the device once it's done. It might also require it in an error handling path in case something went wrong. Create mipi_dsi_device_unregister() for this purpose and use it within mipi_dsi_remove_device_fn() as it does the same thing. Reviewed-by: Andrzej Hajda Signed-off-by: Archit Taneja Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_mipi_dsi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 42a7aacf7a2f..f2f5a6d3669a 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -225,6 +225,16 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host, } EXPORT_SYMBOL(mipi_dsi_device_register_full); +/** + * mipi_dsi_device_unregister - unregister MIPI DSI device + * @dsi: DSI peripheral device + */ +void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi) +{ + device_unregister(&dsi->dev); +} +EXPORT_SYMBOL(mipi_dsi_device_unregister); + int mipi_dsi_host_register(struct mipi_dsi_host *host) { struct device_node *node; @@ -244,7 +254,7 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv) { struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); - device_unregister(&dsi->dev); + mipi_dsi_device_unregister(dsi); return 0; } -- cgit v1.2.3 From 97b6ae50e05c533b6455e304d36bdf2bb5604ee6 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 12 Feb 2016 14:48:34 +0530 Subject: drm/dsi: Get DSI host by DT device node MIPI DSI devices are inherently aware of their host because they share a parent-child hierarchy in the device tree. Non-DSI drivers that create DSI device don't have this data. In order to get this information, they require to a phandle to the DSI host in the device tree. Maintain a list of all the DSI hosts that are currently registered. This list will be used to find the struct mipi_dsi_host corresponding to the device tree node passed to of_find_mipi_dsi_host_by_node(). Reviewed-by: Andrzej Hajda Signed-off-by: Archit Taneja Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_mipi_dsi.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index f2f5a6d3669a..f5d80839a90c 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -235,6 +235,37 @@ void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi) } EXPORT_SYMBOL(mipi_dsi_device_unregister); +static DEFINE_MUTEX(host_lock); +static LIST_HEAD(host_list); + +/** + * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a + * device tree node + * @node: device tree node + * + * Returns: + * A pointer to the MIPI DSI host corresponding to @node or NULL if no + * such device exists (or has not been registered yet). + */ +struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node) +{ + struct mipi_dsi_host *host; + + mutex_lock(&host_lock); + + list_for_each_entry(host, &host_list, list) { + if (host->dev->of_node == node) { + mutex_unlock(&host_lock); + return host; + } + } + + mutex_unlock(&host_lock); + + return NULL; +} +EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node); + int mipi_dsi_host_register(struct mipi_dsi_host *host) { struct device_node *node; @@ -246,6 +277,10 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host) of_mipi_dsi_device_add(host, node); } + mutex_lock(&host_lock); + list_add_tail(&host->list, &host_list); + mutex_unlock(&host_lock); + return 0; } EXPORT_SYMBOL(mipi_dsi_host_register); @@ -262,6 +297,10 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv) void mipi_dsi_host_unregister(struct mipi_dsi_host *host) { device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn); + + mutex_lock(&host_lock); + list_del_init(&host->list); + mutex_unlock(&host_lock); } EXPORT_SYMBOL(mipi_dsi_host_unregister); -- cgit v1.2.3 From 2e8c5eb9ef938a069fd9586769787021b2541698 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Tue, 1 Mar 2016 18:06:54 -0500 Subject: drm/panel: simple: Fix g121x1_l03 hsync/vsync polarity Set hsync/vsync to active low for g121x1_l03 panel to match the recommended setting in the datasheet. Signed-off-by: Akshay Bhat Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index f88a631c43ab..7a65cc849355 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -847,6 +847,7 @@ static const struct drm_display_mode innolux_g121x1_l03_mode = { .vsync_end = 768 + 38 + 1, .vtotal = 768 + 38 + 1 + 0, .vrefresh = 60, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, }; static const struct panel_desc innolux_g121x1_l03 = { -- cgit v1.2.3 From 690d8fa70da2f81cf880a656d254d02172ed9c7b Mon Sep 17 00:00:00 2001 From: Jitao Shi Date: Mon, 22 Feb 2016 19:01:44 +0800 Subject: drm/panel: simple: Support for LG lp120up1 panel The LG lp120up1 TFT LCD panel with eDP interface is a 12.0" 1920x1280 panel, which can be supported by the simple panel driver. Signed-off-by: Jitao Shi Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 7a65cc849355..5186dbf6901c 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -983,6 +983,29 @@ static const struct panel_desc lg_lb070wv8 = { .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, }; +static const struct drm_display_mode lg_lp120up1_mode = { + .clock = 162300, + .hdisplay = 1920, + .hsync_start = 1920 + 40, + .hsync_end = 1920 + 40 + 40, + .htotal = 1920 + 40 + 40+ 80, + .vdisplay = 1280, + .vsync_start = 1280 + 4, + .vsync_end = 1280 + 4 + 4, + .vtotal = 1280 + 4 + 4 + 12, + .vrefresh = 60, +}; + +static const struct panel_desc lg_lp120up1 = { + .modes = &lg_lp120up1_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 267, + .height = 183, + }, +}; + static const struct drm_display_mode lg_lp129qe_mode = { .clock = 285250, .hdisplay = 2560, @@ -1256,6 +1279,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "lg,lb070wv8", .data = &lg_lb070wv8, + }, { + .compatible = "lg,lp120up1", + .data = &lg_lp120up1, }, { .compatible = "lg,lp129qe", .data = &lg_lp129qe, -- cgit v1.2.3 From 06a9dc65afbd9d9e81ee6352a13f968e0540237e Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sat, 13 Feb 2016 22:52:03 +0100 Subject: drm/panel: simple: Add URT UMSH-8596MD-xT panels support Add support for United Radiant Technology UMSH-8596MD-xT 7.0" WVGA TFT LCD panels in the simple-panel driver. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 5186dbf6901c..1d194c8581dc 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1200,6 +1200,42 @@ static const struct panel_desc shelly_sca07010_bfn_lnn = { .bus_format = MEDIA_BUS_FMT_RGB666_1X18, }; +static const struct display_timing urt_umsh_8596md_timing = { + .pixelclock = { 33260000, 33260000, 33260000 }, + .hactive = { 800, 800, 800 }, + .hfront_porch = { 41, 41, 41 }, + .hback_porch = { 216 - 128, 216 - 128, 216 - 128 }, + .hsync_len = { 71, 128, 128 }, + .vactive = { 480, 480, 480 }, + .vfront_porch = { 10, 10, 10 }, + .vback_porch = { 35 - 2, 35 - 2, 35 - 2 }, + .vsync_len = { 2, 2, 2 }, + .flags = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE | + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc urt_umsh_8596md_lvds = { + .timings = &urt_umsh_8596md_timing, + .num_timings = 1, + .bpc = 6, + .size = { + .width = 152, + .height = 91, + }, + .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, +}; + +static const struct panel_desc urt_umsh_8596md_parallel = { + .timings = &urt_umsh_8596md_timing, + .num_timings = 1, + .bpc = 6, + .size = { + .width = 152, + .height = 91, + }, + .bus_format = MEDIA_BUS_FMT_RGB666_1X18, +}; + static const struct of_device_id platform_of_match[] = { { .compatible = "ampire,am800480r3tmqwa1h", @@ -1306,6 +1342,24 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "shelly,sca07010-bfn-lnn", .data = &shelly_sca07010_bfn_lnn, + }, { + .compatible = "urt,umsh-8596md-t", + .data = &urt_umsh_8596md_parallel, + }, { + .compatible = "urt,umsh-8596md-1t", + .data = &urt_umsh_8596md_parallel, + }, { + .compatible = "urt,umsh-8596md-7t", + .data = &urt_umsh_8596md_parallel, + }, { + .compatible = "urt,umsh-8596md-11t", + .data = &urt_umsh_8596md_lvds, + }, { + .compatible = "urt,umsh-8596md-19t", + .data = &urt_umsh_8596md_lvds, + }, { + .compatible = "urt,umsh-8596md-20t", + .data = &urt_umsh_8596md_parallel, }, { /* sentinel */ } -- cgit v1.2.3 From c8a3b2ae07130042682bc8e031bcfbae3754463d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Feb 2016 11:51:06 +0200 Subject: drm/bridge: Make (pre/post) enable/disable callbacks optional Instead of forcing bridges to implement empty callbacks make them all optional. Signed-off-by: Laurent Pinchart Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_bridge.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index bd93453afa61..b3654404abd0 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -186,7 +186,8 @@ void drm_bridge_disable(struct drm_bridge *bridge) drm_bridge_disable(bridge->next); - bridge->funcs->disable(bridge); + if (bridge->funcs->disable) + bridge->funcs->disable(bridge); } EXPORT_SYMBOL(drm_bridge_disable); @@ -206,7 +207,8 @@ void drm_bridge_post_disable(struct drm_bridge *bridge) if (!bridge) return; - bridge->funcs->post_disable(bridge); + if (bridge->funcs->post_disable) + bridge->funcs->post_disable(bridge); drm_bridge_post_disable(bridge->next); } @@ -256,7 +258,8 @@ void drm_bridge_pre_enable(struct drm_bridge *bridge) drm_bridge_pre_enable(bridge->next); - bridge->funcs->pre_enable(bridge); + if (bridge->funcs->pre_enable) + bridge->funcs->pre_enable(bridge); } EXPORT_SYMBOL(drm_bridge_pre_enable); @@ -276,7 +279,8 @@ void drm_bridge_enable(struct drm_bridge *bridge) if (!bridge) return; - bridge->funcs->enable(bridge); + if (bridge->funcs->enable) + bridge->funcs->enable(bridge); drm_bridge_enable(bridge->next); } -- cgit v1.2.3