0001
0002
0003
0004
0005
0006
0007 #include <linux/component.h>
0008 #include <linux/of_graph.h>
0009
0010 #include <drm/drm_atomic_helper.h>
0011 #include <drm/drm_bridge.h>
0012 #include <drm/drm_of.h>
0013 #include <drm/drm_simple_kms_helper.h>
0014
0015 #include "tilcdc_drv.h"
0016 #include "tilcdc_external.h"
0017
0018 static const struct tilcdc_panel_info panel_info_tda998x = {
0019 .ac_bias = 255,
0020 .ac_bias_intrpt = 0,
0021 .dma_burst_sz = 16,
0022 .bpp = 16,
0023 .fdd = 0x80,
0024 .tft_alt_mode = 0,
0025 .invert_pxl_clk = 1,
0026 .sync_edge = 1,
0027 .sync_ctrl = 1,
0028 .raster_order = 0,
0029 };
0030
0031 static const struct tilcdc_panel_info panel_info_default = {
0032 .ac_bias = 255,
0033 .ac_bias_intrpt = 0,
0034 .dma_burst_sz = 16,
0035 .bpp = 16,
0036 .fdd = 0x80,
0037 .tft_alt_mode = 0,
0038 .sync_edge = 0,
0039 .sync_ctrl = 1,
0040 .raster_order = 0,
0041 };
0042
0043 static
0044 struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
0045 struct drm_encoder *encoder)
0046 {
0047 struct drm_connector *connector;
0048
0049 list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
0050 if (drm_connector_has_possible_encoder(connector, encoder))
0051 return connector;
0052 }
0053
0054 dev_err(ddev->dev, "No connector found for %s encoder (id %d)\n",
0055 encoder->name, encoder->base.id);
0056
0057 return NULL;
0058 }
0059
0060 int tilcdc_add_component_encoder(struct drm_device *ddev)
0061 {
0062 struct tilcdc_drm_private *priv = ddev->dev_private;
0063 struct drm_encoder *encoder = NULL, *iter;
0064
0065 list_for_each_entry(iter, &ddev->mode_config.encoder_list, head)
0066 if (iter->possible_crtcs & (1 << priv->crtc->index)) {
0067 encoder = iter;
0068 break;
0069 }
0070
0071 if (!encoder) {
0072 dev_err(ddev->dev, "%s: No suitable encoder found\n", __func__);
0073 return -ENODEV;
0074 }
0075
0076 priv->external_connector =
0077 tilcdc_encoder_find_connector(ddev, encoder);
0078
0079 if (!priv->external_connector)
0080 return -ENODEV;
0081
0082
0083 tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true);
0084 tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x);
0085
0086 return 0;
0087 }
0088
0089 static
0090 int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
0091 {
0092 struct tilcdc_drm_private *priv = ddev->dev_private;
0093 int ret;
0094
0095 priv->external_encoder->possible_crtcs = BIT(0);
0096
0097 ret = drm_bridge_attach(priv->external_encoder, bridge, NULL, 0);
0098 if (ret)
0099 return ret;
0100
0101 tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default);
0102
0103 priv->external_connector =
0104 tilcdc_encoder_find_connector(ddev, priv->external_encoder);
0105 if (!priv->external_connector)
0106 return -ENODEV;
0107
0108 return 0;
0109 }
0110
0111 int tilcdc_attach_external_device(struct drm_device *ddev)
0112 {
0113 struct tilcdc_drm_private *priv = ddev->dev_private;
0114 struct drm_bridge *bridge;
0115 struct drm_panel *panel;
0116 int ret;
0117
0118 ret = drm_of_find_panel_or_bridge(ddev->dev->of_node, 0, 0,
0119 &panel, &bridge);
0120 if (ret == -ENODEV)
0121 return 0;
0122 else if (ret)
0123 return ret;
0124
0125 priv->external_encoder = devm_kzalloc(ddev->dev,
0126 sizeof(*priv->external_encoder),
0127 GFP_KERNEL);
0128 if (!priv->external_encoder)
0129 return -ENOMEM;
0130
0131 ret = drm_simple_encoder_init(ddev, priv->external_encoder,
0132 DRM_MODE_ENCODER_NONE);
0133 if (ret) {
0134 dev_err(ddev->dev, "drm_encoder_init() failed %d\n", ret);
0135 return ret;
0136 }
0137
0138 if (panel) {
0139 bridge = devm_drm_panel_bridge_add_typed(ddev->dev, panel,
0140 DRM_MODE_CONNECTOR_DPI);
0141 if (IS_ERR(bridge)) {
0142 ret = PTR_ERR(bridge);
0143 goto err_encoder_cleanup;
0144 }
0145 }
0146
0147 ret = tilcdc_attach_bridge(ddev, bridge);
0148 if (ret)
0149 goto err_encoder_cleanup;
0150
0151 return 0;
0152
0153 err_encoder_cleanup:
0154 drm_encoder_cleanup(priv->external_encoder);
0155 return ret;
0156 }
0157
0158 static int dev_match_of(struct device *dev, void *data)
0159 {
0160 return dev->of_node == data;
0161 }
0162
0163 int tilcdc_get_external_components(struct device *dev,
0164 struct component_match **match)
0165 {
0166 struct device_node *node;
0167
0168 node = of_graph_get_remote_node(dev->of_node, 0, 0);
0169
0170 if (!of_device_is_compatible(node, "nxp,tda998x")) {
0171 of_node_put(node);
0172 return 0;
0173 }
0174
0175 if (match)
0176 drm_of_component_match_add(dev, match, dev_match_of, node);
0177 of_node_put(node);
0178 return 1;
0179 }