950-0158-drm-panel-Add-support-for-the-Raspberry-Pi-7-Touchsc.patch 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. From e2d195723ec030733cdaf623c9419af5f308b230 Mon Sep 17 00:00:00 2001
  2. From: Eric Anholt <[email protected]>
  3. Date: Tue, 26 Apr 2016 13:46:13 -0700
  4. Subject: [PATCH] drm/panel: Add support for the Raspberry Pi 7" Touchscreen.
  5. This driver communicates with the Atmel microcontroller for sequencing
  6. the poweron of the TC358762 DSI-DPI bridge and controlling the
  7. backlight PWM.
  8. The following lines are required in config.txt, to keep the firmware
  9. from trying to bash our I2C lines and steal the DSI interrupts:
  10. disable_touchscreen=1
  11. ignore_lcd=2
  12. mask_gpu_interrupt1=0x1000
  13. This means that the firmware won't power on the panel at boot time (no
  14. rainbow) and the touchscreen input won't work. The native input
  15. driver for the touchscreen still needs to be written.
  16. v2: Set the same default orientation as the closed source firmware
  17. used, which is the best for viewing angle.
  18. Signed-off-by: Eric Anholt <[email protected]>
  19. ---
  20. drivers/gpu/drm/panel/Kconfig | 8 +
  21. drivers/gpu/drm/panel/Makefile | 1 +
  22. .../gpu/drm/panel/panel-raspberrypi-touchscreen.c | 514 +++++++++++++++++++++
  23. 3 files changed, 523 insertions(+)
  24. create mode 100644 drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
  25. --- a/drivers/gpu/drm/panel/Kconfig
  26. +++ b/drivers/gpu/drm/panel/Kconfig
  27. @@ -52,6 +52,14 @@ config DRM_PANEL_PANASONIC_VVX10F034N00
  28. WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some
  29. Xperia Z2 tablets
  30. +config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
  31. + tristate "Raspberry Pi 7-inch touchscreen panel"
  32. + depends on DRM_MIPI_DSI
  33. + help
  34. + Say Y here if you want to enable support for the Raspberry
  35. + Pi 7" Touchscreen. To compile this driver as a module,
  36. + choose M here.
  37. +
  38. config DRM_PANEL_SAMSUNG_S6E8AA0
  39. tristate "Samsung S6E8AA0 DSI video mode panel"
  40. depends on OF
  41. --- a/drivers/gpu/drm/panel/Makefile
  42. +++ b/drivers/gpu/drm/panel/Makefile
  43. @@ -2,6 +2,7 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-
  44. obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
  45. obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
  46. obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o
  47. +obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o
  48. obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
  49. obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
  50. obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
  51. --- /dev/null
  52. +++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
  53. @@ -0,0 +1,514 @@
  54. +/*
  55. + * Copyright © 2016 Broadcom
  56. + *
  57. + * This program is free software; you can redistribute it and/or modify
  58. + * it under the terms of the GNU General Public License version 2 as
  59. + * published by the Free Software Foundation.
  60. + *
  61. + * Portions of this file (derived from panel-simple.c) are:
  62. + *
  63. + * Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
  64. + *
  65. + * Permission is hereby granted, free of charge, to any person obtaining a
  66. + * copy of this software and associated documentation files (the "Software"),
  67. + * to deal in the Software without restriction, including without limitation
  68. + * the rights to use, copy, modify, merge, publish, distribute, sub license,
  69. + * and/or sell copies of the Software, and to permit persons to whom the
  70. + * Software is furnished to do so, subject to the following conditions:
  71. + *
  72. + * The above copyright notice and this permission notice (including the
  73. + * next paragraph) shall be included in all copies or substantial portions
  74. + * of the Software.
  75. + *
  76. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  77. + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  78. + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  79. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  80. + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  81. + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  82. + * DEALINGS IN THE SOFTWARE.
  83. + */
  84. +
  85. +/**
  86. + * DOC: Raspberry Pi 7" touchscreen panel driver.
  87. + *
  88. + * The 7" touchscreen consists of a DPI LCD panel, a Toshiba
  89. + * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR
  90. + * controlling power management, the LCD PWM, and the touchscreen.
  91. + *
  92. + * This driver presents this device as a MIPI DSI panel to the DRM
  93. + * driver, and should expose the touchscreen as a HID device.
  94. + */
  95. +
  96. +#include <linux/delay.h>
  97. +#include <linux/err.h>
  98. +#include <linux/fb.h>
  99. +#include <linux/gpio.h>
  100. +#include <linux/gpio/consumer.h>
  101. +#include <linux/i2c.h>
  102. +#include <linux/module.h>
  103. +#include <linux/of.h>
  104. +#include <linux/of_device.h>
  105. +#include <linux/of_graph.h>
  106. +#include <linux/pm.h>
  107. +
  108. +#include <drm/drm_panel.h>
  109. +#include <drm/drmP.h>
  110. +#include <drm/drm_crtc.h>
  111. +#include <drm/drm_mipi_dsi.h>
  112. +#include <drm/drm_panel.h>
  113. +
  114. +/* I2C registers of the Atmel microcontroller. */
  115. +enum REG_ADDR {
  116. + REG_ID = 0x80,
  117. + REG_PORTA, // BIT(2) for horizontal flip, BIT(3) for vertical flip
  118. + REG_PORTB,
  119. + REG_PORTC,
  120. + REG_PORTD,
  121. + REG_POWERON,
  122. + REG_PWM,
  123. + REG_DDRA,
  124. + REG_DDRB,
  125. + REG_DDRC,
  126. + REG_DDRD,
  127. + REG_TEST,
  128. + REG_WR_ADDRL,
  129. + REG_WR_ADDRH,
  130. + REG_READH,
  131. + REG_READL,
  132. + REG_WRITEH,
  133. + REG_WRITEL,
  134. + REG_ID2,
  135. +};
  136. +
  137. +/* We only turn the PWM on or off, without varying values. */
  138. +#define RPI_TOUCHSCREEN_MAX_BRIGHTNESS 1
  139. +
  140. +/* DSI D-PHY Layer Registers */
  141. +#define D0W_DPHYCONTTX 0x0004
  142. +#define CLW_DPHYCONTRX 0x0020
  143. +#define D0W_DPHYCONTRX 0x0024
  144. +#define D1W_DPHYCONTRX 0x0028
  145. +#define COM_DPHYCONTRX 0x0038
  146. +#define CLW_CNTRL 0x0040
  147. +#define D0W_CNTRL 0x0044
  148. +#define D1W_CNTRL 0x0048
  149. +#define DFTMODE_CNTRL 0x0054
  150. +
  151. +/* DSI PPI Layer Registers */
  152. +#define PPI_STARTPPI 0x0104
  153. +#define PPI_BUSYPPI 0x0108
  154. +#define PPI_LINEINITCNT 0x0110
  155. +#define PPI_LPTXTIMECNT 0x0114
  156. +//#define PPI_LANEENABLE 0x0134
  157. +//#define PPI_TX_RX_TA 0x013C
  158. +#define PPI_CLS_ATMR 0x0140
  159. +#define PPI_D0S_ATMR 0x0144
  160. +#define PPI_D1S_ATMR 0x0148
  161. +#define PPI_D0S_CLRSIPOCOUNT 0x0164
  162. +#define PPI_D1S_CLRSIPOCOUNT 0x0168
  163. +#define CLS_PRE 0x0180
  164. +#define D0S_PRE 0x0184
  165. +#define D1S_PRE 0x0188
  166. +#define CLS_PREP 0x01A0
  167. +#define D0S_PREP 0x01A4
  168. +#define D1S_PREP 0x01A8
  169. +#define CLS_ZERO 0x01C0
  170. +#define D0S_ZERO 0x01C4
  171. +#define D1S_ZERO 0x01C8
  172. +#define PPI_CLRFLG 0x01E0
  173. +#define PPI_CLRSIPO 0x01E4
  174. +#define HSTIMEOUT 0x01F0
  175. +#define HSTIMEOUTENABLE 0x01F4
  176. +
  177. +/* DSI Protocol Layer Registers */
  178. +#define DSI_STARTDSI 0x0204
  179. +#define DSI_BUSYDSI 0x0208
  180. +#define DSI_LANEENABLE 0x0210
  181. +# define DSI_LANEENABLE_CLOCK BIT(0)
  182. +# define DSI_LANEENABLE_D0 BIT(1)
  183. +# define DSI_LANEENABLE_D1 BIT(2)
  184. +
  185. +#define DSI_LANESTATUS0 0x0214
  186. +#define DSI_LANESTATUS1 0x0218
  187. +#define DSI_INTSTATUS 0x0220
  188. +#define DSI_INTMASK 0x0224
  189. +#define DSI_INTCLR 0x0228
  190. +#define DSI_LPTXTO 0x0230
  191. +#define DSI_MODE 0x0260
  192. +#define DSI_PAYLOAD0 0x0268
  193. +#define DSI_PAYLOAD1 0x026C
  194. +#define DSI_SHORTPKTDAT 0x0270
  195. +#define DSI_SHORTPKTREQ 0x0274
  196. +#define DSI_BTASTA 0x0278
  197. +#define DSI_BTACLR 0x027C
  198. +
  199. +/* DSI General Registers */
  200. +#define DSIERRCNT 0x0300
  201. +#define DSISIGMOD 0x0304
  202. +
  203. +/* DSI Application Layer Registers */
  204. +#define APLCTRL 0x0400
  205. +#define APLSTAT 0x0404
  206. +#define APLERR 0x0408
  207. +#define PWRMOD 0x040C
  208. +#define RDPKTLN 0x0410
  209. +#define PXLFMT 0x0414
  210. +#define MEMWRCMD 0x0418
  211. +
  212. +/* LCDC/DPI Host Registers */
  213. +#define LCDCTRL 0x0420
  214. +#define HSR 0x0424
  215. +#define HDISPR 0x0428
  216. +#define VSR 0x042C
  217. +#define VDISPR 0x0430
  218. +#define VFUEN 0x0434
  219. +
  220. +/* DBI-B Host Registers */
  221. +#define DBIBCTRL 0x0440
  222. +
  223. +/* SPI Master Registers */
  224. +#define SPICMR 0x0450
  225. +#define SPITCR 0x0454
  226. +
  227. +/* System Controller Registers */
  228. +#define SYSSTAT 0x0460
  229. +#define SYSCTRL 0x0464
  230. +#define SYSPLL1 0x0468
  231. +#define SYSPLL2 0x046C
  232. +#define SYSPLL3 0x0470
  233. +#define SYSPMCTRL 0x047C
  234. +
  235. +/* GPIO Registers */
  236. +#define GPIOC 0x0480
  237. +#define GPIOO 0x0484
  238. +#define GPIOI 0x0488
  239. +
  240. +/* I2C Registers */
  241. +#define I2CCLKCTRL 0x0490
  242. +
  243. +/* Chip/Rev Registers */
  244. +#define IDREG 0x04A0
  245. +
  246. +/* Debug Registers */
  247. +#define WCMDQUEUE 0x0500
  248. +#define RCMDQUEUE 0x0504
  249. +
  250. +struct rpi_touchscreen {
  251. + struct drm_panel base;
  252. + struct mipi_dsi_device *dsi;
  253. + struct i2c_client *bridge_i2c;
  254. +
  255. + /* Version of the firmware on the bridge chip */
  256. + int atmel_ver;
  257. +};
  258. +
  259. +static const struct drm_display_mode rpi_touchscreen_modes[] = {
  260. + {
  261. + /* The DSI PLL can only integer divide from the 2Ghz
  262. + * PLLD, giving us few choices. We pick a divide by 3
  263. + * as our DSI HS clock, giving us a pixel clock of
  264. + * that divided by 24 bits. Pad out HFP to get our
  265. + * panel to refresh at 60Hz, even if that doesn't
  266. + * match the datasheet.
  267. + */
  268. +#define PIXEL_CLOCK ((2000000000 / 3) / 24)
  269. +#define VREFRESH 60
  270. +#define VTOTAL (480 + 7 + 2 + 21)
  271. +#define HACT 800
  272. +#define HSW 2
  273. +#define HBP 46
  274. +#define HFP ((PIXEL_CLOCK / (VTOTAL * VREFRESH)) - (HACT + HSW + HBP))
  275. +
  276. + .clock = PIXEL_CLOCK / 1000,
  277. + .hdisplay = HACT,
  278. + .hsync_start = HACT + HFP,
  279. + .hsync_end = HACT + HFP + HSW,
  280. + .htotal = HACT + HFP + HSW + HBP,
  281. + .vdisplay = 480,
  282. + .vsync_start = 480 + 7,
  283. + .vsync_end = 480 + 7 + 2,
  284. + .vtotal = VTOTAL,
  285. + .vrefresh = 60,
  286. + },
  287. +};
  288. +
  289. +static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel)
  290. +{
  291. + return container_of(panel, struct rpi_touchscreen, base);
  292. +}
  293. +
  294. +static u8 rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg)
  295. +{
  296. + return i2c_smbus_read_byte_data(ts->bridge_i2c, reg);
  297. +}
  298. +
  299. +static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts,
  300. + u8 reg, u8 val)
  301. +{
  302. + int ret;
  303. +
  304. + ret = i2c_smbus_write_byte_data(ts->bridge_i2c, reg, val);
  305. + if (ret)
  306. + dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret);
  307. +}
  308. +
  309. +static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val)
  310. +{
  311. +#if 0
  312. + /* The firmware uses LP DSI transactions like this to bring up
  313. + * the hardware, which should be faster than using I2C to then
  314. + * pass to the Toshiba. However, I was unable to get it to
  315. + * work.
  316. + */
  317. + u8 msg[] = {
  318. + reg,
  319. + reg >> 8,
  320. + val,
  321. + val >> 8,
  322. + val >> 16,
  323. + val >> 24,
  324. + };
  325. +
  326. + mipi_dsi_dcs_write_buffer(ts->dsi, msg, sizeof(msg));
  327. +#else
  328. + rpi_touchscreen_i2c_write(ts, REG_WR_ADDRH, reg >> 8);
  329. + rpi_touchscreen_i2c_write(ts, REG_WR_ADDRL, reg);
  330. + rpi_touchscreen_i2c_write(ts, REG_WRITEH, val >> 8);
  331. + rpi_touchscreen_i2c_write(ts, REG_WRITEL, val);
  332. +#endif
  333. +
  334. + return 0;
  335. +}
  336. +
  337. +static int rpi_touchscreen_disable(struct drm_panel *panel)
  338. +{
  339. + struct rpi_touchscreen *ts = panel_to_ts(panel);
  340. +
  341. + rpi_touchscreen_i2c_write(ts, REG_PWM, 0);
  342. +
  343. + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
  344. + udelay(1);
  345. +
  346. + return 0;
  347. +}
  348. +
  349. +static int rpi_touchscreen_noop(struct drm_panel *panel)
  350. +{
  351. + return 0;
  352. +}
  353. +
  354. +static int rpi_touchscreen_enable(struct drm_panel *panel)
  355. +{
  356. + struct rpi_touchscreen *ts = panel_to_ts(panel);
  357. + int i;
  358. +
  359. + rpi_touchscreen_i2c_write(ts, REG_POWERON, 1);
  360. + /* Wait for nPWRDWN to go low to indicate poweron is done. */
  361. + for (i = 0; i < 100; i++) {
  362. + if (rpi_touchscreen_i2c_read(ts, REG_PORTB) & 1)
  363. + break;
  364. + }
  365. +
  366. + rpi_touchscreen_write(ts, DSI_LANEENABLE,
  367. + DSI_LANEENABLE_CLOCK |
  368. + DSI_LANEENABLE_D0 |
  369. + (ts->dsi->lanes > 1 ? DSI_LANEENABLE_D1 : 0));
  370. + rpi_touchscreen_write(ts, PPI_D0S_CLRSIPOCOUNT, 0x05);
  371. + rpi_touchscreen_write(ts, PPI_D1S_CLRSIPOCOUNT, 0x05);
  372. + rpi_touchscreen_write(ts, PPI_D0S_ATMR, 0x00);
  373. + rpi_touchscreen_write(ts, PPI_D1S_ATMR, 0x00);
  374. + rpi_touchscreen_write(ts, PPI_LPTXTIMECNT, 0x03);
  375. +
  376. + rpi_touchscreen_write(ts, SPICMR, 0x00);
  377. + rpi_touchscreen_write(ts, LCDCTRL, 0x00100150);
  378. + rpi_touchscreen_write(ts, SYSCTRL, 0x040f);
  379. + msleep(100);
  380. +
  381. + rpi_touchscreen_write(ts, PPI_STARTPPI, 0x01);
  382. + rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01);
  383. + msleep(100);
  384. +
  385. + /* Turn on the backlight. */
  386. + rpi_touchscreen_i2c_write(ts, REG_PWM, 255);
  387. +
  388. + /* Default to the same orientation as the closed source
  389. + * firmware used for the panel. Runtime rotation
  390. + * configuration will be supported using VC4's plane
  391. + * orientation bits.
  392. + */
  393. + rpi_touchscreen_i2c_write(ts, REG_PORTA, BIT(2));
  394. +
  395. + return 0;
  396. +}
  397. +
  398. +static int rpi_touchscreen_get_modes(struct drm_panel *panel)
  399. +{
  400. + struct drm_connector *connector = panel->connector;
  401. + struct drm_device *drm = panel->drm;
  402. + unsigned int i, num = 0;
  403. +
  404. + for (i = 0; i < ARRAY_SIZE(rpi_touchscreen_modes); i++) {
  405. + const struct drm_display_mode *m = &rpi_touchscreen_modes[i];
  406. + struct drm_display_mode *mode;
  407. +
  408. + mode = drm_mode_duplicate(drm, m);
  409. + if (!mode) {
  410. + dev_err(drm->dev, "failed to add mode %ux%u@%u\n",
  411. + m->hdisplay, m->vdisplay, m->vrefresh);
  412. + continue;
  413. + }
  414. +
  415. + mode->type |= DRM_MODE_TYPE_DRIVER;
  416. +
  417. + if (i == 0)
  418. + mode->type |= DRM_MODE_TYPE_PREFERRED;
  419. +
  420. + drm_mode_set_name(mode);
  421. +
  422. + drm_mode_probed_add(connector, mode);
  423. + num++;
  424. + }
  425. +
  426. + connector->display_info.bpc = 8;
  427. + connector->display_info.width_mm = 154;
  428. + connector->display_info.height_mm = 86;
  429. +
  430. + return num;
  431. +}
  432. +
  433. +static const struct drm_panel_funcs rpi_touchscreen_funcs = {
  434. + .disable = rpi_touchscreen_disable,
  435. + .unprepare = rpi_touchscreen_noop,
  436. + .prepare = rpi_touchscreen_noop,
  437. + .enable = rpi_touchscreen_enable,
  438. + .get_modes = rpi_touchscreen_get_modes,
  439. +};
  440. +
  441. +static struct i2c_client *rpi_touchscreen_get_i2c(struct device *dev,
  442. + const char *name)
  443. +{
  444. + struct device_node *node;
  445. + struct i2c_client *client;
  446. +
  447. + node = of_parse_phandle(dev->of_node, name, 0);
  448. + if (!node)
  449. + return ERR_PTR(-ENODEV);
  450. +
  451. + client = of_find_i2c_device_by_node(node);
  452. +
  453. + of_node_put(node);
  454. +
  455. + return client;
  456. +}
  457. +
  458. +static int rpi_touchscreen_dsi_probe(struct mipi_dsi_device *dsi)
  459. +{
  460. + struct device *dev = &dsi->dev;
  461. + struct rpi_touchscreen *ts;
  462. + int ret, ver;
  463. +
  464. + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
  465. + if (!ts)
  466. + return -ENOMEM;
  467. +
  468. + dev_set_drvdata(dev, ts);
  469. +
  470. + ts->dsi = dsi;
  471. + dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
  472. + MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
  473. + MIPI_DSI_MODE_LPM);
  474. + dsi->format = MIPI_DSI_FMT_RGB888;
  475. + dsi->lanes = 1;
  476. +
  477. + ts->bridge_i2c =
  478. + rpi_touchscreen_get_i2c(dev, "raspberrypi,touchscreen-bridge");
  479. + if (IS_ERR(ts->bridge_i2c)) {
  480. + ret = -EPROBE_DEFER;
  481. + return ret;
  482. + }
  483. +
  484. + ver = rpi_touchscreen_i2c_read(ts, REG_ID);
  485. + if (ver < 0) {
  486. + dev_err(dev, "Atmel I2C read failed: %d\n", ver);
  487. + return -ENODEV;
  488. + }
  489. +
  490. + switch (ver) {
  491. + case 0xde:
  492. + ts->atmel_ver = 1;
  493. + break;
  494. + case 0xc3:
  495. + ts->atmel_ver = 2;
  496. + break;
  497. + default:
  498. + dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", ver);
  499. + return -ENODEV;
  500. + }
  501. +
  502. + /* Turn off at boot, so we can cleanly sequence powering on. */
  503. + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
  504. +
  505. + drm_panel_init(&ts->base);
  506. + ts->base.dev = dev;
  507. + ts->base.funcs = &rpi_touchscreen_funcs;
  508. +
  509. + ret = drm_panel_add(&ts->base);
  510. + if (ret < 0)
  511. + goto err_release_bridge;
  512. +
  513. + return mipi_dsi_attach(dsi);
  514. +
  515. +err_release_bridge:
  516. + put_device(&ts->bridge_i2c->dev);
  517. + return ret;
  518. +}
  519. +
  520. +static int rpi_touchscreen_dsi_remove(struct mipi_dsi_device *dsi)
  521. +{
  522. + struct device *dev = &dsi->dev;
  523. + struct rpi_touchscreen *ts = dev_get_drvdata(dev);
  524. + int ret;
  525. +
  526. + ret = mipi_dsi_detach(dsi);
  527. + if (ret < 0) {
  528. + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
  529. + return ret;
  530. + }
  531. +
  532. + drm_panel_detach(&ts->base);
  533. + drm_panel_remove(&ts->base);
  534. +
  535. + put_device(&ts->bridge_i2c->dev);
  536. +
  537. + return 0;
  538. +}
  539. +
  540. +static void rpi_touchscreen_dsi_shutdown(struct mipi_dsi_device *dsi)
  541. +{
  542. + struct device *dev = &dsi->dev;
  543. + struct rpi_touchscreen *ts = dev_get_drvdata(dev);
  544. +
  545. + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
  546. +}
  547. +
  548. +static const struct of_device_id rpi_touchscreen_of_match[] = {
  549. + { .compatible = "raspberrypi,touchscreen" },
  550. + { } /* sentinel */
  551. +};
  552. +MODULE_DEVICE_TABLE(of, rpi_touchscreen_of_match);
  553. +
  554. +static struct mipi_dsi_driver rpi_touchscreen_driver = {
  555. + .driver = {
  556. + .name = "raspberrypi-touchscreen",
  557. + .of_match_table = rpi_touchscreen_of_match,
  558. + },
  559. + .probe = rpi_touchscreen_dsi_probe,
  560. + .remove = rpi_touchscreen_dsi_remove,
  561. + .shutdown = rpi_touchscreen_dsi_shutdown,
  562. +};
  563. +module_mipi_dsi_driver(rpi_touchscreen_driver);
  564. +
  565. +MODULE_AUTHOR("Eric Anholt <[email protected]>");
  566. +MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver");
  567. +MODULE_LICENSE("GPL v2");