1 /*
2 * Copyright (C) 2022 Unionman Technology Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <linux/debugfs.h>
20 #include <linux/delay.h>
21 #include <linux/gpio/consumer.h>
22 #include <linux/media-bus-format.h>
23 #include <linux/mod_devicetable.h>
24 #include <linux/module.h>
25 #include <linux/of_device.h>
26 #include <linux/regulator/consumer.h>
27
28 #include <video/display_timing.h>
29 #include <video/mipi_display.h>
30
31 #include <drm/drm_mipi_dsi.h>
32 #include <drm/drm_modes.h>
33 #include <drm/drm_panel.h>
34
35 #include <linux/backlight.h>
36 #include <linux/device/class.h>
37
38 #define DRV_NAME "panel-chipone-icn6211"
39
40 struct icn6211 {
41 struct device *dev;
42 struct drm_panel panel;
43 struct gpio_desc *reset_gpio;
44 bool prepared;
45 bool enabled;
46 const struct icn6211_panel_desc *desc;
47 };
48
49 struct icn6211_panel_desc {
50 const struct drm_display_mode *mode;
51 unsigned int lanes;
52 unsigned long mode_flags;
53 enum mipi_dsi_pixel_format format;
54 int (*init_sequence)(struct icn6211 *ctx);
55 };
56
57 /* I2C registers. */
58 #define REG_ID 0x80
59 #define REG_PORTA 0x81
60 #define REG_PORTA_HF BIT(2)
61 #define REG_PORTA_VF BIT(3)
62 #define REG_PORTB 0x82
63 #define REG_POWERON 0x85
64 #define REG_PWM 0x86
65
66 #define HACTIVE_LI 0x20
67 #define VACTIVE_LI 0x21
68 #define VACTIVE_HACTIVE_HI 0x22
69 #define HFP_LI 0x23
70 #define HSYNC_LI 0x24
71 #define HBP_LI 0x25
72 #define HFP_HSW_HBP_HI 0x26
73 #define VFP 0x27
74 #define VSYNC 0x28
75 #define VBP 0x29
76
77 /* DSI D-PHY Layer Registers */
78 #define D0W_DPHYCONTTX 0x0004
79 #define CLW_DPHYCONTRX 0x0020
80 #define D0W_DPHYCONTRX 0x0024
81 #define D1W_DPHYCONTRX 0x0028
82 #define COM_DPHYCONTRX 0x0038
83 #define CLW_CNTRL 0x0040
84 #define D0W_CNTRL 0x0044
85 #define D1W_CNTRL 0x0048
86 #define DFTMODE_CNTRL 0x0054
87
88 /* DSI PPI Layer Registers */
89 #define PPI_STARTPPI 0x0104
90 #define PPI_BUSYPPI 0x0108
91 #define PPI_LINEINITCNT 0x0110
92 #define PPI_LPTXTIMECNT 0x0114
93 #define PPI_CLS_ATMR 0x0140
94 #define PPI_D0S_ATMR 0x0144
95 #define PPI_D1S_ATMR 0x0148
96 #define PPI_D0S_CLRSIPOCOUNT 0x0164
97 #define PPI_D1S_CLRSIPOCOUNT 0x0168
98 #define CLS_PRE 0x0180
99 #define D0S_PRE 0x0184
100 #define D1S_PRE 0x0188
101 #define CLS_PREP 0x01A0
102 #define D0S_PREP 0x01A4
103 #define D1S_PREP 0x01A8
104 #define CLS_ZERO 0x01C0
105 #define D0S_ZERO 0x01C4
106 #define D1S_ZERO 0x01C8
107 #define PPI_CLRFLG 0x01E0
108 #define PPI_CLRSIPO 0x01E4
109 #define HSTIMEOUT 0x01F0
110 #define HSTIMEOUTENABLE 0x01F4
111
112 /* DSI Protocol Layer Registers */
113 #define DSI_STARTDSI 0x0204
114 #define DSI_BUSYDSI 0x0208
115 #define DSI_LANEENABLE 0x0210
116 #define DSI_LANEENABLE_CLOCK BIT(0)
117 #define DSI_LANEENABLE_D0 BIT(1)
118 #define DSI_LANEENABLE_D1 BIT(2)
119
120 #define DSI_LANESTATUS0 0x0214
121 #define DSI_LANESTATUS1 0x0218
122 #define DSI_INTSTATUS 0x0220
123 #define DSI_INTMASK 0x0224
124 #define DSI_INTCLR 0x0228
125 #define DSI_LPTXTO 0x0230
126 #define DSI_MODE 0x0260
127 #define DSI_PAYLOAD0 0x0268
128 #define DSI_PAYLOAD1 0x026C
129 #define DSI_SHORTPKTDAT 0x0270
130 #define DSI_SHORTPKTREQ 0x0274
131 #define DSI_BTASTA 0x0278
132 #define DSI_BTACLR 0x027C
133
134 /* DSI General Registers */
135 #define DSIERRCNT 0x0300
136 #define DSISIGMOD 0x0304
137
138 /* DSI Application Layer Registers */
139 #define APLCTRL 0x0400
140 #define APLSTAT 0x0404
141 #define APLERR 0x0408
142 #define PWRMOD 0x040C
143 #define RDPKTLN 0x0410
144 #define PXLFMT 0x0414
145 #define MEMWRCMD 0x0418
146
147 /* LCDC/DPI Host Registers */
148 #define LCDCTRL 0x0420
149 #define HSR 0x0424
150 #define HDISPR 0x0428
151 #define VSR 0x042C
152 #define VDISPR 0x0430
153 #define VFUEN 0x0434
154
155 /* DBI-B Host Registers */
156 #define DBIBCTRL 0x0440
157
158 /* SPI Master Registers */
159 #define SPICMR 0x0450
160 #define SPITCR 0x0454
161
162 /* System Controller Registers */
163 #define SYSSTAT 0x0460
164 #define SYSCTRL 0x0464
165 #define SYSPLL1 0x0468
166 #define SYSPLL2 0x046C
167 #define SYSPLL3 0x0470
168 #define SYSPMCTRL 0x047C
169
170 #define BRIGHTNESS_DEVICE_NAME "icn6211"
171 #define BRIGHTNESS_CLASS_NAME "brightness"
172
173 #define ICN6211_DSI(dsi, seq...) \
174 do { \
175 const u8 d[] = {seq}; \
176 mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
177 }while (0)
178
179 struct panel_icn6211_i2c {
180 int brightness;
181 struct i2c_client *i2c;
182 };
183
184 static struct panel_icn6211_i2c *icn6211_i2c = NULL;
185 static bool panel_icn6211_enable = false;
186
panel_icn6211_i2c_read(struct panel_icn6211_i2c * ts,u8 reg)187 static int panel_icn6211_i2c_read(struct panel_icn6211_i2c *ts, u8 reg)
188 {
189 return i2c_smbus_read_byte_data(ts->i2c, reg);
190 }
191
panel_icn6211_i2c_write(struct panel_icn6211_i2c * ts,u8 reg,u8 val)192 static void panel_icn6211_i2c_write(struct panel_icn6211_i2c *ts, u8 reg, u8 val)
193 {
194 int ret;
195
196 ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
197 if (ret)
198 dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret);
199 }
200
panel_icn6211_dsi_write(struct mipi_dsi_device * dsi,u16 reg,u32 val)201 static int panel_icn6211_dsi_write(struct mipi_dsi_device *dsi, u16 reg, u32 val)
202 {
203 u8 msg[] = {
204 reg, reg >> 8L, val, val >> 8L, val >> 16L, val >> 24L,
205 };
206
207 mipi_dsi_generic_write(dsi, msg, sizeof(msg));
208
209 return 0;
210 }
211
panel_to_icn6211(struct drm_panel * panel)212 static inline struct icn6211 *panel_to_icn6211(struct drm_panel *panel)
213 {
214 return container_of(panel, struct icn6211, panel);
215 }
216
217 static const struct drm_display_mode icn6211_mode = {
218 .clock = 28344600L / 1000L,
219 .hdisplay = 800L,
220 .hsync_start = 800L + 16L,
221 .hsync_end = 800L + 16L + 1,
222 .htotal = 800L + 16L + 1 + 88L,
223 .vdisplay = 480L,
224 .vsync_start = 480L + 7L,
225 .vsync_end = 480L + 7L + 3L,
226 .vtotal = 480L + 7L + 3L + 32L,
227 .width_mm = 105L,
228 .height_mm = 67L,
229 };
230
231 struct icn6211_panel_desc icn6211_panel_desc = {
232 .mode = &icn6211_mode,
233 .lanes = 1,
234 .mode_flags = (MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM),
235 .format = MIPI_DSI_FMT_RGB888,
236 };
237
icn6211_enable(struct drm_panel * panel)238 static int icn6211_enable(struct drm_panel *panel)
239 {
240 struct icn6211 *ctx = panel_to_icn6211(panel);
241 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
242 int i;
243
244 if (!panel_icn6211_enable) {
245 return -1;
246 }
247
248 if (ctx->enabled) {
249 dev_info(ctx->dev, "panel enabled\n");
250 return 0;
251 }
252
253 dev_info(ctx->dev, "panel enable\n");
254
255 panel_icn6211_i2c_write(icn6211_i2c, REG_POWERON, 1);
256
257 /* Wait for nPWRDWN to go low to indicate poweron is done. */
258 for (i = 0; i < 100L; i++) {
259 if (panel_icn6211_i2c_read(icn6211_i2c, REG_PORTB) & 1)
260 break;
261 }
262
263 panel_icn6211_dsi_write(dsi, DSI_LANEENABLE, DSI_LANEENABLE_CLOCK | DSI_LANEENABLE_D0);
264 panel_icn6211_dsi_write(dsi, PPI_D0S_CLRSIPOCOUNT, 0x05);
265 panel_icn6211_dsi_write(dsi, PPI_D1S_CLRSIPOCOUNT, 0x05);
266 panel_icn6211_dsi_write(dsi, PPI_D0S_ATMR, 0x00);
267 panel_icn6211_dsi_write(dsi, PPI_D1S_ATMR, 0x00);
268 panel_icn6211_dsi_write(dsi, PPI_LPTXTIMECNT, 0x03);
269
270 panel_icn6211_dsi_write(dsi, SPICMR, 0x00);
271 panel_icn6211_dsi_write(dsi, LCDCTRL, 0x00100150);
272 panel_icn6211_dsi_write(dsi, SYSCTRL, 0x040f);
273 msleep(100L);
274
275 panel_icn6211_dsi_write(dsi, PPI_STARTPPI, 0x01);
276 panel_icn6211_dsi_write(dsi, DSI_STARTDSI, 0x01);
277 msleep(100L);
278
279 /* Turn on the backlight. */
280 panel_icn6211_i2c_write(icn6211_i2c, REG_PWM, 255L);
281 icn6211_i2c->brightness = 255L;
282
283 /* Default to the same orientation as the closed source
284 * firmware used for the panel.
285 */
286 panel_icn6211_i2c_write(icn6211_i2c, REG_PORTA, BIT(2L));
287
288 ctx->enabled = true;
289
290 return 0;
291 }
292
icn6211_disable(struct drm_panel * panel)293 static int icn6211_disable(struct drm_panel *panel)
294 {
295 struct icn6211 *ctx = panel_to_icn6211(panel);
296
297 if (!panel_icn6211_enable) {
298 return -1;
299 }
300
301 dev_info(ctx->dev, "panel disable\n");
302
303 panel_icn6211_i2c_write(icn6211_i2c, REG_PWM, 0);
304 panel_icn6211_i2c_write(icn6211_i2c, REG_POWERON, 0);
305
306 ctx->enabled = false;
307
308 return 0;
309 }
310
icn6211_unprepare(struct drm_panel * panel)311 static int icn6211_unprepare(struct drm_panel *panel)
312 {
313 if (!panel_icn6211_enable)
314 return 0;
315
316 struct icn6211 *ctx = panel_to_icn6211(panel);
317
318 if (!ctx->prepared)
319 return 0;
320
321 if (ctx->reset_gpio != NULL)
322 gpiod_set_value_cansleep(ctx->reset_gpio, 0);
323
324 ctx->prepared = false;
325
326 return 0;
327 }
328
icn6211_prepare(struct drm_panel * panel)329 static int icn6211_prepare(struct drm_panel *panel)
330 {
331 int ret;
332 struct icn6211 *ctx = panel_to_icn6211(panel);
333 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
334
335 if (!panel_icn6211_enable) {
336 return -1;
337 }
338
339 if (ctx->prepared)
340 return 0;
341
342 ret = mipi_dsi_turn_on_peripheral(dsi);
343 if (ret < 0) {
344 dev_err(panel->dev, "failed to turn on peripheral: %d\n", ret);
345 return ret;
346 }
347
348 ctx->prepared = true;
349
350 return 0;
351 }
352
icn6211_get_modes(struct drm_panel * panel,struct drm_connector * connector)353 static int icn6211_get_modes(struct drm_panel *panel, struct drm_connector *connector)
354 {
355 struct icn6211 *ctx = panel_to_icn6211(panel);
356 struct drm_display_mode *mode;
357 static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
358
359 if (!panel_icn6211_enable) {
360 connector->status = connector_status_disconnected;
361 return 0;
362 }
363
364 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
365 if (!mode) {
366 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
367 drm_mode_vrefresh(ctx->desc->mode));
368 return -ENOMEM;
369 }
370
371 drm_mode_set_name(mode);
372
373 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
374 connector->display_info.bpc = 8L;
375 connector->display_info.width_mm = mode->width_mm;
376 connector->display_info.height_mm = mode->height_mm;
377 drm_mode_probed_add(connector, mode);
378
379 drm_display_info_set_bus_formats(&connector->display_info, &bus_format, 1);
380
381 return 1;
382 }
383
384 static const struct drm_panel_funcs icn6211_drm_funcs = {
385 .disable = icn6211_disable,
386 .unprepare = icn6211_unprepare,
387 .prepare = icn6211_prepare,
388 .enable = icn6211_enable,
389 .get_modes = icn6211_get_modes,
390 };
391
icn6211_probe(struct mipi_dsi_device * dsi)392 static int icn6211_probe(struct mipi_dsi_device *dsi)
393 {
394 struct device *dev = &dsi->dev;
395 struct icn6211 *ctx;
396 int ret;
397
398 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
399 if (!ctx)
400 return -ENOMEM;
401
402 mipi_dsi_set_drvdata(dsi, ctx);
403
404 ctx->dev = dev;
405 ctx->desc = of_device_get_match_data(dev);
406
407 dsi->mode_flags = ctx->desc->mode_flags;
408 dsi->format = ctx->desc->format;
409 dsi->lanes = ctx->desc->lanes;
410
411 drm_panel_init(&ctx->panel, dev, &icn6211_drm_funcs, DRM_MODE_CONNECTOR_DSI);
412
413 drm_panel_add(&ctx->panel);
414
415 ret = mipi_dsi_attach(dsi);
416 if (ret < 0) {
417 dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
418 drm_panel_remove(&ctx->panel);
419 return ret;
420 }
421
422 dev_info(dev, "%ux%u@%u %ubpp dsi %ulanes\n", ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
423 drm_mode_vrefresh(ctx->desc->mode), mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
424
425 return 0;
426 }
427
icn6211_shutdown(struct mipi_dsi_device * dsi)428 static void icn6211_shutdown(struct mipi_dsi_device *dsi)
429 {
430 struct icn6211 *ctx = mipi_dsi_get_drvdata(dsi);
431 int ret;
432
433 ret = drm_panel_unprepare(&ctx->panel);
434 if (ret < 0)
435 dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
436
437 ret = drm_panel_disable(&ctx->panel);
438 if (ret < 0)
439 dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
440 }
441
icn6211_remove(struct mipi_dsi_device * dsi)442 static int icn6211_remove(struct mipi_dsi_device *dsi)
443 {
444 struct icn6211 *ctx = mipi_dsi_get_drvdata(dsi);
445 int ret;
446
447 icn6211_shutdown(dsi);
448
449 ret = mipi_dsi_detach(dsi);
450 if (ret < 0)
451 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
452
453 drm_panel_remove(&ctx->panel);
454
455 return 0;
456 }
457
458 static const struct of_device_id icn6211_of_match[] = {{.compatible = "chipone,icn6211", .data = &icn6211_panel_desc},
459 {}};
460 MODULE_DEVICE_TABLE(of, icn6211_of_match);
461
462 static struct mipi_dsi_driver icn6211_panel_driver = {
463 .probe = icn6211_probe,
464 .remove = icn6211_remove,
465 .shutdown = icn6211_shutdown,
466 .driver =
467 {
468 .name = DRV_NAME,
469 .of_match_table = icn6211_of_match,
470 },
471 };
472 module_mipi_dsi_driver(icn6211_panel_driver);
473
brightness_show(struct class * cla,struct class_attribute * attr,char * buf)474 static ssize_t brightness_show(struct class *cla, struct class_attribute *attr, char *buf)
475 {
476 int brightness = 0;
477
478 if (panel_icn6211_enable) {
479 brightness = icn6211_i2c->brightness;
480 }
481
482 if ((brightness >= 0) && (brightness <= 255L)) {
483 brightness = (brightness * 100L) / 255L;
484 } else {
485 brightness = 100L;
486 }
487
488 return snprintf(buf, 8L, "%d\n", brightness);
489 }
490
brightness_store(struct class * cla,struct class_attribute * attr,const char * buf,size_t count)491 static ssize_t brightness_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count)
492 {
493 int brightness;
494
495 brightness = simple_strtoul(buf, NULL, 10L);
496 if ((brightness >= 0) && (brightness <= 100L)) {
497 brightness = (brightness * 255L) / 100L;
498 } else {
499 brightness = 255L;
500 }
501
502 if (panel_icn6211_enable) {
503 if (brightness == 0) {
504 if (icn6211_i2c->brightness != 0) {
505 panel_icn6211_i2c_write(icn6211_i2c, REG_PWM, 0);
506 panel_icn6211_i2c_write(icn6211_i2c, REG_POWERON, 0);
507 }
508 } else {
509 if (icn6211_i2c->brightness == 0) {
510 panel_icn6211_i2c_write(icn6211_i2c, REG_POWERON, 1);
511 udelay(120L);
512 }
513
514 panel_icn6211_i2c_write(icn6211_i2c, REG_PWM, brightness);
515 panel_icn6211_i2c_write(icn6211_i2c, REG_PORTA, BIT(2L));
516 }
517
518 icn6211_i2c->brightness = brightness;
519 }
520
521 return count;
522 }
523
524 static CLASS_ATTR_RW(brightness);
525
526 static struct attribute *icn6211_class_attrs[] = {&class_attr_brightness.attr, NULL};
527 ATTRIBUTE_GROUPS(icn6211_class);
528
529 static struct class icn6211_class = {
530 .name = BRIGHTNESS_CLASS_NAME,
531 .class_groups = icn6211_class_groups,
532 };
533
panel_icn6211_i2c_probe(struct i2c_client * i2c,const struct i2c_device_id * id)534 static int panel_icn6211_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
535 {
536 struct device *dev = &i2c->dev;
537 struct device *brightness_dev;
538 int ret;
539 int ver;
540
541 icn6211_i2c = devm_kzalloc(dev, sizeof(*icn6211_i2c), GFP_KERNEL);
542 if (!icn6211_i2c) {
543 dev_err(dev, "devm_kzalloc failed!\n");
544 return -ENOMEM;
545 }
546
547 i2c_set_clientdata(i2c, icn6211_i2c);
548
549 icn6211_i2c->i2c = i2c;
550 panel_icn6211_enable = false;
551
552 ver = panel_icn6211_i2c_read(icn6211_i2c, 0x80);
553 if (ver < 0) {
554 dev_err(dev, "I2C read failed: %d\n", ver);
555 return -ENODEV;
556 }
557
558 dev_info(dev, "icn6211 reg id 0x%x\n", ver);
559
560 switch (ver) {
561 case 0xde: /* ver 1 */
562 case 0xc3: /* ver 2 */
563 break;
564 default:
565 dev_err(dev, "Unknown firmware revision: 0x%02x\n", ver);
566 return -ENODEV;
567 }
568
569 /* Turn off at boot, so we can cleanly sequence powering on. */
570 panel_icn6211_enable = true;
571 panel_icn6211_i2c_write(icn6211_i2c, REG_POWERON, 0);
572
573 ret = class_register(&icn6211_class);
574 if (ret < 0) {
575 dev_warn(dev, "register icn6211 class fail! %d\n", ret);
576 }
577
578 brightness_dev = device_create(&icn6211_class, NULL, 0, NULL, BRIGHTNESS_DEVICE_NAME);
579 if (IS_ERR_OR_NULL(brightness_dev)) {
580 dev_err(dev, "create brightness device error\n");
581 class_unregister(&icn6211_class);
582 }
583
584 return 0;
585 }
586
panel_icn6211_i2c_remove(struct i2c_client * i2c)587 static int panel_icn6211_i2c_remove(struct i2c_client *i2c)
588 {
589 return 0;
590 }
591
592 static const struct of_device_id panel_icn6211_i2c_of_ids[] = {
593 {.compatible = "chipone,icn6211-i2c"}, {} /* sentinel */
594 };
595 MODULE_DEVICE_TABLE(of, panel_icn6211_i2c_of_ids);
596
597 static struct i2c_driver panel_icn6211_i2c_driver = {
598 .driver =
599 {
600 .name = "panel-icn6211-i2c",
601 .of_match_table = panel_icn6211_i2c_of_ids,
602 },
603 .probe = panel_icn6211_i2c_probe,
604 .remove = panel_icn6211_i2c_remove,
605 };
606
panel_icn6211_i2c_init(void)607 static int __init panel_icn6211_i2c_init(void)
608 {
609 return i2c_add_driver(&panel_icn6211_i2c_driver);
610 }
611 module_init(panel_icn6211_i2c_init);
612
panel_icn6211_i2c_exit(void)613 static void __exit panel_icn6211_i2c_exit(void)
614 {
615 i2c_del_driver(&panel_icn6211_i2c_driver);
616 }
617 module_exit(panel_icn6211_i2c_exit);
618
619 MODULE_AUTHOR("AlgoIdeas <yu19881234@163.com>");
620 MODULE_DESCRIPTION("DRM driver for chipone icn6211 based MIPI DSI panels");
621 MODULE_LICENSE("GPL v2");
622