aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/staging/sm750fb/sm750_cursor.c
blob: 9d24159226d12b063d2d27c2ce38226109f7bad0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/console.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>

#include "sm750.h"
#include "sm750_cursor.h"



#define poke32(addr, data) \
writel((data), cursor->mmio + (addr))

/* cursor control for voyager and 718/750*/
#define HWC_ADDRESS                         0x0
#define HWC_ADDRESS_ENABLE                  BIT(31)
#define HWC_ADDRESS_EXT                     BIT(27)
#define HWC_ADDRESS_CS                      BIT(26)
#define HWC_ADDRESS_ADDRESS_MASK            0x3ffffff

#define HWC_LOCATION                        0x4
#define HWC_LOCATION_TOP                    BIT(27)
#define HWC_LOCATION_Y_SHIFT                16
#define HWC_LOCATION_Y_MASK                 (0x7ff << 16)
#define HWC_LOCATION_LEFT                   BIT(11)
#define HWC_LOCATION_X_MASK                 0x7ff

#define HWC_COLOR_12                        0x8
#define HWC_COLOR_12_2_RGB565_SHIFT         16
#define HWC_COLOR_12_2_RGB565_MASK          (0xffff << 16)
#define HWC_COLOR_12_1_RGB565_MASK          0xffff

#define HWC_COLOR_3                         0xC
#define HWC_COLOR_3_RGB565_MASK             0xffff


/* hw_cursor_xxx works for voyager,718 and 750 */
void sm750_hw_cursor_enable(struct lynx_cursor *cursor)
{
	u32 reg;

	reg = (cursor->offset & HWC_ADDRESS_ADDRESS_MASK) | HWC_ADDRESS_ENABLE;
	poke32(HWC_ADDRESS, reg);
}

void sm750_hw_cursor_disable(struct lynx_cursor *cursor)
{
	poke32(HWC_ADDRESS, 0);
}

void sm750_hw_cursor_setSize(struct lynx_cursor *cursor, int w, int h)
{
	cursor->w = w;
	cursor->h = h;
}

void sm750_hw_cursor_setPos(struct lynx_cursor *cursor, int x, int y)
{
	u32 reg;

	reg = ((y << HWC_LOCATION_Y_SHIFT) & HWC_LOCATION_Y_MASK) |
	       (x & HWC_LOCATION_X_MASK);
	poke32(HWC_LOCATION, reg);
}

void sm750_hw_cursor_setColor(struct lynx_cursor *cursor, u32 fg, u32 bg)
{
	u32 reg = (fg << HWC_COLOR_12_2_RGB565_SHIFT) &
		HWC_COLOR_12_2_RGB565_MASK;

	poke32(HWC_COLOR_12, reg | (bg & HWC_COLOR_12_1_RGB565_MASK));
	poke32(HWC_COLOR_3, 0xffe0);
}

void sm750_hw_cursor_setData(struct lynx_cursor *cursor, u16 rop,
			     const u8 *pcol, const u8 *pmsk)
{
	int i, j, count, pitch, offset;
	u8 color, mask, opr;
	u16 data;
	void __iomem *pbuffer, *pstart;

	/*  in byte*/
	pitch = cursor->w >> 3;

	/* in byte	*/
	count = pitch * cursor->h;

	/* in byte */
	offset = cursor->maxW * 2 / 8;

	data = 0;
	pstart = cursor->vstart;
	pbuffer = pstart;

	for (i = 0; i < count; i++) {
		color = *pcol++;
		mask = *pmsk++;
		data = 0;

		for (j = 0; j < 8; j++) {
			if (mask & (0x80 >> j)) {
				if (rop == ROP_XOR)
					opr = mask ^ color;
				else
					opr = mask & color;

				/* 2 stands for forecolor and 1 for backcolor */
				data |= ((opr & (0x80 >> j)) ? 2 : 1) << (j * 2);
			}
		}
		iowrite16(data, pbuffer);

		/* assume pitch is 1,2,4,8,...*/
		if ((i + 1) % pitch == 0) {
			/* need a return */
			pstart += offset;
			pbuffer = pstart;
		} else {
			pbuffer += sizeof(u16);
		}
	}
}


void sm750_hw_cursor_setData2(struct lynx_cursor *cursor, u16 rop,
			      const u8 *pcol, const u8 *pmsk)
{
	int i, j, count, pitch, offset;
	u8 color, mask;
	u16 data;
	void __iomem *pbuffer, *pstart;

	/*  in byte*/
	pitch = cursor->w >> 3;

	/* in byte	*/
	count = pitch * cursor->h;

	/* in byte */
	offset = cursor->maxW * 2 / 8;

	data = 0;
	pstart = cursor->vstart;
	pbuffer = pstart;

	for (i = 0; i < count; i++) {
		color = *pcol++;
		mask = *pmsk++;
		data = 0;

		for (j = 0; j < 8; j++) {
			if (mask & (1 << j))
				data |= ((color & (1 << j)) ? 1 : 2) << (j * 2);
		}
		iowrite16(data, pbuffer);

		/* assume pitch is 1,2,4,8,...*/
		if (!(i & (pitch - 1))) {
			/* need a return */
			pstart += offset;
			pbuffer = pstart;
		} else {
			pbuffer += sizeof(u16);
		}
	}
}