0001
0002
0003
0004
0005
0006
0007 #include <linux/gpio/consumer.h>
0008 #include <linux/module.h>
0009 #include <linux/of.h>
0010 #include <linux/of_device.h>
0011 #include <linux/of_graph.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/regulator/consumer.h>
0014
0015 #include <drm/drm_atomic_helper.h>
0016 #include <drm/drm_bridge.h>
0017 #include <drm/drm_of.h>
0018 #include <drm/drm_panel.h>
0019
0020 struct lvds_codec {
0021 struct device *dev;
0022 struct drm_bridge bridge;
0023 struct drm_bridge *panel_bridge;
0024 struct drm_bridge_timings timings;
0025 struct regulator *vcc;
0026 struct gpio_desc *powerdown_gpio;
0027 u32 connector_type;
0028 unsigned int bus_format;
0029 };
0030
0031 static inline struct lvds_codec *to_lvds_codec(struct drm_bridge *bridge)
0032 {
0033 return container_of(bridge, struct lvds_codec, bridge);
0034 }
0035
0036 static int lvds_codec_attach(struct drm_bridge *bridge,
0037 enum drm_bridge_attach_flags flags)
0038 {
0039 struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
0040
0041 return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge,
0042 bridge, flags);
0043 }
0044
0045 static void lvds_codec_enable(struct drm_bridge *bridge)
0046 {
0047 struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
0048 int ret;
0049
0050 ret = regulator_enable(lvds_codec->vcc);
0051 if (ret) {
0052 dev_err(lvds_codec->dev,
0053 "Failed to enable regulator \"vcc\": %d\n", ret);
0054 return;
0055 }
0056
0057 if (lvds_codec->powerdown_gpio)
0058 gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0);
0059 }
0060
0061 static void lvds_codec_disable(struct drm_bridge *bridge)
0062 {
0063 struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
0064 int ret;
0065
0066 if (lvds_codec->powerdown_gpio)
0067 gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1);
0068
0069 ret = regulator_disable(lvds_codec->vcc);
0070 if (ret)
0071 dev_err(lvds_codec->dev,
0072 "Failed to disable regulator \"vcc\": %d\n", ret);
0073 }
0074
0075 static const struct drm_bridge_funcs funcs = {
0076 .attach = lvds_codec_attach,
0077 .enable = lvds_codec_enable,
0078 .disable = lvds_codec_disable,
0079 };
0080
0081 #define MAX_INPUT_SEL_FORMATS 1
0082 static u32 *
0083 lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
0084 struct drm_bridge_state *bridge_state,
0085 struct drm_crtc_state *crtc_state,
0086 struct drm_connector_state *conn_state,
0087 u32 output_fmt,
0088 unsigned int *num_input_fmts)
0089 {
0090 struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
0091 u32 *input_fmts;
0092
0093 *num_input_fmts = 0;
0094
0095 input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
0096 GFP_KERNEL);
0097 if (!input_fmts)
0098 return NULL;
0099
0100 input_fmts[0] = lvds_codec->bus_format;
0101 *num_input_fmts = MAX_INPUT_SEL_FORMATS;
0102
0103 return input_fmts;
0104 }
0105
0106 static const struct drm_bridge_funcs funcs_decoder = {
0107 .attach = lvds_codec_attach,
0108 .enable = lvds_codec_enable,
0109 .disable = lvds_codec_disable,
0110 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
0111 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
0112 .atomic_reset = drm_atomic_helper_bridge_reset,
0113 .atomic_get_input_bus_fmts = lvds_codec_atomic_get_input_bus_fmts,
0114 };
0115
0116 static int lvds_codec_probe(struct platform_device *pdev)
0117 {
0118 struct device *dev = &pdev->dev;
0119 struct device_node *panel_node;
0120 struct device_node *bus_node;
0121 struct drm_panel *panel;
0122 struct lvds_codec *lvds_codec;
0123 u32 val;
0124 int ret;
0125
0126 lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL);
0127 if (!lvds_codec)
0128 return -ENOMEM;
0129
0130 lvds_codec->dev = &pdev->dev;
0131 lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev);
0132
0133 lvds_codec->vcc = devm_regulator_get(lvds_codec->dev, "power");
0134 if (IS_ERR(lvds_codec->vcc))
0135 return dev_err_probe(dev, PTR_ERR(lvds_codec->vcc),
0136 "Unable to get \"vcc\" supply\n");
0137
0138 lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
0139 GPIOD_OUT_HIGH);
0140 if (IS_ERR(lvds_codec->powerdown_gpio))
0141 return dev_err_probe(dev, PTR_ERR(lvds_codec->powerdown_gpio),
0142 "powerdown GPIO failure\n");
0143
0144
0145 panel_node = of_graph_get_remote_node(dev->of_node, 1, 0);
0146 if (!panel_node) {
0147 dev_dbg(dev, "panel DT node not found\n");
0148 return -ENXIO;
0149 }
0150
0151 panel = of_drm_find_panel(panel_node);
0152 of_node_put(panel_node);
0153 if (IS_ERR(panel)) {
0154 dev_dbg(dev, "panel not found, deferring probe\n");
0155 return PTR_ERR(panel);
0156 }
0157
0158 lvds_codec->panel_bridge =
0159 devm_drm_panel_bridge_add_typed(dev, panel,
0160 lvds_codec->connector_type);
0161 if (IS_ERR(lvds_codec->panel_bridge))
0162 return PTR_ERR(lvds_codec->panel_bridge);
0163
0164 lvds_codec->bridge.funcs = &funcs;
0165
0166
0167
0168
0169
0170
0171
0172 if (lvds_codec->connector_type != DRM_MODE_CONNECTOR_LVDS) {
0173 bus_node = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0);
0174 if (!bus_node) {
0175 dev_dbg(dev, "bus DT node not found\n");
0176 return -ENXIO;
0177 }
0178
0179 ret = drm_of_lvds_get_data_mapping(bus_node);
0180 of_node_put(bus_node);
0181 if (ret == -ENODEV) {
0182 dev_warn(dev, "missing 'data-mapping' DT property\n");
0183 } else if (ret < 0) {
0184 dev_err(dev, "invalid 'data-mapping' DT property\n");
0185 return ret;
0186 } else {
0187 lvds_codec->bus_format = ret;
0188 lvds_codec->bridge.funcs = &funcs_decoder;
0189 }
0190 }
0191
0192
0193
0194
0195
0196
0197 if (lvds_codec->connector_type == DRM_MODE_CONNECTOR_LVDS &&
0198 !of_property_read_u32(dev->of_node, "pclk-sample", &val)) {
0199 lvds_codec->timings.input_bus_flags = val ?
0200 DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE :
0201 DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
0202 }
0203
0204
0205
0206
0207
0208
0209 lvds_codec->bridge.of_node = dev->of_node;
0210 lvds_codec->bridge.timings = &lvds_codec->timings;
0211 drm_bridge_add(&lvds_codec->bridge);
0212
0213 platform_set_drvdata(pdev, lvds_codec);
0214
0215 return 0;
0216 }
0217
0218 static int lvds_codec_remove(struct platform_device *pdev)
0219 {
0220 struct lvds_codec *lvds_codec = platform_get_drvdata(pdev);
0221
0222 drm_bridge_remove(&lvds_codec->bridge);
0223
0224 return 0;
0225 }
0226
0227 static const struct of_device_id lvds_codec_match[] = {
0228 {
0229 .compatible = "lvds-decoder",
0230 .data = (void *)DRM_MODE_CONNECTOR_DPI,
0231 },
0232 {
0233 .compatible = "lvds-encoder",
0234 .data = (void *)DRM_MODE_CONNECTOR_LVDS,
0235 },
0236 {
0237 .compatible = "thine,thc63lvdm83d",
0238 .data = (void *)DRM_MODE_CONNECTOR_LVDS,
0239 },
0240 {},
0241 };
0242 MODULE_DEVICE_TABLE(of, lvds_codec_match);
0243
0244 static struct platform_driver lvds_codec_driver = {
0245 .probe = lvds_codec_probe,
0246 .remove = lvds_codec_remove,
0247 .driver = {
0248 .name = "lvds-codec",
0249 .of_match_table = lvds_codec_match,
0250 },
0251 };
0252 module_platform_driver(lvds_codec_driver);
0253
0254 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
0255 MODULE_DESCRIPTION("LVDS encoders and decoders");
0256 MODULE_LICENSE("GPL");