0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/delay.h>
0016 #include <linux/gpio/consumer.h>
0017 #include <linux/module.h>
0018 #include <linux/regulator/consumer.h>
0019 #include <linux/spi/spi.h>
0020
0021 #include <video/mipi_display.h>
0022 #include <video/of_videomode.h>
0023 #include <video/videomode.h>
0024
0025 #include <drm/drm_device.h>
0026 #include <drm/drm_modes.h>
0027 #include <drm/drm_panel.h>
0028
0029 struct lg4573 {
0030 struct drm_panel panel;
0031 struct spi_device *spi;
0032 struct videomode vm;
0033 };
0034
0035 static inline struct lg4573 *panel_to_lg4573(struct drm_panel *panel)
0036 {
0037 return container_of(panel, struct lg4573, panel);
0038 }
0039
0040 static int lg4573_spi_write_u16(struct lg4573 *ctx, u16 data)
0041 {
0042 struct spi_transfer xfer = {
0043 .len = 2,
0044 };
0045 __be16 temp = cpu_to_be16(data);
0046 struct spi_message msg;
0047
0048 dev_dbg(ctx->panel.dev, "writing data: %x\n", data);
0049 xfer.tx_buf = &temp;
0050 spi_message_init(&msg);
0051 spi_message_add_tail(&xfer, &msg);
0052
0053 return spi_sync(ctx->spi, &msg);
0054 }
0055
0056 static int lg4573_spi_write_u16_array(struct lg4573 *ctx, const u16 *buffer,
0057 unsigned int count)
0058 {
0059 unsigned int i;
0060 int ret;
0061
0062 for (i = 0; i < count; i++) {
0063 ret = lg4573_spi_write_u16(ctx, buffer[i]);
0064 if (ret)
0065 return ret;
0066 }
0067
0068 return 0;
0069 }
0070
0071 static int lg4573_spi_write_dcs(struct lg4573 *ctx, u8 dcs)
0072 {
0073 return lg4573_spi_write_u16(ctx, (0x70 << 8 | dcs));
0074 }
0075
0076 static int lg4573_display_on(struct lg4573 *ctx)
0077 {
0078 int ret;
0079
0080 ret = lg4573_spi_write_dcs(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
0081 if (ret)
0082 return ret;
0083
0084 msleep(5);
0085
0086 return lg4573_spi_write_dcs(ctx, MIPI_DCS_SET_DISPLAY_ON);
0087 }
0088
0089 static int lg4573_display_off(struct lg4573 *ctx)
0090 {
0091 int ret;
0092
0093 ret = lg4573_spi_write_dcs(ctx, MIPI_DCS_SET_DISPLAY_OFF);
0094 if (ret)
0095 return ret;
0096
0097 msleep(120);
0098
0099 return lg4573_spi_write_dcs(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
0100 }
0101
0102 static int lg4573_display_mode_settings(struct lg4573 *ctx)
0103 {
0104 static const u16 display_mode_settings[] = {
0105 0x703A, 0x7270, 0x70B1, 0x7208,
0106 0x723B, 0x720F, 0x70B2, 0x7200,
0107 0x72C8, 0x70B3, 0x7200, 0x70B4,
0108 0x7200, 0x70B5, 0x7242, 0x7210,
0109 0x7210, 0x7200, 0x7220, 0x70B6,
0110 0x720B, 0x720F, 0x723C, 0x7213,
0111 0x7213, 0x72E8, 0x70B7, 0x7246,
0112 0x7206, 0x720C, 0x7200, 0x7200,
0113 };
0114
0115 dev_dbg(ctx->panel.dev, "transfer display mode settings\n");
0116 return lg4573_spi_write_u16_array(ctx, display_mode_settings,
0117 ARRAY_SIZE(display_mode_settings));
0118 }
0119
0120 static int lg4573_power_settings(struct lg4573 *ctx)
0121 {
0122 static const u16 power_settings[] = {
0123 0x70C0, 0x7201, 0x7211, 0x70C3,
0124 0x7207, 0x7203, 0x7204, 0x7204,
0125 0x7204, 0x70C4, 0x7212, 0x7224,
0126 0x7218, 0x7218, 0x7202, 0x7249,
0127 0x70C5, 0x726F, 0x70C6, 0x7241,
0128 0x7263,
0129 };
0130
0131 dev_dbg(ctx->panel.dev, "transfer power settings\n");
0132 return lg4573_spi_write_u16_array(ctx, power_settings,
0133 ARRAY_SIZE(power_settings));
0134 }
0135
0136 static int lg4573_gamma_settings(struct lg4573 *ctx)
0137 {
0138 static const u16 gamma_settings[] = {
0139 0x70D0, 0x7203, 0x7207, 0x7273,
0140 0x7235, 0x7200, 0x7201, 0x7220,
0141 0x7200, 0x7203, 0x70D1, 0x7203,
0142 0x7207, 0x7273, 0x7235, 0x7200,
0143 0x7201, 0x7220, 0x7200, 0x7203,
0144 0x70D2, 0x7203, 0x7207, 0x7273,
0145 0x7235, 0x7200, 0x7201, 0x7220,
0146 0x7200, 0x7203, 0x70D3, 0x7203,
0147 0x7207, 0x7273, 0x7235, 0x7200,
0148 0x7201, 0x7220, 0x7200, 0x7203,
0149 0x70D4, 0x7203, 0x7207, 0x7273,
0150 0x7235, 0x7200, 0x7201, 0x7220,
0151 0x7200, 0x7203, 0x70D5, 0x7203,
0152 0x7207, 0x7273, 0x7235, 0x7200,
0153 0x7201, 0x7220, 0x7200, 0x7203,
0154 };
0155
0156 dev_dbg(ctx->panel.dev, "transfer gamma settings\n");
0157 return lg4573_spi_write_u16_array(ctx, gamma_settings,
0158 ARRAY_SIZE(gamma_settings));
0159 }
0160
0161 static int lg4573_init(struct lg4573 *ctx)
0162 {
0163 int ret;
0164
0165 dev_dbg(ctx->panel.dev, "initializing LCD\n");
0166
0167 ret = lg4573_display_mode_settings(ctx);
0168 if (ret)
0169 return ret;
0170
0171 ret = lg4573_power_settings(ctx);
0172 if (ret)
0173 return ret;
0174
0175 return lg4573_gamma_settings(ctx);
0176 }
0177
0178 static int lg4573_power_on(struct lg4573 *ctx)
0179 {
0180 return lg4573_display_on(ctx);
0181 }
0182
0183 static int lg4573_disable(struct drm_panel *panel)
0184 {
0185 struct lg4573 *ctx = panel_to_lg4573(panel);
0186
0187 return lg4573_display_off(ctx);
0188 }
0189
0190 static int lg4573_enable(struct drm_panel *panel)
0191 {
0192 struct lg4573 *ctx = panel_to_lg4573(panel);
0193
0194 lg4573_init(ctx);
0195
0196 return lg4573_power_on(ctx);
0197 }
0198
0199 static const struct drm_display_mode default_mode = {
0200 .clock = 28341,
0201 .hdisplay = 480,
0202 .hsync_start = 480 + 10,
0203 .hsync_end = 480 + 10 + 59,
0204 .htotal = 480 + 10 + 59 + 10,
0205 .vdisplay = 800,
0206 .vsync_start = 800 + 15,
0207 .vsync_end = 800 + 15 + 15,
0208 .vtotal = 800 + 15 + 15 + 15,
0209 };
0210
0211 static int lg4573_get_modes(struct drm_panel *panel,
0212 struct drm_connector *connector)
0213 {
0214 struct drm_display_mode *mode;
0215
0216 mode = drm_mode_duplicate(connector->dev, &default_mode);
0217 if (!mode) {
0218 dev_err(panel->dev, "failed to add mode %ux%ux@%u\n",
0219 default_mode.hdisplay, default_mode.vdisplay,
0220 drm_mode_vrefresh(&default_mode));
0221 return -ENOMEM;
0222 }
0223
0224 drm_mode_set_name(mode);
0225
0226 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0227 drm_mode_probed_add(connector, mode);
0228
0229 connector->display_info.width_mm = 61;
0230 connector->display_info.height_mm = 103;
0231
0232 return 1;
0233 }
0234
0235 static const struct drm_panel_funcs lg4573_drm_funcs = {
0236 .disable = lg4573_disable,
0237 .enable = lg4573_enable,
0238 .get_modes = lg4573_get_modes,
0239 };
0240
0241 static int lg4573_probe(struct spi_device *spi)
0242 {
0243 struct lg4573 *ctx;
0244 int ret;
0245
0246 ctx = devm_kzalloc(&spi->dev, sizeof(*ctx), GFP_KERNEL);
0247 if (!ctx)
0248 return -ENOMEM;
0249
0250 ctx->spi = spi;
0251
0252 spi_set_drvdata(spi, ctx);
0253 spi->bits_per_word = 8;
0254
0255 ret = spi_setup(spi);
0256 if (ret < 0) {
0257 dev_err(&spi->dev, "SPI setup failed: %d\n", ret);
0258 return ret;
0259 }
0260
0261 drm_panel_init(&ctx->panel, &spi->dev, &lg4573_drm_funcs,
0262 DRM_MODE_CONNECTOR_DPI);
0263
0264 drm_panel_add(&ctx->panel);
0265
0266 return 0;
0267 }
0268
0269 static void lg4573_remove(struct spi_device *spi)
0270 {
0271 struct lg4573 *ctx = spi_get_drvdata(spi);
0272
0273 lg4573_display_off(ctx);
0274 drm_panel_remove(&ctx->panel);
0275 }
0276
0277 static const struct of_device_id lg4573_of_match[] = {
0278 { .compatible = "lg,lg4573" },
0279 { }
0280 };
0281 MODULE_DEVICE_TABLE(of, lg4573_of_match);
0282
0283 static struct spi_driver lg4573_driver = {
0284 .probe = lg4573_probe,
0285 .remove = lg4573_remove,
0286 .driver = {
0287 .name = "lg4573",
0288 .of_match_table = lg4573_of_match,
0289 },
0290 };
0291 module_spi_driver(lg4573_driver);
0292
0293 MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");
0294 MODULE_DESCRIPTION("lg4573 LCD Driver");
0295 MODULE_LICENSE("GPL v2");