1*0f9e9ec2Sjsg /* $OpenBSD: ssdfb.c,v 1.14 2024/05/13 01:15:50 jsg Exp $ */
2dab1a984Spatrick /*
3dab1a984Spatrick * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
4dab1a984Spatrick *
5dab1a984Spatrick * Permission to use, copy, modify, and distribute this software for any
6dab1a984Spatrick * purpose with or without fee is hereby granted, provided that the above
7dab1a984Spatrick * copyright notice and this permission notice appear in all copies.
8dab1a984Spatrick *
9dab1a984Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10dab1a984Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11dab1a984Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12dab1a984Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13dab1a984Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14dab1a984Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15dab1a984Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16dab1a984Spatrick */
17dab1a984Spatrick
18dab1a984Spatrick #include <sys/param.h>
19dab1a984Spatrick #include <sys/systm.h>
20dab1a984Spatrick #include <sys/kernel.h>
21dab1a984Spatrick #include <sys/device.h>
22dab1a984Spatrick #include <sys/malloc.h>
23dab1a984Spatrick #include <sys/stdint.h>
24dab1a984Spatrick
253f4c1042Spatrick #include <uvm/uvm_extern.h>
263f4c1042Spatrick
27c6a62e52Spatrick #include <dev/i2c/i2cvar.h>
28dab1a984Spatrick #include <dev/spi/spivar.h>
293f4c1042Spatrick #include <dev/usb/udlio.h>
30dab1a984Spatrick
31dab1a984Spatrick #include <dev/ofw/openfirm.h>
32dab1a984Spatrick #include <dev/ofw/ofw_gpio.h>
33dab1a984Spatrick #include <dev/ofw/ofw_pinctrl.h>
34dab1a984Spatrick
35dab1a984Spatrick #include <dev/wscons/wsconsio.h>
36dab1a984Spatrick #include <dev/wscons/wsdisplayvar.h>
37dab1a984Spatrick #include <dev/rasops/rasops.h>
38dab1a984Spatrick
39eb4f240eSpatrick #define SSDFB_SET_LOWER_COLUMN_START_ADDRESS 0x00
40eb4f240eSpatrick #define SSDFB_SET_HIGHER_COLUMN_START_ADDRESS 0x10
41eb4f240eSpatrick #define SSDFB_SET_MEMORY_ADDRESSING_MODE 0x20
42eb4f240eSpatrick #define SSDFB_SET_COLUMN_RANGE 0x21
43eb4f240eSpatrick #define SSDFB_SET_PAGE_RANGE 0x22
44dab1a984Spatrick #define SSDFB_SET_START_LINE 0x40
45dab1a984Spatrick #define SSDFB_SET_CONTRAST_CONTROL 0x81
46fb481783Spatrick #define SSDFB_CHARGE_PUMP 0x8d
47ad478a58Spatrick #define SSDFB_SET_COLUMN_DIRECTION_NORMAL 0xa0
48dab1a984Spatrick #define SSDFB_SET_COLUMN_DIRECTION_REVERSE 0xa1
49dab1a984Spatrick #define SSDFB_SET_MULTIPLEX_RATIO 0xa8
50ad478a58Spatrick #define SSDFB_SET_COM_OUTPUT_DIRECTION_NORMAL 0xc0
51ad478a58Spatrick #define SSDFB_SET_COM_OUTPUT_DIRECTION_REMAP 0xc8
52dab1a984Spatrick #define SSDFB_ENTIRE_DISPLAY_ON 0xa4
53dab1a984Spatrick #define SSDFB_SET_DISPLAY_MODE_NORMAL 0xa6
54dab1a984Spatrick #define SSDFB_SET_DISPLAY_MODE_INVERS 0xa7
55dab1a984Spatrick #define SSDFB_SET_DISPLAY_OFF 0xae
56dab1a984Spatrick #define SSDFB_SET_DISPLAY_ON 0xaf
57dab1a984Spatrick #define SSDFB_SET_DISPLAY_OFFSET 0xd3
58dab1a984Spatrick #define SSDFB_SET_DISPLAY_CLOCK_DIVIDE_RATIO 0xd5
59dab1a984Spatrick #define SSDFB_SET_PRE_CHARGE_PERIOD 0xd9
60dab1a984Spatrick #define SSDFB_SET_COM_PINS_HARD_CONF 0xda
61dab1a984Spatrick #define SSDFB_SET_VCOM_DESELECT_LEVEL 0xdb
62eb4f240eSpatrick #define SSDFB_SET_PAGE_START_ADDRESS 0xb0
63dab1a984Spatrick
64c6a62e52Spatrick #define SSDFB_I2C_COMMAND 0x00
65c6a62e52Spatrick #define SSDFB_I2C_DATA 0x40
66c6a62e52Spatrick
67dab1a984Spatrick struct ssdfb_softc {
68dab1a984Spatrick struct device sc_dev;
69dab1a984Spatrick int sc_node;
70ad478a58Spatrick int sc_width;
71ad478a58Spatrick int sc_height;
72ad478a58Spatrick int sc_pgoff;
73dab1a984Spatrick
74dab1a984Spatrick uint8_t *sc_fb;
75dab1a984Spatrick size_t sc_fbsize;
76dab1a984Spatrick struct rasops_info sc_rinfo;
771c999b93Spatrick struct wsdisplay_emulops sc_riops;
781c999b93Spatrick int (*sc_ri_do_cursor)(struct rasops_info *);
79dab1a984Spatrick
803f4c1042Spatrick uint8_t sc_brightness;
813f4c1042Spatrick int sc_mode;
823f4c1042Spatrick
83eb4f240eSpatrick uint8_t sc_column_range[2];
84eb4f240eSpatrick uint8_t sc_page_range[2];
85eb4f240eSpatrick
86c6a62e52Spatrick /* I2C */
87c6a62e52Spatrick i2c_tag_t sc_i2c_tag;
88c6a62e52Spatrick i2c_addr_t sc_i2c_addr;
89c6a62e52Spatrick
90c6a62e52Spatrick /* SPI */
91c6a62e52Spatrick spi_tag_t sc_spi_tag;
92c6a62e52Spatrick struct spi_config sc_spi_conf;
93c6a62e52Spatrick uint32_t *sc_gpio;
94c6a62e52Spatrick size_t sc_gpiolen;
95c6a62e52Spatrick int sc_cd;
96c6a62e52Spatrick
97c6a62e52Spatrick void (*sc_write_command)(struct ssdfb_softc *,
98c6a62e52Spatrick char *, size_t);
99c6a62e52Spatrick void (*sc_write_data)(struct ssdfb_softc *,
100c6a62e52Spatrick char *, size_t);
101c6a62e52Spatrick
102dab1a984Spatrick };
103dab1a984Spatrick
104c6a62e52Spatrick int ssdfb_i2c_match(struct device *, void *, void *);
105c6a62e52Spatrick void ssdfb_i2c_attach(struct device *, struct device *, void *);
106c6a62e52Spatrick int ssdfb_i2c_detach(struct device *, int);
107c6a62e52Spatrick void ssdfb_i2c_write_command(struct ssdfb_softc *, char *, size_t);
108c6a62e52Spatrick void ssdfb_i2c_write_data(struct ssdfb_softc *, char *, size_t);
109dab1a984Spatrick
110c6a62e52Spatrick int ssdfb_spi_match(struct device *, void *, void *);
111c6a62e52Spatrick void ssdfb_spi_attach(struct device *, struct device *, void *);
112c6a62e52Spatrick int ssdfb_spi_detach(struct device *, int);
113c6a62e52Spatrick void ssdfb_spi_write_command(struct ssdfb_softc *, char *, size_t);
114c6a62e52Spatrick void ssdfb_spi_write_data(struct ssdfb_softc *, char *, size_t);
115c6a62e52Spatrick
116c6a62e52Spatrick void ssdfb_attach(struct ssdfb_softc *);
117c6a62e52Spatrick int ssdfb_detach(struct ssdfb_softc *, int);
118dab1a984Spatrick void ssdfb_write_command(struct ssdfb_softc *, char *, size_t);
119dab1a984Spatrick void ssdfb_write_data(struct ssdfb_softc *, char *, size_t);
120dab1a984Spatrick
121dab1a984Spatrick void ssdfb_init(struct ssdfb_softc *);
122dab1a984Spatrick
123eb4f240eSpatrick void ssdfb_partial(struct ssdfb_softc *, uint32_t, uint32_t,
124eb4f240eSpatrick uint32_t, uint32_t);
125eb4f240eSpatrick void ssdfb_set_range(struct ssdfb_softc *, uint8_t, uint8_t,
126eb4f240eSpatrick uint8_t, uint8_t);
127eb4f240eSpatrick
128dab1a984Spatrick int ssdfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
129dab1a984Spatrick paddr_t ssdfb_mmap(void *, off_t, int);
130dab1a984Spatrick int ssdfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
131e0c3e559Sjsg int *, int *, uint32_t *);
132dab1a984Spatrick void ssdfb_free_screen(void *, void *);
133dab1a984Spatrick int ssdfb_show_screen(void *, void *, int, void (*cb) (void *, int, int),
134dab1a984Spatrick void *);
135dab1a984Spatrick int ssdfb_list_font(void *, struct wsdisplay_font *);
136dab1a984Spatrick int ssdfb_load_font(void *, void *, struct wsdisplay_font *);
137dab1a984Spatrick
138e0c3e559Sjsg int ssdfb_putchar(void *, int, int, u_int, uint32_t);
1391c999b93Spatrick int ssdfb_copycols(void *, int, int, int, int);
140e0c3e559Sjsg int ssdfb_erasecols(void *, int, int, int, uint32_t);
1411c999b93Spatrick int ssdfb_copyrows(void *, int, int, int);
142e0c3e559Sjsg int ssdfb_eraserows(void *, int, int, uint32_t);
1431c999b93Spatrick int ssdfb_do_cursor(struct rasops_info *);
1441c999b93Spatrick
1459fdf0c62Smpi const struct cfattach ssdfb_i2c_ca = {
146dab1a984Spatrick sizeof(struct ssdfb_softc),
147c6a62e52Spatrick ssdfb_i2c_match,
148c6a62e52Spatrick ssdfb_i2c_attach,
149c6a62e52Spatrick ssdfb_i2c_detach,
150c6a62e52Spatrick };
151c6a62e52Spatrick
1529fdf0c62Smpi const struct cfattach ssdfb_spi_ca = {
153c6a62e52Spatrick sizeof(struct ssdfb_softc),
154c6a62e52Spatrick ssdfb_spi_match,
155c6a62e52Spatrick ssdfb_spi_attach,
156c6a62e52Spatrick ssdfb_spi_detach,
157dab1a984Spatrick };
158dab1a984Spatrick
159dab1a984Spatrick struct cfdriver ssdfb_cd = {
160dab1a984Spatrick NULL, "ssdfb", DV_DULL
161dab1a984Spatrick };
162dab1a984Spatrick
163dab1a984Spatrick struct wsscreen_descr ssdfb_std_descr = { "std" };
164dab1a984Spatrick
165dab1a984Spatrick const struct wsscreen_descr *ssdfb_descrs[] = {
166dab1a984Spatrick &ssdfb_std_descr
167dab1a984Spatrick };
168dab1a984Spatrick
169dab1a984Spatrick const struct wsscreen_list ssdfb_screen_list = {
170dab1a984Spatrick nitems(ssdfb_descrs), ssdfb_descrs
171dab1a984Spatrick };
172dab1a984Spatrick
173dab1a984Spatrick struct wsdisplay_accessops ssdfb_accessops = {
174dab1a984Spatrick .ioctl = ssdfb_ioctl,
175dab1a984Spatrick .mmap = ssdfb_mmap,
176dab1a984Spatrick .alloc_screen = ssdfb_alloc_screen,
177dab1a984Spatrick .free_screen = ssdfb_free_screen,
178dab1a984Spatrick .show_screen = ssdfb_show_screen,
179dab1a984Spatrick .load_font = ssdfb_load_font,
180dab1a984Spatrick .list_font = ssdfb_list_font
181dab1a984Spatrick };
182dab1a984Spatrick
183dab1a984Spatrick int
ssdfb_i2c_match(struct device * parent,void * match,void * aux)184c6a62e52Spatrick ssdfb_i2c_match(struct device *parent, void *match, void *aux)
185c6a62e52Spatrick {
186c6a62e52Spatrick struct i2c_attach_args *ia = aux;
187c6a62e52Spatrick
188fb481783Spatrick if (strcmp(ia->ia_name, "solomon,ssd1306fb-i2c") == 0 ||
189fb481783Spatrick strcmp(ia->ia_name, "solomon,ssd1309fb-i2c") == 0)
190c6a62e52Spatrick return 1;
191c6a62e52Spatrick
192c6a62e52Spatrick return 0;
193c6a62e52Spatrick }
194c6a62e52Spatrick
195c6a62e52Spatrick void
ssdfb_i2c_attach(struct device * parent,struct device * self,void * aux)196c6a62e52Spatrick ssdfb_i2c_attach(struct device *parent, struct device *self, void *aux)
197c6a62e52Spatrick {
198c6a62e52Spatrick struct ssdfb_softc *sc = (struct ssdfb_softc *)self;
199c6a62e52Spatrick struct i2c_attach_args *ia = aux;
200c6a62e52Spatrick
201c6a62e52Spatrick sc->sc_i2c_tag = ia->ia_tag;
202c6a62e52Spatrick sc->sc_i2c_addr = ia->ia_addr;
203c6a62e52Spatrick sc->sc_node = *(int *)ia->ia_cookie;
204c6a62e52Spatrick
205c6a62e52Spatrick sc->sc_write_command = ssdfb_i2c_write_command;
206c6a62e52Spatrick sc->sc_write_data = ssdfb_i2c_write_data;
207c6a62e52Spatrick
208c6a62e52Spatrick ssdfb_attach(sc);
209c6a62e52Spatrick }
210c6a62e52Spatrick
211c6a62e52Spatrick int
ssdfb_i2c_detach(struct device * self,int flags)212c6a62e52Spatrick ssdfb_i2c_detach(struct device *self, int flags)
213c6a62e52Spatrick {
214c6a62e52Spatrick struct ssdfb_softc *sc = (struct ssdfb_softc *)self;
215c6a62e52Spatrick ssdfb_detach(sc, flags);
216c6a62e52Spatrick return 0;
217c6a62e52Spatrick }
218c6a62e52Spatrick
219c6a62e52Spatrick int
ssdfb_spi_match(struct device * parent,void * match,void * aux)220c6a62e52Spatrick ssdfb_spi_match(struct device *parent, void *match, void *aux)
221dab1a984Spatrick {
222dab1a984Spatrick struct spi_attach_args *sa = aux;
223dab1a984Spatrick
224dab1a984Spatrick if (strcmp(sa->sa_name, "solomon,ssd1309fb-spi") == 0)
225dab1a984Spatrick return 1;
226dab1a984Spatrick
227dab1a984Spatrick return 0;
228dab1a984Spatrick }
229dab1a984Spatrick
230dab1a984Spatrick void
ssdfb_spi_attach(struct device * parent,struct device * self,void * aux)231c6a62e52Spatrick ssdfb_spi_attach(struct device *parent, struct device *self, void *aux)
232dab1a984Spatrick {
233dab1a984Spatrick struct ssdfb_softc *sc = (struct ssdfb_softc *)self;
234dab1a984Spatrick struct spi_attach_args *sa = aux;
235c6a62e52Spatrick ssize_t len;
236dab1a984Spatrick
237c6a62e52Spatrick sc->sc_spi_tag = sa->sa_tag;
238dab1a984Spatrick sc->sc_node = *(int *)sa->sa_cookie;
239dab1a984Spatrick
240c6a62e52Spatrick sc->sc_spi_conf.sc_bpw = 8;
241c6a62e52Spatrick sc->sc_spi_conf.sc_freq = 1000 * 1000;
242c6a62e52Spatrick sc->sc_spi_conf.sc_cs = OF_getpropint(sc->sc_node, "reg", 0);
243dab1a984Spatrick if (OF_getproplen(sc->sc_node, "spi-cpol") == 0)
244c6a62e52Spatrick sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPOL;
245dab1a984Spatrick if (OF_getproplen(sc->sc_node, "spi-cpha") == 0)
246c6a62e52Spatrick sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPHA;
247dab1a984Spatrick if (OF_getproplen(sc->sc_node, "spi-cs-high") == 0)
248c6a62e52Spatrick sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CS_HIGH;
249dab1a984Spatrick
250dab1a984Spatrick len = OF_getproplen(sc->sc_node, "cd-gpio");
251dab1a984Spatrick if (len <= 0)
252dab1a984Spatrick return;
253dab1a984Spatrick
254dab1a984Spatrick sc->sc_gpio = malloc(len, M_DEVBUF, M_WAITOK);
255dab1a984Spatrick OF_getpropintarray(sc->sc_node, "cd-gpio", sc->sc_gpio, len);
256dab1a984Spatrick sc->sc_gpiolen = len;
257dab1a984Spatrick gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_OUTPUT);
258dab1a984Spatrick gpio_controller_set_pin(sc->sc_gpio, 0);
259dab1a984Spatrick
260c6a62e52Spatrick sc->sc_write_command = ssdfb_spi_write_command;
261c6a62e52Spatrick sc->sc_write_data = ssdfb_spi_write_data;
262c6a62e52Spatrick
263c6a62e52Spatrick ssdfb_attach(sc);
264c6a62e52Spatrick }
265c6a62e52Spatrick
266c6a62e52Spatrick int
ssdfb_spi_detach(struct device * self,int flags)267c6a62e52Spatrick ssdfb_spi_detach(struct device *self, int flags)
268c6a62e52Spatrick {
269c6a62e52Spatrick struct ssdfb_softc *sc = (struct ssdfb_softc *)self;
270c6a62e52Spatrick ssdfb_detach(sc, flags);
271c6a62e52Spatrick free(sc->sc_gpio, M_DEVBUF, sc->sc_gpiolen);
272c6a62e52Spatrick return 0;
273c6a62e52Spatrick }
274c6a62e52Spatrick
275c6a62e52Spatrick void
ssdfb_attach(struct ssdfb_softc * sc)276c6a62e52Spatrick ssdfb_attach(struct ssdfb_softc *sc)
277c6a62e52Spatrick {
278c6a62e52Spatrick struct wsemuldisplaydev_attach_args aa;
279c6a62e52Spatrick struct rasops_info *ri;
280c6a62e52Spatrick uint32_t *gpio;
281c6a62e52Spatrick ssize_t len;
282c6a62e52Spatrick
283c6a62e52Spatrick pinctrl_byname(sc->sc_node, "default");
284c6a62e52Spatrick
2850d547c3bSpatrick len = OF_getproplen(sc->sc_node, "reset-gpios");
286c6a62e52Spatrick if (len > 0) {
287c6a62e52Spatrick gpio = malloc(len, M_DEVBUF, M_WAITOK);
2880d547c3bSpatrick OF_getpropintarray(sc->sc_node, "reset-gpios",
289c6a62e52Spatrick gpio, len);
290c6a62e52Spatrick gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
291c6a62e52Spatrick gpio_controller_set_pin(gpio, 1);
292c6a62e52Spatrick delay(100 * 1000);
293c6a62e52Spatrick gpio_controller_set_pin(gpio, 0);
294c6a62e52Spatrick delay(1000 * 1000);
295c6a62e52Spatrick free(gpio, M_DEVBUF, len);
296c6a62e52Spatrick }
297c6a62e52Spatrick
298ad478a58Spatrick sc->sc_width = OF_getpropint(sc->sc_node, "solomon,width", 96);
299ad478a58Spatrick sc->sc_height = OF_getpropint(sc->sc_node, "solomon,height", 16);
300ad478a58Spatrick sc->sc_pgoff = OF_getpropint(sc->sc_node, "solomon,page-offset", 1);
301ad478a58Spatrick
3023f4c1042Spatrick sc->sc_fbsize = round_page((sc->sc_width * sc->sc_height) / 8);
303dab1a984Spatrick sc->sc_fb = malloc(sc->sc_fbsize, M_DEVBUF, M_WAITOK | M_ZERO);
304dab1a984Spatrick
3053f4c1042Spatrick sc->sc_brightness = 223;
3063f4c1042Spatrick
307dab1a984Spatrick ri = &sc->sc_rinfo;
308dab1a984Spatrick ri->ri_bits = malloc(sc->sc_fbsize, M_DEVBUF, M_WAITOK | M_ZERO);
309ad478a58Spatrick ri->ri_bs = mallocarray(sc->sc_width * sc->sc_height,
310ad478a58Spatrick sizeof(struct wsdisplay_charcell), M_DEVBUF, M_WAITOK | M_ZERO);
311dab1a984Spatrick ri->ri_flg = RI_CLEAR | RI_VCONS;
312dab1a984Spatrick ri->ri_depth = 1;
313ad478a58Spatrick ri->ri_width = sc->sc_width;
314ad478a58Spatrick ri->ri_height = sc->sc_height;
315dab1a984Spatrick ri->ri_stride = ri->ri_width * ri->ri_depth / 8;
3161c999b93Spatrick ri->ri_hw = sc;
317dab1a984Spatrick
318ad478a58Spatrick rasops_init(ri, sc->sc_height, sc->sc_width);
319dab1a984Spatrick ssdfb_std_descr.ncols = ri->ri_cols;
320dab1a984Spatrick ssdfb_std_descr.nrows = ri->ri_rows;
321dab1a984Spatrick ssdfb_std_descr.textops = &ri->ri_ops;
322dab1a984Spatrick ssdfb_std_descr.fontwidth = ri->ri_font->fontwidth;
323dab1a984Spatrick ssdfb_std_descr.fontheight = ri->ri_font->fontheight;
324dab1a984Spatrick ssdfb_std_descr.capabilities = ri->ri_caps;
325dab1a984Spatrick
3261c999b93Spatrick sc->sc_riops.putchar = ri->ri_putchar;
3271c999b93Spatrick sc->sc_riops.copycols = ri->ri_copycols;
3281c999b93Spatrick sc->sc_riops.erasecols = ri->ri_erasecols;
3291c999b93Spatrick sc->sc_riops.copyrows = ri->ri_copyrows;
3301c999b93Spatrick sc->sc_riops.eraserows = ri->ri_eraserows;
3311c999b93Spatrick sc->sc_ri_do_cursor = ri->ri_do_cursor;
3321c999b93Spatrick
3331c999b93Spatrick ri->ri_putchar = ssdfb_putchar;
3341c999b93Spatrick ri->ri_copycols = ssdfb_copycols;
3351c999b93Spatrick ri->ri_erasecols = ssdfb_erasecols;
3361c999b93Spatrick ri->ri_copyrows = ssdfb_copyrows;
3371c999b93Spatrick ri->ri_eraserows = ssdfb_eraserows;
3381c999b93Spatrick ri->ri_do_cursor = ssdfb_do_cursor;
339dab1a984Spatrick
340dab1a984Spatrick printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
341dab1a984Spatrick
342dab1a984Spatrick memset(&aa, 0, sizeof(aa));
343dab1a984Spatrick aa.console = 0;
344dab1a984Spatrick aa.scrdata = &ssdfb_screen_list;
345dab1a984Spatrick aa.accessops = &ssdfb_accessops;
346dab1a984Spatrick aa.accesscookie = sc;
347dab1a984Spatrick aa.defaultscreens = 0;
348dab1a984Spatrick
349c6a62e52Spatrick config_found_sm(&sc->sc_dev, &aa, wsemuldisplaydevprint,
350dab1a984Spatrick wsemuldisplaydevsubmatch);
351dab1a984Spatrick ssdfb_init(sc);
352dab1a984Spatrick }
353dab1a984Spatrick
354dab1a984Spatrick int
ssdfb_detach(struct ssdfb_softc * sc,int flags)355c6a62e52Spatrick ssdfb_detach(struct ssdfb_softc *sc, int flags)
356dab1a984Spatrick {
357dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
358ad478a58Spatrick free(ri->ri_bs, M_DEVBUF, sc->sc_width * sc->sc_height *
359ad478a58Spatrick sizeof(struct wsdisplay_charcell));
360dab1a984Spatrick free(ri->ri_bits, M_DEVBUF, sc->sc_fbsize);
361dab1a984Spatrick free(sc->sc_fb, M_DEVBUF, sc->sc_fbsize);
362dab1a984Spatrick return 0;
363dab1a984Spatrick }
364dab1a984Spatrick
365dab1a984Spatrick void
ssdfb_init(struct ssdfb_softc * sc)366dab1a984Spatrick ssdfb_init(struct ssdfb_softc *sc)
367dab1a984Spatrick {
368dab1a984Spatrick uint8_t reg[2];
369dab1a984Spatrick
370dab1a984Spatrick reg[0] = SSDFB_SET_DISPLAY_OFF;
371dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
372dab1a984Spatrick
373eb4f240eSpatrick reg[0] = SSDFB_SET_MEMORY_ADDRESSING_MODE;
374eb4f240eSpatrick reg[1] = 0x00; /* Horizontal Addressing Mode */
375dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
376eb4f240eSpatrick reg[0] = SSDFB_SET_PAGE_START_ADDRESS;
377dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
378ad478a58Spatrick ssdfb_set_range(sc, 0, sc->sc_width - 1,
379ad478a58Spatrick 0, (sc->sc_height / 8) - 1);
380ad478a58Spatrick if (OF_is_compatible(sc->sc_node, "solomon,ssd1309fb-i2c") ||
381ad478a58Spatrick OF_is_compatible(sc->sc_node, "solomon,ssd1309fb-spi")) {
382dab1a984Spatrick reg[0] = SSDFB_SET_DISPLAY_CLOCK_DIVIDE_RATIO;
383dab1a984Spatrick reg[1] = 0xa0;
384dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
385ad478a58Spatrick }
386fb481783Spatrick if (OF_is_compatible(sc->sc_node, "solomon,ssd1306fb-i2c")) {
387fb481783Spatrick reg[0] = SSDFB_SET_DISPLAY_CLOCK_DIVIDE_RATIO;
388fb481783Spatrick reg[1] = 0x80;
389fb481783Spatrick ssdfb_write_command(sc, reg, 2);
390fb481783Spatrick }
391dab1a984Spatrick reg[0] = SSDFB_SET_MULTIPLEX_RATIO;
392dab1a984Spatrick reg[1] = 0x3f;
393dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
394dab1a984Spatrick reg[0] = SSDFB_SET_DISPLAY_OFFSET;
395ad478a58Spatrick reg[1] = OF_getpropint(sc->sc_node, "solomon,com-offset", 0);
396dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
397dab1a984Spatrick reg[0] = SSDFB_SET_START_LINE | 0x00;
398dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
399ad478a58Spatrick reg[0] = SSDFB_SET_COLUMN_DIRECTION_NORMAL;
400ad478a58Spatrick if (OF_getproplen(sc->sc_node, "solomon,com-invdir") == 0)
401dab1a984Spatrick reg[0] = SSDFB_SET_COLUMN_DIRECTION_REVERSE;
402dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
403ad478a58Spatrick reg[0] = SSDFB_SET_COM_OUTPUT_DIRECTION_REMAP;
404ad478a58Spatrick if (OF_getproplen(sc->sc_node, "solomon,segment-no-remap") == 0)
405ad478a58Spatrick reg[0] = SSDFB_SET_COM_OUTPUT_DIRECTION_NORMAL;
406dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
407dab1a984Spatrick reg[0] = SSDFB_SET_COM_PINS_HARD_CONF;
408dab1a984Spatrick reg[1] = 0x12;
409ad478a58Spatrick if (OF_getproplen(sc->sc_node, "solomon,com-seq") == 0)
410ad478a58Spatrick reg[1] &= ~(1 << 4);
411ad478a58Spatrick if (OF_getproplen(sc->sc_node, "solomon,com-lrremap") == 0)
412ad478a58Spatrick reg[1] |= 1 << 5;
413dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
414dab1a984Spatrick reg[0] = SSDFB_SET_CONTRAST_CONTROL;
4153f4c1042Spatrick reg[1] = sc->sc_brightness;
416dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
417dab1a984Spatrick reg[0] = SSDFB_SET_PRE_CHARGE_PERIOD;
418ad478a58Spatrick reg[1] = (OF_getpropint(sc->sc_node, "solomon,prechargep1", 2) & 0xf) << 0;
419ad478a58Spatrick reg[1] |= (OF_getpropint(sc->sc_node, "solomon,prechargep2", 2) & 0xf) << 4;
420dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
421ad478a58Spatrick if (OF_is_compatible(sc->sc_node, "solomon,ssd1309fb-i2c") ||
422ad478a58Spatrick OF_is_compatible(sc->sc_node, "solomon,ssd1309fb-spi")) {
423dab1a984Spatrick reg[0] = SSDFB_SET_VCOM_DESELECT_LEVEL;
424dab1a984Spatrick reg[1] = 0x34;
425dab1a984Spatrick ssdfb_write_command(sc, reg, 2);
426ad478a58Spatrick }
427fb481783Spatrick if (OF_is_compatible(sc->sc_node, "solomon,ssd1306fb-i2c")) {
428fb481783Spatrick reg[0] = SSDFB_SET_VCOM_DESELECT_LEVEL;
429fb481783Spatrick reg[1] = 0x20;
430fb481783Spatrick ssdfb_write_command(sc, reg, 2);
431fb481783Spatrick }
432fb481783Spatrick reg[0] = SSDFB_CHARGE_PUMP;
433fb481783Spatrick reg[1] = 0x10;
434fb481783Spatrick if (OF_is_compatible(sc->sc_node, "solomon,ssd1306fb-i2c"))
435fb481783Spatrick reg[1] |= 1 << 2;
436fb481783Spatrick ssdfb_write_command(sc, reg, 2);
437dab1a984Spatrick reg[0] = SSDFB_ENTIRE_DISPLAY_ON;
438dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
439dab1a984Spatrick reg[0] = SSDFB_SET_DISPLAY_MODE_NORMAL;
440dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
441dab1a984Spatrick
442ad478a58Spatrick ssdfb_partial(sc, 0, sc->sc_width, 0, sc->sc_height);
443dab1a984Spatrick
444dab1a984Spatrick reg[0] = SSDFB_SET_DISPLAY_ON;
445dab1a984Spatrick ssdfb_write_command(sc, reg, 1);
446dab1a984Spatrick }
447dab1a984Spatrick
448dab1a984Spatrick void
ssdfb_set_range(struct ssdfb_softc * sc,uint8_t x1,uint8_t x2,uint8_t y1,uint8_t y2)449eb4f240eSpatrick ssdfb_set_range(struct ssdfb_softc *sc, uint8_t x1, uint8_t x2,
450eb4f240eSpatrick uint8_t y1, uint8_t y2)
451eb4f240eSpatrick {
452eb4f240eSpatrick uint8_t reg[3];
453eb4f240eSpatrick
454ad478a58Spatrick y1 += sc->sc_pgoff;
455ad478a58Spatrick y2 += sc->sc_pgoff;
456ad478a58Spatrick
457eb4f240eSpatrick if (sc->sc_column_range[0] != x1 || sc->sc_column_range[1] != x2) {
458eb4f240eSpatrick sc->sc_column_range[0] = x1;
459eb4f240eSpatrick sc->sc_column_range[1] = x2;
460eb4f240eSpatrick reg[0] = SSDFB_SET_COLUMN_RANGE;
461eb4f240eSpatrick reg[1] = sc->sc_column_range[0];
462eb4f240eSpatrick reg[2] = sc->sc_column_range[1];
463eb4f240eSpatrick ssdfb_write_command(sc, reg, 3);
464eb4f240eSpatrick }
465eb4f240eSpatrick if (sc->sc_page_range[0] != y1 || sc->sc_page_range[1] != y2) {
466eb4f240eSpatrick sc->sc_page_range[0] = y1;
467eb4f240eSpatrick sc->sc_page_range[1] = y2;
468eb4f240eSpatrick reg[0] = SSDFB_SET_PAGE_RANGE;
469eb4f240eSpatrick reg[1] = sc->sc_page_range[0];
470eb4f240eSpatrick reg[2] = sc->sc_page_range[1];
471eb4f240eSpatrick ssdfb_write_command(sc, reg, 3);
472eb4f240eSpatrick }
473eb4f240eSpatrick }
474eb4f240eSpatrick
475eb4f240eSpatrick void
ssdfb_partial(struct ssdfb_softc * sc,uint32_t x1,uint32_t x2,uint32_t y1,uint32_t y2)476eb4f240eSpatrick ssdfb_partial(struct ssdfb_softc *sc, uint32_t x1, uint32_t x2,
477eb4f240eSpatrick uint32_t y1, uint32_t y2)
478eb4f240eSpatrick {
479dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
480eb4f240eSpatrick uint32_t off, width, height;
481dab1a984Spatrick uint8_t *bit, val;
482dab1a984Spatrick int i, j, k;
483dab1a984Spatrick
484eb4f240eSpatrick if (x2 < x1 || y2 < y1)
485eb4f240eSpatrick return;
486dab1a984Spatrick
487ad478a58Spatrick if (x2 > sc->sc_width || y2 > sc->sc_height)
488eb4f240eSpatrick return;
489eb4f240eSpatrick
490eb4f240eSpatrick y1 = y1 & ~0x7;
491eb4f240eSpatrick y2 = roundup(y2, 8);
492eb4f240eSpatrick
493eb4f240eSpatrick width = x2 - x1;
494eb4f240eSpatrick height = y2 - y1;
495eb4f240eSpatrick
496eb4f240eSpatrick memset(sc->sc_fb, 0, (width * height) / 8);
497eb4f240eSpatrick
498eb4f240eSpatrick for (i = 0; i < height; i += 8) {
499eb4f240eSpatrick for (j = 0; j < width; j++) {
500eb4f240eSpatrick bit = &sc->sc_fb[(i / 8) * width + j];
501dab1a984Spatrick for (k = 0; k < 8; k++) {
502eb4f240eSpatrick off = ri->ri_stride * (y1 + i + k);
503eb4f240eSpatrick off += (x1 + j) / 8;
504dab1a984Spatrick val = *(ri->ri_bits + off);
505eb4f240eSpatrick val &= (1 << ((x1 + j) % 8));
506dab1a984Spatrick *bit |= !!val << k;
507dab1a984Spatrick }
508dab1a984Spatrick }
509dab1a984Spatrick }
510dab1a984Spatrick
511eb4f240eSpatrick ssdfb_set_range(sc, x1, x2 - 1, y1 / 8, (y2 / 8) - 1);
512eb4f240eSpatrick ssdfb_write_data(sc, sc->sc_fb, (width * height) / 8);
513dab1a984Spatrick }
514dab1a984Spatrick
515dab1a984Spatrick void
ssdfb_write_command(struct ssdfb_softc * sc,char * buf,size_t len)516dab1a984Spatrick ssdfb_write_command(struct ssdfb_softc *sc, char *buf, size_t len)
517dab1a984Spatrick {
518c6a62e52Spatrick return sc->sc_write_command(sc, buf, len);
519c6a62e52Spatrick }
520c6a62e52Spatrick
521c6a62e52Spatrick void
ssdfb_write_data(struct ssdfb_softc * sc,char * buf,size_t len)522c6a62e52Spatrick ssdfb_write_data(struct ssdfb_softc *sc, char *buf, size_t len)
523c6a62e52Spatrick {
524c6a62e52Spatrick return sc->sc_write_data(sc, buf, len);
525c6a62e52Spatrick }
526c6a62e52Spatrick
527c6a62e52Spatrick void
ssdfb_i2c_write_command(struct ssdfb_softc * sc,char * buf,size_t len)528c6a62e52Spatrick ssdfb_i2c_write_command(struct ssdfb_softc *sc, char *buf, size_t len)
529c6a62e52Spatrick {
530c6a62e52Spatrick uint8_t type;
531c6a62e52Spatrick
532c6a62e52Spatrick type = SSDFB_I2C_COMMAND;
533c6a62e52Spatrick iic_acquire_bus(sc->sc_i2c_tag, 0);
534c6a62e52Spatrick if (iic_exec(sc->sc_i2c_tag, I2C_OP_WRITE_WITH_STOP,
535c6a62e52Spatrick sc->sc_i2c_addr, &type, sizeof(type), buf, len, 0)) {
536c6a62e52Spatrick printf("%s: cannot write\n", sc->sc_dev.dv_xname);
537c6a62e52Spatrick }
538c6a62e52Spatrick iic_release_bus(sc->sc_i2c_tag, 0);
539c6a62e52Spatrick }
540c6a62e52Spatrick
541c6a62e52Spatrick void
ssdfb_i2c_write_data(struct ssdfb_softc * sc,char * buf,size_t len)542c6a62e52Spatrick ssdfb_i2c_write_data(struct ssdfb_softc *sc, char *buf, size_t len)
543c6a62e52Spatrick {
544c6a62e52Spatrick uint8_t type;
545c6a62e52Spatrick
546c6a62e52Spatrick type = SSDFB_I2C_DATA;
547c6a62e52Spatrick iic_acquire_bus(sc->sc_i2c_tag, 0);
548c6a62e52Spatrick if (iic_exec(sc->sc_i2c_tag, I2C_OP_WRITE_WITH_STOP,
549c6a62e52Spatrick sc->sc_i2c_addr, &type, sizeof(type), buf, len, 0)) {
550c6a62e52Spatrick printf("%s: cannot write\n", sc->sc_dev.dv_xname);
551c6a62e52Spatrick }
552c6a62e52Spatrick iic_release_bus(sc->sc_i2c_tag, 0);
553c6a62e52Spatrick }
554c6a62e52Spatrick
555c6a62e52Spatrick void
ssdfb_spi_write_command(struct ssdfb_softc * sc,char * buf,size_t len)556c6a62e52Spatrick ssdfb_spi_write_command(struct ssdfb_softc *sc, char *buf, size_t len)
557c6a62e52Spatrick {
558dab1a984Spatrick if (sc->sc_cd != 0) {
559dab1a984Spatrick gpio_controller_set_pin(sc->sc_gpio, 0);
560dab1a984Spatrick sc->sc_cd = 0;
561dab1a984Spatrick delay(1);
562dab1a984Spatrick }
563dab1a984Spatrick
564c6a62e52Spatrick spi_acquire_bus(sc->sc_spi_tag, 0);
565c6a62e52Spatrick spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
566c6a62e52Spatrick if (spi_write(sc->sc_spi_tag, buf, len))
567dab1a984Spatrick printf("%s: cannot write\n", sc->sc_dev.dv_xname);
568c6a62e52Spatrick spi_release_bus(sc->sc_spi_tag, 0);
569dab1a984Spatrick }
570dab1a984Spatrick
571dab1a984Spatrick void
ssdfb_spi_write_data(struct ssdfb_softc * sc,char * buf,size_t len)572c6a62e52Spatrick ssdfb_spi_write_data(struct ssdfb_softc *sc, char *buf, size_t len)
573dab1a984Spatrick {
574dab1a984Spatrick if (sc->sc_cd != 1) {
575dab1a984Spatrick gpio_controller_set_pin(sc->sc_gpio, 1);
576dab1a984Spatrick sc->sc_cd = 1;
577dab1a984Spatrick delay(1);
578dab1a984Spatrick }
579dab1a984Spatrick
580c6a62e52Spatrick spi_acquire_bus(sc->sc_spi_tag, 0);
581c6a62e52Spatrick spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
582c6a62e52Spatrick if (spi_write(sc->sc_spi_tag, buf, len))
583dab1a984Spatrick printf("%s: cannot write\n", sc->sc_dev.dv_xname);
584c6a62e52Spatrick spi_release_bus(sc->sc_spi_tag, 0);
585dab1a984Spatrick }
586dab1a984Spatrick
587dab1a984Spatrick int
ssdfb_ioctl(void * v,u_long cmd,caddr_t data,int flag,struct proc * p)588dab1a984Spatrick ssdfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
589dab1a984Spatrick {
590dab1a984Spatrick struct ssdfb_softc *sc = v;
591dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
5923f4c1042Spatrick struct wsdisplay_param *dp = (struct wsdisplay_param *)data;
593dab1a984Spatrick struct wsdisplay_fbinfo *wdf;
5943f4c1042Spatrick struct udl_ioctl_damage *d;
5953f4c1042Spatrick int mode;
5963f4c1042Spatrick uint8_t reg[2];
597dab1a984Spatrick
598dab1a984Spatrick switch (cmd) {
599dab1a984Spatrick case WSDISPLAYIO_GETPARAM:
6003f4c1042Spatrick switch (dp->param) {
6013f4c1042Spatrick case WSDISPLAYIO_PARAM_BRIGHTNESS:
6023f4c1042Spatrick dp->min = 0;
6033f4c1042Spatrick dp->max = 255;
6043f4c1042Spatrick dp->curval = sc->sc_brightness;
6053f4c1042Spatrick break;
6063f4c1042Spatrick default:
607dab1a984Spatrick return (-1);
6083f4c1042Spatrick }
6093f4c1042Spatrick break;
6103f4c1042Spatrick case WSDISPLAYIO_SETPARAM:
6113f4c1042Spatrick switch (dp->param) {
6123f4c1042Spatrick case WSDISPLAYIO_PARAM_BRIGHTNESS:
6133f4c1042Spatrick if (dp->curval == 0) {
6143f4c1042Spatrick reg[0] = SSDFB_SET_DISPLAY_OFF;
6153f4c1042Spatrick ssdfb_write_command(sc, reg, 1);
6163f4c1042Spatrick } else if (sc->sc_brightness == 0) {
6173f4c1042Spatrick reg[0] = SSDFB_SET_DISPLAY_ON;
6183f4c1042Spatrick ssdfb_write_command(sc, reg, 1);
6193f4c1042Spatrick }
6203f4c1042Spatrick reg[0] = SSDFB_SET_CONTRAST_CONTROL;
6213f4c1042Spatrick reg[1] = sc->sc_brightness = dp->curval;
6223f4c1042Spatrick ssdfb_write_command(sc, reg, 2);
6233f4c1042Spatrick break;
6243f4c1042Spatrick default:
6253f4c1042Spatrick return (-1);
6263f4c1042Spatrick }
6273f4c1042Spatrick break;
628dab1a984Spatrick case WSDISPLAYIO_GTYPE:
6293f4c1042Spatrick *(u_int *)data = WSDISPLAY_TYPE_DL;
630dab1a984Spatrick break;
631dab1a984Spatrick case WSDISPLAYIO_GINFO:
632dab1a984Spatrick wdf = (struct wsdisplay_fbinfo *)data;
633dab1a984Spatrick wdf->width = ri->ri_width;
634dab1a984Spatrick wdf->height = ri->ri_height;
635dab1a984Spatrick wdf->depth = ri->ri_depth;
63663294167Skettenis wdf->stride = ri->ri_stride;
63763294167Skettenis wdf->offset = 0;
638dab1a984Spatrick wdf->cmsize = 0; /* color map is unavailable */
639dab1a984Spatrick break;
640dab1a984Spatrick case WSDISPLAYIO_LINEBYTES:
641dab1a984Spatrick *(u_int *)data = ri->ri_stride;
642dab1a984Spatrick break;
643dab1a984Spatrick case WSDISPLAYIO_SMODE:
6443f4c1042Spatrick mode = *(u_int *)data;
6453f4c1042Spatrick switch (mode) {
6463f4c1042Spatrick case WSDISPLAYIO_MODE_EMUL:
6473f4c1042Spatrick if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) {
6483f4c1042Spatrick memset(ri->ri_bits, 0, sc->sc_fbsize);
6493f4c1042Spatrick ssdfb_partial(sc, 0, sc->sc_width,
6503f4c1042Spatrick 0, sc->sc_height);
6513f4c1042Spatrick sc->sc_mode = mode;
6523f4c1042Spatrick }
6533f4c1042Spatrick break;
6543f4c1042Spatrick case WSDISPLAYIO_MODE_DUMBFB:
6553f4c1042Spatrick if (sc->sc_mode != WSDISPLAYIO_MODE_DUMBFB) {
6563f4c1042Spatrick memset(ri->ri_bits, 0, sc->sc_fbsize);
6573f4c1042Spatrick ssdfb_partial(sc, 0, sc->sc_width,
6583f4c1042Spatrick 0, sc->sc_height);
6593f4c1042Spatrick sc->sc_mode = mode;
6603f4c1042Spatrick }
6613f4c1042Spatrick break;
6623f4c1042Spatrick case WSDISPLAYIO_MODE_MAPPED:
6633f4c1042Spatrick default:
6643f4c1042Spatrick return (-1);
6653f4c1042Spatrick }
666dab1a984Spatrick break;
667dab1a984Spatrick case WSDISPLAYIO_GETSUPPORTEDDEPTH:
668dab1a984Spatrick *(u_int *)data = WSDISPLAYIO_DEPTH_1;
669dab1a984Spatrick break;
6703f4c1042Spatrick case UDLIO_DAMAGE:
6713f4c1042Spatrick d = (struct udl_ioctl_damage *)data;
6723f4c1042Spatrick d->status = UDLIO_STATUS_OK;
6733f4c1042Spatrick ssdfb_partial(sc, d->x1, d->x2, d->y1, d->y2);
6743f4c1042Spatrick break;
675dab1a984Spatrick default:
676dab1a984Spatrick return (-1);
677dab1a984Spatrick }
678dab1a984Spatrick
679dab1a984Spatrick return (0);
680dab1a984Spatrick }
681dab1a984Spatrick
682dab1a984Spatrick paddr_t
ssdfb_mmap(void * v,off_t off,int prot)683dab1a984Spatrick ssdfb_mmap(void *v, off_t off, int prot)
684dab1a984Spatrick {
6853f4c1042Spatrick struct ssdfb_softc *sc = v;
6863f4c1042Spatrick struct rasops_info *ri = &sc->sc_rinfo;
6873f4c1042Spatrick paddr_t pa;
6883f4c1042Spatrick
6893f4c1042Spatrick if (off >= sc->sc_fbsize || off < 0)
6903f4c1042Spatrick return (-1);
6913f4c1042Spatrick
6923f4c1042Spatrick if (!pmap_extract(pmap_kernel(), (vaddr_t)ri->ri_bits, &pa))
6933f4c1042Spatrick return (-1);
6943f4c1042Spatrick
6953f4c1042Spatrick return (pa + off);
696dab1a984Spatrick }
697dab1a984Spatrick
698dab1a984Spatrick int
ssdfb_alloc_screen(void * v,const struct wsscreen_descr * descr,void ** cookiep,int * curxp,int * curyp,uint32_t * attrp)699dab1a984Spatrick ssdfb_alloc_screen(void *v, const struct wsscreen_descr *descr,
700e0c3e559Sjsg void **cookiep, int *curxp, int *curyp, uint32_t *attrp)
701dab1a984Spatrick {
702dab1a984Spatrick struct ssdfb_softc *sc = v;
703dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
704dab1a984Spatrick
705dab1a984Spatrick return rasops_alloc_screen(ri, cookiep, curxp, curyp, attrp);
706dab1a984Spatrick }
707dab1a984Spatrick
708dab1a984Spatrick void
ssdfb_free_screen(void * v,void * cookie)709dab1a984Spatrick ssdfb_free_screen(void *v, void *cookie)
710dab1a984Spatrick {
711dab1a984Spatrick struct ssdfb_softc *sc = v;
712dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
713dab1a984Spatrick
714dab1a984Spatrick rasops_free_screen(ri, cookie);
715dab1a984Spatrick }
716dab1a984Spatrick
717dab1a984Spatrick int
ssdfb_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cb_arg)718dab1a984Spatrick ssdfb_show_screen(void *v, void *cookie, int waitok,
719dab1a984Spatrick void (*cb) (void *, int, int), void *cb_arg)
720dab1a984Spatrick {
721dab1a984Spatrick struct ssdfb_softc *sc = v;
722dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
723dab1a984Spatrick
724dab1a984Spatrick return rasops_show_screen(ri, cookie, waitok, cb, cb_arg);
725dab1a984Spatrick }
726dab1a984Spatrick
727dab1a984Spatrick int
ssdfb_load_font(void * v,void * cookie,struct wsdisplay_font * font)728dab1a984Spatrick ssdfb_load_font(void *v, void *cookie, struct wsdisplay_font *font)
729dab1a984Spatrick {
730dab1a984Spatrick struct ssdfb_softc *sc = v;
731dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
732dab1a984Spatrick
733dab1a984Spatrick return (rasops_load_font(ri, cookie, font));
734dab1a984Spatrick }
735dab1a984Spatrick
736dab1a984Spatrick int
ssdfb_list_font(void * v,struct wsdisplay_font * font)737dab1a984Spatrick ssdfb_list_font(void *v, struct wsdisplay_font *font)
738dab1a984Spatrick {
739dab1a984Spatrick struct ssdfb_softc *sc = v;
740dab1a984Spatrick struct rasops_info *ri = &sc->sc_rinfo;
741dab1a984Spatrick
742dab1a984Spatrick return (rasops_list_font(ri, font));
743dab1a984Spatrick }
7441c999b93Spatrick
7451c999b93Spatrick int
ssdfb_putchar(void * cookie,int row,int col,u_int uc,uint32_t attr)746e0c3e559Sjsg ssdfb_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr)
7471c999b93Spatrick {
7481c999b93Spatrick struct rasops_info *ri = (struct rasops_info *)cookie;
7491c999b93Spatrick struct ssdfb_softc *sc = ri->ri_hw;
7501c999b93Spatrick
7511c999b93Spatrick sc->sc_riops.putchar(cookie, row, col, uc, attr);
7521c999b93Spatrick ssdfb_partial(sc,
7531c999b93Spatrick col * ri->ri_font->fontwidth,
7541c999b93Spatrick (col + 1) * ri->ri_font->fontwidth,
7551c999b93Spatrick row * ri->ri_font->fontheight,
7561c999b93Spatrick (row + 1) * ri->ri_font->fontheight);
7571c999b93Spatrick return 0;
7581c999b93Spatrick }
7591c999b93Spatrick
7601c999b93Spatrick int
ssdfb_copycols(void * cookie,int row,int src,int dst,int num)7611c999b93Spatrick ssdfb_copycols(void *cookie, int row, int src, int dst, int num)
7621c999b93Spatrick {
7631c999b93Spatrick struct rasops_info *ri = (struct rasops_info *)cookie;
7641c999b93Spatrick struct ssdfb_softc *sc = ri->ri_hw;
7651c999b93Spatrick
7661c999b93Spatrick sc->sc_riops.copycols(cookie, row, src, dst, num);
7671c999b93Spatrick ssdfb_partial(sc,
7681c999b93Spatrick dst * ri->ri_font->fontwidth,
7691c999b93Spatrick (dst + num) * ri->ri_font->fontwidth,
7701c999b93Spatrick row * ri->ri_font->fontheight,
7711c999b93Spatrick (row + 1) * ri->ri_font->fontheight);
7721c999b93Spatrick return 0;
7731c999b93Spatrick }
7741c999b93Spatrick
7751c999b93Spatrick int
ssdfb_erasecols(void * cookie,int row,int col,int num,uint32_t attr)776e0c3e559Sjsg ssdfb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
7771c999b93Spatrick {
7781c999b93Spatrick struct rasops_info *ri = (struct rasops_info *)cookie;
7791c999b93Spatrick struct ssdfb_softc *sc = ri->ri_hw;
7801c999b93Spatrick
7811c999b93Spatrick sc->sc_riops.erasecols(cookie, row, col, num, attr);
7821c999b93Spatrick ssdfb_partial(sc,
7831c999b93Spatrick col * ri->ri_font->fontwidth,
7841c999b93Spatrick (col + num) * ri->ri_font->fontwidth,
7851c999b93Spatrick row * ri->ri_font->fontheight,
7861c999b93Spatrick (row + 1) * ri->ri_font->fontheight);
7871c999b93Spatrick return 0;
7881c999b93Spatrick }
7891c999b93Spatrick
7901c999b93Spatrick int
ssdfb_copyrows(void * cookie,int src,int dst,int num)7911c999b93Spatrick ssdfb_copyrows(void *cookie, int src, int dst, int num)
7921c999b93Spatrick {
7931c999b93Spatrick struct rasops_info *ri = (struct rasops_info *)cookie;
7941c999b93Spatrick struct ssdfb_softc *sc = ri->ri_hw;
7951c999b93Spatrick
7961c999b93Spatrick sc->sc_riops.copyrows(cookie, src, dst, num);
797ad478a58Spatrick ssdfb_partial(sc, 0, sc->sc_width,
7981c999b93Spatrick dst * ri->ri_font->fontheight,
7991c999b93Spatrick (dst + num) * ri->ri_font->fontheight);
8001c999b93Spatrick return 0;
8011c999b93Spatrick }
8021c999b93Spatrick
8031c999b93Spatrick int
ssdfb_eraserows(void * cookie,int row,int num,uint32_t attr)804e0c3e559Sjsg ssdfb_eraserows(void *cookie, int row, int num, uint32_t attr)
8051c999b93Spatrick {
8061c999b93Spatrick struct rasops_info *ri = (struct rasops_info *)cookie;
8071c999b93Spatrick struct ssdfb_softc *sc = ri->ri_hw;
8081c999b93Spatrick
8091c999b93Spatrick sc->sc_riops.eraserows(cookie, row, num, attr);
8101c999b93Spatrick if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0)
811ad478a58Spatrick ssdfb_partial(sc, 0, sc->sc_width, 0, sc->sc_height);
8121c999b93Spatrick else
813ad478a58Spatrick ssdfb_partial(sc, 0, sc->sc_width,
8141c999b93Spatrick row * ri->ri_font->fontheight,
8151c999b93Spatrick (row + num) * ri->ri_font->fontheight);
8161c999b93Spatrick return 0;
8171c999b93Spatrick }
8181c999b93Spatrick
8191c999b93Spatrick int
ssdfb_do_cursor(struct rasops_info * ri)8201c999b93Spatrick ssdfb_do_cursor(struct rasops_info *ri)
8211c999b93Spatrick {
8221c999b93Spatrick struct ssdfb_softc *sc = ri->ri_hw;
8231c999b93Spatrick int orow, ocol, nrow, ncol;
8241c999b93Spatrick
8251c999b93Spatrick orow = ri->ri_crow;
8261c999b93Spatrick ocol = ri->ri_ccol;
8271c999b93Spatrick sc->sc_ri_do_cursor(ri);
8281c999b93Spatrick nrow = ri->ri_crow;
8291c999b93Spatrick ncol = ri->ri_ccol;
8301c999b93Spatrick
8311c999b93Spatrick ssdfb_partial(sc,
8321c999b93Spatrick ocol * ri->ri_font->fontwidth,
8331c999b93Spatrick (ocol + 1) * ri->ri_font->fontwidth,
8341c999b93Spatrick orow * ri->ri_font->fontheight,
8351c999b93Spatrick (orow + 1) * ri->ri_font->fontheight);
8361c999b93Spatrick ssdfb_partial(sc,
8371c999b93Spatrick ncol * ri->ri_font->fontwidth,
8381c999b93Spatrick (ncol + 1) * ri->ri_font->fontwidth,
8391c999b93Spatrick nrow * ri->ri_font->fontheight,
8401c999b93Spatrick (nrow + 1) * ri->ri_font->fontheight);
8411c999b93Spatrick
8421c999b93Spatrick return 0;
8431c999b93Spatrick }
844