1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c
4 * active panel using spi interface to do init
5 *
6 * Copyright (C) 2012 Marvell Technology Group Ltd.
7 * Authors:  Guoqing Li <ligq@marvell.com>
8 *          Lisa Du <cldu@marvell.com>
9 *          Zhou Zhu <zzhu3@marvell.com>
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/string.h>
17#include <linux/delay.h>
18#include <linux/platform_device.h>
19#include <linux/err.h>
20#include <linux/spi/spi.h>
21#include <video/mmp_disp.h>
22
23static u16 init[] = {
24	0x0801,
25	0x0800,
26	0x0200,
27	0x0304,
28	0x040e,
29	0x0903,
30	0x0b18,
31	0x0c53,
32	0x0d01,
33	0x0ee0,
34	0x0f01,
35	0x1058,
36	0x201e,
37	0x210a,
38	0x220a,
39	0x231e,
40	0x2400,
41	0x2532,
42	0x2600,
43	0x27ac,
44	0x2904,
45	0x2aa2,
46	0x2b45,
47	0x2c45,
48	0x2d15,
49	0x2e5a,
50	0x2fff,
51	0x306b,
52	0x310d,
53	0x3248,
54	0x3382,
55	0x34bd,
56	0x35e7,
57	0x3618,
58	0x3794,
59	0x3801,
60	0x395d,
61	0x3aae,
62	0x3bff,
63	0x07c9,
64};
65
66static u16 poweroff[] = {
67	0x07d9,
68};
69
70struct tpohvga_plat_data {
71	void (*plat_onoff)(int status);
72	struct spi_device *spi;
73};
74
75static void tpohvga_onoff(struct mmp_panel *panel, int status)
76{
77	struct tpohvga_plat_data *plat = panel->plat_data;
78	int ret;
79
80	if (status) {
81		plat->plat_onoff(1);
82
83		ret = spi_write(plat->spi, init, sizeof(init));
84		if (ret < 0)
85			dev_warn(panel->dev, "init cmd failed(%d)\n", ret);
86	} else {
87		ret = spi_write(plat->spi, poweroff, sizeof(poweroff));
88		if (ret < 0)
89			dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret);
90
91		plat->plat_onoff(0);
92	}
93}
94
95static struct mmp_mode mmp_modes_tpohvga[] = {
96	[0] = {
97		.pixclock_freq = 10394400,
98		.refresh = 60,
99		.xres = 320,
100		.yres = 480,
101		.hsync_len = 10,
102		.left_margin = 15,
103		.right_margin = 10,
104		.vsync_len = 2,
105		.upper_margin = 4,
106		.lower_margin = 2,
107		.invert_pixclock = 1,
108		.pix_fmt_out = PIXFMT_RGB565,
109	},
110};
111
112static int tpohvga_get_modelist(struct mmp_panel *panel,
113		struct mmp_mode **modelist)
114{
115	*modelist = mmp_modes_tpohvga;
116	return 1;
117}
118
119static struct mmp_panel panel_tpohvga = {
120	.name = "tpohvga",
121	.panel_type = PANELTYPE_ACTIVE,
122	.get_modelist = tpohvga_get_modelist,
123	.set_onoff = tpohvga_onoff,
124};
125
126static int tpohvga_probe(struct spi_device *spi)
127{
128	struct mmp_mach_panel_info *mi;
129	int ret;
130	struct tpohvga_plat_data *plat_data;
131
132	/* get configs from platform data */
133	mi = spi->dev.platform_data;
134	if (mi == NULL) {
135		dev_err(&spi->dev, "%s: no platform data defined\n", __func__);
136		return -EINVAL;
137	}
138
139	/* setup spi related info */
140	spi->bits_per_word = 16;
141	ret = spi_setup(spi);
142	if (ret < 0) {
143		dev_err(&spi->dev, "spi setup failed %d", ret);
144		return ret;
145	}
146
147	plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL);
148	if (plat_data == NULL)
149		return -ENOMEM;
150
151	plat_data->spi = spi;
152	plat_data->plat_onoff = mi->plat_set_onoff;
153	panel_tpohvga.plat_data = plat_data;
154	panel_tpohvga.plat_path_name = mi->plat_path_name;
155	panel_tpohvga.dev = &spi->dev;
156
157	mmp_register_panel(&panel_tpohvga);
158
159	return 0;
160}
161
162static struct spi_driver panel_tpohvga_driver = {
163	.driver		= {
164		.name	= "tpo-hvga",
165	},
166	.probe		= tpohvga_probe,
167};
168module_spi_driver(panel_tpohvga_driver);
169
170MODULE_AUTHOR("Lisa Du<cldu@marvell.com>");
171MODULE_DESCRIPTION("Panel driver for tpohvga");
172MODULE_LICENSE("GPL");
173