Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: Repurpose lvds-encoder.c

lvds-encoder.c implementation is also suitable for LVDS decoders,
not just LVDS encoders.
Instead of creating a new driver for addressing support for
transparent LVDS decoders, repurpose lvds-encoder.c for the greater
good with this patch.

This patch only "rebrands" the lvds-encoder.c driver, to make it
suitable for hosting LVDS decoders support. The actual support for
LVDS decoders will come with a later patch.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-6-git-send-email-fabrizio.castro@bp.renesas.com

authored by

Fabrizio Castro and committed by
Neil Armstrong
0d60131a 4788f4e1

+159 -160
+4 -4
drivers/gpu/drm/bridge/Kconfig
··· 35 35 Support for non-programmable RGB to VGA DAC bridges, such as ADI 36 36 ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs. 37 37 38 - config DRM_LVDS_ENCODER 39 - tristate "Transparent parallel to LVDS encoder support" 38 + config DRM_LVDS_CODEC 39 + tristate "Transparent LVDS encoders and decoders support" 40 40 depends on OF 41 41 select DRM_KMS_HELPER 42 42 select DRM_PANEL_BRIDGE 43 43 help 44 - Support for transparent parallel to LVDS encoders that don't require 45 - any configuration. 44 + Support for transparent LVDS encoders and decoders that don't 45 + require any configuration. 46 46 47 47 config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW 48 48 tristate "MegaChips stdp4028-ge-b850v3-fw and stdp2690-ge-b850v3-fw"
+1 -1
drivers/gpu/drm/bridge/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o 3 3 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o 4 - obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o 4 + obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o 5 5 obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o 6 6 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o 7 7 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
+154
drivers/gpu/drm/bridge/lvds-codec.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright (C) 2019 Renesas Electronics Corporation 4 + * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com> 5 + */ 6 + 7 + #include <linux/gpio/consumer.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/of_graph.h> 11 + #include <linux/platform_device.h> 12 + 13 + #include <drm/drm_bridge.h> 14 + #include <drm/drm_panel.h> 15 + 16 + struct lvds_codec { 17 + struct drm_bridge bridge; 18 + struct drm_bridge *panel_bridge; 19 + struct gpio_desc *powerdown_gpio; 20 + }; 21 + 22 + static int lvds_codec_attach(struct drm_bridge *bridge) 23 + { 24 + struct lvds_codec *lvds_codec = container_of(bridge, 25 + struct lvds_codec, bridge); 26 + 27 + return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge, 28 + bridge); 29 + } 30 + 31 + static void lvds_codec_enable(struct drm_bridge *bridge) 32 + { 33 + struct lvds_codec *lvds_codec = container_of(bridge, 34 + struct lvds_codec, bridge); 35 + 36 + if (lvds_codec->powerdown_gpio) 37 + gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0); 38 + } 39 + 40 + static void lvds_codec_disable(struct drm_bridge *bridge) 41 + { 42 + struct lvds_codec *lvds_codec = container_of(bridge, 43 + struct lvds_codec, bridge); 44 + 45 + if (lvds_codec->powerdown_gpio) 46 + gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1); 47 + } 48 + 49 + static struct drm_bridge_funcs funcs = { 50 + .attach = lvds_codec_attach, 51 + .enable = lvds_codec_enable, 52 + .disable = lvds_codec_disable, 53 + }; 54 + 55 + static int lvds_codec_probe(struct platform_device *pdev) 56 + { 57 + struct device *dev = &pdev->dev; 58 + struct device_node *port; 59 + struct device_node *endpoint; 60 + struct device_node *panel_node; 61 + struct drm_panel *panel; 62 + struct lvds_codec *lvds_codec; 63 + 64 + lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL); 65 + if (!lvds_codec) 66 + return -ENOMEM; 67 + 68 + lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", 69 + GPIOD_OUT_HIGH); 70 + if (IS_ERR(lvds_codec->powerdown_gpio)) { 71 + int err = PTR_ERR(lvds_codec->powerdown_gpio); 72 + 73 + if (err != -EPROBE_DEFER) 74 + dev_err(dev, "powerdown GPIO failure: %d\n", err); 75 + return err; 76 + } 77 + 78 + /* Locate the panel DT node. */ 79 + port = of_graph_get_port_by_id(dev->of_node, 1); 80 + if (!port) { 81 + dev_dbg(dev, "port 1 not found\n"); 82 + return -ENXIO; 83 + } 84 + 85 + endpoint = of_get_child_by_name(port, "endpoint"); 86 + of_node_put(port); 87 + if (!endpoint) { 88 + dev_dbg(dev, "no endpoint for port 1\n"); 89 + return -ENXIO; 90 + } 91 + 92 + panel_node = of_graph_get_remote_port_parent(endpoint); 93 + of_node_put(endpoint); 94 + if (!panel_node) { 95 + dev_dbg(dev, "no remote endpoint for port 1\n"); 96 + return -ENXIO; 97 + } 98 + 99 + panel = of_drm_find_panel(panel_node); 100 + of_node_put(panel_node); 101 + if (IS_ERR(panel)) { 102 + dev_dbg(dev, "panel not found, deferring probe\n"); 103 + return PTR_ERR(panel); 104 + } 105 + 106 + lvds_codec->panel_bridge = 107 + devm_drm_panel_bridge_add_typed(dev, panel, 108 + DRM_MODE_CONNECTOR_LVDS); 109 + if (IS_ERR(lvds_codec->panel_bridge)) 110 + return PTR_ERR(lvds_codec->panel_bridge); 111 + 112 + /* 113 + * The panel_bridge bridge is attached to the panel's of_node, 114 + * but we need a bridge attached to our of_node for our user 115 + * to look up. 116 + */ 117 + lvds_codec->bridge.of_node = dev->of_node; 118 + lvds_codec->bridge.funcs = &funcs; 119 + drm_bridge_add(&lvds_codec->bridge); 120 + 121 + platform_set_drvdata(pdev, lvds_codec); 122 + 123 + return 0; 124 + } 125 + 126 + static int lvds_codec_remove(struct platform_device *pdev) 127 + { 128 + struct lvds_codec *lvds_codec = platform_get_drvdata(pdev); 129 + 130 + drm_bridge_remove(&lvds_codec->bridge); 131 + 132 + return 0; 133 + } 134 + 135 + static const struct of_device_id lvds_codec_match[] = { 136 + { .compatible = "lvds-encoder" }, 137 + { .compatible = "thine,thc63lvdm83d" }, 138 + {}, 139 + }; 140 + MODULE_DEVICE_TABLE(of, lvds_codec_match); 141 + 142 + static struct platform_driver lvds_codec_driver = { 143 + .probe = lvds_codec_probe, 144 + .remove = lvds_codec_remove, 145 + .driver = { 146 + .name = "lvds-codec", 147 + .of_match_table = lvds_codec_match, 148 + }, 149 + }; 150 + module_platform_driver(lvds_codec_driver); 151 + 152 + MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 153 + MODULE_DESCRIPTION("LVDS encoders and decoders"); 154 + MODULE_LICENSE("GPL");
-155
drivers/gpu/drm/bridge/lvds-encoder.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com> 4 - */ 5 - 6 - #include <linux/gpio/consumer.h> 7 - #include <linux/module.h> 8 - #include <linux/of.h> 9 - #include <linux/of_graph.h> 10 - #include <linux/platform_device.h> 11 - 12 - #include <drm/drm_bridge.h> 13 - #include <drm/drm_panel.h> 14 - 15 - struct lvds_encoder { 16 - struct drm_bridge bridge; 17 - struct drm_bridge *panel_bridge; 18 - struct gpio_desc *powerdown_gpio; 19 - }; 20 - 21 - static int lvds_encoder_attach(struct drm_bridge *bridge) 22 - { 23 - struct lvds_encoder *lvds_encoder = container_of(bridge, 24 - struct lvds_encoder, 25 - bridge); 26 - 27 - return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge, 28 - bridge); 29 - } 30 - 31 - static void lvds_encoder_enable(struct drm_bridge *bridge) 32 - { 33 - struct lvds_encoder *lvds_encoder = container_of(bridge, 34 - struct lvds_encoder, 35 - bridge); 36 - 37 - if (lvds_encoder->powerdown_gpio) 38 - gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 0); 39 - } 40 - 41 - static void lvds_encoder_disable(struct drm_bridge *bridge) 42 - { 43 - struct lvds_encoder *lvds_encoder = container_of(bridge, 44 - struct lvds_encoder, 45 - bridge); 46 - 47 - if (lvds_encoder->powerdown_gpio) 48 - gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1); 49 - } 50 - 51 - static struct drm_bridge_funcs funcs = { 52 - .attach = lvds_encoder_attach, 53 - .enable = lvds_encoder_enable, 54 - .disable = lvds_encoder_disable, 55 - }; 56 - 57 - static int lvds_encoder_probe(struct platform_device *pdev) 58 - { 59 - struct device *dev = &pdev->dev; 60 - struct device_node *port; 61 - struct device_node *endpoint; 62 - struct device_node *panel_node; 63 - struct drm_panel *panel; 64 - struct lvds_encoder *lvds_encoder; 65 - 66 - lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL); 67 - if (!lvds_encoder) 68 - return -ENOMEM; 69 - 70 - lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", 71 - GPIOD_OUT_HIGH); 72 - if (IS_ERR(lvds_encoder->powerdown_gpio)) { 73 - int err = PTR_ERR(lvds_encoder->powerdown_gpio); 74 - 75 - if (err != -EPROBE_DEFER) 76 - dev_err(dev, "powerdown GPIO failure: %d\n", err); 77 - return err; 78 - } 79 - 80 - /* Locate the panel DT node. */ 81 - port = of_graph_get_port_by_id(dev->of_node, 1); 82 - if (!port) { 83 - dev_dbg(dev, "port 1 not found\n"); 84 - return -ENXIO; 85 - } 86 - 87 - endpoint = of_get_child_by_name(port, "endpoint"); 88 - of_node_put(port); 89 - if (!endpoint) { 90 - dev_dbg(dev, "no endpoint for port 1\n"); 91 - return -ENXIO; 92 - } 93 - 94 - panel_node = of_graph_get_remote_port_parent(endpoint); 95 - of_node_put(endpoint); 96 - if (!panel_node) { 97 - dev_dbg(dev, "no remote endpoint for port 1\n"); 98 - return -ENXIO; 99 - } 100 - 101 - panel = of_drm_find_panel(panel_node); 102 - of_node_put(panel_node); 103 - if (IS_ERR(panel)) { 104 - dev_dbg(dev, "panel not found, deferring probe\n"); 105 - return PTR_ERR(panel); 106 - } 107 - 108 - lvds_encoder->panel_bridge = 109 - devm_drm_panel_bridge_add_typed(dev, panel, 110 - DRM_MODE_CONNECTOR_LVDS); 111 - if (IS_ERR(lvds_encoder->panel_bridge)) 112 - return PTR_ERR(lvds_encoder->panel_bridge); 113 - 114 - /* The panel_bridge bridge is attached to the panel's of_node, 115 - * but we need a bridge attached to our of_node for our user 116 - * to look up. 117 - */ 118 - lvds_encoder->bridge.of_node = dev->of_node; 119 - lvds_encoder->bridge.funcs = &funcs; 120 - drm_bridge_add(&lvds_encoder->bridge); 121 - 122 - platform_set_drvdata(pdev, lvds_encoder); 123 - 124 - return 0; 125 - } 126 - 127 - static int lvds_encoder_remove(struct platform_device *pdev) 128 - { 129 - struct lvds_encoder *lvds_encoder = platform_get_drvdata(pdev); 130 - 131 - drm_bridge_remove(&lvds_encoder->bridge); 132 - 133 - return 0; 134 - } 135 - 136 - static const struct of_device_id lvds_encoder_match[] = { 137 - { .compatible = "lvds-encoder" }, 138 - { .compatible = "thine,thc63lvdm83d" }, 139 - {}, 140 - }; 141 - MODULE_DEVICE_TABLE(of, lvds_encoder_match); 142 - 143 - static struct platform_driver lvds_encoder_driver = { 144 - .probe = lvds_encoder_probe, 145 - .remove = lvds_encoder_remove, 146 - .driver = { 147 - .name = "lvds-encoder", 148 - .of_match_table = lvds_encoder_match, 149 - }, 150 - }; 151 - module_platform_driver(lvds_encoder_driver); 152 - 153 - MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 154 - MODULE_DESCRIPTION("Transparent parallel to LVDS encoder"); 155 - MODULE_LICENSE("GPL");