1 /* $NetBSD: netwalker_lcd.c,v 1.1 2012/04/17 10:19:57 bsh Exp $ */ 2 3 /*- 4 * Copyright (c) 2011, 2012 Genetec corp. All rights reserved. 5 * Written by Hashimoto Kenichi for Genetec corp. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/conf.h> 31 #include <sys/uio.h> 32 #include <sys/malloc.h> 33 #include <sys/device.h> 34 35 #include <dev/cons.h> 36 #include <dev/wscons/wsconsio.h> 37 #include <dev/wscons/wsdisplayvar.h> 38 #include <dev/wscons/wscons_callbacks.h> 39 40 #include <sys/bus.h> 41 #include <arm/imx/imx51var.h> 42 #include <arm/imx/imx51reg.h> 43 #include <arm/imx/imx51_ipuv3var.h> 44 #include <arm/imx/imx51_ipuv3reg.h> 45 #include <arm/imx/imx51_iomuxreg.h> 46 #include <arm/imx/imxgpiovar.h> 47 48 #include "opt_imx51_ipuv3.h" 49 #include "opt_netwalker_lcd.h" 50 51 #include "wsdisplay.h" 52 #include "ioconf.h" 53 54 int lcd_match(device_t, cfdata_t, void *); 55 void lcd_attach(device_t, device_t, void *); 56 57 void netwalker_cnattach(void); 58 59 #if NWSDISPLAY > 0 60 #else 61 #ifdef LCD_DEBUG 62 static void draw_test_pattern(struct imx51_ipuv3_softc *, 63 struct imx51_ipuv3_screen *); 64 #endif 65 66 /* 67 * Interface to LCD framebuffer without wscons 68 */ 69 extern struct cfdriver ipu_cd; 70 71 dev_type_open(lcdopen); 72 dev_type_close(lcdclose); 73 dev_type_ioctl(lcdioctl); 74 dev_type_mmap(lcdmmap); 75 const struct cdevsw ipu_cdevsw = { 76 lcdopen, lcdclose, noread, nowrite, lcdioctl, 77 nostop, notty, nopoll, lcdmmap, nokqfilter, D_TTY 78 }; 79 80 #endif 81 82 CFATTACH_DECL_NEW(lcd_netwalker, sizeof (struct imx51_ipuv3_softc), 83 lcd_match, lcd_attach, NULL, NULL); 84 85 int 86 lcd_match( device_t parent, cfdata_t cf, void *aux ) 87 { 88 return 1; 89 } 90 91 /* Sharp's LCD */ 92 static const struct lcd_panel_geometry sharp_panel = 93 { 94 .panel_width = 1024, /* Width */ 95 .panel_height = 600, /* Height */ 96 97 .pixel_clk = 30076000, 98 99 .hsync_width = 8, 100 .left = 20, 101 .right = 20, 102 103 .vsync_width = 4, 104 .upper = 2, 105 .lower = 2, 106 107 .panel_info = 0, 108 }; 109 110 #define PANEL sharp_panel 111 112 void lcd_attach( device_t parent, device_t self, void *aux ) 113 { 114 struct imx51_ipuv3_softc *sc = device_private(self); 115 struct axi_attach_args *axia = aux; 116 bus_space_tag_t iot = axia->aa_iot; 117 118 sc->dev = self; 119 120 #if (NWSDISPLAY > 0) && defined(IMXIPUCONSOLE) 121 netwalker_cnattach(); 122 #endif 123 124 #if 0 125 /* IOMUX registers are already set correctly for LCD display */ 126 iomux_mux_config(iomux_ipuv3_config); 127 #endif 128 129 /* XXX move this to imx51_ipuv3.c */ 130 { 131 bus_space_handle_t mipi_ioh; 132 uint32_t reg; 133 134 if (bus_space_map(iot, 0x83fdc000, 0x1000, 0, &mipi_ioh)) 135 aprint_error_dev(self, "can't map MIPI HSC"); 136 else { 137 bus_space_write_4(iot, mipi_ioh, 0x000, 0xf00); 138 139 reg = bus_space_read_4(iot, mipi_ioh, 0x800); 140 bus_space_write_4(iot, mipi_ioh, 0x800, reg | 0x0ff); 141 142 reg = bus_space_read_4(iot, mipi_ioh, 0x800); 143 bus_space_write_4(iot, mipi_ioh, 0x800, reg | 0x10000); 144 } 145 } 146 147 /* LCD power on */ 148 gpio_set_direction(GPIO_NO(4, 9), GPIO_DIR_OUT); 149 gpio_set_direction(GPIO_NO(4, 10), GPIO_DIR_OUT); 150 gpio_set_direction(GPIO_NO(3, 3), GPIO_DIR_OUT); 151 152 gpio_data_write(GPIO_NO(3, 3), 1); 153 gpio_data_write(GPIO_NO(4, 9), 1); 154 delay(180 * 1000); 155 gpio_data_write(GPIO_NO(4, 10), 1); 156 157 /* pwm pin (100%) */ 158 gpio_set_direction(GPIO_NO(1, 2), GPIO_DIR_OUT); 159 gpio_data_write(GPIO_NO(1, 2), 1); 160 161 gpio_set_direction(GPIO_NO(2, 13), GPIO_DIR_OUT); 162 gpio_data_write(GPIO_NO(2, 13), 1); 163 164 imx51_ipuv3_attach_sub(sc, aux, &PANEL); 165 166 #if NWSDISPLAY == 0 167 { 168 struct imx51_ipuv3_screen *screen; 169 int error; 170 171 error = imx51_ipuv3_new_screen(sc, 16, &screen); 172 #ifdef LCD_DEBUG 173 draw_test_pattern(sc, screen); 174 #endif 175 if (error == 0) { 176 sc->active = screen; 177 imx51_ipuv3_start_dma(sc, screen); 178 } 179 } 180 #endif 181 } 182 183 #if NWSDISPLAY > 0 184 void 185 netwalker_cnattach(void) 186 { 187 imx51_ipuv3_cnattach(&PANEL); 188 return; 189 } 190 #else 191 192 int 193 lcdopen(dev_t dev, int oflags, int devtype, struct lwp *l) 194 { 195 return 0; 196 } 197 198 int 199 lcdclose(dev_t dev, int fflag, int devtype, struct lwp *l) 200 { 201 return 0; 202 } 203 204 paddr_t 205 lcdmmap(dev_t dev, off_t offset, int size) 206 { 207 struct imx51_ipuv3_softc *sc = 208 device_lookup_private(&ipu_cd, minor(dev)); 209 struct imx51_ipuv3_screen *scr = sc->active; 210 211 return bus_dmamem_mmap(sc->dma_tag, scr->segs, scr->nsegs, 212 offset, 0, BUS_DMA_WAITOK|BUS_DMA_COHERENT); 213 } 214 215 int 216 lcdioctl(dev_t dev, u_long cmd, void *data, 217 int fflag, struct lwp *l) 218 { 219 return EOPNOTSUPP; 220 } 221 222 #ifdef LCD_DEBUG 223 static void 224 draw_test_pattern(struct imx51_ipuv3_softc *sc, 225 struct imx51_ipuv3_screen *scr) 226 { 227 int x, y; 228 uint16_t color, *line; 229 char *buf = (char *)(scr->buf_va); 230 231 printf("%s: buf_va %p, size 0x%x\n", __func__, buf, 232 (uint)scr->buf_size); 233 printf("%s: panel %d x %d\n", __func__, 234 sc->geometry->panel_width, 235 sc->geometry->panel_height); 236 #define rgb(r,g,b) (((r)<<11) | ((g)<<5) | (b)) 237 238 for (y=0; y < sc->geometry->panel_height; ++y) { 239 line = (uint16_t *)(buf + scr->stride * y); 240 241 for (x=0; x < sc->geometry->panel_width; ++x) { 242 switch (((x/30) + (y/10)) % 8) { 243 default: 244 case 0: color = rgb(0x00, 0x00, 0x00); break; 245 case 1: color = rgb(0x00, 0x00, 0x1f); break; 246 case 2: color = rgb(0x00, 0x3f, 0x00); break; 247 case 3: color = rgb(0x00, 0x3f, 0x1f); break; 248 case 4: color = rgb(0x1f, 0x00, 0x00); break; 249 case 5: color = rgb(0x1f, 0x00, 0x1f); break; 250 case 6: color = rgb(0x1f, 0x3f, 0x00); break; 251 case 7: color = rgb(0x1f, 0x3f, 0x1f); break; 252 } 253 254 line[x] = color; 255 } 256 } 257 258 for (x=0; x < MIN(sc->geometry->panel_height, 259 sc->geometry->panel_width); ++x) { 260 line = (uint16_t *)(buf + scr->stride * x); 261 line[x] = rgb(0x1f, 0x3f, 0x1f); 262 } 263 } 264 #endif 265 266 #endif /* NWSDISPLAY > 0 */ 267 268 269