1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2016-2017 Broadcom
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
5*4882a593Smuzhiyun * it under the terms of the GNU General Public License version 2 as
6*4882a593Smuzhiyun * published by the Free Software Foundation.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Portions of this file (derived from panel-simple.c) are:
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
13*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
14*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
15*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sub license,
16*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
17*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the
20*4882a593Smuzhiyun * next paragraph) shall be included in all copies or substantial portions
21*4882a593Smuzhiyun * of the Software.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
26*4882a593Smuzhiyun * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27*4882a593Smuzhiyun * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28*4882a593Smuzhiyun * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29*4882a593Smuzhiyun * DEALINGS IN THE SOFTWARE.
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /**
33*4882a593Smuzhiyun * Raspberry Pi 7" touchscreen panel driver.
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * The 7" touchscreen consists of a DPI LCD panel, a Toshiba
36*4882a593Smuzhiyun * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR
37*4882a593Smuzhiyun * controlling power management, the LCD PWM, and initial register
38*4882a593Smuzhiyun * setup of the Tohsiba.
39*4882a593Smuzhiyun *
40*4882a593Smuzhiyun * This driver controls the TC358762 and ATTINY88, presenting a DSI
41*4882a593Smuzhiyun * device with a drm_panel.
42*4882a593Smuzhiyun */
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #include <linux/delay.h>
45*4882a593Smuzhiyun #include <linux/err.h>
46*4882a593Smuzhiyun #include <linux/fb.h>
47*4882a593Smuzhiyun #include <linux/i2c.h>
48*4882a593Smuzhiyun #include <linux/module.h>
49*4882a593Smuzhiyun #include <linux/of.h>
50*4882a593Smuzhiyun #include <linux/of_device.h>
51*4882a593Smuzhiyun #include <linux/of_graph.h>
52*4882a593Smuzhiyun #include <linux/pm.h>
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #include <drm/drm_crtc.h>
55*4882a593Smuzhiyun #include <drm/drm_device.h>
56*4882a593Smuzhiyun #include <drm/drm_mipi_dsi.h>
57*4882a593Smuzhiyun #include <drm/drm_panel.h>
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define RPI_DSI_DRIVER_NAME "rpi-ts-dsi"
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* I2C registers of the Atmel microcontroller. */
62*4882a593Smuzhiyun enum REG_ADDR {
63*4882a593Smuzhiyun REG_ID = 0x80,
64*4882a593Smuzhiyun REG_PORTA, /* BIT(2) for horizontal flip, BIT(3) for vertical flip */
65*4882a593Smuzhiyun REG_PORTB,
66*4882a593Smuzhiyun REG_PORTC,
67*4882a593Smuzhiyun REG_PORTD,
68*4882a593Smuzhiyun REG_POWERON,
69*4882a593Smuzhiyun REG_PWM,
70*4882a593Smuzhiyun REG_DDRA,
71*4882a593Smuzhiyun REG_DDRB,
72*4882a593Smuzhiyun REG_DDRC,
73*4882a593Smuzhiyun REG_DDRD,
74*4882a593Smuzhiyun REG_TEST,
75*4882a593Smuzhiyun REG_WR_ADDRL,
76*4882a593Smuzhiyun REG_WR_ADDRH,
77*4882a593Smuzhiyun REG_READH,
78*4882a593Smuzhiyun REG_READL,
79*4882a593Smuzhiyun REG_WRITEH,
80*4882a593Smuzhiyun REG_WRITEL,
81*4882a593Smuzhiyun REG_ID2,
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /* DSI D-PHY Layer Registers */
85*4882a593Smuzhiyun #define D0W_DPHYCONTTX 0x0004
86*4882a593Smuzhiyun #define CLW_DPHYCONTRX 0x0020
87*4882a593Smuzhiyun #define D0W_DPHYCONTRX 0x0024
88*4882a593Smuzhiyun #define D1W_DPHYCONTRX 0x0028
89*4882a593Smuzhiyun #define COM_DPHYCONTRX 0x0038
90*4882a593Smuzhiyun #define CLW_CNTRL 0x0040
91*4882a593Smuzhiyun #define D0W_CNTRL 0x0044
92*4882a593Smuzhiyun #define D1W_CNTRL 0x0048
93*4882a593Smuzhiyun #define DFTMODE_CNTRL 0x0054
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* DSI PPI Layer Registers */
96*4882a593Smuzhiyun #define PPI_STARTPPI 0x0104
97*4882a593Smuzhiyun #define PPI_BUSYPPI 0x0108
98*4882a593Smuzhiyun #define PPI_LINEINITCNT 0x0110
99*4882a593Smuzhiyun #define PPI_LPTXTIMECNT 0x0114
100*4882a593Smuzhiyun #define PPI_CLS_ATMR 0x0140
101*4882a593Smuzhiyun #define PPI_D0S_ATMR 0x0144
102*4882a593Smuzhiyun #define PPI_D1S_ATMR 0x0148
103*4882a593Smuzhiyun #define PPI_D0S_CLRSIPOCOUNT 0x0164
104*4882a593Smuzhiyun #define PPI_D1S_CLRSIPOCOUNT 0x0168
105*4882a593Smuzhiyun #define CLS_PRE 0x0180
106*4882a593Smuzhiyun #define D0S_PRE 0x0184
107*4882a593Smuzhiyun #define D1S_PRE 0x0188
108*4882a593Smuzhiyun #define CLS_PREP 0x01A0
109*4882a593Smuzhiyun #define D0S_PREP 0x01A4
110*4882a593Smuzhiyun #define D1S_PREP 0x01A8
111*4882a593Smuzhiyun #define CLS_ZERO 0x01C0
112*4882a593Smuzhiyun #define D0S_ZERO 0x01C4
113*4882a593Smuzhiyun #define D1S_ZERO 0x01C8
114*4882a593Smuzhiyun #define PPI_CLRFLG 0x01E0
115*4882a593Smuzhiyun #define PPI_CLRSIPO 0x01E4
116*4882a593Smuzhiyun #define HSTIMEOUT 0x01F0
117*4882a593Smuzhiyun #define HSTIMEOUTENABLE 0x01F4
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* DSI Protocol Layer Registers */
120*4882a593Smuzhiyun #define DSI_STARTDSI 0x0204
121*4882a593Smuzhiyun #define DSI_BUSYDSI 0x0208
122*4882a593Smuzhiyun #define DSI_LANEENABLE 0x0210
123*4882a593Smuzhiyun # define DSI_LANEENABLE_CLOCK BIT(0)
124*4882a593Smuzhiyun # define DSI_LANEENABLE_D0 BIT(1)
125*4882a593Smuzhiyun # define DSI_LANEENABLE_D1 BIT(2)
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun #define DSI_LANESTATUS0 0x0214
128*4882a593Smuzhiyun #define DSI_LANESTATUS1 0x0218
129*4882a593Smuzhiyun #define DSI_INTSTATUS 0x0220
130*4882a593Smuzhiyun #define DSI_INTMASK 0x0224
131*4882a593Smuzhiyun #define DSI_INTCLR 0x0228
132*4882a593Smuzhiyun #define DSI_LPTXTO 0x0230
133*4882a593Smuzhiyun #define DSI_MODE 0x0260
134*4882a593Smuzhiyun #define DSI_PAYLOAD0 0x0268
135*4882a593Smuzhiyun #define DSI_PAYLOAD1 0x026C
136*4882a593Smuzhiyun #define DSI_SHORTPKTDAT 0x0270
137*4882a593Smuzhiyun #define DSI_SHORTPKTREQ 0x0274
138*4882a593Smuzhiyun #define DSI_BTASTA 0x0278
139*4882a593Smuzhiyun #define DSI_BTACLR 0x027C
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /* DSI General Registers */
142*4882a593Smuzhiyun #define DSIERRCNT 0x0300
143*4882a593Smuzhiyun #define DSISIGMOD 0x0304
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* DSI Application Layer Registers */
146*4882a593Smuzhiyun #define APLCTRL 0x0400
147*4882a593Smuzhiyun #define APLSTAT 0x0404
148*4882a593Smuzhiyun #define APLERR 0x0408
149*4882a593Smuzhiyun #define PWRMOD 0x040C
150*4882a593Smuzhiyun #define RDPKTLN 0x0410
151*4882a593Smuzhiyun #define PXLFMT 0x0414
152*4882a593Smuzhiyun #define MEMWRCMD 0x0418
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* LCDC/DPI Host Registers */
155*4882a593Smuzhiyun #define LCDCTRL 0x0420
156*4882a593Smuzhiyun #define HSR 0x0424
157*4882a593Smuzhiyun #define HDISPR 0x0428
158*4882a593Smuzhiyun #define VSR 0x042C
159*4882a593Smuzhiyun #define VDISPR 0x0430
160*4882a593Smuzhiyun #define VFUEN 0x0434
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /* DBI-B Host Registers */
163*4882a593Smuzhiyun #define DBIBCTRL 0x0440
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* SPI Master Registers */
166*4882a593Smuzhiyun #define SPICMR 0x0450
167*4882a593Smuzhiyun #define SPITCR 0x0454
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* System Controller Registers */
170*4882a593Smuzhiyun #define SYSSTAT 0x0460
171*4882a593Smuzhiyun #define SYSCTRL 0x0464
172*4882a593Smuzhiyun #define SYSPLL1 0x0468
173*4882a593Smuzhiyun #define SYSPLL2 0x046C
174*4882a593Smuzhiyun #define SYSPLL3 0x0470
175*4882a593Smuzhiyun #define SYSPMCTRL 0x047C
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* GPIO Registers */
178*4882a593Smuzhiyun #define GPIOC 0x0480
179*4882a593Smuzhiyun #define GPIOO 0x0484
180*4882a593Smuzhiyun #define GPIOI 0x0488
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* I2C Registers */
183*4882a593Smuzhiyun #define I2CCLKCTRL 0x0490
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* Chip/Rev Registers */
186*4882a593Smuzhiyun #define IDREG 0x04A0
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* Debug Registers */
189*4882a593Smuzhiyun #define WCMDQUEUE 0x0500
190*4882a593Smuzhiyun #define RCMDQUEUE 0x0504
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun struct rpi_touchscreen {
193*4882a593Smuzhiyun struct drm_panel base;
194*4882a593Smuzhiyun struct mipi_dsi_device *dsi;
195*4882a593Smuzhiyun struct i2c_client *i2c;
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun static const struct drm_display_mode rpi_touchscreen_modes[] = {
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun /* Modeline comes from the Raspberry Pi firmware, with HFP=1
201*4882a593Smuzhiyun * plugged in and clock re-computed from that.
202*4882a593Smuzhiyun */
203*4882a593Smuzhiyun .clock = 25979400 / 1000,
204*4882a593Smuzhiyun .hdisplay = 800,
205*4882a593Smuzhiyun .hsync_start = 800 + 1,
206*4882a593Smuzhiyun .hsync_end = 800 + 1 + 2,
207*4882a593Smuzhiyun .htotal = 800 + 1 + 2 + 46,
208*4882a593Smuzhiyun .vdisplay = 480,
209*4882a593Smuzhiyun .vsync_start = 480 + 7,
210*4882a593Smuzhiyun .vsync_end = 480 + 7 + 2,
211*4882a593Smuzhiyun .vtotal = 480 + 7 + 2 + 21,
212*4882a593Smuzhiyun },
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun
panel_to_ts(struct drm_panel * panel)215*4882a593Smuzhiyun static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun return container_of(panel, struct rpi_touchscreen, base);
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
rpi_touchscreen_i2c_read(struct rpi_touchscreen * ts,u8 reg)220*4882a593Smuzhiyun static int rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun return i2c_smbus_read_byte_data(ts->i2c, reg);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
rpi_touchscreen_i2c_write(struct rpi_touchscreen * ts,u8 reg,u8 val)225*4882a593Smuzhiyun static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts,
226*4882a593Smuzhiyun u8 reg, u8 val)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun int ret;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
231*4882a593Smuzhiyun if (ret)
232*4882a593Smuzhiyun dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
rpi_touchscreen_write(struct rpi_touchscreen * ts,u16 reg,u32 val)235*4882a593Smuzhiyun static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun u8 msg[] = {
238*4882a593Smuzhiyun reg,
239*4882a593Smuzhiyun reg >> 8,
240*4882a593Smuzhiyun val,
241*4882a593Smuzhiyun val >> 8,
242*4882a593Smuzhiyun val >> 16,
243*4882a593Smuzhiyun val >> 24,
244*4882a593Smuzhiyun };
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun mipi_dsi_generic_write(ts->dsi, msg, sizeof(msg));
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun return 0;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
rpi_touchscreen_disable(struct drm_panel * panel)251*4882a593Smuzhiyun static int rpi_touchscreen_disable(struct drm_panel *panel)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun struct rpi_touchscreen *ts = panel_to_ts(panel);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun rpi_touchscreen_i2c_write(ts, REG_PWM, 0);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
258*4882a593Smuzhiyun udelay(1);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun return 0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
rpi_touchscreen_noop(struct drm_panel * panel)263*4882a593Smuzhiyun static int rpi_touchscreen_noop(struct drm_panel *panel)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun return 0;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
rpi_touchscreen_prepare(struct drm_panel * panel)268*4882a593Smuzhiyun static int rpi_touchscreen_prepare(struct drm_panel *panel)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun struct rpi_touchscreen *ts = panel_to_ts(panel);
271*4882a593Smuzhiyun int i;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun rpi_touchscreen_i2c_write(ts, REG_POWERON, 1);
274*4882a593Smuzhiyun /* Wait for nPWRDWN to go low to indicate poweron is done. */
275*4882a593Smuzhiyun for (i = 0; i < 100; i++) {
276*4882a593Smuzhiyun if (rpi_touchscreen_i2c_read(ts, REG_PORTB) & 1)
277*4882a593Smuzhiyun break;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun rpi_touchscreen_write(ts, DSI_LANEENABLE,
281*4882a593Smuzhiyun DSI_LANEENABLE_CLOCK |
282*4882a593Smuzhiyun DSI_LANEENABLE_D0);
283*4882a593Smuzhiyun rpi_touchscreen_write(ts, PPI_D0S_CLRSIPOCOUNT, 0x05);
284*4882a593Smuzhiyun rpi_touchscreen_write(ts, PPI_D1S_CLRSIPOCOUNT, 0x05);
285*4882a593Smuzhiyun rpi_touchscreen_write(ts, PPI_D0S_ATMR, 0x00);
286*4882a593Smuzhiyun rpi_touchscreen_write(ts, PPI_D1S_ATMR, 0x00);
287*4882a593Smuzhiyun rpi_touchscreen_write(ts, PPI_LPTXTIMECNT, 0x03);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun rpi_touchscreen_write(ts, SPICMR, 0x00);
290*4882a593Smuzhiyun rpi_touchscreen_write(ts, LCDCTRL, 0x00100150);
291*4882a593Smuzhiyun rpi_touchscreen_write(ts, SYSCTRL, 0x040f);
292*4882a593Smuzhiyun msleep(100);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun rpi_touchscreen_write(ts, PPI_STARTPPI, 0x01);
295*4882a593Smuzhiyun rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01);
296*4882a593Smuzhiyun msleep(100);
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun return 0;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
rpi_touchscreen_enable(struct drm_panel * panel)301*4882a593Smuzhiyun static int rpi_touchscreen_enable(struct drm_panel *panel)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun struct rpi_touchscreen *ts = panel_to_ts(panel);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /* Turn on the backlight. */
306*4882a593Smuzhiyun rpi_touchscreen_i2c_write(ts, REG_PWM, 255);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun /* Default to the same orientation as the closed source
309*4882a593Smuzhiyun * firmware used for the panel. Runtime rotation
310*4882a593Smuzhiyun * configuration will be supported using VC4's plane
311*4882a593Smuzhiyun * orientation bits.
312*4882a593Smuzhiyun */
313*4882a593Smuzhiyun rpi_touchscreen_i2c_write(ts, REG_PORTA, BIT(2));
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun return 0;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
rpi_touchscreen_get_modes(struct drm_panel * panel,struct drm_connector * connector)318*4882a593Smuzhiyun static int rpi_touchscreen_get_modes(struct drm_panel *panel,
319*4882a593Smuzhiyun struct drm_connector *connector)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun unsigned int i, num = 0;
322*4882a593Smuzhiyun static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(rpi_touchscreen_modes); i++) {
325*4882a593Smuzhiyun const struct drm_display_mode *m = &rpi_touchscreen_modes[i];
326*4882a593Smuzhiyun struct drm_display_mode *mode;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun mode = drm_mode_duplicate(connector->dev, m);
329*4882a593Smuzhiyun if (!mode) {
330*4882a593Smuzhiyun dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
331*4882a593Smuzhiyun m->hdisplay, m->vdisplay,
332*4882a593Smuzhiyun drm_mode_vrefresh(m));
333*4882a593Smuzhiyun continue;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun mode->type |= DRM_MODE_TYPE_DRIVER;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun if (i == 0)
339*4882a593Smuzhiyun mode->type |= DRM_MODE_TYPE_PREFERRED;
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun drm_mode_set_name(mode);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun drm_mode_probed_add(connector, mode);
344*4882a593Smuzhiyun num++;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun connector->display_info.bpc = 8;
348*4882a593Smuzhiyun connector->display_info.width_mm = 154;
349*4882a593Smuzhiyun connector->display_info.height_mm = 86;
350*4882a593Smuzhiyun drm_display_info_set_bus_formats(&connector->display_info,
351*4882a593Smuzhiyun &bus_format, 1);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun return num;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun static const struct drm_panel_funcs rpi_touchscreen_funcs = {
357*4882a593Smuzhiyun .disable = rpi_touchscreen_disable,
358*4882a593Smuzhiyun .unprepare = rpi_touchscreen_noop,
359*4882a593Smuzhiyun .prepare = rpi_touchscreen_prepare,
360*4882a593Smuzhiyun .enable = rpi_touchscreen_enable,
361*4882a593Smuzhiyun .get_modes = rpi_touchscreen_get_modes,
362*4882a593Smuzhiyun };
363*4882a593Smuzhiyun
rpi_touchscreen_probe(struct i2c_client * i2c,const struct i2c_device_id * id)364*4882a593Smuzhiyun static int rpi_touchscreen_probe(struct i2c_client *i2c,
365*4882a593Smuzhiyun const struct i2c_device_id *id)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun struct device *dev = &i2c->dev;
368*4882a593Smuzhiyun struct rpi_touchscreen *ts;
369*4882a593Smuzhiyun struct device_node *endpoint, *dsi_host_node;
370*4882a593Smuzhiyun struct mipi_dsi_host *host;
371*4882a593Smuzhiyun int ver;
372*4882a593Smuzhiyun struct mipi_dsi_device_info info = {
373*4882a593Smuzhiyun .type = RPI_DSI_DRIVER_NAME,
374*4882a593Smuzhiyun .channel = 0,
375*4882a593Smuzhiyun .node = NULL,
376*4882a593Smuzhiyun };
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
379*4882a593Smuzhiyun if (!ts)
380*4882a593Smuzhiyun return -ENOMEM;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun i2c_set_clientdata(i2c, ts);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun ts->i2c = i2c;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun ver = rpi_touchscreen_i2c_read(ts, REG_ID);
387*4882a593Smuzhiyun if (ver < 0) {
388*4882a593Smuzhiyun dev_err(dev, "Atmel I2C read failed: %d\n", ver);
389*4882a593Smuzhiyun return -ENODEV;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun switch (ver) {
393*4882a593Smuzhiyun case 0xde: /* ver 1 */
394*4882a593Smuzhiyun case 0xc3: /* ver 2 */
395*4882a593Smuzhiyun break;
396*4882a593Smuzhiyun default:
397*4882a593Smuzhiyun dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", ver);
398*4882a593Smuzhiyun return -ENODEV;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /* Turn off at boot, so we can cleanly sequence powering on. */
402*4882a593Smuzhiyun rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun /* Look up the DSI host. It needs to probe before we do. */
405*4882a593Smuzhiyun endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
406*4882a593Smuzhiyun if (!endpoint)
407*4882a593Smuzhiyun return -ENODEV;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun dsi_host_node = of_graph_get_remote_port_parent(endpoint);
410*4882a593Smuzhiyun if (!dsi_host_node)
411*4882a593Smuzhiyun goto error;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun host = of_find_mipi_dsi_host_by_node(dsi_host_node);
414*4882a593Smuzhiyun of_node_put(dsi_host_node);
415*4882a593Smuzhiyun if (!host) {
416*4882a593Smuzhiyun of_node_put(endpoint);
417*4882a593Smuzhiyun return -EPROBE_DEFER;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun info.node = of_graph_get_remote_port(endpoint);
421*4882a593Smuzhiyun if (!info.node)
422*4882a593Smuzhiyun goto error;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun of_node_put(endpoint);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun ts->dsi = mipi_dsi_device_register_full(host, &info);
427*4882a593Smuzhiyun if (IS_ERR(ts->dsi)) {
428*4882a593Smuzhiyun dev_err(dev, "DSI device registration failed: %ld\n",
429*4882a593Smuzhiyun PTR_ERR(ts->dsi));
430*4882a593Smuzhiyun return PTR_ERR(ts->dsi);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun drm_panel_init(&ts->base, dev, &rpi_touchscreen_funcs,
434*4882a593Smuzhiyun DRM_MODE_CONNECTOR_DSI);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /* This appears last, as it's what will unblock the DSI host
437*4882a593Smuzhiyun * driver's component bind function.
438*4882a593Smuzhiyun */
439*4882a593Smuzhiyun drm_panel_add(&ts->base);
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun return 0;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun error:
444*4882a593Smuzhiyun of_node_put(endpoint);
445*4882a593Smuzhiyun return -ENODEV;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
rpi_touchscreen_remove(struct i2c_client * i2c)448*4882a593Smuzhiyun static int rpi_touchscreen_remove(struct i2c_client *i2c)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun struct rpi_touchscreen *ts = i2c_get_clientdata(i2c);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun mipi_dsi_detach(ts->dsi);
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun drm_panel_remove(&ts->base);
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun mipi_dsi_device_unregister(ts->dsi);
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun return 0;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
rpi_touchscreen_dsi_probe(struct mipi_dsi_device * dsi)461*4882a593Smuzhiyun static int rpi_touchscreen_dsi_probe(struct mipi_dsi_device *dsi)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun int ret;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun dsi->mode_flags = (MIPI_DSI_MODE_VIDEO |
466*4882a593Smuzhiyun MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
467*4882a593Smuzhiyun MIPI_DSI_MODE_LPM);
468*4882a593Smuzhiyun dsi->format = MIPI_DSI_FMT_RGB888;
469*4882a593Smuzhiyun dsi->lanes = 1;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun ret = mipi_dsi_attach(dsi);
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun if (ret)
474*4882a593Smuzhiyun dev_err(&dsi->dev, "failed to attach dsi to host: %d\n", ret);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun return ret;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun static struct mipi_dsi_driver rpi_touchscreen_dsi_driver = {
480*4882a593Smuzhiyun .driver.name = RPI_DSI_DRIVER_NAME,
481*4882a593Smuzhiyun .probe = rpi_touchscreen_dsi_probe,
482*4882a593Smuzhiyun };
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun static const struct of_device_id rpi_touchscreen_of_ids[] = {
485*4882a593Smuzhiyun { .compatible = "raspberrypi,7inch-touchscreen-panel" },
486*4882a593Smuzhiyun { } /* sentinel */
487*4882a593Smuzhiyun };
488*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rpi_touchscreen_of_ids);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun static struct i2c_driver rpi_touchscreen_driver = {
491*4882a593Smuzhiyun .driver = {
492*4882a593Smuzhiyun .name = "rpi_touchscreen",
493*4882a593Smuzhiyun .of_match_table = rpi_touchscreen_of_ids,
494*4882a593Smuzhiyun },
495*4882a593Smuzhiyun .probe = rpi_touchscreen_probe,
496*4882a593Smuzhiyun .remove = rpi_touchscreen_remove,
497*4882a593Smuzhiyun };
498*4882a593Smuzhiyun
rpi_touchscreen_init(void)499*4882a593Smuzhiyun static int __init rpi_touchscreen_init(void)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun mipi_dsi_driver_register(&rpi_touchscreen_dsi_driver);
502*4882a593Smuzhiyun return i2c_add_driver(&rpi_touchscreen_driver);
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun module_init(rpi_touchscreen_init);
505*4882a593Smuzhiyun
rpi_touchscreen_exit(void)506*4882a593Smuzhiyun static void __exit rpi_touchscreen_exit(void)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun i2c_del_driver(&rpi_touchscreen_driver);
509*4882a593Smuzhiyun mipi_dsi_driver_unregister(&rpi_touchscreen_dsi_driver);
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun module_exit(rpi_touchscreen_exit);
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
514*4882a593Smuzhiyun MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver");
515*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
516