0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/backlight.h>
0013 #include <linux/delay.h>
0014 #include <linux/gpio/consumer.h>
0015 #include <linux/module.h>
0016 #include <linux/property.h>
0017 #include <linux/spi/spi.h>
0018
0019 #include <drm/drm_atomic_helper.h>
0020 #include <drm/drm_drv.h>
0021 #include <drm/drm_fb_helper.h>
0022 #include <drm/drm_gem_atomic_helper.h>
0023 #include <drm/drm_gem_cma_helper.h>
0024 #include <drm/drm_managed.h>
0025 #include <drm/drm_mipi_dbi.h>
0026 #include <drm/drm_modeset_helper.h>
0027 #include <video/mipi_display.h>
0028
0029 #define HX8357D_SETOSC 0xb0
0030 #define HX8357D_SETPOWER 0xb1
0031 #define HX8357D_SETRGB 0xb3
0032 #define HX8357D_SETCYC 0xb3
0033 #define HX8357D_SETCOM 0xb6
0034 #define HX8357D_SETEXTC 0xb9
0035 #define HX8357D_SETSTBA 0xc0
0036 #define HX8357D_SETPANEL 0xcc
0037 #define HX8357D_SETGAMMA 0xe0
0038
0039 #define HX8357D_MADCTL_MY 0x80
0040 #define HX8357D_MADCTL_MX 0x40
0041 #define HX8357D_MADCTL_MV 0x20
0042 #define HX8357D_MADCTL_ML 0x10
0043 #define HX8357D_MADCTL_RGB 0x00
0044 #define HX8357D_MADCTL_BGR 0x08
0045 #define HX8357D_MADCTL_MH 0x04
0046
0047 static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
0048 struct drm_crtc_state *crtc_state,
0049 struct drm_plane_state *plane_state)
0050 {
0051 struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
0052 struct mipi_dbi *dbi = &dbidev->dbi;
0053 u8 addr_mode;
0054 int ret, idx;
0055
0056 if (!drm_dev_enter(pipe->crtc.dev, &idx))
0057 return;
0058
0059 DRM_DEBUG_KMS("\n");
0060
0061 ret = mipi_dbi_poweron_conditional_reset(dbidev);
0062 if (ret < 0)
0063 goto out_exit;
0064 if (ret == 1)
0065 goto out_enable;
0066
0067
0068 mipi_dbi_command(dbi, HX8357D_SETEXTC, 0xFF, 0x83, 0x57);
0069 msleep(150);
0070
0071
0072 mipi_dbi_command(dbi, HX8357D_SETRGB, 0x00, 0x00, 0x06, 0x06);
0073
0074
0075 mipi_dbi_command(dbi, HX8357D_SETCOM, 0x25);
0076
0077
0078 mipi_dbi_command(dbi, HX8357D_SETOSC, 0x68);
0079
0080
0081 mipi_dbi_command(dbi, HX8357D_SETPANEL, 0x05);
0082
0083 mipi_dbi_command(dbi, HX8357D_SETPOWER,
0084 0x00,
0085 0x15,
0086 0x1C,
0087 0x1C,
0088 0x83,
0089 0xAA);
0090
0091 mipi_dbi_command(dbi, HX8357D_SETSTBA,
0092 0x50,
0093 0x50,
0094 0x01,
0095 0x3C,
0096 0x1E,
0097 0x08);
0098
0099 mipi_dbi_command(dbi, HX8357D_SETCYC,
0100 0x02,
0101 0x40,
0102 0x00,
0103 0x2A,
0104 0x2A,
0105 0x0D,
0106 0x78);
0107
0108 mipi_dbi_command(dbi, HX8357D_SETGAMMA,
0109 0x02,
0110 0x0A,
0111 0x11,
0112 0x1d,
0113 0x23,
0114 0x35,
0115 0x41,
0116 0x4b,
0117 0x4b,
0118 0x42,
0119 0x3A,
0120 0x27,
0121 0x1B,
0122 0x08,
0123 0x09,
0124 0x03,
0125 0x02,
0126 0x0A,
0127 0x11,
0128 0x1d,
0129 0x23,
0130 0x35,
0131 0x41,
0132 0x4b,
0133 0x4b,
0134 0x42,
0135 0x3A,
0136 0x27,
0137 0x1B,
0138 0x08,
0139 0x09,
0140 0x03,
0141 0x00,
0142 0x01);
0143
0144
0145 mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
0146 MIPI_DCS_PIXEL_FMT_16BIT);
0147
0148
0149 mipi_dbi_command(dbi, MIPI_DCS_SET_TEAR_ON, 0x00);
0150
0151
0152 mipi_dbi_command(dbi, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02);
0153
0154
0155 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
0156 msleep(150);
0157
0158
0159 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
0160 usleep_range(5000, 7000);
0161
0162 out_enable:
0163 switch (dbidev->rotation) {
0164 default:
0165 addr_mode = HX8357D_MADCTL_MX | HX8357D_MADCTL_MY;
0166 break;
0167 case 90:
0168 addr_mode = HX8357D_MADCTL_MV | HX8357D_MADCTL_MY;
0169 break;
0170 case 180:
0171 addr_mode = 0;
0172 break;
0173 case 270:
0174 addr_mode = HX8357D_MADCTL_MV | HX8357D_MADCTL_MX;
0175 break;
0176 }
0177 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
0178 mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
0179 out_exit:
0180 drm_dev_exit(idx);
0181 }
0182
0183 static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
0184 .enable = yx240qv29_enable,
0185 .disable = mipi_dbi_pipe_disable,
0186 .update = mipi_dbi_pipe_update,
0187 };
0188
0189 static const struct drm_display_mode yx350hv15_mode = {
0190 DRM_SIMPLE_MODE(320, 480, 60, 75),
0191 };
0192
0193 DEFINE_DRM_GEM_CMA_FOPS(hx8357d_fops);
0194
0195 static const struct drm_driver hx8357d_driver = {
0196 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
0197 .fops = &hx8357d_fops,
0198 DRM_GEM_CMA_DRIVER_OPS_VMAP,
0199 .debugfs_init = mipi_dbi_debugfs_init,
0200 .name = "hx8357d",
0201 .desc = "HX8357D",
0202 .date = "20181023",
0203 .major = 1,
0204 .minor = 0,
0205 };
0206
0207 static const struct of_device_id hx8357d_of_match[] = {
0208 { .compatible = "adafruit,yx350hv15" },
0209 { }
0210 };
0211 MODULE_DEVICE_TABLE(of, hx8357d_of_match);
0212
0213 static const struct spi_device_id hx8357d_id[] = {
0214 { "yx350hv15", 0 },
0215 { }
0216 };
0217 MODULE_DEVICE_TABLE(spi, hx8357d_id);
0218
0219 static int hx8357d_probe(struct spi_device *spi)
0220 {
0221 struct device *dev = &spi->dev;
0222 struct mipi_dbi_dev *dbidev;
0223 struct drm_device *drm;
0224 struct gpio_desc *dc;
0225 u32 rotation = 0;
0226 int ret;
0227
0228 dbidev = devm_drm_dev_alloc(dev, &hx8357d_driver,
0229 struct mipi_dbi_dev, drm);
0230 if (IS_ERR(dbidev))
0231 return PTR_ERR(dbidev);
0232
0233 drm = &dbidev->drm;
0234
0235 dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
0236 if (IS_ERR(dc))
0237 return dev_err_probe(dev, PTR_ERR(dc), "Failed to get GPIO 'dc'\n");
0238
0239 dbidev->backlight = devm_of_find_backlight(dev);
0240 if (IS_ERR(dbidev->backlight))
0241 return PTR_ERR(dbidev->backlight);
0242
0243 device_property_read_u32(dev, "rotation", &rotation);
0244
0245 ret = mipi_dbi_spi_init(spi, &dbidev->dbi, dc);
0246 if (ret)
0247 return ret;
0248
0249 ret = mipi_dbi_dev_init(dbidev, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation);
0250 if (ret)
0251 return ret;
0252
0253 drm_mode_config_reset(drm);
0254
0255 ret = drm_dev_register(drm, 0);
0256 if (ret)
0257 return ret;
0258
0259 spi_set_drvdata(spi, drm);
0260
0261 drm_fbdev_generic_setup(drm, 0);
0262
0263 return 0;
0264 }
0265
0266 static void hx8357d_remove(struct spi_device *spi)
0267 {
0268 struct drm_device *drm = spi_get_drvdata(spi);
0269
0270 drm_dev_unplug(drm);
0271 drm_atomic_helper_shutdown(drm);
0272 }
0273
0274 static void hx8357d_shutdown(struct spi_device *spi)
0275 {
0276 drm_atomic_helper_shutdown(spi_get_drvdata(spi));
0277 }
0278
0279 static struct spi_driver hx8357d_spi_driver = {
0280 .driver = {
0281 .name = "hx8357d",
0282 .of_match_table = hx8357d_of_match,
0283 },
0284 .id_table = hx8357d_id,
0285 .probe = hx8357d_probe,
0286 .remove = hx8357d_remove,
0287 .shutdown = hx8357d_shutdown,
0288 };
0289 module_spi_driver(hx8357d_spi_driver);
0290
0291 MODULE_DESCRIPTION("HX8357D DRM driver");
0292 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
0293 MODULE_LICENSE("GPL");