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_device.h> 11 #include <linux/of_graph.h> 12 #include <linux/platform_device.h> 13 #include <linux/regulator/consumer.h> 14 15 #include <drm/drm_atomic_helper.h> 16 #include <drm/drm_bridge.h> 17 #include <drm/drm_panel.h> 18 19 struct lvds_codec { 20 struct device *dev; 21 struct drm_bridge bridge; 22 struct drm_bridge *panel_bridge; 23 struct regulator *vcc; 24 struct gpio_desc *powerdown_gpio; 25 u32 connector_type; 26 unsigned int bus_format; 27 }; 28 29 static inline struct lvds_codec *to_lvds_codec(struct drm_bridge *bridge) 30 { 31 return container_of(bridge, struct lvds_codec, bridge); 32 } 33 34 static int lvds_codec_attach(struct drm_bridge *bridge, 35 enum drm_bridge_attach_flags flags) 36 { 37 struct lvds_codec *lvds_codec = to_lvds_codec(bridge); 38 39 return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge, 40 bridge, flags); 41 } 42 43 static void lvds_codec_enable(struct drm_bridge *bridge) 44 { 45 struct lvds_codec *lvds_codec = to_lvds_codec(bridge); 46 int ret; 47 48 ret = regulator_enable(lvds_codec->vcc); 49 if (ret) { 50 dev_err(lvds_codec->dev, 51 "Failed to enable regulator \"vcc\": %d\n", ret); 52 return; 53 } 54 55 if (lvds_codec->powerdown_gpio) 56 gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0); 57 } 58 59 static void lvds_codec_disable(struct drm_bridge *bridge) 60 { 61 struct lvds_codec *lvds_codec = to_lvds_codec(bridge); 62 int ret; 63 64 if (lvds_codec->powerdown_gpio) 65 gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1); 66 67 ret = regulator_disable(lvds_codec->vcc); 68 if (ret) 69 dev_err(lvds_codec->dev, 70 "Failed to disable regulator \"vcc\": %d\n", ret); 71 } 72 73 static const struct drm_bridge_funcs funcs = { 74 .attach = lvds_codec_attach, 75 .enable = lvds_codec_enable, 76 .disable = lvds_codec_disable, 77 }; 78 79 #define MAX_INPUT_SEL_FORMATS 1 80 static u32 * 81 lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge, 82 struct drm_bridge_state *bridge_state, 83 struct drm_crtc_state *crtc_state, 84 struct drm_connector_state *conn_state, 85 u32 output_fmt, 86 unsigned int *num_input_fmts) 87 { 88 struct lvds_codec *lvds_codec = to_lvds_codec(bridge); 89 u32 *input_fmts; 90 91 *num_input_fmts = 0; 92 93 input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts), 94 GFP_KERNEL); 95 if (!input_fmts) 96 return NULL; 97 98 input_fmts[0] = lvds_codec->bus_format; 99 *num_input_fmts = MAX_INPUT_SEL_FORMATS; 100 101 return input_fmts; 102 } 103 104 static const struct drm_bridge_funcs funcs_decoder = { 105 .attach = lvds_codec_attach, 106 .enable = lvds_codec_enable, 107 .disable = lvds_codec_disable, 108 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 109 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 110 .atomic_reset = drm_atomic_helper_bridge_reset, 111 .atomic_get_input_bus_fmts = lvds_codec_atomic_get_input_bus_fmts, 112 }; 113 114 static int lvds_codec_probe(struct platform_device *pdev) 115 { 116 struct device *dev = &pdev->dev; 117 struct device_node *panel_node; 118 struct device_node *bus_node; 119 struct drm_panel *panel; 120 struct lvds_codec *lvds_codec; 121 const char *mapping; 122 int ret; 123 124 lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL); 125 if (!lvds_codec) 126 return -ENOMEM; 127 128 lvds_codec->dev = &pdev->dev; 129 lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev); 130 131 lvds_codec->vcc = devm_regulator_get(lvds_codec->dev, "power"); 132 if (IS_ERR(lvds_codec->vcc)) 133 return dev_err_probe(dev, PTR_ERR(lvds_codec->vcc), 134 "Unable to get \"vcc\" supply\n"); 135 136 lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", 137 GPIOD_OUT_HIGH); 138 if (IS_ERR(lvds_codec->powerdown_gpio)) 139 return dev_err_probe(dev, PTR_ERR(lvds_codec->powerdown_gpio), 140 "powerdown GPIO failure\n"); 141 142 /* Locate the panel DT node. */ 143 panel_node = of_graph_get_remote_node(dev->of_node, 1, 0); 144 if (!panel_node) { 145 dev_dbg(dev, "panel DT node not found\n"); 146 return -ENXIO; 147 } 148 149 panel = of_drm_find_panel(panel_node); 150 of_node_put(panel_node); 151 if (IS_ERR(panel)) { 152 dev_dbg(dev, "panel not found, deferring probe\n"); 153 return PTR_ERR(panel); 154 } 155 156 lvds_codec->panel_bridge = 157 devm_drm_panel_bridge_add_typed(dev, panel, 158 lvds_codec->connector_type); 159 if (IS_ERR(lvds_codec->panel_bridge)) 160 return PTR_ERR(lvds_codec->panel_bridge); 161 162 lvds_codec->bridge.funcs = &funcs; 163 164 /* 165 * Decoder input LVDS format is a property of the decoder chip or even 166 * its strapping. Handle data-mapping the same way lvds-panel does. In 167 * case data-mapping is not present, do nothing, since there are still 168 * legacy bindings which do not specify this property. 169 */ 170 if (lvds_codec->connector_type != DRM_MODE_CONNECTOR_LVDS) { 171 bus_node = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0); 172 if (!bus_node) { 173 dev_dbg(dev, "bus DT node not found\n"); 174 return -ENXIO; 175 } 176 177 ret = of_property_read_string(bus_node, "data-mapping", 178 &mapping); 179 of_node_put(bus_node); 180 if (ret < 0) { 181 dev_warn(dev, "missing 'data-mapping' DT property\n"); 182 } else { 183 if (!strcmp(mapping, "jeida-18")) { 184 lvds_codec->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG; 185 } else if (!strcmp(mapping, "jeida-24")) { 186 lvds_codec->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA; 187 } else if (!strcmp(mapping, "vesa-24")) { 188 lvds_codec->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG; 189 } else { 190 dev_err(dev, "invalid 'data-mapping' DT property\n"); 191 return -EINVAL; 192 } 193 lvds_codec->bridge.funcs = &funcs_decoder; 194 } 195 } 196 197 /* 198 * The panel_bridge bridge is attached to the panel's of_node, 199 * but we need a bridge attached to our of_node for our user 200 * to look up. 201 */ 202 lvds_codec->bridge.of_node = dev->of_node; 203 drm_bridge_add(&lvds_codec->bridge); 204 205 platform_set_drvdata(pdev, lvds_codec); 206 207 return 0; 208 } 209 210 static int lvds_codec_remove(struct platform_device *pdev) 211 { 212 struct lvds_codec *lvds_codec = platform_get_drvdata(pdev); 213 214 drm_bridge_remove(&lvds_codec->bridge); 215 216 return 0; 217 } 218 219 static const struct of_device_id lvds_codec_match[] = { 220 { 221 .compatible = "lvds-decoder", 222 .data = (void *)DRM_MODE_CONNECTOR_DPI, 223 }, 224 { 225 .compatible = "lvds-encoder", 226 .data = (void *)DRM_MODE_CONNECTOR_LVDS, 227 }, 228 { 229 .compatible = "thine,thc63lvdm83d", 230 .data = (void *)DRM_MODE_CONNECTOR_LVDS, 231 }, 232 {}, 233 }; 234 MODULE_DEVICE_TABLE(of, lvds_codec_match); 235 236 static struct platform_driver lvds_codec_driver = { 237 .probe = lvds_codec_probe, 238 .remove = lvds_codec_remove, 239 .driver = { 240 .name = "lvds-codec", 241 .of_match_table = lvds_codec_match, 242 }, 243 }; 244 module_platform_driver(lvds_codec_driver); 245 246 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 247 MODULE_DESCRIPTION("LVDS encoders and decoders"); 248 MODULE_LICENSE("GPL"); 249