xref: /netbsd-src/sys/arch/evbarm/netwalker/netwalker_lcd.c (revision a10897af822efa378460c88423597e3608385784)
1*a10897afSskrll /*	$NetBSD: netwalker_lcd.c,v 1.7 2020/01/15 10:25:47 skrll Exp $	*/
2456cfa81Sbsh 
3456cfa81Sbsh /*-
4456cfa81Sbsh  * Copyright (c) 2011, 2012 Genetec corp. All rights reserved.
5456cfa81Sbsh  * Written by Hashimoto Kenichi for Genetec corp.
6456cfa81Sbsh  *
7456cfa81Sbsh  * Redistribution and use in source and binary forms, with or without
8456cfa81Sbsh  * modification, are permitted provided that the following conditions
9456cfa81Sbsh  * are met:
10456cfa81Sbsh  * 1. Redistributions of source code must retain the above copyright
11456cfa81Sbsh  *    notice, this list of conditions and the following disclaimer.
12456cfa81Sbsh  * 2. Redistributions in binary form must reproduce the above copyright
13456cfa81Sbsh  *    notice, this list of conditions and the following disclaimer in the
14456cfa81Sbsh  *    documentation and/or other materials provided with the distribution.
15456cfa81Sbsh  *
16456cfa81Sbsh  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17456cfa81Sbsh  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18456cfa81Sbsh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19456cfa81Sbsh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20456cfa81Sbsh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21456cfa81Sbsh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22456cfa81Sbsh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23456cfa81Sbsh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24456cfa81Sbsh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25456cfa81Sbsh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26456cfa81Sbsh  * POSSIBILITY OF SUCH DAMAGE.
27456cfa81Sbsh  */
28b9040788Shkenken 
29b9040788Shkenken #include <sys/cdefs.h>
30*a10897afSskrll __KERNEL_RCSID(0, "$NetBSD: netwalker_lcd.c,v 1.7 2020/01/15 10:25:47 skrll Exp $");
31b9040788Shkenken 
32b9040788Shkenken #include "opt_imx51_ipuv3.h"
33b9040788Shkenken #include "opt_netwalker_lcd.h"
34b9040788Shkenken 
35b9040788Shkenken #include "wsdisplay.h"
36b9040788Shkenken #include "ioconf.h"
37b9040788Shkenken #include "netwalker_backlight.h"
38b9040788Shkenken 
39001dea06Shkenken #define	_INTR_PRIVATE
40001dea06Shkenken 
41456cfa81Sbsh #include <sys/param.h>
42456cfa81Sbsh #include <sys/device.h>
43001dea06Shkenken #include <sys/gpio.h>
44456cfa81Sbsh 
45456cfa81Sbsh #include <sys/bus.h>
46456cfa81Sbsh #include <arm/imx/imx51var.h>
47456cfa81Sbsh #include <arm/imx/imx51reg.h>
48456cfa81Sbsh #include <arm/imx/imx51_ipuv3var.h>
49456cfa81Sbsh #include <arm/imx/imx51_ipuv3reg.h>
50456cfa81Sbsh #include <arm/imx/imxgpiovar.h>
51456cfa81Sbsh 
52b9040788Shkenken #include <evbarm/netwalker/netwalker_backlightvar.h>
53456cfa81Sbsh 
54456cfa81Sbsh int lcd_match(device_t, cfdata_t, void *);
55456cfa81Sbsh void lcd_attach(device_t, device_t, void *);
56456cfa81Sbsh 
577bb55e03Shkenken #if NWSDISPLAY == 0
58456cfa81Sbsh 
59456cfa81Sbsh #ifdef LCD_DEBUG
60456cfa81Sbsh static void draw_test_pattern(struct imx51_ipuv3_softc *,
61456cfa81Sbsh     struct imx51_ipuv3_screen *);
62456cfa81Sbsh #endif
63456cfa81Sbsh 
64456cfa81Sbsh /*
65456cfa81Sbsh  * Interface to LCD framebuffer without wscons
66456cfa81Sbsh  */
67456cfa81Sbsh extern struct cfdriver ipu_cd;
68456cfa81Sbsh 
69456cfa81Sbsh dev_type_open(lcdopen);
70456cfa81Sbsh dev_type_close(lcdclose);
71456cfa81Sbsh dev_type_ioctl(lcdioctl);
72456cfa81Sbsh dev_type_mmap(lcdmmap);
73456cfa81Sbsh const struct cdevsw ipu_cdevsw = {
74a68f9396Sdholland 	.d_open = lcdopen,
75a68f9396Sdholland 	.d_close = lcdclose,
76a68f9396Sdholland 	.d_read = noread,
77a68f9396Sdholland 	.d_write = nowrite,
78a68f9396Sdholland 	.d_ioctl = lcdioctl,
79a68f9396Sdholland 	.d_stop = nostop,
80a68f9396Sdholland 	.d_tty = notty,
81a68f9396Sdholland 	.d_poll = nopoll,
82a68f9396Sdholland 	.d_mmap = lcdmmap,
83a68f9396Sdholland 	.d_kqfilter = nokqfilter,
84f9228f42Sdholland 	.d_discard = nodiscard,
85a68f9396Sdholland 	.d_flag = D_TTY
86456cfa81Sbsh };
87456cfa81Sbsh 
88456cfa81Sbsh #endif
89456cfa81Sbsh 
90456cfa81Sbsh CFATTACH_DECL_NEW(lcd_netwalker, sizeof (struct imx51_ipuv3_softc),
91456cfa81Sbsh     lcd_match, lcd_attach, NULL, NULL);
92456cfa81Sbsh 
93456cfa81Sbsh int
lcd_match(device_t parent,cfdata_t cf,void * aux)94456cfa81Sbsh lcd_match( device_t parent, cfdata_t cf, void *aux )
95456cfa81Sbsh {
96456cfa81Sbsh 	return 1;
97456cfa81Sbsh }
98456cfa81Sbsh 
99456cfa81Sbsh /* Sharp's LCD */
1007bb55e03Shkenken static const struct lcd_panel_geometry sharp_panel = {
1017bb55e03Shkenken 	.depth = 16,
1027bb55e03Shkenken 
103456cfa81Sbsh 	.panel_width = 1024,	/* Width */
104456cfa81Sbsh 	.panel_height = 600,	/* Height */
105456cfa81Sbsh 
106456cfa81Sbsh 	.pixel_clk = 30076000,
107456cfa81Sbsh 
108456cfa81Sbsh 	.hsync_width = 8,
109456cfa81Sbsh 	.left  = 20,
110456cfa81Sbsh 	.right = 20,
111456cfa81Sbsh 
112456cfa81Sbsh 	.vsync_width = 4,
113456cfa81Sbsh 	.upper = 2,
114456cfa81Sbsh 	.lower = 2,
115456cfa81Sbsh 
116456cfa81Sbsh 	.panel_info = 0,
117456cfa81Sbsh };
118456cfa81Sbsh 
lcd_attach(device_t parent,device_t self,void * aux)119456cfa81Sbsh void lcd_attach( device_t parent, device_t self, void *aux )
120456cfa81Sbsh {
121456cfa81Sbsh 	struct imx51_ipuv3_softc *sc = device_private(self);
122456cfa81Sbsh 	struct axi_attach_args *axia = aux;
123456cfa81Sbsh 	bus_space_tag_t iot = axia->aa_iot;
124456cfa81Sbsh 
125456cfa81Sbsh 	sc->dev = self;
126456cfa81Sbsh 
127456cfa81Sbsh 	/* XXX move this to imx51_ipuv3.c */
128456cfa81Sbsh 	{
129456cfa81Sbsh 		bus_space_handle_t mipi_ioh;
130456cfa81Sbsh 		uint32_t reg;
131456cfa81Sbsh 
132456cfa81Sbsh 		if (bus_space_map(iot, 0x83fdc000, 0x1000, 0, &mipi_ioh))
133456cfa81Sbsh 			aprint_error_dev(self, "can't map MIPI HSC");
134456cfa81Sbsh 		else {
135456cfa81Sbsh 			bus_space_write_4(iot, mipi_ioh, 0x000, 0xf00);
136456cfa81Sbsh 
137456cfa81Sbsh 			reg = bus_space_read_4(iot, mipi_ioh, 0x800);
138456cfa81Sbsh 			bus_space_write_4(iot, mipi_ioh, 0x800, reg | 0x0ff);
139456cfa81Sbsh 
140456cfa81Sbsh 			reg = bus_space_read_4(iot, mipi_ioh, 0x800);
141456cfa81Sbsh 			bus_space_write_4(iot, mipi_ioh, 0x800, reg | 0x10000);
142456cfa81Sbsh 		}
143456cfa81Sbsh 	}
144456cfa81Sbsh 
145456cfa81Sbsh 	/* LCD power on */
146*a10897afSskrll 	imxgpio_set_direction(GPIO_NO(4, 9), GPIO_PIN_OUTPUT);
147*a10897afSskrll 	imxgpio_set_direction(GPIO_NO(4, 10), GPIO_PIN_OUTPUT);
148*a10897afSskrll 	imxgpio_set_direction(GPIO_NO(3, 3), GPIO_PIN_OUTPUT);
149456cfa81Sbsh 
150*a10897afSskrll 	imxgpio_data_write(GPIO_NO(3, 3), GPIO_PIN_HIGH);
151*a10897afSskrll 	imxgpio_data_write(GPIO_NO(4, 9), GPIO_PIN_HIGH);
152456cfa81Sbsh 	delay(180 * 1000);
153*a10897afSskrll 	imxgpio_data_write(GPIO_NO(4, 10), GPIO_PIN_HIGH);
154456cfa81Sbsh 
155*a10897afSskrll 	imxgpio_set_direction(GPIO_NO(2, 13), GPIO_PIN_OUTPUT);
156*a10897afSskrll 	imxgpio_data_write(GPIO_NO(2, 13), GPIO_PIN_HIGH);
157456cfa81Sbsh 
158b9040788Shkenken 	imx51_ipuv3_attach_sub(sc, aux, &sharp_panel);
159456cfa81Sbsh 
160456cfa81Sbsh #if NWSDISPLAY == 0
161456cfa81Sbsh 	struct imx51_ipuv3_screen *screen;
162456cfa81Sbsh 	int error;
163456cfa81Sbsh 
1647bb55e03Shkenken 	error = imx51_ipuv3_new_screen(sc, &screen);
165456cfa81Sbsh #ifdef LCD_DEBUG
166456cfa81Sbsh 	draw_test_pattern(sc, screen);
167456cfa81Sbsh #endif
168456cfa81Sbsh 	if (error == 0) {
169456cfa81Sbsh 		sc->active = screen;
170456cfa81Sbsh 		imx51_ipuv3_start_dma(sc, screen);
171456cfa81Sbsh 	}
172456cfa81Sbsh #endif
173456cfa81Sbsh }
174456cfa81Sbsh 
1757bb55e03Shkenken #if NWSDISPLAY == 0
176456cfa81Sbsh 
177456cfa81Sbsh int
lcdopen(dev_t dev,int oflags,int devtype,struct lwp * l)178456cfa81Sbsh lcdopen(dev_t dev, int oflags, int devtype, struct lwp *l)
179456cfa81Sbsh {
180456cfa81Sbsh 	return 0;
181456cfa81Sbsh }
182456cfa81Sbsh 
183456cfa81Sbsh int
lcdclose(dev_t dev,int fflag,int devtype,struct lwp * l)184456cfa81Sbsh lcdclose(dev_t dev, int fflag, int devtype, struct lwp *l)
185456cfa81Sbsh {
186456cfa81Sbsh 	return 0;
187456cfa81Sbsh }
188456cfa81Sbsh 
189456cfa81Sbsh paddr_t
lcdmmap(dev_t dev,off_t offset,int size)190456cfa81Sbsh lcdmmap(dev_t dev, off_t offset, int size)
191456cfa81Sbsh {
192456cfa81Sbsh 	struct imx51_ipuv3_softc *sc =
193456cfa81Sbsh 	    device_lookup_private(&ipu_cd, minor(dev));
194456cfa81Sbsh 	struct imx51_ipuv3_screen *scr = sc->active;
195456cfa81Sbsh 
196456cfa81Sbsh 	return bus_dmamem_mmap(sc->dma_tag, scr->segs, scr->nsegs,
197456cfa81Sbsh 	    offset, 0, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
198456cfa81Sbsh }
199456cfa81Sbsh 
200456cfa81Sbsh int
lcdioctl(dev_t dev,u_long cmd,void * data,int fflag,struct lwp * l)201456cfa81Sbsh lcdioctl(dev_t dev, u_long cmd, void *data,
202456cfa81Sbsh     int fflag, struct lwp *l)
203456cfa81Sbsh {
204456cfa81Sbsh 	return EOPNOTSUPP;
205456cfa81Sbsh }
206456cfa81Sbsh 
207456cfa81Sbsh #ifdef LCD_DEBUG
208456cfa81Sbsh static void
draw_test_pattern(struct imx51_ipuv3_softc * sc,struct imx51_ipuv3_screen * scr)209456cfa81Sbsh draw_test_pattern(struct imx51_ipuv3_softc *sc,
210456cfa81Sbsh     struct imx51_ipuv3_screen *scr)
211456cfa81Sbsh {
212456cfa81Sbsh 	int x, y;
213456cfa81Sbsh 	uint16_t color, *line;
214456cfa81Sbsh 	char *buf = (char *)(scr->buf_va);
215456cfa81Sbsh 
216456cfa81Sbsh 	printf("%s: buf_va %p, size 0x%x\n", __func__, buf,
217456cfa81Sbsh 	       (uint)scr->buf_size);
218456cfa81Sbsh 	printf("%s: panel %d x %d\n", __func__,
219456cfa81Sbsh 	    sc->geometry->panel_width,
220456cfa81Sbsh 	    sc->geometry->panel_height);
221456cfa81Sbsh #define	rgb(r,g,b)	(((r)<<11) | ((g)<<5) | (b))
222456cfa81Sbsh 
223456cfa81Sbsh 	for (y=0; y < sc->geometry->panel_height; ++y) {
224456cfa81Sbsh 		line = (uint16_t *)(buf + scr->stride * y);
225456cfa81Sbsh 
226456cfa81Sbsh 		for (x=0; x < sc->geometry->panel_width; ++x) {
227456cfa81Sbsh 			switch (((x/30) + (y/10)) % 8) {
228456cfa81Sbsh 			default:
229456cfa81Sbsh 			case 0: color = rgb(0x00, 0x00, 0x00); break;
230456cfa81Sbsh 			case 1: color = rgb(0x00, 0x00, 0x1f); break;
231456cfa81Sbsh 			case 2: color = rgb(0x00, 0x3f, 0x00); break;
232456cfa81Sbsh 			case 3: color = rgb(0x00, 0x3f, 0x1f); break;
233456cfa81Sbsh 			case 4: color = rgb(0x1f, 0x00, 0x00); break;
234456cfa81Sbsh 			case 5: color = rgb(0x1f, 0x00, 0x1f); break;
235456cfa81Sbsh 			case 6: color = rgb(0x1f, 0x3f, 0x00); break;
236456cfa81Sbsh 			case 7: color = rgb(0x1f, 0x3f, 0x1f); break;
237456cfa81Sbsh 			}
238456cfa81Sbsh 
239456cfa81Sbsh 			line[x] = color;
240456cfa81Sbsh 		}
241456cfa81Sbsh 	}
242456cfa81Sbsh 
243456cfa81Sbsh 	for (x=0; x < MIN(sc->geometry->panel_height,
244456cfa81Sbsh 		sc->geometry->panel_width); ++x) {
245456cfa81Sbsh 		line = (uint16_t *)(buf + scr->stride * x);
246456cfa81Sbsh 		line[x] = rgb(0x1f, 0x3f, 0x1f);
247456cfa81Sbsh 	}
248456cfa81Sbsh }
249456cfa81Sbsh #endif
250456cfa81Sbsh 
2517bb55e03Shkenken #endif /* NWSDISPLAY == 0 */
252456cfa81Sbsh 
253456cfa81Sbsh 
254