Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2016-2017 Broadcom
0003  *
0004  * This program is free software; you can redistribute it and/or modify
0005  * it under the terms of the GNU General Public License version 2 as
0006  * published by the Free Software Foundation.
0007  *
0008  * Portions of this file (derived from panel-simple.c) are:
0009  *
0010  * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
0011  *
0012  * Permission is hereby granted, free of charge, to any person obtaining a
0013  * copy of this software and associated documentation files (the "Software"),
0014  * to deal in the Software without restriction, including without limitation
0015  * the rights to use, copy, modify, merge, publish, distribute, sub license,
0016  * and/or sell copies of the Software, and to permit persons to whom the
0017  * Software is furnished to do so, subject to the following conditions:
0018  *
0019  * The above copyright notice and this permission notice (including the
0020  * next paragraph) shall be included in all copies or substantial portions
0021  * of the Software.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0024  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0025  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
0026  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0027  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0028  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0029  * DEALINGS IN THE SOFTWARE.
0030  */
0031 
0032 /*
0033  * Raspberry Pi 7" touchscreen panel driver.
0034  *
0035  * The 7" touchscreen consists of a DPI LCD panel, a Toshiba
0036  * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR
0037  * controlling power management, the LCD PWM, and initial register
0038  * setup of the Tohsiba.
0039  *
0040  * This driver controls the TC358762 and ATTINY88, presenting a DSI
0041  * device with a drm_panel.
0042  */
0043 
0044 #include <linux/delay.h>
0045 #include <linux/err.h>
0046 #include <linux/fb.h>
0047 #include <linux/i2c.h>
0048 #include <linux/media-bus-format.h>
0049 #include <linux/module.h>
0050 #include <linux/of.h>
0051 #include <linux/of_device.h>
0052 #include <linux/of_graph.h>
0053 #include <linux/pm.h>
0054 
0055 #include <drm/drm_crtc.h>
0056 #include <drm/drm_device.h>
0057 #include <drm/drm_mipi_dsi.h>
0058 #include <drm/drm_panel.h>
0059 
0060 #define RPI_DSI_DRIVER_NAME "rpi-ts-dsi"
0061 
0062 /* I2C registers of the Atmel microcontroller. */
0063 enum REG_ADDR {
0064     REG_ID = 0x80,
0065     REG_PORTA, /* BIT(2) for horizontal flip, BIT(3) for vertical flip */
0066     REG_PORTB,
0067     REG_PORTC,
0068     REG_PORTD,
0069     REG_POWERON,
0070     REG_PWM,
0071     REG_DDRA,
0072     REG_DDRB,
0073     REG_DDRC,
0074     REG_DDRD,
0075     REG_TEST,
0076     REG_WR_ADDRL,
0077     REG_WR_ADDRH,
0078     REG_READH,
0079     REG_READL,
0080     REG_WRITEH,
0081     REG_WRITEL,
0082     REG_ID2,
0083 };
0084 
0085 /* DSI D-PHY Layer Registers */
0086 #define D0W_DPHYCONTTX      0x0004
0087 #define CLW_DPHYCONTRX      0x0020
0088 #define D0W_DPHYCONTRX      0x0024
0089 #define D1W_DPHYCONTRX      0x0028
0090 #define COM_DPHYCONTRX      0x0038
0091 #define CLW_CNTRL       0x0040
0092 #define D0W_CNTRL       0x0044
0093 #define D1W_CNTRL       0x0048
0094 #define DFTMODE_CNTRL       0x0054
0095 
0096 /* DSI PPI Layer Registers */
0097 #define PPI_STARTPPI        0x0104
0098 #define PPI_BUSYPPI     0x0108
0099 #define PPI_LINEINITCNT     0x0110
0100 #define PPI_LPTXTIMECNT     0x0114
0101 #define PPI_CLS_ATMR        0x0140
0102 #define PPI_D0S_ATMR        0x0144
0103 #define PPI_D1S_ATMR        0x0148
0104 #define PPI_D0S_CLRSIPOCOUNT    0x0164
0105 #define PPI_D1S_CLRSIPOCOUNT    0x0168
0106 #define CLS_PRE         0x0180
0107 #define D0S_PRE         0x0184
0108 #define D1S_PRE         0x0188
0109 #define CLS_PREP        0x01A0
0110 #define D0S_PREP        0x01A4
0111 #define D1S_PREP        0x01A8
0112 #define CLS_ZERO        0x01C0
0113 #define D0S_ZERO        0x01C4
0114 #define D1S_ZERO        0x01C8
0115 #define PPI_CLRFLG      0x01E0
0116 #define PPI_CLRSIPO     0x01E4
0117 #define HSTIMEOUT       0x01F0
0118 #define HSTIMEOUTENABLE     0x01F4
0119 
0120 /* DSI Protocol Layer Registers */
0121 #define DSI_STARTDSI        0x0204
0122 #define DSI_BUSYDSI     0x0208
0123 #define DSI_LANEENABLE      0x0210
0124 # define DSI_LANEENABLE_CLOCK       BIT(0)
0125 # define DSI_LANEENABLE_D0      BIT(1)
0126 # define DSI_LANEENABLE_D1      BIT(2)
0127 
0128 #define DSI_LANESTATUS0     0x0214
0129 #define DSI_LANESTATUS1     0x0218
0130 #define DSI_INTSTATUS       0x0220
0131 #define DSI_INTMASK     0x0224
0132 #define DSI_INTCLR      0x0228
0133 #define DSI_LPTXTO      0x0230
0134 #define DSI_MODE        0x0260
0135 #define DSI_PAYLOAD0        0x0268
0136 #define DSI_PAYLOAD1        0x026C
0137 #define DSI_SHORTPKTDAT     0x0270
0138 #define DSI_SHORTPKTREQ     0x0274
0139 #define DSI_BTASTA      0x0278
0140 #define DSI_BTACLR      0x027C
0141 
0142 /* DSI General Registers */
0143 #define DSIERRCNT       0x0300
0144 #define DSISIGMOD       0x0304
0145 
0146 /* DSI Application Layer Registers */
0147 #define APLCTRL         0x0400
0148 #define APLSTAT         0x0404
0149 #define APLERR          0x0408
0150 #define PWRMOD          0x040C
0151 #define RDPKTLN         0x0410
0152 #define PXLFMT          0x0414
0153 #define MEMWRCMD        0x0418
0154 
0155 /* LCDC/DPI Host Registers */
0156 #define LCDCTRL         0x0420
0157 #define HSR         0x0424
0158 #define HDISPR          0x0428
0159 #define VSR         0x042C
0160 #define VDISPR          0x0430
0161 #define VFUEN           0x0434
0162 
0163 /* DBI-B Host Registers */
0164 #define DBIBCTRL        0x0440
0165 
0166 /* SPI Master Registers */
0167 #define SPICMR          0x0450
0168 #define SPITCR          0x0454
0169 
0170 /* System Controller Registers */
0171 #define SYSSTAT         0x0460
0172 #define SYSCTRL         0x0464
0173 #define SYSPLL1         0x0468
0174 #define SYSPLL2         0x046C
0175 #define SYSPLL3         0x0470
0176 #define SYSPMCTRL       0x047C
0177 
0178 /* GPIO Registers */
0179 #define GPIOC           0x0480
0180 #define GPIOO           0x0484
0181 #define GPIOI           0x0488
0182 
0183 /* I2C Registers */
0184 #define I2CCLKCTRL      0x0490
0185 
0186 /* Chip/Rev Registers */
0187 #define IDREG           0x04A0
0188 
0189 /* Debug Registers */
0190 #define WCMDQUEUE       0x0500
0191 #define RCMDQUEUE       0x0504
0192 
0193 struct rpi_touchscreen {
0194     struct drm_panel base;
0195     struct mipi_dsi_device *dsi;
0196     struct i2c_client *i2c;
0197 };
0198 
0199 static const struct drm_display_mode rpi_touchscreen_modes[] = {
0200     {
0201         /* Modeline comes from the Raspberry Pi firmware, with HFP=1
0202          * plugged in and clock re-computed from that.
0203          */
0204         .clock = 25979400 / 1000,
0205         .hdisplay = 800,
0206         .hsync_start = 800 + 1,
0207         .hsync_end = 800 + 1 + 2,
0208         .htotal = 800 + 1 + 2 + 46,
0209         .vdisplay = 480,
0210         .vsync_start = 480 + 7,
0211         .vsync_end = 480 + 7 + 2,
0212         .vtotal = 480 + 7 + 2 + 21,
0213     },
0214 };
0215 
0216 static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel)
0217 {
0218     return container_of(panel, struct rpi_touchscreen, base);
0219 }
0220 
0221 static int rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg)
0222 {
0223     return i2c_smbus_read_byte_data(ts->i2c, reg);
0224 }
0225 
0226 static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts,
0227                       u8 reg, u8 val)
0228 {
0229     int ret;
0230 
0231     ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
0232     if (ret)
0233         dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret);
0234 }
0235 
0236 static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val)
0237 {
0238     u8 msg[] = {
0239         reg,
0240         reg >> 8,
0241         val,
0242         val >> 8,
0243         val >> 16,
0244         val >> 24,
0245     };
0246 
0247     mipi_dsi_generic_write(ts->dsi, msg, sizeof(msg));
0248 
0249     return 0;
0250 }
0251 
0252 static int rpi_touchscreen_disable(struct drm_panel *panel)
0253 {
0254     struct rpi_touchscreen *ts = panel_to_ts(panel);
0255 
0256     rpi_touchscreen_i2c_write(ts, REG_PWM, 0);
0257 
0258     rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
0259     udelay(1);
0260 
0261     return 0;
0262 }
0263 
0264 static int rpi_touchscreen_noop(struct drm_panel *panel)
0265 {
0266     return 0;
0267 }
0268 
0269 static int rpi_touchscreen_prepare(struct drm_panel *panel)
0270 {
0271     struct rpi_touchscreen *ts = panel_to_ts(panel);
0272     int i;
0273 
0274     rpi_touchscreen_i2c_write(ts, REG_POWERON, 1);
0275     /* Wait for nPWRDWN to go low to indicate poweron is done. */
0276     for (i = 0; i < 100; i++) {
0277         if (rpi_touchscreen_i2c_read(ts, REG_PORTB) & 1)
0278             break;
0279     }
0280 
0281     rpi_touchscreen_write(ts, DSI_LANEENABLE,
0282                   DSI_LANEENABLE_CLOCK |
0283                   DSI_LANEENABLE_D0);
0284     rpi_touchscreen_write(ts, PPI_D0S_CLRSIPOCOUNT, 0x05);
0285     rpi_touchscreen_write(ts, PPI_D1S_CLRSIPOCOUNT, 0x05);
0286     rpi_touchscreen_write(ts, PPI_D0S_ATMR, 0x00);
0287     rpi_touchscreen_write(ts, PPI_D1S_ATMR, 0x00);
0288     rpi_touchscreen_write(ts, PPI_LPTXTIMECNT, 0x03);
0289 
0290     rpi_touchscreen_write(ts, SPICMR, 0x00);
0291     rpi_touchscreen_write(ts, LCDCTRL, 0x00100150);
0292     rpi_touchscreen_write(ts, SYSCTRL, 0x040f);
0293     msleep(100);
0294 
0295     rpi_touchscreen_write(ts, PPI_STARTPPI, 0x01);
0296     rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01);
0297     msleep(100);
0298 
0299     return 0;
0300 }
0301 
0302 static int rpi_touchscreen_enable(struct drm_panel *panel)
0303 {
0304     struct rpi_touchscreen *ts = panel_to_ts(panel);
0305 
0306     /* Turn on the backlight. */
0307     rpi_touchscreen_i2c_write(ts, REG_PWM, 255);
0308 
0309     /* Default to the same orientation as the closed source
0310      * firmware used for the panel.  Runtime rotation
0311      * configuration will be supported using VC4's plane
0312      * orientation bits.
0313      */
0314     rpi_touchscreen_i2c_write(ts, REG_PORTA, BIT(2));
0315 
0316     return 0;
0317 }
0318 
0319 static int rpi_touchscreen_get_modes(struct drm_panel *panel,
0320                      struct drm_connector *connector)
0321 {
0322     unsigned int i, num = 0;
0323     static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
0324 
0325     for (i = 0; i < ARRAY_SIZE(rpi_touchscreen_modes); i++) {
0326         const struct drm_display_mode *m = &rpi_touchscreen_modes[i];
0327         struct drm_display_mode *mode;
0328 
0329         mode = drm_mode_duplicate(connector->dev, m);
0330         if (!mode) {
0331             dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
0332                 m->hdisplay, m->vdisplay,
0333                 drm_mode_vrefresh(m));
0334             continue;
0335         }
0336 
0337         mode->type |= DRM_MODE_TYPE_DRIVER;
0338 
0339         if (i == 0)
0340             mode->type |= DRM_MODE_TYPE_PREFERRED;
0341 
0342         drm_mode_set_name(mode);
0343 
0344         drm_mode_probed_add(connector, mode);
0345         num++;
0346     }
0347 
0348     connector->display_info.bpc = 8;
0349     connector->display_info.width_mm = 154;
0350     connector->display_info.height_mm = 86;
0351     drm_display_info_set_bus_formats(&connector->display_info,
0352                      &bus_format, 1);
0353 
0354     return num;
0355 }
0356 
0357 static const struct drm_panel_funcs rpi_touchscreen_funcs = {
0358     .disable = rpi_touchscreen_disable,
0359     .unprepare = rpi_touchscreen_noop,
0360     .prepare = rpi_touchscreen_prepare,
0361     .enable = rpi_touchscreen_enable,
0362     .get_modes = rpi_touchscreen_get_modes,
0363 };
0364 
0365 static int rpi_touchscreen_probe(struct i2c_client *i2c,
0366                  const struct i2c_device_id *id)
0367 {
0368     struct device *dev = &i2c->dev;
0369     struct rpi_touchscreen *ts;
0370     struct device_node *endpoint, *dsi_host_node;
0371     struct mipi_dsi_host *host;
0372     int ver;
0373     struct mipi_dsi_device_info info = {
0374         .type = RPI_DSI_DRIVER_NAME,
0375         .channel = 0,
0376         .node = NULL,
0377     };
0378 
0379     ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
0380     if (!ts)
0381         return -ENOMEM;
0382 
0383     i2c_set_clientdata(i2c, ts);
0384 
0385     ts->i2c = i2c;
0386 
0387     ver = rpi_touchscreen_i2c_read(ts, REG_ID);
0388     if (ver < 0) {
0389         dev_err(dev, "Atmel I2C read failed: %d\n", ver);
0390         return -ENODEV;
0391     }
0392 
0393     switch (ver) {
0394     case 0xde: /* ver 1 */
0395     case 0xc3: /* ver 2 */
0396         break;
0397     default:
0398         dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", ver);
0399         return -ENODEV;
0400     }
0401 
0402     /* Turn off at boot, so we can cleanly sequence powering on. */
0403     rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
0404 
0405     /* Look up the DSI host.  It needs to probe before we do. */
0406     endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
0407     if (!endpoint)
0408         return -ENODEV;
0409 
0410     dsi_host_node = of_graph_get_remote_port_parent(endpoint);
0411     if (!dsi_host_node)
0412         goto error;
0413 
0414     host = of_find_mipi_dsi_host_by_node(dsi_host_node);
0415     of_node_put(dsi_host_node);
0416     if (!host) {
0417         of_node_put(endpoint);
0418         return -EPROBE_DEFER;
0419     }
0420 
0421     info.node = of_graph_get_remote_port(endpoint);
0422     if (!info.node)
0423         goto error;
0424 
0425     of_node_put(endpoint);
0426 
0427     ts->dsi = mipi_dsi_device_register_full(host, &info);
0428     if (IS_ERR(ts->dsi)) {
0429         dev_err(dev, "DSI device registration failed: %ld\n",
0430             PTR_ERR(ts->dsi));
0431         return PTR_ERR(ts->dsi);
0432     }
0433 
0434     drm_panel_init(&ts->base, dev, &rpi_touchscreen_funcs,
0435                DRM_MODE_CONNECTOR_DSI);
0436 
0437     /* This appears last, as it's what will unblock the DSI host
0438      * driver's component bind function.
0439      */
0440     drm_panel_add(&ts->base);
0441 
0442     return 0;
0443 
0444 error:
0445     of_node_put(endpoint);
0446     return -ENODEV;
0447 }
0448 
0449 static int rpi_touchscreen_remove(struct i2c_client *i2c)
0450 {
0451     struct rpi_touchscreen *ts = i2c_get_clientdata(i2c);
0452 
0453     mipi_dsi_detach(ts->dsi);
0454 
0455     drm_panel_remove(&ts->base);
0456 
0457     mipi_dsi_device_unregister(ts->dsi);
0458 
0459     return 0;
0460 }
0461 
0462 static int rpi_touchscreen_dsi_probe(struct mipi_dsi_device *dsi)
0463 {
0464     int ret;
0465 
0466     dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
0467                MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
0468                MIPI_DSI_MODE_LPM);
0469     dsi->format = MIPI_DSI_FMT_RGB888;
0470     dsi->lanes = 1;
0471 
0472     ret = mipi_dsi_attach(dsi);
0473 
0474     if (ret)
0475         dev_err(&dsi->dev, "failed to attach dsi to host: %d\n", ret);
0476 
0477     return ret;
0478 }
0479 
0480 static struct mipi_dsi_driver rpi_touchscreen_dsi_driver = {
0481     .driver.name = RPI_DSI_DRIVER_NAME,
0482     .probe = rpi_touchscreen_dsi_probe,
0483 };
0484 
0485 static const struct of_device_id rpi_touchscreen_of_ids[] = {
0486     { .compatible = "raspberrypi,7inch-touchscreen-panel" },
0487     { } /* sentinel */
0488 };
0489 MODULE_DEVICE_TABLE(of, rpi_touchscreen_of_ids);
0490 
0491 static struct i2c_driver rpi_touchscreen_driver = {
0492     .driver = {
0493         .name = "rpi_touchscreen",
0494         .of_match_table = rpi_touchscreen_of_ids,
0495     },
0496     .probe = rpi_touchscreen_probe,
0497     .remove = rpi_touchscreen_remove,
0498 };
0499 
0500 static int __init rpi_touchscreen_init(void)
0501 {
0502     mipi_dsi_driver_register(&rpi_touchscreen_dsi_driver);
0503     return i2c_add_driver(&rpi_touchscreen_driver);
0504 }
0505 module_init(rpi_touchscreen_init);
0506 
0507 static void __exit rpi_touchscreen_exit(void)
0508 {
0509     i2c_del_driver(&rpi_touchscreen_driver);
0510     mipi_dsi_driver_unregister(&rpi_touchscreen_dsi_driver);
0511 }
0512 module_exit(rpi_touchscreen_exit);
0513 
0514 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
0515 MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver");
0516 MODULE_LICENSE("GPL v2");