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