0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/delay.h>
0014 #include <linux/module.h>
0015 #include <linux/of_graph.h>
0016 #include <linux/regulator/consumer.h>
0017
0018 #include <video/mipi_display.h>
0019
0020 #include <drm/drm_atomic_helper.h>
0021 #include <drm/drm_crtc.h>
0022 #include <drm/drm_fb_helper.h>
0023 #include <drm/drm_mipi_dsi.h>
0024 #include <drm/drm_of.h>
0025 #include <drm/drm_panel.h>
0026 #include <drm/drm_print.h>
0027 #include <drm/drm_probe_helper.h>
0028
0029
0030 #define PPI_STARTPPI 0x0104
0031 #define PPI_LPTXTIMECNT 0x0114
0032 #define PPI_D0S_ATMR 0x0144
0033 #define PPI_D1S_ATMR 0x0148
0034 #define PPI_D0S_CLRSIPOCOUNT 0x0164
0035 #define PPI_D1S_CLRSIPOCOUNT 0x0168
0036 #define PPI_START_FUNCTION 1
0037
0038
0039 #define DSI_STARTDSI 0x0204
0040 #define DSI_LANEENABLE 0x0210
0041 #define DSI_RX_START 1
0042
0043
0044 #define LCDCTRL 0x0420
0045
0046
0047 #define SPICMR 0x0450
0048 #define SPITCR 0x0454
0049
0050
0051 #define SYSCTRL 0x0464
0052
0053
0054 #define LPX_PERIOD 3
0055
0056
0057 #define LANEENABLE_CLEN BIT(0)
0058 #define LANEENABLE_L0EN BIT(1)
0059 #define LANEENABLE_L1EN BIT(2)
0060
0061 struct tc358762 {
0062 struct device *dev;
0063 struct drm_bridge bridge;
0064 struct regulator *regulator;
0065 struct drm_bridge *panel_bridge;
0066 bool pre_enabled;
0067 int error;
0068 };
0069
0070 static int tc358762_clear_error(struct tc358762 *ctx)
0071 {
0072 int ret = ctx->error;
0073
0074 ctx->error = 0;
0075 return ret;
0076 }
0077
0078 static void tc358762_write(struct tc358762 *ctx, u16 addr, u32 val)
0079 {
0080 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0081 ssize_t ret;
0082 u8 data[6];
0083
0084 if (ctx->error)
0085 return;
0086
0087 data[0] = addr;
0088 data[1] = addr >> 8;
0089 data[2] = val;
0090 data[3] = val >> 8;
0091 data[4] = val >> 16;
0092 data[5] = val >> 24;
0093
0094 ret = mipi_dsi_generic_write(dsi, data, sizeof(data));
0095 if (ret < 0)
0096 ctx->error = ret;
0097 }
0098
0099 static inline struct tc358762 *bridge_to_tc358762(struct drm_bridge *bridge)
0100 {
0101 return container_of(bridge, struct tc358762, bridge);
0102 }
0103
0104 static int tc358762_init(struct tc358762 *ctx)
0105 {
0106 tc358762_write(ctx, DSI_LANEENABLE,
0107 LANEENABLE_L0EN | LANEENABLE_CLEN);
0108 tc358762_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5);
0109 tc358762_write(ctx, PPI_D1S_CLRSIPOCOUNT, 5);
0110 tc358762_write(ctx, PPI_D0S_ATMR, 0);
0111 tc358762_write(ctx, PPI_D1S_ATMR, 0);
0112 tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD);
0113
0114 tc358762_write(ctx, SPICMR, 0x00);
0115 tc358762_write(ctx, LCDCTRL, 0x00100150);
0116 tc358762_write(ctx, SYSCTRL, 0x040f);
0117 msleep(100);
0118
0119 tc358762_write(ctx, PPI_STARTPPI, PPI_START_FUNCTION);
0120 tc358762_write(ctx, DSI_STARTDSI, DSI_RX_START);
0121
0122 msleep(100);
0123
0124 return tc358762_clear_error(ctx);
0125 }
0126
0127 static void tc358762_post_disable(struct drm_bridge *bridge)
0128 {
0129 struct tc358762 *ctx = bridge_to_tc358762(bridge);
0130 int ret;
0131
0132
0133
0134
0135
0136 if (!ctx->pre_enabled)
0137 return;
0138
0139 ctx->pre_enabled = false;
0140
0141 ret = regulator_disable(ctx->regulator);
0142 if (ret < 0)
0143 dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
0144 }
0145
0146 static void tc358762_pre_enable(struct drm_bridge *bridge)
0147 {
0148 struct tc358762 *ctx = bridge_to_tc358762(bridge);
0149 int ret;
0150
0151 ret = regulator_enable(ctx->regulator);
0152 if (ret < 0)
0153 dev_err(ctx->dev, "error enabling regulators (%d)\n", ret);
0154
0155 ret = tc358762_init(ctx);
0156 if (ret < 0)
0157 dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);
0158
0159 ctx->pre_enabled = true;
0160 }
0161
0162 static int tc358762_attach(struct drm_bridge *bridge,
0163 enum drm_bridge_attach_flags flags)
0164 {
0165 struct tc358762 *ctx = bridge_to_tc358762(bridge);
0166
0167 return drm_bridge_attach(bridge->encoder, ctx->panel_bridge,
0168 bridge, flags);
0169 }
0170
0171 static const struct drm_bridge_funcs tc358762_bridge_funcs = {
0172 .post_disable = tc358762_post_disable,
0173 .pre_enable = tc358762_pre_enable,
0174 .attach = tc358762_attach,
0175 };
0176
0177 static int tc358762_parse_dt(struct tc358762 *ctx)
0178 {
0179 struct drm_bridge *panel_bridge;
0180 struct device *dev = ctx->dev;
0181
0182 panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
0183 if (IS_ERR(panel_bridge))
0184 return PTR_ERR(panel_bridge);
0185
0186 ctx->panel_bridge = panel_bridge;
0187
0188 return 0;
0189 }
0190
0191 static int tc358762_configure_regulators(struct tc358762 *ctx)
0192 {
0193 ctx->regulator = devm_regulator_get(ctx->dev, "vddc");
0194 if (IS_ERR(ctx->regulator))
0195 return PTR_ERR(ctx->regulator);
0196
0197 return 0;
0198 }
0199
0200 static int tc358762_probe(struct mipi_dsi_device *dsi)
0201 {
0202 struct device *dev = &dsi->dev;
0203 struct tc358762 *ctx;
0204 int ret;
0205
0206 ctx = devm_kzalloc(dev, sizeof(struct tc358762), GFP_KERNEL);
0207 if (!ctx)
0208 return -ENOMEM;
0209
0210 mipi_dsi_set_drvdata(dsi, ctx);
0211
0212 ctx->dev = dev;
0213 ctx->pre_enabled = false;
0214
0215
0216 dsi->lanes = 1;
0217 dsi->format = MIPI_DSI_FMT_RGB888;
0218 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
0219 MIPI_DSI_MODE_LPM;
0220
0221 ret = tc358762_parse_dt(ctx);
0222 if (ret < 0)
0223 return ret;
0224
0225 ret = tc358762_configure_regulators(ctx);
0226 if (ret < 0)
0227 return ret;
0228
0229 ctx->bridge.funcs = &tc358762_bridge_funcs;
0230 ctx->bridge.type = DRM_MODE_CONNECTOR_DPI;
0231 ctx->bridge.of_node = dev->of_node;
0232
0233 drm_bridge_add(&ctx->bridge);
0234
0235 ret = mipi_dsi_attach(dsi);
0236 if (ret < 0) {
0237 drm_bridge_remove(&ctx->bridge);
0238 dev_err(dev, "failed to attach dsi\n");
0239 }
0240
0241 return ret;
0242 }
0243
0244 static int tc358762_remove(struct mipi_dsi_device *dsi)
0245 {
0246 struct tc358762 *ctx = mipi_dsi_get_drvdata(dsi);
0247
0248 mipi_dsi_detach(dsi);
0249 drm_bridge_remove(&ctx->bridge);
0250
0251 return 0;
0252 }
0253
0254 static const struct of_device_id tc358762_of_match[] = {
0255 { .compatible = "toshiba,tc358762" },
0256 { }
0257 };
0258 MODULE_DEVICE_TABLE(of, tc358762_of_match);
0259
0260 static struct mipi_dsi_driver tc358762_driver = {
0261 .probe = tc358762_probe,
0262 .remove = tc358762_remove,
0263 .driver = {
0264 .name = "tc358762",
0265 .of_match_table = tc358762_of_match,
0266 },
0267 };
0268 module_mipi_dsi_driver(tc358762_driver);
0269
0270 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
0271 MODULE_DESCRIPTION("MIPI-DSI based Driver for TC358762 DSI/DPI Bridge");
0272 MODULE_LICENSE("GPL v2");