0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/dma-buf.h>
0013 #include <linux/gpio/consumer.h>
0014 #include <linux/module.h>
0015 #include <linux/property.h>
0016 #include <linux/spi/spi.h>
0017 #include <video/mipi_display.h>
0018
0019 #include <drm/drm_atomic_helper.h>
0020 #include <drm/drm_damage_helper.h>
0021 #include <drm/drm_drv.h>
0022 #include <drm/drm_fb_cma_helper.h>
0023 #include <drm/drm_fb_helper.h>
0024 #include <drm/drm_fourcc.h>
0025 #include <drm/drm_framebuffer.h>
0026 #include <drm/drm_gem_atomic_helper.h>
0027 #include <drm/drm_gem_cma_helper.h>
0028 #include <drm/drm_managed.h>
0029 #include <drm/drm_mipi_dbi.h>
0030 #include <drm/drm_rect.h>
0031
0032 #define ILI9225_DRIVER_READ_CODE 0x00
0033 #define ILI9225_DRIVER_OUTPUT_CONTROL 0x01
0034 #define ILI9225_LCD_AC_DRIVING_CONTROL 0x02
0035 #define ILI9225_ENTRY_MODE 0x03
0036 #define ILI9225_DISPLAY_CONTROL_1 0x07
0037 #define ILI9225_BLANK_PERIOD_CONTROL_1 0x08
0038 #define ILI9225_FRAME_CYCLE_CONTROL 0x0b
0039 #define ILI9225_INTERFACE_CONTROL 0x0c
0040 #define ILI9225_OSCILLATION_CONTROL 0x0f
0041 #define ILI9225_POWER_CONTROL_1 0x10
0042 #define ILI9225_POWER_CONTROL_2 0x11
0043 #define ILI9225_POWER_CONTROL_3 0x12
0044 #define ILI9225_POWER_CONTROL_4 0x13
0045 #define ILI9225_POWER_CONTROL_5 0x14
0046 #define ILI9225_VCI_RECYCLING 0x15
0047 #define ILI9225_RAM_ADDRESS_SET_1 0x20
0048 #define ILI9225_RAM_ADDRESS_SET_2 0x21
0049 #define ILI9225_WRITE_DATA_TO_GRAM 0x22
0050 #define ILI9225_SOFTWARE_RESET 0x28
0051 #define ILI9225_GATE_SCAN_CONTROL 0x30
0052 #define ILI9225_VERTICAL_SCROLL_1 0x31
0053 #define ILI9225_VERTICAL_SCROLL_2 0x32
0054 #define ILI9225_VERTICAL_SCROLL_3 0x33
0055 #define ILI9225_PARTIAL_DRIVING_POS_1 0x34
0056 #define ILI9225_PARTIAL_DRIVING_POS_2 0x35
0057 #define ILI9225_HORIZ_WINDOW_ADDR_1 0x36
0058 #define ILI9225_HORIZ_WINDOW_ADDR_2 0x37
0059 #define ILI9225_VERT_WINDOW_ADDR_1 0x38
0060 #define ILI9225_VERT_WINDOW_ADDR_2 0x39
0061 #define ILI9225_GAMMA_CONTROL_1 0x50
0062 #define ILI9225_GAMMA_CONTROL_2 0x51
0063 #define ILI9225_GAMMA_CONTROL_3 0x52
0064 #define ILI9225_GAMMA_CONTROL_4 0x53
0065 #define ILI9225_GAMMA_CONTROL_5 0x54
0066 #define ILI9225_GAMMA_CONTROL_6 0x55
0067 #define ILI9225_GAMMA_CONTROL_7 0x56
0068 #define ILI9225_GAMMA_CONTROL_8 0x57
0069 #define ILI9225_GAMMA_CONTROL_9 0x58
0070 #define ILI9225_GAMMA_CONTROL_10 0x59
0071
0072 static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data)
0073 {
0074 u8 par[2] = { data >> 8, data & 0xff };
0075
0076 return mipi_dbi_command_buf(dbi, cmd, par, 2);
0077 }
0078
0079 static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
0080 {
0081 struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
0082 struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
0083 unsigned int height = rect->y2 - rect->y1;
0084 unsigned int width = rect->x2 - rect->x1;
0085 struct mipi_dbi *dbi = &dbidev->dbi;
0086 bool swap = dbi->swap_bytes;
0087 u16 x_start, y_start;
0088 u16 x1, x2, y1, y2;
0089 int idx, ret = 0;
0090 bool full;
0091 void *tr;
0092
0093 if (!drm_dev_enter(fb->dev, &idx))
0094 return;
0095
0096 full = width == fb->width && height == fb->height;
0097
0098 DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
0099
0100 if (!dbi->dc || !full || swap ||
0101 fb->format->format == DRM_FORMAT_XRGB8888) {
0102 tr = dbidev->tx_buf;
0103 ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap);
0104 if (ret)
0105 goto err_msg;
0106 } else {
0107 tr = cma_obj->vaddr;
0108 }
0109
0110 switch (dbidev->rotation) {
0111 default:
0112 x1 = rect->x1;
0113 x2 = rect->x2 - 1;
0114 y1 = rect->y1;
0115 y2 = rect->y2 - 1;
0116 x_start = x1;
0117 y_start = y1;
0118 break;
0119 case 90:
0120 x1 = rect->y1;
0121 x2 = rect->y2 - 1;
0122 y1 = fb->width - rect->x2;
0123 y2 = fb->width - rect->x1 - 1;
0124 x_start = x1;
0125 y_start = y2;
0126 break;
0127 case 180:
0128 x1 = fb->width - rect->x2;
0129 x2 = fb->width - rect->x1 - 1;
0130 y1 = fb->height - rect->y2;
0131 y2 = fb->height - rect->y1 - 1;
0132 x_start = x2;
0133 y_start = y2;
0134 break;
0135 case 270:
0136 x1 = fb->height - rect->y2;
0137 x2 = fb->height - rect->y1 - 1;
0138 y1 = rect->x1;
0139 y2 = rect->x2 - 1;
0140 x_start = x2;
0141 y_start = y1;
0142 break;
0143 }
0144
0145 ili9225_command(dbi, ILI9225_HORIZ_WINDOW_ADDR_1, x2);
0146 ili9225_command(dbi, ILI9225_HORIZ_WINDOW_ADDR_2, x1);
0147 ili9225_command(dbi, ILI9225_VERT_WINDOW_ADDR_1, y2);
0148 ili9225_command(dbi, ILI9225_VERT_WINDOW_ADDR_2, y1);
0149
0150 ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_1, x_start);
0151 ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_2, y_start);
0152
0153 ret = mipi_dbi_command_buf(dbi, ILI9225_WRITE_DATA_TO_GRAM, tr,
0154 width * height * 2);
0155 err_msg:
0156 if (ret)
0157 dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
0158
0159 drm_dev_exit(idx);
0160 }
0161
0162 static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
0163 struct drm_plane_state *old_state)
0164 {
0165 struct drm_plane_state *state = pipe->plane.state;
0166 struct drm_rect rect;
0167
0168 if (!pipe->crtc.state->active)
0169 return;
0170
0171 if (drm_atomic_helper_damage_merged(old_state, state, &rect))
0172 ili9225_fb_dirty(state->fb, &rect);
0173 }
0174
0175 static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
0176 struct drm_crtc_state *crtc_state,
0177 struct drm_plane_state *plane_state)
0178 {
0179 struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
0180 struct drm_framebuffer *fb = plane_state->fb;
0181 struct device *dev = pipe->crtc.dev->dev;
0182 struct mipi_dbi *dbi = &dbidev->dbi;
0183 struct drm_rect rect = {
0184 .x1 = 0,
0185 .x2 = fb->width,
0186 .y1 = 0,
0187 .y2 = fb->height,
0188 };
0189 int ret, idx;
0190 u8 am_id;
0191
0192 if (!drm_dev_enter(pipe->crtc.dev, &idx))
0193 return;
0194
0195 DRM_DEBUG_KMS("\n");
0196
0197 mipi_dbi_hw_reset(dbi);
0198
0199
0200
0201
0202
0203
0204
0205 ret = ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0000);
0206 if (ret) {
0207 DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
0208 goto out_exit;
0209 }
0210 ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0000);
0211 ili9225_command(dbi, ILI9225_POWER_CONTROL_3, 0x0000);
0212 ili9225_command(dbi, ILI9225_POWER_CONTROL_4, 0x0000);
0213 ili9225_command(dbi, ILI9225_POWER_CONTROL_5, 0x0000);
0214
0215 msleep(40);
0216
0217 ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0018);
0218 ili9225_command(dbi, ILI9225_POWER_CONTROL_3, 0x6121);
0219 ili9225_command(dbi, ILI9225_POWER_CONTROL_4, 0x006f);
0220 ili9225_command(dbi, ILI9225_POWER_CONTROL_5, 0x495f);
0221 ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0800);
0222
0223 msleep(10);
0224
0225 ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x103b);
0226
0227 msleep(50);
0228
0229 switch (dbidev->rotation) {
0230 default:
0231 am_id = 0x30;
0232 break;
0233 case 90:
0234 am_id = 0x18;
0235 break;
0236 case 180:
0237 am_id = 0x00;
0238 break;
0239 case 270:
0240 am_id = 0x28;
0241 break;
0242 }
0243 ili9225_command(dbi, ILI9225_DRIVER_OUTPUT_CONTROL, 0x011c);
0244 ili9225_command(dbi, ILI9225_LCD_AC_DRIVING_CONTROL, 0x0100);
0245 ili9225_command(dbi, ILI9225_ENTRY_MODE, 0x1000 | am_id);
0246 ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0000);
0247 ili9225_command(dbi, ILI9225_BLANK_PERIOD_CONTROL_1, 0x0808);
0248 ili9225_command(dbi, ILI9225_FRAME_CYCLE_CONTROL, 0x1100);
0249 ili9225_command(dbi, ILI9225_INTERFACE_CONTROL, 0x0000);
0250 ili9225_command(dbi, ILI9225_OSCILLATION_CONTROL, 0x0d01);
0251 ili9225_command(dbi, ILI9225_VCI_RECYCLING, 0x0020);
0252 ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_1, 0x0000);
0253 ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_2, 0x0000);
0254
0255 ili9225_command(dbi, ILI9225_GATE_SCAN_CONTROL, 0x0000);
0256 ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_1, 0x00db);
0257 ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_2, 0x0000);
0258 ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_3, 0x0000);
0259 ili9225_command(dbi, ILI9225_PARTIAL_DRIVING_POS_1, 0x00db);
0260 ili9225_command(dbi, ILI9225_PARTIAL_DRIVING_POS_2, 0x0000);
0261
0262 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_1, 0x0000);
0263 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_2, 0x0808);
0264 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_3, 0x080a);
0265 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_4, 0x000a);
0266 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_5, 0x0a08);
0267 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_6, 0x0808);
0268 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_7, 0x0000);
0269 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_8, 0x0a00);
0270 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_9, 0x0710);
0271 ili9225_command(dbi, ILI9225_GAMMA_CONTROL_10, 0x0710);
0272
0273 ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0012);
0274
0275 msleep(50);
0276
0277 ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
0278
0279 ili9225_fb_dirty(fb, &rect);
0280 out_exit:
0281 drm_dev_exit(idx);
0282 }
0283
0284 static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
0285 {
0286 struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
0287 struct mipi_dbi *dbi = &dbidev->dbi;
0288
0289 DRM_DEBUG_KMS("\n");
0290
0291
0292
0293
0294
0295
0296
0297
0298 ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0000);
0299 msleep(50);
0300 ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0007);
0301 msleep(50);
0302 ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0a02);
0303 }
0304
0305 static int ili9225_dbi_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par,
0306 size_t num)
0307 {
0308 struct spi_device *spi = dbi->spi;
0309 unsigned int bpw = 8;
0310 u32 speed_hz;
0311 int ret;
0312
0313 gpiod_set_value_cansleep(dbi->dc, 0);
0314 speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1);
0315 ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, cmd, 1);
0316 if (ret || !num)
0317 return ret;
0318
0319 if (*cmd == ILI9225_WRITE_DATA_TO_GRAM && !dbi->swap_bytes)
0320 bpw = 16;
0321
0322 gpiod_set_value_cansleep(dbi->dc, 1);
0323 speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
0324
0325 return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num);
0326 }
0327
0328 static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = {
0329 .enable = ili9225_pipe_enable,
0330 .disable = ili9225_pipe_disable,
0331 .update = ili9225_pipe_update,
0332 };
0333
0334 static const struct drm_display_mode ili9225_mode = {
0335 DRM_SIMPLE_MODE(176, 220, 35, 44),
0336 };
0337
0338 DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops);
0339
0340 static const struct drm_driver ili9225_driver = {
0341 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
0342 .fops = &ili9225_fops,
0343 DRM_GEM_CMA_DRIVER_OPS_VMAP,
0344 .name = "ili9225",
0345 .desc = "Ilitek ILI9225",
0346 .date = "20171106",
0347 .major = 1,
0348 .minor = 0,
0349 };
0350
0351 static const struct of_device_id ili9225_of_match[] = {
0352 { .compatible = "vot,v220hf01a-t" },
0353 {},
0354 };
0355 MODULE_DEVICE_TABLE(of, ili9225_of_match);
0356
0357 static const struct spi_device_id ili9225_id[] = {
0358 { "v220hf01a-t", 0 },
0359 { },
0360 };
0361 MODULE_DEVICE_TABLE(spi, ili9225_id);
0362
0363 static int ili9225_probe(struct spi_device *spi)
0364 {
0365 struct device *dev = &spi->dev;
0366 struct mipi_dbi_dev *dbidev;
0367 struct drm_device *drm;
0368 struct mipi_dbi *dbi;
0369 struct gpio_desc *rs;
0370 u32 rotation = 0;
0371 int ret;
0372
0373 dbidev = devm_drm_dev_alloc(dev, &ili9225_driver,
0374 struct mipi_dbi_dev, drm);
0375 if (IS_ERR(dbidev))
0376 return PTR_ERR(dbidev);
0377
0378 dbi = &dbidev->dbi;
0379 drm = &dbidev->drm;
0380
0381 dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0382 if (IS_ERR(dbi->reset))
0383 return dev_err_probe(dev, PTR_ERR(dbi->reset), "Failed to get GPIO 'reset'\n");
0384
0385 rs = devm_gpiod_get(dev, "rs", GPIOD_OUT_LOW);
0386 if (IS_ERR(rs))
0387 return dev_err_probe(dev, PTR_ERR(rs), "Failed to get GPIO 'rs'\n");
0388
0389 device_property_read_u32(dev, "rotation", &rotation);
0390
0391 ret = mipi_dbi_spi_init(spi, dbi, rs);
0392 if (ret)
0393 return ret;
0394
0395
0396 dbi->command = ili9225_dbi_command;
0397
0398 ret = mipi_dbi_dev_init(dbidev, &ili9225_pipe_funcs, &ili9225_mode, rotation);
0399 if (ret)
0400 return ret;
0401
0402 drm_mode_config_reset(drm);
0403
0404 ret = drm_dev_register(drm, 0);
0405 if (ret)
0406 return ret;
0407
0408 spi_set_drvdata(spi, drm);
0409
0410 drm_fbdev_generic_setup(drm, 0);
0411
0412 return 0;
0413 }
0414
0415 static void ili9225_remove(struct spi_device *spi)
0416 {
0417 struct drm_device *drm = spi_get_drvdata(spi);
0418
0419 drm_dev_unplug(drm);
0420 drm_atomic_helper_shutdown(drm);
0421 }
0422
0423 static void ili9225_shutdown(struct spi_device *spi)
0424 {
0425 drm_atomic_helper_shutdown(spi_get_drvdata(spi));
0426 }
0427
0428 static struct spi_driver ili9225_spi_driver = {
0429 .driver = {
0430 .name = "ili9225",
0431 .owner = THIS_MODULE,
0432 .of_match_table = ili9225_of_match,
0433 },
0434 .id_table = ili9225_id,
0435 .probe = ili9225_probe,
0436 .remove = ili9225_remove,
0437 .shutdown = ili9225_shutdown,
0438 };
0439 module_spi_driver(ili9225_spi_driver);
0440
0441 MODULE_DESCRIPTION("Ilitek ILI9225 DRM driver");
0442 MODULE_AUTHOR("David Lechner <david@lechnology.com>");
0443 MODULE_LICENSE("GPL");