0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <drm/drm_modes.h>
0014 #include <drm/drm_panel.h>
0015
0016 #include <linux/bitops.h>
0017 #include <linux/delay.h>
0018 #include <linux/gpio/consumer.h>
0019 #include <linux/init.h>
0020 #include <linux/kernel.h>
0021 #include <linux/module.h>
0022 #include <linux/of.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/spi/spi.h>
0025
0026 #define TPG110_TEST 0x00
0027 #define TPG110_CHIPID 0x01
0028 #define TPG110_CTRL1 0x02
0029 #define TPG110_RES_MASK GENMASK(2, 0)
0030 #define TPG110_RES_800X480 0x07
0031 #define TPG110_RES_640X480 0x06
0032 #define TPG110_RES_480X272 0x05
0033 #define TPG110_RES_480X640 0x04
0034 #define TPG110_RES_480X272_D 0x01
0035 #define TPG110_RES_400X240_D 0x00
0036 #define TPG110_CTRL2 0x03
0037 #define TPG110_CTRL2_PM BIT(0)
0038 #define TPG110_CTRL2_RES_PM_CTRL BIT(7)
0039
0040
0041
0042
0043 struct tpg110_panel_mode {
0044
0045
0046
0047 const char *name;
0048
0049
0050
0051 u32 magic;
0052
0053
0054
0055 struct drm_display_mode mode;
0056
0057
0058
0059 u32 bus_flags;
0060 };
0061
0062
0063
0064
0065 struct tpg110 {
0066
0067
0068
0069 struct device *dev;
0070
0071
0072
0073 struct spi_device *spi;
0074
0075
0076
0077 struct drm_panel panel;
0078
0079
0080
0081 const struct tpg110_panel_mode *panel_mode;
0082
0083
0084
0085 u32 width;
0086
0087
0088
0089 u32 height;
0090
0091
0092
0093 struct gpio_desc *grestb;
0094 };
0095
0096
0097
0098
0099
0100 static const struct tpg110_panel_mode tpg110_modes[] = {
0101 {
0102 .name = "800x480 RGB",
0103 .magic = TPG110_RES_800X480,
0104 .mode = {
0105 .clock = 33200,
0106 .hdisplay = 800,
0107 .hsync_start = 800 + 40,
0108 .hsync_end = 800 + 40 + 1,
0109 .htotal = 800 + 40 + 1 + 216,
0110 .vdisplay = 480,
0111 .vsync_start = 480 + 10,
0112 .vsync_end = 480 + 10 + 1,
0113 .vtotal = 480 + 10 + 1 + 35,
0114 },
0115 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
0116 },
0117 {
0118 .name = "640x480 RGB",
0119 .magic = TPG110_RES_640X480,
0120 .mode = {
0121 .clock = 25200,
0122 .hdisplay = 640,
0123 .hsync_start = 640 + 24,
0124 .hsync_end = 640 + 24 + 1,
0125 .htotal = 640 + 24 + 1 + 136,
0126 .vdisplay = 480,
0127 .vsync_start = 480 + 18,
0128 .vsync_end = 480 + 18 + 1,
0129 .vtotal = 480 + 18 + 1 + 27,
0130 },
0131 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
0132 },
0133 {
0134 .name = "480x272 RGB",
0135 .magic = TPG110_RES_480X272,
0136 .mode = {
0137 .clock = 9000,
0138 .hdisplay = 480,
0139 .hsync_start = 480 + 2,
0140 .hsync_end = 480 + 2 + 1,
0141 .htotal = 480 + 2 + 1 + 43,
0142 .vdisplay = 272,
0143 .vsync_start = 272 + 2,
0144 .vsync_end = 272 + 2 + 1,
0145 .vtotal = 272 + 2 + 1 + 12,
0146 },
0147 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
0148 },
0149 {
0150 .name = "480x640 RGB",
0151 .magic = TPG110_RES_480X640,
0152 .mode = {
0153 .clock = 20500,
0154 .hdisplay = 480,
0155 .hsync_start = 480 + 2,
0156 .hsync_end = 480 + 2 + 1,
0157 .htotal = 480 + 2 + 1 + 43,
0158 .vdisplay = 640,
0159 .vsync_start = 640 + 4,
0160 .vsync_end = 640 + 4 + 1,
0161 .vtotal = 640 + 4 + 1 + 8,
0162 },
0163 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
0164 },
0165 {
0166 .name = "400x240 RGB",
0167 .magic = TPG110_RES_400X240_D,
0168 .mode = {
0169 .clock = 8300,
0170 .hdisplay = 400,
0171 .hsync_start = 400 + 20,
0172 .hsync_end = 400 + 20 + 1,
0173 .htotal = 400 + 20 + 1 + 108,
0174 .vdisplay = 240,
0175 .vsync_start = 240 + 2,
0176 .vsync_end = 240 + 2 + 1,
0177 .vtotal = 240 + 2 + 1 + 20,
0178 },
0179 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
0180 },
0181 };
0182
0183 static inline struct tpg110 *
0184 to_tpg110(struct drm_panel *panel)
0185 {
0186 return container_of(panel, struct tpg110, panel);
0187 }
0188
0189 static u8 tpg110_readwrite_reg(struct tpg110 *tpg, bool write,
0190 u8 address, u8 outval)
0191 {
0192 struct spi_message m;
0193 struct spi_transfer t[2];
0194 u8 buf[2];
0195 int ret;
0196
0197 spi_message_init(&m);
0198 memset(t, 0, sizeof(t));
0199
0200 if (write) {
0201
0202
0203
0204
0205
0206 buf[0] = address << 2;
0207 buf[0] &= ~0x03;
0208 buf[1] = outval;
0209
0210 t[0].bits_per_word = 8;
0211 t[0].tx_buf = &buf[0];
0212 t[0].len = 1;
0213
0214 t[1].tx_buf = &buf[1];
0215 t[1].len = 1;
0216 t[1].bits_per_word = 8;
0217 } else {
0218
0219 buf[0] = address << 1;
0220 buf[0] |= 0x01;
0221
0222
0223
0224
0225
0226
0227 t[0].bits_per_word = 7;
0228 t[0].tx_buf = &buf[0];
0229 t[0].len = 1;
0230
0231 t[1].rx_buf = &buf[1];
0232 t[1].len = 1;
0233 t[1].bits_per_word = 8;
0234 }
0235
0236 spi_message_add_tail(&t[0], &m);
0237 spi_message_add_tail(&t[1], &m);
0238 ret = spi_sync(tpg->spi, &m);
0239 if (ret) {
0240 dev_err(tpg->dev, "SPI message error %d\n", ret);
0241 return ret;
0242 }
0243 if (write)
0244 return 0;
0245
0246 return buf[1];
0247 }
0248
0249 static u8 tpg110_read_reg(struct tpg110 *tpg, u8 address)
0250 {
0251 return tpg110_readwrite_reg(tpg, false, address, 0);
0252 }
0253
0254 static void tpg110_write_reg(struct tpg110 *tpg, u8 address, u8 outval)
0255 {
0256 tpg110_readwrite_reg(tpg, true, address, outval);
0257 }
0258
0259 static int tpg110_startup(struct tpg110 *tpg)
0260 {
0261 u8 val;
0262 int i;
0263
0264
0265 gpiod_set_value_cansleep(tpg->grestb, 0);
0266 usleep_range(1000, 2000);
0267 dev_dbg(tpg->dev, "de-asserted GRESTB\n");
0268
0269
0270 tpg110_write_reg(tpg, TPG110_TEST, 0x55);
0271 val = tpg110_read_reg(tpg, TPG110_TEST);
0272 if (val != 0x55) {
0273 dev_err(tpg->dev, "failed communication test\n");
0274 return -ENODEV;
0275 }
0276
0277 val = tpg110_read_reg(tpg, TPG110_CHIPID);
0278 dev_info(tpg->dev, "TPG110 chip ID: %d version: %d\n",
0279 val >> 4, val & 0x0f);
0280
0281
0282 val = tpg110_read_reg(tpg, TPG110_CTRL1);
0283 val &= TPG110_RES_MASK;
0284 switch (val) {
0285 case TPG110_RES_400X240_D:
0286 dev_info(tpg->dev, "IN 400x240 RGB -> OUT 800x480 RGB (dual scan)\n");
0287 break;
0288 case TPG110_RES_480X272_D:
0289 dev_info(tpg->dev, "IN 480x272 RGB -> OUT 800x480 RGB (dual scan)\n");
0290 break;
0291 case TPG110_RES_480X640:
0292 dev_info(tpg->dev, "480x640 RGB\n");
0293 break;
0294 case TPG110_RES_480X272:
0295 dev_info(tpg->dev, "480x272 RGB\n");
0296 break;
0297 case TPG110_RES_640X480:
0298 dev_info(tpg->dev, "640x480 RGB\n");
0299 break;
0300 case TPG110_RES_800X480:
0301 dev_info(tpg->dev, "800x480 RGB\n");
0302 break;
0303 default:
0304 dev_err(tpg->dev, "ILLEGAL RESOLUTION 0x%02x\n", val);
0305 break;
0306 }
0307
0308
0309 if (val == TPG110_RES_480X272_D)
0310 val = TPG110_RES_480X272;
0311
0312 for (i = 0; i < ARRAY_SIZE(tpg110_modes); i++) {
0313 const struct tpg110_panel_mode *pm;
0314
0315 pm = &tpg110_modes[i];
0316 if (pm->magic == val) {
0317 tpg->panel_mode = pm;
0318 break;
0319 }
0320 }
0321 if (i == ARRAY_SIZE(tpg110_modes)) {
0322 dev_err(tpg->dev, "unsupported mode (%02x) detected\n", val);
0323 return -ENODEV;
0324 }
0325
0326 val = tpg110_read_reg(tpg, TPG110_CTRL2);
0327 dev_info(tpg->dev, "resolution and standby is controlled by %s\n",
0328 (val & TPG110_CTRL2_RES_PM_CTRL) ? "software" : "hardware");
0329
0330 val |= TPG110_CTRL2_RES_PM_CTRL;
0331 tpg110_write_reg(tpg, TPG110_CTRL2, val);
0332
0333 return 0;
0334 }
0335
0336 static int tpg110_disable(struct drm_panel *panel)
0337 {
0338 struct tpg110 *tpg = to_tpg110(panel);
0339 u8 val;
0340
0341
0342 val = tpg110_read_reg(tpg, TPG110_CTRL2_PM);
0343 val &= ~TPG110_CTRL2_PM;
0344 tpg110_write_reg(tpg, TPG110_CTRL2_PM, val);
0345
0346 return 0;
0347 }
0348
0349 static int tpg110_enable(struct drm_panel *panel)
0350 {
0351 struct tpg110 *tpg = to_tpg110(panel);
0352 u8 val;
0353
0354
0355 val = tpg110_read_reg(tpg, TPG110_CTRL2_PM);
0356 val |= TPG110_CTRL2_PM;
0357 tpg110_write_reg(tpg, TPG110_CTRL2_PM, val);
0358
0359 return 0;
0360 }
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371 static int tpg110_get_modes(struct drm_panel *panel,
0372 struct drm_connector *connector)
0373 {
0374 struct tpg110 *tpg = to_tpg110(panel);
0375 struct drm_display_mode *mode;
0376
0377 connector->display_info.width_mm = tpg->width;
0378 connector->display_info.height_mm = tpg->height;
0379 connector->display_info.bus_flags = tpg->panel_mode->bus_flags;
0380
0381 mode = drm_mode_duplicate(connector->dev, &tpg->panel_mode->mode);
0382 drm_mode_set_name(mode);
0383 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0384
0385 mode->width_mm = tpg->width;
0386 mode->height_mm = tpg->height;
0387
0388 drm_mode_probed_add(connector, mode);
0389
0390 return 1;
0391 }
0392
0393 static const struct drm_panel_funcs tpg110_drm_funcs = {
0394 .disable = tpg110_disable,
0395 .enable = tpg110_enable,
0396 .get_modes = tpg110_get_modes,
0397 };
0398
0399 static int tpg110_probe(struct spi_device *spi)
0400 {
0401 struct device *dev = &spi->dev;
0402 struct device_node *np = dev->of_node;
0403 struct tpg110 *tpg;
0404 int ret;
0405
0406 tpg = devm_kzalloc(dev, sizeof(*tpg), GFP_KERNEL);
0407 if (!tpg)
0408 return -ENOMEM;
0409 tpg->dev = dev;
0410
0411
0412 ret = of_property_read_u32(np, "width-mm", &tpg->width);
0413 if (ret)
0414 dev_err(dev, "no panel width specified\n");
0415 ret = of_property_read_u32(np, "height-mm", &tpg->height);
0416 if (ret)
0417 dev_err(dev, "no panel height specified\n");
0418
0419
0420 tpg->grestb = devm_gpiod_get(dev, "grestb", GPIOD_OUT_HIGH);
0421 if (IS_ERR(tpg->grestb)) {
0422 dev_err(dev, "no GRESTB GPIO\n");
0423 return -ENODEV;
0424 }
0425
0426 spi->bits_per_word = 8;
0427 spi->mode |= SPI_3WIRE_HIZ;
0428 ret = spi_setup(spi);
0429 if (ret < 0) {
0430 dev_err(dev, "spi setup failed.\n");
0431 return ret;
0432 }
0433 tpg->spi = spi;
0434
0435 ret = tpg110_startup(tpg);
0436 if (ret)
0437 return ret;
0438
0439 drm_panel_init(&tpg->panel, dev, &tpg110_drm_funcs,
0440 DRM_MODE_CONNECTOR_DPI);
0441
0442 ret = drm_panel_of_backlight(&tpg->panel);
0443 if (ret)
0444 return ret;
0445
0446 spi_set_drvdata(spi, tpg);
0447
0448 drm_panel_add(&tpg->panel);
0449
0450 return 0;
0451 }
0452
0453 static void tpg110_remove(struct spi_device *spi)
0454 {
0455 struct tpg110 *tpg = spi_get_drvdata(spi);
0456
0457 drm_panel_remove(&tpg->panel);
0458 }
0459
0460 static const struct of_device_id tpg110_match[] = {
0461 { .compatible = "tpo,tpg110", },
0462 {},
0463 };
0464 MODULE_DEVICE_TABLE(of, tpg110_match);
0465
0466 static struct spi_driver tpg110_driver = {
0467 .probe = tpg110_probe,
0468 .remove = tpg110_remove,
0469 .driver = {
0470 .name = "tpo-tpg110-panel",
0471 .of_match_table = tpg110_match,
0472 },
0473 };
0474 module_spi_driver(tpg110_driver);
0475
0476 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
0477 MODULE_DESCRIPTION("TPO TPG110 panel driver");
0478 MODULE_LICENSE("GPL v2");