2 * Copyright (C) STMicroelectronics SA 2014
3 * Authors: Vincent Abriou <vincent.abriou@st.com>
4 * Fabien Dessenne <fabien.dessenne@st.com>
5 * for STMicroelectronics.
6 * License terms: GNU General Public License (GPL), version 2
10 #include "sti_cursor.h"
11 #include "sti_layer.h"
24 #define CUR_CTL_CLUT_UPDATE BIT(1)
26 #define STI_CURS_MIN_SIZE 1
27 #define STI_CURS_MAX_SIZE 128
30 * pixmap dma buffer stucture
32 * @paddr: physical address
34 * @base: virtual address
43 * STI Cursor structure
45 * @layer: layer structure
46 * @width: cursor width
47 * @height: cursor height
48 * @clut: color look up table
49 * @clut_paddr: color look up table physical address
50 * @pixmap: pixmap dma buffer (clut8-format cursor)
53 struct sti_layer layer
;
57 dma_addr_t clut_paddr
;
58 struct dma_pixmap pixmap
;
61 static const uint32_t cursor_supported_formats
[] = {
65 #define to_sti_cursor(x) container_of(x, struct sti_cursor, layer)
67 static const uint32_t *sti_cursor_get_formats(struct sti_layer
*layer
)
69 return cursor_supported_formats
;
72 static unsigned int sti_cursor_get_nb_formats(struct sti_layer
*layer
)
74 return ARRAY_SIZE(cursor_supported_formats
);
77 static void sti_cursor_argb8888_to_clut8(struct sti_layer
*layer
)
79 struct sti_cursor
*cursor
= to_sti_cursor(layer
);
80 u32
*src
= layer
->vaddr
;
81 u8
*dst
= cursor
->pixmap
.base
;
85 for (i
= 0; i
< cursor
->height
; i
++) {
86 for (j
= 0; j
< cursor
->width
; j
++) {
87 /* Pick the 2 higher bits of each component */
92 *dst
= a
<< 6 | r
<< 4 | g
<< 2 | b
;
99 static int sti_cursor_prepare_layer(struct sti_layer
*layer
, bool first_prepare
)
101 struct sti_cursor
*cursor
= to_sti_cursor(layer
);
102 struct drm_display_mode
*mode
= layer
->mode
;
106 DRM_DEBUG_DRIVER("\n");
108 dev_dbg(layer
->dev
, "%s %s\n", __func__
, sti_layer_to_str(layer
));
110 if (layer
->src_w
< STI_CURS_MIN_SIZE
||
111 layer
->src_h
< STI_CURS_MIN_SIZE
||
112 layer
->src_w
> STI_CURS_MAX_SIZE
||
113 layer
->src_h
> STI_CURS_MAX_SIZE
) {
114 DRM_ERROR("Invalid cursor size (%dx%d)\n",
115 layer
->src_w
, layer
->src_h
);
119 /* If the cursor size has changed, re-allocated the pixmap */
120 if (!cursor
->pixmap
.base
||
121 (cursor
->width
!= layer
->src_w
) ||
122 (cursor
->height
!= layer
->src_h
)) {
123 cursor
->width
= layer
->src_w
;
124 cursor
->height
= layer
->src_h
;
126 if (cursor
->pixmap
.base
)
127 dma_free_writecombine(layer
->dev
,
130 cursor
->pixmap
.paddr
);
132 cursor
->pixmap
.size
= cursor
->width
* cursor
->height
;
134 cursor
->pixmap
.base
= dma_alloc_writecombine(layer
->dev
,
136 &cursor
->pixmap
.paddr
,
137 GFP_KERNEL
| GFP_DMA
);
138 if (!cursor
->pixmap
.base
) {
139 DRM_ERROR("Failed to allocate memory for pixmap\n");
144 /* Convert ARGB8888 to CLUT8 */
145 sti_cursor_argb8888_to_clut8(layer
);
147 /* AWS and AWE depend on the mode */
148 y
= sti_vtg_get_line_number(*mode
, 0);
149 x
= sti_vtg_get_pixel_number(*mode
, 0);
151 writel(val
, layer
->regs
+ CUR_AWS
);
152 y
= sti_vtg_get_line_number(*mode
, mode
->vdisplay
- 1);
153 x
= sti_vtg_get_pixel_number(*mode
, mode
->hdisplay
- 1);
155 writel(val
, layer
->regs
+ CUR_AWE
);
158 /* Set and fetch CLUT */
159 writel(cursor
->clut_paddr
, layer
->regs
+ CUR_CML
);
160 writel(CUR_CTL_CLUT_UPDATE
, layer
->regs
+ CUR_CTL
);
166 static int sti_cursor_commit_layer(struct sti_layer
*layer
)
168 struct sti_cursor
*cursor
= to_sti_cursor(layer
);
169 struct drm_display_mode
*mode
= layer
->mode
;
172 dev_dbg(layer
->dev
, "%s %s\n", __func__
, sti_layer_to_str(layer
));
174 /* Set memory location, size, and position */
175 writel(cursor
->pixmap
.paddr
, layer
->regs
+ CUR_PML
);
176 writel(cursor
->width
, layer
->regs
+ CUR_PMP
);
177 writel(cursor
->height
<< 16 | cursor
->width
, layer
->regs
+ CUR_SIZE
);
179 ydo
= sti_vtg_get_line_number(*mode
, layer
->dst_y
);
180 xdo
= sti_vtg_get_pixel_number(*mode
, layer
->dst_y
);
181 writel((ydo
<< 16) | xdo
, layer
->regs
+ CUR_VPO
);
186 static int sti_cursor_disable_layer(struct sti_layer
*layer
)
191 static void sti_cursor_init(struct sti_layer
*layer
)
193 struct sti_cursor
*cursor
= to_sti_cursor(layer
);
194 unsigned short *base
= cursor
->clut
;
195 unsigned int a
, r
, g
, b
;
197 /* Assign CLUT values, ARGB444 format */
198 for (a
= 0; a
< 4; a
++)
199 for (r
= 0; r
< 4; r
++)
200 for (g
= 0; g
< 4; g
++)
201 for (b
= 0; b
< 4; b
++)
202 *base
++ = (a
* 5) << 12 |
208 static const struct sti_layer_funcs cursor_ops
= {
209 .get_formats
= sti_cursor_get_formats
,
210 .get_nb_formats
= sti_cursor_get_nb_formats
,
211 .init
= sti_cursor_init
,
212 .prepare
= sti_cursor_prepare_layer
,
213 .commit
= sti_cursor_commit_layer
,
214 .disable
= sti_cursor_disable_layer
,
217 struct sti_layer
*sti_cursor_create(struct device
*dev
)
219 struct sti_cursor
*cursor
;
221 cursor
= devm_kzalloc(dev
, sizeof(*cursor
), GFP_KERNEL
);
223 DRM_ERROR("Failed to allocate memory for cursor\n");
227 /* Allocate clut buffer */
228 cursor
->clut
= dma_alloc_writecombine(dev
,
229 0x100 * sizeof(unsigned short),
231 GFP_KERNEL
| GFP_DMA
);
234 DRM_ERROR("Failed to allocate memory for cursor clut\n");
235 devm_kfree(dev
, cursor
);
239 cursor
->layer
.ops
= &cursor_ops
;
241 return (struct sti_layer
*)cursor
;