diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/sti/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/Makefile | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_compositor.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_compositor.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_cursor.c | 242 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_cursor.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_drm_crtc.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_drm_drv.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_drm_plane.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_gdp.c | 62 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.c | 84 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hqvdp.c | 1072 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hqvdp.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_hqvdp_lut.h | 373 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_layer.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_layer.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_mixer.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_mixer.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_tvout.c | 104 | ||||
-rw-r--r-- | drivers/gpu/drm/sti/sti_vtg.c | 31 |
21 files changed, 1972 insertions, 133 deletions
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index ae8850f3e63b..d6d6b705b8c1 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig | |||
@@ -5,6 +5,7 @@ config DRM_STI | |||
5 | select DRM_KMS_HELPER | 5 | select DRM_KMS_HELPER |
6 | select DRM_GEM_CMA_HELPER | 6 | select DRM_GEM_CMA_HELPER |
7 | select DRM_KMS_CMA_HELPER | 7 | select DRM_KMS_CMA_HELPER |
8 | select FW_LOADER_USER_HELPER_FALLBACK | ||
8 | help | 9 | help |
9 | Choose this option to enable DRM on STM stiH41x chipset | 10 | Choose this option to enable DRM on STM stiH41x chipset |
10 | 11 | ||
diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile index 04ac2ceef27f..6ba9d27c1b90 100644 --- a/drivers/gpu/drm/sti/Makefile +++ b/drivers/gpu/drm/sti/Makefile | |||
@@ -3,6 +3,7 @@ sticompositor-y := \ | |||
3 | sti_mixer.o \ | 3 | sti_mixer.o \ |
4 | sti_gdp.o \ | 4 | sti_gdp.o \ |
5 | sti_vid.o \ | 5 | sti_vid.o \ |
6 | sti_cursor.o \ | ||
6 | sti_compositor.o \ | 7 | sti_compositor.o \ |
7 | sti_drm_crtc.o \ | 8 | sti_drm_crtc.o \ |
8 | sti_drm_plane.o | 9 | sti_drm_plane.o |
@@ -18,4 +19,5 @@ obj-$(CONFIG_DRM_STI) = \ | |||
18 | sti_hda.o \ | 19 | sti_hda.o \ |
19 | sti_tvout.o \ | 20 | sti_tvout.o \ |
20 | sticompositor.o \ | 21 | sticompositor.o \ |
21 | sti_drm_drv.o \ No newline at end of file | 22 | sti_hqvdp.o \ |
23 | sti_drm_drv.o | ||
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c index 390d93e9a06c..c5cf4aea9694 100644 --- a/drivers/gpu/drm/sti/sti_compositor.c +++ b/drivers/gpu/drm/sti/sti_compositor.c | |||
@@ -24,14 +24,16 @@ | |||
24 | * stiH407 compositor properties | 24 | * stiH407 compositor properties |
25 | */ | 25 | */ |
26 | struct sti_compositor_data stih407_compositor_data = { | 26 | struct sti_compositor_data stih407_compositor_data = { |
27 | .nb_subdev = 6, | 27 | .nb_subdev = 8, |
28 | .subdev_desc = { | 28 | .subdev_desc = { |
29 | {STI_CURSOR_SUBDEV, (int)STI_CURSOR, 0x000}, | ||
29 | {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100}, | 30 | {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100}, |
30 | {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200}, | 31 | {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200}, |
31 | {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300}, | 32 | {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300}, |
32 | {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400}, | 33 | {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400}, |
33 | {STI_VID_SUBDEV, (int)STI_VID_0, 0x700}, | 34 | {STI_VID_SUBDEV, (int)STI_VID_0, 0x700}, |
34 | {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00} | 35 | {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00}, |
36 | {STI_MIXER_AUX_SUBDEV, STI_MIXER_AUX, 0xD00}, | ||
35 | }, | 37 | }, |
36 | }; | 38 | }; |
37 | 39 | ||
@@ -67,11 +69,11 @@ static int sti_compositor_init_subdev(struct sti_compositor *compo, | |||
67 | break; | 69 | break; |
68 | case STI_GPD_SUBDEV: | 70 | case STI_GPD_SUBDEV: |
69 | case STI_VID_SUBDEV: | 71 | case STI_VID_SUBDEV: |
72 | case STI_CURSOR_SUBDEV: | ||
70 | compo->layer[layer_id++] = | 73 | compo->layer[layer_id++] = |
71 | sti_layer_create(compo->dev, desc[i].id, | 74 | sti_layer_create(compo->dev, desc[i].id, |
72 | compo->regs + desc[i].offset); | 75 | compo->regs + desc[i].offset); |
73 | break; | 76 | break; |
74 | /* case STI_CURSOR_SUBDEV : TODO */ | ||
75 | default: | 77 | default: |
76 | DRM_ERROR("Unknow subdev compoment type\n"); | 78 | DRM_ERROR("Unknow subdev compoment type\n"); |
77 | return 1; | 79 | return 1; |
@@ -102,33 +104,35 @@ static int sti_compositor_bind(struct device *dev, struct device *master, | |||
102 | enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK; | 104 | enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK; |
103 | enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY; | 105 | enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY; |
104 | 106 | ||
105 | if (compo->mixer[crtc]) | 107 | if (crtc < compo->nb_mixers) |
106 | plane_type = DRM_PLANE_TYPE_PRIMARY; | 108 | plane_type = DRM_PLANE_TYPE_PRIMARY; |
107 | 109 | ||
108 | switch (type) { | 110 | switch (type) { |
109 | case STI_CUR: | 111 | case STI_CUR: |
110 | cursor = sti_drm_plane_init(drm_dev, | 112 | cursor = sti_drm_plane_init(drm_dev, |
111 | compo->layer[i], | 113 | compo->layer[i], |
112 | (1 << crtc) - 1, | 114 | 1, DRM_PLANE_TYPE_CURSOR); |
113 | DRM_PLANE_TYPE_CURSOR); | ||
114 | break; | 115 | break; |
115 | case STI_GDP: | 116 | case STI_GDP: |
116 | case STI_VID: | 117 | case STI_VID: |
117 | primary = sti_drm_plane_init(drm_dev, | 118 | primary = sti_drm_plane_init(drm_dev, |
118 | compo->layer[i], | 119 | compo->layer[i], |
119 | (1 << crtc) - 1, plane_type); | 120 | (1 << compo->nb_mixers) - 1, |
121 | plane_type); | ||
120 | plane++; | 122 | plane++; |
121 | break; | 123 | break; |
122 | case STI_BCK: | 124 | case STI_BCK: |
125 | case STI_VDP: | ||
123 | break; | 126 | break; |
124 | } | 127 | } |
125 | 128 | ||
126 | /* The first planes are reserved for primary planes*/ | 129 | /* The first planes are reserved for primary planes*/ |
127 | if (compo->mixer[crtc]) { | 130 | if (crtc < compo->nb_mixers && primary) { |
128 | sti_drm_crtc_init(drm_dev, compo->mixer[crtc], | 131 | sti_drm_crtc_init(drm_dev, compo->mixer[crtc], |
129 | primary, cursor); | 132 | primary, cursor); |
130 | crtc++; | 133 | crtc++; |
131 | cursor = NULL; | 134 | cursor = NULL; |
135 | primary = NULL; | ||
132 | } | 136 | } |
133 | } | 137 | } |
134 | } | 138 | } |
diff --git a/drivers/gpu/drm/sti/sti_compositor.h b/drivers/gpu/drm/sti/sti_compositor.h index 3ea19db72e0f..019eb44c62cc 100644 --- a/drivers/gpu/drm/sti/sti_compositor.h +++ b/drivers/gpu/drm/sti/sti_compositor.h | |||
@@ -64,7 +64,6 @@ struct sti_compositor_data { | |||
64 | * @layer: array of layers | 64 | * @layer: array of layers |
65 | * @nb_mixers: number of mixers for this compositor | 65 | * @nb_mixers: number of mixers for this compositor |
66 | * @nb_layers: number of layers (GDP,VID,...) for this compositor | 66 | * @nb_layers: number of layers (GDP,VID,...) for this compositor |
67 | * @enable: true if compositor is enable else false | ||
68 | * @vtg_vblank_nb: callback for VTG VSYNC notification | 67 | * @vtg_vblank_nb: callback for VTG VSYNC notification |
69 | */ | 68 | */ |
70 | struct sti_compositor { | 69 | struct sti_compositor { |
@@ -83,7 +82,6 @@ struct sti_compositor { | |||
83 | struct sti_layer *layer[STI_MAX_LAYER]; | 82 | struct sti_layer *layer[STI_MAX_LAYER]; |
84 | int nb_mixers; | 83 | int nb_mixers; |
85 | int nb_layers; | 84 | int nb_layers; |
86 | bool enable; | ||
87 | struct notifier_block vtg_vblank_nb; | 85 | struct notifier_block vtg_vblank_nb; |
88 | }; | 86 | }; |
89 | 87 | ||
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c new file mode 100644 index 000000000000..010eaee60bf7 --- /dev/null +++ b/drivers/gpu/drm/sti/sti_cursor.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
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 | ||
7 | */ | ||
8 | #include <drm/drmP.h> | ||
9 | |||
10 | #include "sti_cursor.h" | ||
11 | #include "sti_layer.h" | ||
12 | #include "sti_vtg.h" | ||
13 | |||
14 | /* Registers */ | ||
15 | #define CUR_CTL 0x00 | ||
16 | #define CUR_VPO 0x0C | ||
17 | #define CUR_PML 0x14 | ||
18 | #define CUR_PMP 0x18 | ||
19 | #define CUR_SIZE 0x1C | ||
20 | #define CUR_CML 0x20 | ||
21 | #define CUR_AWS 0x28 | ||
22 | #define CUR_AWE 0x2C | ||
23 | |||
24 | #define CUR_CTL_CLUT_UPDATE BIT(1) | ||
25 | |||
26 | #define STI_CURS_MIN_SIZE 1 | ||
27 | #define STI_CURS_MAX_SIZE 128 | ||
28 | |||
29 | /* | ||
30 | * pixmap dma buffer stucture | ||
31 | * | ||
32 | * @paddr: physical address | ||
33 | * @size: buffer size | ||
34 | * @base: virtual address | ||
35 | */ | ||
36 | struct dma_pixmap { | ||
37 | dma_addr_t paddr; | ||
38 | size_t size; | ||
39 | void *base; | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * STI Cursor structure | ||
44 | * | ||
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) | ||
51 | */ | ||
52 | struct sti_cursor { | ||
53 | struct sti_layer layer; | ||
54 | unsigned int width; | ||
55 | unsigned int height; | ||
56 | unsigned short *clut; | ||
57 | dma_addr_t clut_paddr; | ||
58 | struct dma_pixmap pixmap; | ||
59 | }; | ||
60 | |||
61 | static const uint32_t cursor_supported_formats[] = { | ||
62 | DRM_FORMAT_ARGB8888, | ||
63 | }; | ||
64 | |||
65 | #define to_sti_cursor(x) container_of(x, struct sti_cursor, layer) | ||
66 | |||
67 | static const uint32_t *sti_cursor_get_formats(struct sti_layer *layer) | ||
68 | { | ||
69 | return cursor_supported_formats; | ||
70 | } | ||
71 | |||
72 | static unsigned int sti_cursor_get_nb_formats(struct sti_layer *layer) | ||
73 | { | ||
74 | return ARRAY_SIZE(cursor_supported_formats); | ||
75 | } | ||
76 | |||
77 | static void sti_cursor_argb8888_to_clut8(struct sti_layer *layer) | ||
78 | { | ||
79 | struct sti_cursor *cursor = to_sti_cursor(layer); | ||
80 | u32 *src = layer->vaddr; | ||
81 | u8 *dst = cursor->pixmap.base; | ||
82 | unsigned int i, j; | ||
83 | u32 a, r, g, b; | ||
84 | |||
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 */ | ||
88 | a = (*src >> 30) & 3; | ||
89 | r = (*src >> 22) & 3; | ||
90 | g = (*src >> 14) & 3; | ||
91 | b = (*src >> 6) & 3; | ||
92 | *dst = a << 6 | r << 4 | g << 2 | b; | ||
93 | src++; | ||
94 | dst++; | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | |||
99 | static int sti_cursor_prepare_layer(struct sti_layer *layer, bool first_prepare) | ||
100 | { | ||
101 | struct sti_cursor *cursor = to_sti_cursor(layer); | ||
102 | struct drm_display_mode *mode = layer->mode; | ||
103 | u32 y, x; | ||
104 | u32 val; | ||
105 | |||
106 | DRM_DEBUG_DRIVER("\n"); | ||
107 | |||
108 | dev_dbg(layer->dev, "%s %s\n", __func__, sti_layer_to_str(layer)); | ||
109 | |||
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); | ||
116 | return -EINVAL; | ||
117 | } | ||
118 | |||
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; | ||
125 | |||
126 | if (cursor->pixmap.base) | ||
127 | dma_free_writecombine(layer->dev, | ||
128 | cursor->pixmap.size, | ||
129 | cursor->pixmap.base, | ||
130 | cursor->pixmap.paddr); | ||
131 | |||
132 | cursor->pixmap.size = cursor->width * cursor->height; | ||
133 | |||
134 | cursor->pixmap.base = dma_alloc_writecombine(layer->dev, | ||
135 | cursor->pixmap.size, | ||
136 | &cursor->pixmap.paddr, | ||
137 | GFP_KERNEL | GFP_DMA); | ||
138 | if (!cursor->pixmap.base) { | ||
139 | DRM_ERROR("Failed to allocate memory for pixmap\n"); | ||
140 | return -ENOMEM; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | /* Convert ARGB8888 to CLUT8 */ | ||
145 | sti_cursor_argb8888_to_clut8(layer); | ||
146 | |||
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); | ||
150 | val = y << 16 | x; | ||
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); | ||
154 | val = y << 16 | x; | ||
155 | writel(val, layer->regs + CUR_AWE); | ||
156 | |||
157 | if (first_prepare) { | ||
158 | /* Set and fetch CLUT */ | ||
159 | writel(cursor->clut_paddr, layer->regs + CUR_CML); | ||
160 | writel(CUR_CTL_CLUT_UPDATE, layer->regs + CUR_CTL); | ||
161 | } | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int sti_cursor_commit_layer(struct sti_layer *layer) | ||
167 | { | ||
168 | struct sti_cursor *cursor = to_sti_cursor(layer); | ||
169 | struct drm_display_mode *mode = layer->mode; | ||
170 | u32 ydo, xdo; | ||
171 | |||
172 | dev_dbg(layer->dev, "%s %s\n", __func__, sti_layer_to_str(layer)); | ||
173 | |||
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); | ||
178 | |||
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); | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static int sti_cursor_disable_layer(struct sti_layer *layer) | ||
187 | { | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static void sti_cursor_init(struct sti_layer *layer) | ||
192 | { | ||
193 | struct sti_cursor *cursor = to_sti_cursor(layer); | ||
194 | unsigned short *base = cursor->clut; | ||
195 | unsigned int a, r, g, b; | ||
196 | |||
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 | | ||
203 | (r * 5) << 8 | | ||
204 | (g * 5) << 4 | | ||
205 | (b * 5); | ||
206 | } | ||
207 | |||
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, | ||
215 | }; | ||
216 | |||
217 | struct sti_layer *sti_cursor_create(struct device *dev) | ||
218 | { | ||
219 | struct sti_cursor *cursor; | ||
220 | |||
221 | cursor = devm_kzalloc(dev, sizeof(*cursor), GFP_KERNEL); | ||
222 | if (!cursor) { | ||
223 | DRM_ERROR("Failed to allocate memory for cursor\n"); | ||
224 | return NULL; | ||
225 | } | ||
226 | |||
227 | /* Allocate clut buffer */ | ||
228 | cursor->clut = dma_alloc_writecombine(dev, | ||
229 | 0x100 * sizeof(unsigned short), | ||
230 | &cursor->clut_paddr, | ||
231 | GFP_KERNEL | GFP_DMA); | ||
232 | |||
233 | if (!cursor->clut) { | ||
234 | DRM_ERROR("Failed to allocate memory for cursor clut\n"); | ||
235 | devm_kfree(dev, cursor); | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | cursor->layer.ops = &cursor_ops; | ||
240 | |||
241 | return (struct sti_layer *)cursor; | ||
242 | } | ||
diff --git a/drivers/gpu/drm/sti/sti_cursor.h b/drivers/gpu/drm/sti/sti_cursor.h new file mode 100644 index 000000000000..3c9827404f27 --- /dev/null +++ b/drivers/gpu/drm/sti/sti_cursor.h | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2013 | ||
3 | * Authors: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. | ||
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | ||
6 | |||
7 | #ifndef _STI_CURSOR_H_ | ||
8 | #define _STI_CURSOR_H_ | ||
9 | |||
10 | struct sti_layer *sti_cursor_create(struct device *dev); | ||
11 | |||
12 | #endif | ||
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index 36a1ad3c4823..4c651c200f20 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c | |||
@@ -28,7 +28,7 @@ static void sti_drm_crtc_prepare(struct drm_crtc *crtc) | |||
28 | struct device *dev = mixer->dev; | 28 | struct device *dev = mixer->dev; |
29 | struct sti_compositor *compo = dev_get_drvdata(dev); | 29 | struct sti_compositor *compo = dev_get_drvdata(dev); |
30 | 30 | ||
31 | compo->enable = true; | 31 | mixer->enabled = true; |
32 | 32 | ||
33 | /* Prepare and enable the compo IP clock */ | 33 | /* Prepare and enable the compo IP clock */ |
34 | if (mixer->id == STI_MIXER_MAIN) { | 34 | if (mixer->id == STI_MIXER_MAIN) { |
@@ -38,6 +38,8 @@ static void sti_drm_crtc_prepare(struct drm_crtc *crtc) | |||
38 | if (clk_prepare_enable(compo->clk_compo_aux)) | 38 | if (clk_prepare_enable(compo->clk_compo_aux)) |
39 | DRM_INFO("Failed to prepare/enable compo_aux clk\n"); | 39 | DRM_INFO("Failed to prepare/enable compo_aux clk\n"); |
40 | } | 40 | } |
41 | |||
42 | sti_mixer_clear_all_layers(mixer); | ||
41 | } | 43 | } |
42 | 44 | ||
43 | static void sti_drm_crtc_commit(struct drm_crtc *crtc) | 45 | static void sti_drm_crtc_commit(struct drm_crtc *crtc) |
@@ -62,6 +64,8 @@ static void sti_drm_crtc_commit(struct drm_crtc *crtc) | |||
62 | /* Enable layer on mixer */ | 64 | /* Enable layer on mixer */ |
63 | if (sti_mixer_set_layer_status(mixer, layer, true)) | 65 | if (sti_mixer_set_layer_status(mixer, layer, true)) |
64 | DRM_ERROR("Can not enable layer at mixer\n"); | 66 | DRM_ERROR("Can not enable layer at mixer\n"); |
67 | |||
68 | drm_crtc_vblank_on(crtc); | ||
65 | } | 69 | } |
66 | 70 | ||
67 | static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc, | 71 | static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc, |
@@ -144,7 +148,8 @@ sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
144 | w = crtc->primary->fb->width - x; | 148 | w = crtc->primary->fb->width - x; |
145 | h = crtc->primary->fb->height - y; | 149 | h = crtc->primary->fb->height - y; |
146 | 150 | ||
147 | return sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode, | 151 | return sti_layer_prepare(layer, crtc, |
152 | crtc->primary->fb, &crtc->mode, | ||
148 | mixer->id, 0, 0, w, h, x, y, w, h); | 153 | mixer->id, 0, 0, w, h, x, y, w, h); |
149 | } | 154 | } |
150 | 155 | ||
@@ -171,7 +176,8 @@ static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
171 | w = crtc->primary->fb->width - crtc->x; | 176 | w = crtc->primary->fb->width - crtc->x; |
172 | h = crtc->primary->fb->height - crtc->y; | 177 | h = crtc->primary->fb->height - crtc->y; |
173 | 178 | ||
174 | ret = sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode, | 179 | ret = sti_layer_prepare(layer, crtc, |
180 | crtc->primary->fb, &crtc->mode, | ||
175 | mixer->id, 0, 0, w, h, | 181 | mixer->id, 0, 0, w, h, |
176 | crtc->x, crtc->y, w, h); | 182 | crtc->x, crtc->y, w, h); |
177 | if (ret) { | 183 | if (ret) { |
@@ -196,7 +202,7 @@ static void sti_drm_crtc_disable(struct drm_crtc *crtc) | |||
196 | struct sti_compositor *compo = dev_get_drvdata(dev); | 202 | struct sti_compositor *compo = dev_get_drvdata(dev); |
197 | struct sti_layer *layer; | 203 | struct sti_layer *layer; |
198 | 204 | ||
199 | if (!compo->enable) | 205 | if (!mixer->enabled) |
200 | return; | 206 | return; |
201 | 207 | ||
202 | DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer)); | 208 | DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer)); |
@@ -222,7 +228,7 @@ static void sti_drm_crtc_disable(struct drm_crtc *crtc) | |||
222 | /* Then disable layer itself */ | 228 | /* Then disable layer itself */ |
223 | sti_layer_disable(layer); | 229 | sti_layer_disable(layer); |
224 | 230 | ||
225 | drm_vblank_off(crtc->dev, mixer->id); | 231 | drm_crtc_vblank_off(crtc); |
226 | 232 | ||
227 | /* Disable pixel clock and compo IP clocks */ | 233 | /* Disable pixel clock and compo IP clocks */ |
228 | if (mixer->id == STI_MIXER_MAIN) { | 234 | if (mixer->id == STI_MIXER_MAIN) { |
@@ -233,7 +239,7 @@ static void sti_drm_crtc_disable(struct drm_crtc *crtc) | |||
233 | clk_disable_unprepare(compo->clk_compo_aux); | 239 | clk_disable_unprepare(compo->clk_compo_aux); |
234 | } | 240 | } |
235 | 241 | ||
236 | compo->enable = false; | 242 | mixer->enabled = false; |
237 | } | 243 | } |
238 | 244 | ||
239 | static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { | 245 | static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { |
@@ -364,7 +370,6 @@ void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) | |||
364 | struct sti_drm_private *priv = dev->dev_private; | 370 | struct sti_drm_private *priv = dev->dev_private; |
365 | struct sti_compositor *compo = priv->compo; | 371 | struct sti_compositor *compo = priv->compo; |
366 | struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; | 372 | struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb; |
367 | unsigned long flags; | ||
368 | 373 | ||
369 | DRM_DEBUG_DRIVER("\n"); | 374 | DRM_DEBUG_DRIVER("\n"); |
370 | 375 | ||
@@ -373,13 +378,10 @@ void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) | |||
373 | DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); | 378 | DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); |
374 | 379 | ||
375 | /* free the resources of the pending requests */ | 380 | /* free the resources of the pending requests */ |
376 | spin_lock_irqsave(&dev->event_lock, flags); | ||
377 | if (compo->mixer[crtc]->pending_event) { | 381 | if (compo->mixer[crtc]->pending_event) { |
378 | drm_vblank_put(dev, crtc); | 382 | drm_vblank_put(dev, crtc); |
379 | compo->mixer[crtc]->pending_event = NULL; | 383 | compo->mixer[crtc]->pending_event = NULL; |
380 | } | 384 | } |
381 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
382 | |||
383 | } | 385 | } |
384 | EXPORT_SYMBOL(sti_drm_crtc_disable_vblank); | 386 | EXPORT_SYMBOL(sti_drm_crtc_disable_vblank); |
385 | 387 | ||
@@ -399,6 +401,7 @@ bool sti_drm_crtc_is_main(struct drm_crtc *crtc) | |||
399 | 401 | ||
400 | return false; | 402 | return false; |
401 | } | 403 | } |
404 | EXPORT_SYMBOL(sti_drm_crtc_is_main); | ||
402 | 405 | ||
403 | int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer, | 406 | int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer, |
404 | struct drm_plane *primary, struct drm_plane *cursor) | 407 | struct drm_plane *primary, struct drm_plane *cursor) |
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.c b/drivers/gpu/drm/sti/sti_drm_drv.c index 223d93c3a05d..9ce7574ac873 100644 --- a/drivers/gpu/drm/sti/sti_drm_drv.c +++ b/drivers/gpu/drm/sti/sti_drm_drv.c | |||
@@ -67,8 +67,12 @@ static int sti_drm_load(struct drm_device *dev, unsigned long flags) | |||
67 | sti_drm_mode_config_init(dev); | 67 | sti_drm_mode_config_init(dev); |
68 | 68 | ||
69 | ret = component_bind_all(dev->dev, dev); | 69 | ret = component_bind_all(dev->dev, dev); |
70 | if (ret) | 70 | if (ret) { |
71 | drm_kms_helper_poll_fini(dev); | ||
72 | drm_mode_config_cleanup(dev); | ||
73 | kfree(private); | ||
71 | return ret; | 74 | return ret; |
75 | } | ||
72 | 76 | ||
73 | drm_helper_disable_unused_functions(dev); | 77 | drm_helper_disable_unused_functions(dev); |
74 | 78 | ||
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c index f4118d4cac22..c9dd0e57cac1 100644 --- a/drivers/gpu/drm/sti/sti_drm_plane.c +++ b/drivers/gpu/drm/sti/sti_drm_plane.c | |||
@@ -45,7 +45,8 @@ sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
45 | } | 45 | } |
46 | 46 | ||
47 | /* src_x are in 16.16 format. */ | 47 | /* src_x are in 16.16 format. */ |
48 | res = sti_layer_prepare(layer, fb, &crtc->mode, mixer->id, | 48 | res = sti_layer_prepare(layer, crtc, fb, |
49 | &crtc->mode, mixer->id, | ||
49 | crtc_x, crtc_y, crtc_w, crtc_h, | 50 | crtc_x, crtc_y, crtc_w, crtc_h, |
50 | src_x >> 16, src_y >> 16, | 51 | src_x >> 16, src_y >> 16, |
51 | src_w >> 16, src_h >> 16); | 52 | src_w >> 16, src_h >> 16); |
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 4e30b74559f5..32448d1d1e8f 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c | |||
@@ -73,7 +73,9 @@ struct sti_gdp_node { | |||
73 | 73 | ||
74 | struct sti_gdp_node_list { | 74 | struct sti_gdp_node_list { |
75 | struct sti_gdp_node *top_field; | 75 | struct sti_gdp_node *top_field; |
76 | dma_addr_t top_field_paddr; | ||
76 | struct sti_gdp_node *btm_field; | 77 | struct sti_gdp_node *btm_field; |
78 | dma_addr_t btm_field_paddr; | ||
77 | }; | 79 | }; |
78 | 80 | ||
79 | /** | 81 | /** |
@@ -81,6 +83,8 @@ struct sti_gdp_node_list { | |||
81 | * | 83 | * |
82 | * @layer: layer structure | 84 | * @layer: layer structure |
83 | * @clk_pix: pixel clock for the current gdp | 85 | * @clk_pix: pixel clock for the current gdp |
86 | * @clk_main_parent: gdp parent clock if main path used | ||
87 | * @clk_aux_parent: gdp parent clock if aux path used | ||
84 | * @vtg_field_nb: callback for VTG FIELD (top or bottom) notification | 88 | * @vtg_field_nb: callback for VTG FIELD (top or bottom) notification |
85 | * @is_curr_top: true if the current node processed is the top field | 89 | * @is_curr_top: true if the current node processed is the top field |
86 | * @node_list: array of node list | 90 | * @node_list: array of node list |
@@ -88,6 +92,8 @@ struct sti_gdp_node_list { | |||
88 | struct sti_gdp { | 92 | struct sti_gdp { |
89 | struct sti_layer layer; | 93 | struct sti_layer layer; |
90 | struct clk *clk_pix; | 94 | struct clk *clk_pix; |
95 | struct clk *clk_main_parent; | ||
96 | struct clk *clk_aux_parent; | ||
91 | struct notifier_block vtg_field_nb; | 97 | struct notifier_block vtg_field_nb; |
92 | bool is_curr_top; | 98 | bool is_curr_top; |
93 | struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK]; | 99 | struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK]; |
@@ -168,7 +174,6 @@ static int sti_gdp_get_alpharange(int format) | |||
168 | static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer) | 174 | static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer) |
169 | { | 175 | { |
170 | int hw_nvn; | 176 | int hw_nvn; |
171 | void *virt_nvn; | ||
172 | struct sti_gdp *gdp = to_sti_gdp(layer); | 177 | struct sti_gdp *gdp = to_sti_gdp(layer); |
173 | unsigned int i; | 178 | unsigned int i; |
174 | 179 | ||
@@ -176,11 +181,9 @@ static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer) | |||
176 | if (!hw_nvn) | 181 | if (!hw_nvn) |
177 | goto end; | 182 | goto end; |
178 | 183 | ||
179 | virt_nvn = dma_to_virt(layer->dev, (dma_addr_t) hw_nvn); | ||
180 | |||
181 | for (i = 0; i < GDP_NODE_NB_BANK; i++) | 184 | for (i = 0; i < GDP_NODE_NB_BANK; i++) |
182 | if ((virt_nvn != gdp->node_list[i].btm_field) && | 185 | if ((hw_nvn != gdp->node_list[i].btm_field_paddr) && |
183 | (virt_nvn != gdp->node_list[i].top_field)) | 186 | (hw_nvn != gdp->node_list[i].top_field_paddr)) |
184 | return &gdp->node_list[i]; | 187 | return &gdp->node_list[i]; |
185 | 188 | ||
186 | /* in hazardious cases restart with the first node */ | 189 | /* in hazardious cases restart with the first node */ |
@@ -204,7 +207,6 @@ static | |||
204 | struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer) | 207 | struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer) |
205 | { | 208 | { |
206 | int hw_nvn; | 209 | int hw_nvn; |
207 | void *virt_nvn; | ||
208 | struct sti_gdp *gdp = to_sti_gdp(layer); | 210 | struct sti_gdp *gdp = to_sti_gdp(layer); |
209 | unsigned int i; | 211 | unsigned int i; |
210 | 212 | ||
@@ -212,11 +214,9 @@ struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer) | |||
212 | if (!hw_nvn) | 214 | if (!hw_nvn) |
213 | goto end; | 215 | goto end; |
214 | 216 | ||
215 | virt_nvn = dma_to_virt(layer->dev, (dma_addr_t) hw_nvn); | ||
216 | |||
217 | for (i = 0; i < GDP_NODE_NB_BANK; i++) | 217 | for (i = 0; i < GDP_NODE_NB_BANK; i++) |
218 | if ((virt_nvn == gdp->node_list[i].btm_field) || | 218 | if ((hw_nvn == gdp->node_list[i].btm_field_paddr) || |
219 | (virt_nvn == gdp->node_list[i].top_field)) | 219 | (hw_nvn == gdp->node_list[i].top_field_paddr)) |
220 | return &gdp->node_list[i]; | 220 | return &gdp->node_list[i]; |
221 | 221 | ||
222 | end: | 222 | end: |
@@ -292,8 +292,8 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare) | |||
292 | 292 | ||
293 | /* Same content and chained together */ | 293 | /* Same content and chained together */ |
294 | memcpy(btm_field, top_field, sizeof(*btm_field)); | 294 | memcpy(btm_field, top_field, sizeof(*btm_field)); |
295 | top_field->gam_gdp_nvn = virt_to_dma(dev, btm_field); | 295 | top_field->gam_gdp_nvn = list->btm_field_paddr; |
296 | btm_field->gam_gdp_nvn = virt_to_dma(dev, top_field); | 296 | btm_field->gam_gdp_nvn = list->top_field_paddr; |
297 | 297 | ||
298 | /* Interlaced mode */ | 298 | /* Interlaced mode */ |
299 | if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE) | 299 | if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE) |
@@ -311,6 +311,17 @@ static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare) | |||
311 | 311 | ||
312 | /* Set and enable gdp clock */ | 312 | /* Set and enable gdp clock */ |
313 | if (gdp->clk_pix) { | 313 | if (gdp->clk_pix) { |
314 | struct clk *clkp; | ||
315 | /* According to the mixer used, the gdp pixel clock | ||
316 | * should have a different parent clock. */ | ||
317 | if (layer->mixer_id == STI_MIXER_MAIN) | ||
318 | clkp = gdp->clk_main_parent; | ||
319 | else | ||
320 | clkp = gdp->clk_aux_parent; | ||
321 | |||
322 | if (clkp) | ||
323 | clk_set_parent(gdp->clk_pix, clkp); | ||
324 | |||
314 | res = clk_set_rate(gdp->clk_pix, rate); | 325 | res = clk_set_rate(gdp->clk_pix, rate); |
315 | if (res < 0) { | 326 | if (res < 0) { |
316 | DRM_ERROR("Cannot set rate (%dHz) for gdp\n", | 327 | DRM_ERROR("Cannot set rate (%dHz) for gdp\n", |
@@ -349,8 +360,8 @@ static int sti_gdp_commit_layer(struct sti_layer *layer) | |||
349 | struct sti_gdp_node *updated_top_node = updated_list->top_field; | 360 | struct sti_gdp_node *updated_top_node = updated_list->top_field; |
350 | struct sti_gdp_node *updated_btm_node = updated_list->btm_field; | 361 | struct sti_gdp_node *updated_btm_node = updated_list->btm_field; |
351 | struct sti_gdp *gdp = to_sti_gdp(layer); | 362 | struct sti_gdp *gdp = to_sti_gdp(layer); |
352 | u32 dma_updated_top = virt_to_dma(layer->dev, updated_top_node); | 363 | u32 dma_updated_top = updated_list->top_field_paddr; |
353 | u32 dma_updated_btm = virt_to_dma(layer->dev, updated_btm_node); | 364 | u32 dma_updated_btm = updated_list->btm_field_paddr; |
354 | struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(layer); | 365 | struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(layer); |
355 | 366 | ||
356 | dev_dbg(layer->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__, | 367 | dev_dbg(layer->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__, |
@@ -461,16 +472,16 @@ static void sti_gdp_init(struct sti_layer *layer) | |||
461 | { | 472 | { |
462 | struct sti_gdp *gdp = to_sti_gdp(layer); | 473 | struct sti_gdp *gdp = to_sti_gdp(layer); |
463 | struct device_node *np = layer->dev->of_node; | 474 | struct device_node *np = layer->dev->of_node; |
464 | dma_addr_t dma; | 475 | dma_addr_t dma_addr; |
465 | void *base; | 476 | void *base; |
466 | unsigned int i, size; | 477 | unsigned int i, size; |
467 | 478 | ||
468 | /* Allocate all the nodes within a single memory page */ | 479 | /* Allocate all the nodes within a single memory page */ |
469 | size = sizeof(struct sti_gdp_node) * | 480 | size = sizeof(struct sti_gdp_node) * |
470 | GDP_NODE_PER_FIELD * GDP_NODE_NB_BANK; | 481 | GDP_NODE_PER_FIELD * GDP_NODE_NB_BANK; |
471 | |||
472 | base = dma_alloc_writecombine(layer->dev, | 482 | base = dma_alloc_writecombine(layer->dev, |
473 | size, &dma, GFP_KERNEL | GFP_DMA); | 483 | size, &dma_addr, GFP_KERNEL | GFP_DMA); |
484 | |||
474 | if (!base) { | 485 | if (!base) { |
475 | DRM_ERROR("Failed to allocate memory for GDP node\n"); | 486 | DRM_ERROR("Failed to allocate memory for GDP node\n"); |
476 | return; | 487 | return; |
@@ -478,21 +489,26 @@ static void sti_gdp_init(struct sti_layer *layer) | |||
478 | memset(base, 0, size); | 489 | memset(base, 0, size); |
479 | 490 | ||
480 | for (i = 0; i < GDP_NODE_NB_BANK; i++) { | 491 | for (i = 0; i < GDP_NODE_NB_BANK; i++) { |
481 | if (virt_to_dma(layer->dev, base) & 0xF) { | 492 | if (dma_addr & 0xF) { |
482 | DRM_ERROR("Mem alignment failed\n"); | 493 | DRM_ERROR("Mem alignment failed\n"); |
483 | return; | 494 | return; |
484 | } | 495 | } |
485 | gdp->node_list[i].top_field = base; | 496 | gdp->node_list[i].top_field = base; |
497 | gdp->node_list[i].top_field_paddr = dma_addr; | ||
498 | |||
486 | DRM_DEBUG_DRIVER("node[%d].top_field=%p\n", i, base); | 499 | DRM_DEBUG_DRIVER("node[%d].top_field=%p\n", i, base); |
487 | base += sizeof(struct sti_gdp_node); | 500 | base += sizeof(struct sti_gdp_node); |
501 | dma_addr += sizeof(struct sti_gdp_node); | ||
488 | 502 | ||
489 | if (virt_to_dma(layer->dev, base) & 0xF) { | 503 | if (dma_addr & 0xF) { |
490 | DRM_ERROR("Mem alignment failed\n"); | 504 | DRM_ERROR("Mem alignment failed\n"); |
491 | return; | 505 | return; |
492 | } | 506 | } |
493 | gdp->node_list[i].btm_field = base; | 507 | gdp->node_list[i].btm_field = base; |
508 | gdp->node_list[i].btm_field_paddr = dma_addr; | ||
494 | DRM_DEBUG_DRIVER("node[%d].btm_field=%p\n", i, base); | 509 | DRM_DEBUG_DRIVER("node[%d].btm_field=%p\n", i, base); |
495 | base += sizeof(struct sti_gdp_node); | 510 | base += sizeof(struct sti_gdp_node); |
511 | dma_addr += sizeof(struct sti_gdp_node); | ||
496 | } | 512 | } |
497 | 513 | ||
498 | if (of_device_is_compatible(np, "st,stih407-compositor")) { | 514 | if (of_device_is_compatible(np, "st,stih407-compositor")) { |
@@ -520,6 +536,14 @@ static void sti_gdp_init(struct sti_layer *layer) | |||
520 | gdp->clk_pix = devm_clk_get(layer->dev, clk_name); | 536 | gdp->clk_pix = devm_clk_get(layer->dev, clk_name); |
521 | if (IS_ERR(gdp->clk_pix)) | 537 | if (IS_ERR(gdp->clk_pix)) |
522 | DRM_ERROR("Cannot get %s clock\n", clk_name); | 538 | DRM_ERROR("Cannot get %s clock\n", clk_name); |
539 | |||
540 | gdp->clk_main_parent = devm_clk_get(layer->dev, "main_parent"); | ||
541 | if (IS_ERR(gdp->clk_main_parent)) | ||
542 | DRM_ERROR("Cannot get main_parent clock\n"); | ||
543 | |||
544 | gdp->clk_aux_parent = devm_clk_get(layer->dev, "aux_parent"); | ||
545 | if (IS_ERR(gdp->clk_aux_parent)) | ||
546 | DRM_ERROR("Cannot get aux_parent clock\n"); | ||
523 | } | 547 | } |
524 | } | 548 | } |
525 | 549 | ||
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index b22968c08d1f..d032e024b0b8 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c | |||
@@ -130,8 +130,7 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg) | |||
130 | 130 | ||
131 | /* Hot plug/unplug IRQ */ | 131 | /* Hot plug/unplug IRQ */ |
132 | if (hdmi->irq_status & HDMI_INT_HOT_PLUG) { | 132 | if (hdmi->irq_status & HDMI_INT_HOT_PLUG) { |
133 | /* read gpio to get the status */ | 133 | hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG; |
134 | hdmi->hpd = gpio_get_value(hdmi->hpd_gpio); | ||
135 | if (hdmi->drm_dev) | 134 | if (hdmi->drm_dev) |
136 | drm_helper_hpd_irq_event(hdmi->drm_dev); | 135 | drm_helper_hpd_irq_event(hdmi->drm_dev); |
137 | } | 136 | } |
@@ -273,31 +272,32 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi) | |||
273 | hdmi_write(hdmi, val, HDMI_SW_DI_CFG); | 272 | hdmi_write(hdmi, val, HDMI_SW_DI_CFG); |
274 | 273 | ||
275 | /* Infoframe header */ | 274 | /* Infoframe header */ |
276 | val = buffer[0x0]; | 275 | val = buffer[0]; |
277 | val |= buffer[0x1] << 8; | 276 | val |= buffer[1] << 8; |
278 | val |= buffer[0x2] << 16; | 277 | val |= buffer[2] << 16; |
279 | hdmi_write(hdmi, val, HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI)); | 278 | hdmi_write(hdmi, val, HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI)); |
280 | 279 | ||
281 | /* Infoframe packet bytes */ | 280 | /* Infoframe packet bytes */ |
282 | val = frame[0x0]; | 281 | val = buffer[3]; |
283 | val |= frame[0x1] << 8; | 282 | val |= *(frame++) << 8; |
284 | val |= frame[0x2] << 16; | 283 | val |= *(frame++) << 16; |
285 | val |= frame[0x3] << 24; | 284 | val |= *(frame++) << 24; |
286 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI)); | 285 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI)); |
287 | 286 | ||
288 | val = frame[0x4]; | 287 | val = *(frame++); |
289 | val |= frame[0x5] << 8; | 288 | val |= *(frame++) << 8; |
290 | val |= frame[0x6] << 16; | 289 | val |= *(frame++) << 16; |
291 | val |= frame[0x7] << 24; | 290 | val |= *(frame++) << 24; |
292 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI)); | 291 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI)); |
293 | 292 | ||
294 | val = frame[0x8]; | 293 | val = *(frame++); |
295 | val |= frame[0x9] << 8; | 294 | val |= *(frame++) << 8; |
296 | val |= frame[0xA] << 16; | 295 | val |= *(frame++) << 16; |
297 | val |= frame[0xB] << 24; | 296 | val |= *(frame++) << 24; |
298 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI)); | 297 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI)); |
299 | 298 | ||
300 | val = frame[0xC]; | 299 | val = *(frame++); |
300 | val |= *(frame) << 8; | ||
301 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI)); | 301 | hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI)); |
302 | 302 | ||
303 | /* Enable transmission slot for AVI infoframe | 303 | /* Enable transmission slot for AVI infoframe |
@@ -480,17 +480,15 @@ static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = { | |||
480 | 480 | ||
481 | static int sti_hdmi_connector_get_modes(struct drm_connector *connector) | 481 | static int sti_hdmi_connector_get_modes(struct drm_connector *connector) |
482 | { | 482 | { |
483 | struct i2c_adapter *i2c_adap; | 483 | struct sti_hdmi_connector *hdmi_connector |
484 | = to_sti_hdmi_connector(connector); | ||
485 | struct sti_hdmi *hdmi = hdmi_connector->hdmi; | ||
484 | struct edid *edid; | 486 | struct edid *edid; |
485 | int count; | 487 | int count; |
486 | 488 | ||
487 | DRM_DEBUG_DRIVER("\n"); | 489 | DRM_DEBUG_DRIVER("\n"); |
488 | 490 | ||
489 | i2c_adap = i2c_get_adapter(1); | 491 | edid = drm_get_edid(connector, hdmi->ddc_adapt); |
490 | if (!i2c_adap) | ||
491 | goto fail; | ||
492 | |||
493 | edid = drm_get_edid(connector, i2c_adap); | ||
494 | if (!edid) | 492 | if (!edid) |
495 | goto fail; | 493 | goto fail; |
496 | 494 | ||
@@ -603,29 +601,38 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) | |||
603 | struct sti_hdmi_connector *connector; | 601 | struct sti_hdmi_connector *connector; |
604 | struct drm_connector *drm_connector; | 602 | struct drm_connector *drm_connector; |
605 | struct drm_bridge *bridge; | 603 | struct drm_bridge *bridge; |
606 | struct i2c_adapter *i2c_adap; | 604 | struct device_node *ddc; |
607 | int err; | 605 | int err; |
608 | 606 | ||
609 | i2c_adap = i2c_get_adapter(1); | 607 | ddc = of_parse_phandle(dev->of_node, "ddc", 0); |
610 | if (!i2c_adap) | 608 | if (ddc) { |
611 | return -EPROBE_DEFER; | 609 | hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc); |
610 | if (!hdmi->ddc_adapt) { | ||
611 | err = -EPROBE_DEFER; | ||
612 | of_node_put(ddc); | ||
613 | return err; | ||
614 | } | ||
615 | |||
616 | of_node_put(ddc); | ||
617 | } | ||
612 | 618 | ||
613 | /* Set the drm device handle */ | 619 | /* Set the drm device handle */ |
614 | hdmi->drm_dev = drm_dev; | 620 | hdmi->drm_dev = drm_dev; |
615 | 621 | ||
616 | encoder = sti_hdmi_find_encoder(drm_dev); | 622 | encoder = sti_hdmi_find_encoder(drm_dev); |
617 | if (!encoder) | 623 | if (!encoder) |
618 | return -ENOMEM; | 624 | goto err_adapt; |
619 | 625 | ||
620 | connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); | 626 | connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); |
621 | if (!connector) | 627 | if (!connector) |
622 | return -ENOMEM; | 628 | goto err_adapt; |
629 | |||
623 | 630 | ||
624 | connector->hdmi = hdmi; | 631 | connector->hdmi = hdmi; |
625 | 632 | ||
626 | bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); | 633 | bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); |
627 | if (!bridge) | 634 | if (!bridge) |
628 | return -ENOMEM; | 635 | goto err_adapt; |
629 | 636 | ||
630 | bridge->driver_private = hdmi; | 637 | bridge->driver_private = hdmi; |
631 | drm_bridge_init(drm_dev, bridge, &sti_hdmi_bridge_funcs); | 638 | drm_bridge_init(drm_dev, bridge, &sti_hdmi_bridge_funcs); |
@@ -662,6 +669,8 @@ err_sysfs: | |||
662 | err_connector: | 669 | err_connector: |
663 | drm_bridge_cleanup(bridge); | 670 | drm_bridge_cleanup(bridge); |
664 | drm_connector_cleanup(drm_connector); | 671 | drm_connector_cleanup(drm_connector); |
672 | err_adapt: | ||
673 | put_device(&hdmi->ddc_adapt->dev); | ||
665 | return -EINVAL; | 674 | return -EINVAL; |
666 | } | 675 | } |
667 | 676 | ||
@@ -757,13 +766,7 @@ static int sti_hdmi_probe(struct platform_device *pdev) | |||
757 | return PTR_ERR(hdmi->clk_audio); | 766 | return PTR_ERR(hdmi->clk_audio); |
758 | } | 767 | } |
759 | 768 | ||
760 | hdmi->hpd_gpio = of_get_named_gpio(np, "hdmi,hpd-gpio", 0); | 769 | hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG; |
761 | if (hdmi->hpd_gpio < 0) { | ||
762 | DRM_ERROR("Failed to get hdmi hpd-gpio\n"); | ||
763 | return -EIO; | ||
764 | } | ||
765 | |||
766 | hdmi->hpd = gpio_get_value(hdmi->hpd_gpio); | ||
767 | 770 | ||
768 | init_waitqueue_head(&hdmi->wait_event); | 771 | init_waitqueue_head(&hdmi->wait_event); |
769 | 772 | ||
@@ -788,6 +791,11 @@ static int sti_hdmi_probe(struct platform_device *pdev) | |||
788 | 791 | ||
789 | static int sti_hdmi_remove(struct platform_device *pdev) | 792 | static int sti_hdmi_remove(struct platform_device *pdev) |
790 | { | 793 | { |
794 | struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev); | ||
795 | |||
796 | if (hdmi->ddc_adapt) | ||
797 | put_device(&hdmi->ddc_adapt->dev); | ||
798 | |||
791 | component_del(&pdev->dev, &sti_hdmi_ops); | 799 | component_del(&pdev->dev, &sti_hdmi_ops); |
792 | return 0; | 800 | return 0; |
793 | } | 801 | } |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h index 61bec6557ceb..3d22390e1f3b 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.h +++ b/drivers/gpu/drm/sti/sti_hdmi.h | |||
@@ -14,6 +14,9 @@ | |||
14 | #define HDMI_STA 0x0010 | 14 | #define HDMI_STA 0x0010 |
15 | #define HDMI_STA_DLL_LCK BIT(5) | 15 | #define HDMI_STA_DLL_LCK BIT(5) |
16 | 16 | ||
17 | #define HDMI_STA_HOT_PLUG_SHIFT 4 | ||
18 | #define HDMI_STA_HOT_PLUG (1 << HDMI_STA_HOT_PLUG_SHIFT) | ||
19 | |||
17 | struct sti_hdmi; | 20 | struct sti_hdmi; |
18 | 21 | ||
19 | struct hdmi_phy_ops { | 22 | struct hdmi_phy_ops { |
@@ -37,7 +40,6 @@ struct hdmi_phy_ops { | |||
37 | * @irq_status: interrupt status register | 40 | * @irq_status: interrupt status register |
38 | * @phy_ops: phy start/stop operations | 41 | * @phy_ops: phy start/stop operations |
39 | * @enabled: true if hdmi is enabled else false | 42 | * @enabled: true if hdmi is enabled else false |
40 | * @hpd_gpio: hdmi hot plug detect gpio number | ||
41 | * @hpd: hot plug detect status | 43 | * @hpd: hot plug detect status |
42 | * @wait_event: wait event | 44 | * @wait_event: wait event |
43 | * @event_received: wait event status | 45 | * @event_received: wait event status |
@@ -57,11 +59,11 @@ struct sti_hdmi { | |||
57 | u32 irq_status; | 59 | u32 irq_status; |
58 | struct hdmi_phy_ops *phy_ops; | 60 | struct hdmi_phy_ops *phy_ops; |
59 | bool enabled; | 61 | bool enabled; |
60 | int hpd_gpio; | ||
61 | bool hpd; | 62 | bool hpd; |
62 | wait_queue_head_t wait_event; | 63 | wait_queue_head_t wait_event; |
63 | bool event_received; | 64 | bool event_received; |
64 | struct reset_control *reset; | 65 | struct reset_control *reset; |
66 | struct i2c_adapter *ddc_adapt; | ||
65 | }; | 67 | }; |
66 | 68 | ||
67 | u32 hdmi_read(struct sti_hdmi *hdmi, int offset); | 69 | u32 hdmi_read(struct sti_hdmi *hdmi, int offset); |
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c new file mode 100644 index 000000000000..200d02014575 --- /dev/null +++ b/drivers/gpu/drm/sti/sti_hqvdp.c | |||
@@ -0,0 +1,1072 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2014 | ||
3 | * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | ||
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/clk.h> | ||
8 | #include <linux/component.h> | ||
9 | #include <linux/firmware.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/reset.h> | ||
13 | |||
14 | #include <drm/drmP.h> | ||
15 | |||
16 | #include "sti_drm_plane.h" | ||
17 | #include "sti_hqvdp.h" | ||
18 | #include "sti_hqvdp_lut.h" | ||
19 | #include "sti_layer.h" | ||
20 | #include "sti_vtg.h" | ||
21 | |||
22 | /* Firmware name */ | ||
23 | #define HQVDP_FMW_NAME "hqvdp-stih407.bin" | ||
24 | |||
25 | /* Regs address */ | ||
26 | #define HQVDP_DMEM 0x00000000 /* 0x00000000 */ | ||
27 | #define HQVDP_PMEM 0x00040000 /* 0x00040000 */ | ||
28 | #define HQVDP_RD_PLUG 0x000E0000 /* 0x000E0000 */ | ||
29 | #define HQVDP_RD_PLUG_CONTROL (HQVDP_RD_PLUG + 0x1000) /* 0x000E1000 */ | ||
30 | #define HQVDP_RD_PLUG_PAGE_SIZE (HQVDP_RD_PLUG + 0x1004) /* 0x000E1004 */ | ||
31 | #define HQVDP_RD_PLUG_MIN_OPC (HQVDP_RD_PLUG + 0x1008) /* 0x000E1008 */ | ||
32 | #define HQVDP_RD_PLUG_MAX_OPC (HQVDP_RD_PLUG + 0x100C) /* 0x000E100C */ | ||
33 | #define HQVDP_RD_PLUG_MAX_CHK (HQVDP_RD_PLUG + 0x1010) /* 0x000E1010 */ | ||
34 | #define HQVDP_RD_PLUG_MAX_MSG (HQVDP_RD_PLUG + 0x1014) /* 0x000E1014 */ | ||
35 | #define HQVDP_RD_PLUG_MIN_SPACE (HQVDP_RD_PLUG + 0x1018) /* 0x000E1018 */ | ||
36 | #define HQVDP_WR_PLUG 0x000E2000 /* 0x000E2000 */ | ||
37 | #define HQVDP_WR_PLUG_CONTROL (HQVDP_WR_PLUG + 0x1000) /* 0x000E3000 */ | ||
38 | #define HQVDP_WR_PLUG_PAGE_SIZE (HQVDP_WR_PLUG + 0x1004) /* 0x000E3004 */ | ||
39 | #define HQVDP_WR_PLUG_MIN_OPC (HQVDP_WR_PLUG + 0x1008) /* 0x000E3008 */ | ||
40 | #define HQVDP_WR_PLUG_MAX_OPC (HQVDP_WR_PLUG + 0x100C) /* 0x000E300C */ | ||
41 | #define HQVDP_WR_PLUG_MAX_CHK (HQVDP_WR_PLUG + 0x1010) /* 0x000E3010 */ | ||
42 | #define HQVDP_WR_PLUG_MAX_MSG (HQVDP_WR_PLUG + 0x1014) /* 0x000E3014 */ | ||
43 | #define HQVDP_WR_PLUG_MIN_SPACE (HQVDP_WR_PLUG + 0x1018) /* 0x000E3018 */ | ||
44 | #define HQVDP_MBX 0x000E4000 /* 0x000E4000 */ | ||
45 | #define HQVDP_MBX_IRQ_TO_XP70 (HQVDP_MBX + 0x0000) /* 0x000E4000 */ | ||
46 | #define HQVDP_MBX_INFO_HOST (HQVDP_MBX + 0x0004) /* 0x000E4004 */ | ||
47 | #define HQVDP_MBX_IRQ_TO_HOST (HQVDP_MBX + 0x0008) /* 0x000E4008 */ | ||
48 | #define HQVDP_MBX_INFO_XP70 (HQVDP_MBX + 0x000C) /* 0x000E400C */ | ||
49 | #define HQVDP_MBX_SW_RESET_CTRL (HQVDP_MBX + 0x0010) /* 0x000E4010 */ | ||
50 | #define HQVDP_MBX_STARTUP_CTRL1 (HQVDP_MBX + 0x0014) /* 0x000E4014 */ | ||
51 | #define HQVDP_MBX_STARTUP_CTRL2 (HQVDP_MBX + 0x0018) /* 0x000E4018 */ | ||
52 | #define HQVDP_MBX_GP_STATUS (HQVDP_MBX + 0x001C) /* 0x000E401C */ | ||
53 | #define HQVDP_MBX_NEXT_CMD (HQVDP_MBX + 0x0020) /* 0x000E4020 */ | ||
54 | #define HQVDP_MBX_CURRENT_CMD (HQVDP_MBX + 0x0024) /* 0x000E4024 */ | ||
55 | #define HQVDP_MBX_SOFT_VSYNC (HQVDP_MBX + 0x0028) /* 0x000E4028 */ | ||
56 | |||
57 | /* Plugs config */ | ||
58 | #define PLUG_CONTROL_ENABLE 0x00000001 | ||
59 | #define PLUG_PAGE_SIZE_256 0x00000002 | ||
60 | #define PLUG_MIN_OPC_8 0x00000003 | ||
61 | #define PLUG_MAX_OPC_64 0x00000006 | ||
62 | #define PLUG_MAX_CHK_2X 0x00000001 | ||
63 | #define PLUG_MAX_MSG_1X 0x00000000 | ||
64 | #define PLUG_MIN_SPACE_1 0x00000000 | ||
65 | |||
66 | /* SW reset CTRL */ | ||
67 | #define SW_RESET_CTRL_FULL BIT(0) | ||
68 | #define SW_RESET_CTRL_CORE BIT(1) | ||
69 | |||
70 | /* Startup ctrl 1 */ | ||
71 | #define STARTUP_CTRL1_RST_DONE BIT(0) | ||
72 | #define STARTUP_CTRL1_AUTH_IDLE BIT(2) | ||
73 | |||
74 | /* Startup ctrl 2 */ | ||
75 | #define STARTUP_CTRL2_FETCH_EN BIT(1) | ||
76 | |||
77 | /* Info xP70 */ | ||
78 | #define INFO_XP70_FW_READY BIT(15) | ||
79 | #define INFO_XP70_FW_PROCESSING BIT(14) | ||
80 | #define INFO_XP70_FW_INITQUEUES BIT(13) | ||
81 | |||
82 | /* SOFT_VSYNC */ | ||
83 | #define SOFT_VSYNC_HW 0x00000000 | ||
84 | #define SOFT_VSYNC_SW_CMD 0x00000001 | ||
85 | #define SOFT_VSYNC_SW_CTRL_IRQ 0x00000003 | ||
86 | |||
87 | /* Reset & boot poll config */ | ||
88 | #define POLL_MAX_ATTEMPT 50 | ||
89 | #define POLL_DELAY_MS 20 | ||
90 | |||
91 | #define SCALE_FACTOR 8192 | ||
92 | #define SCALE_MAX_FOR_LEG_LUT_F 4096 | ||
93 | #define SCALE_MAX_FOR_LEG_LUT_E 4915 | ||
94 | #define SCALE_MAX_FOR_LEG_LUT_D 6654 | ||
95 | #define SCALE_MAX_FOR_LEG_LUT_C 8192 | ||
96 | |||
97 | enum sti_hvsrc_orient { | ||
98 | HVSRC_HORI, | ||
99 | HVSRC_VERT | ||
100 | }; | ||
101 | |||
102 | /* Command structures */ | ||
103 | struct sti_hqvdp_top { | ||
104 | u32 config; | ||
105 | u32 mem_format; | ||
106 | u32 current_luma; | ||
107 | u32 current_enh_luma; | ||
108 | u32 current_right_luma; | ||
109 | u32 current_enh_right_luma; | ||
110 | u32 current_chroma; | ||
111 | u32 current_enh_chroma; | ||
112 | u32 current_right_chroma; | ||
113 | u32 current_enh_right_chroma; | ||
114 | u32 output_luma; | ||
115 | u32 output_chroma; | ||
116 | u32 luma_src_pitch; | ||
117 | u32 luma_enh_src_pitch; | ||
118 | u32 luma_right_src_pitch; | ||
119 | u32 luma_enh_right_src_pitch; | ||
120 | u32 chroma_src_pitch; | ||
121 | u32 chroma_enh_src_pitch; | ||
122 | u32 chroma_right_src_pitch; | ||
123 | u32 chroma_enh_right_src_pitch; | ||
124 | u32 luma_processed_pitch; | ||
125 | u32 chroma_processed_pitch; | ||
126 | u32 input_frame_size; | ||
127 | u32 input_viewport_ori; | ||
128 | u32 input_viewport_ori_right; | ||
129 | u32 input_viewport_size; | ||
130 | u32 left_view_border_width; | ||
131 | u32 right_view_border_width; | ||
132 | u32 left_view_3d_offset_width; | ||
133 | u32 right_view_3d_offset_width; | ||
134 | u32 side_stripe_color; | ||
135 | u32 crc_reset_ctrl; | ||
136 | }; | ||
137 | |||
138 | /* Configs for interlaced : no IT, no pass thru, 3 fields */ | ||
139 | #define TOP_CONFIG_INTER_BTM 0x00000000 | ||
140 | #define TOP_CONFIG_INTER_TOP 0x00000002 | ||
141 | |||
142 | /* Config for progressive : no IT, no pass thru, 3 fields */ | ||
143 | #define TOP_CONFIG_PROGRESSIVE 0x00000001 | ||
144 | |||
145 | /* Default MemFormat: in=420_raster_dual out=444_raster;opaque Mem2Tv mode */ | ||
146 | #define TOP_MEM_FORMAT_DFLT 0x00018060 | ||
147 | |||
148 | /* Min/Max size */ | ||
149 | #define MAX_WIDTH 0x1FFF | ||
150 | #define MAX_HEIGHT 0x0FFF | ||
151 | #define MIN_WIDTH 0x0030 | ||
152 | #define MIN_HEIGHT 0x0010 | ||
153 | |||
154 | struct sti_hqvdp_vc1re { | ||
155 | u32 ctrl_prv_csdi; | ||
156 | u32 ctrl_cur_csdi; | ||
157 | u32 ctrl_nxt_csdi; | ||
158 | u32 ctrl_cur_fmd; | ||
159 | u32 ctrl_nxt_fmd; | ||
160 | }; | ||
161 | |||
162 | struct sti_hqvdp_fmd { | ||
163 | u32 config; | ||
164 | u32 viewport_ori; | ||
165 | u32 viewport_size; | ||
166 | u32 next_next_luma; | ||
167 | u32 next_next_right_luma; | ||
168 | u32 next_next_next_luma; | ||
169 | u32 next_next_next_right_luma; | ||
170 | u32 threshold_scd; | ||
171 | u32 threshold_rfd; | ||
172 | u32 threshold_move; | ||
173 | u32 threshold_cfd; | ||
174 | }; | ||
175 | |||
176 | struct sti_hqvdp_csdi { | ||
177 | u32 config; | ||
178 | u32 config2; | ||
179 | u32 dcdi_config; | ||
180 | u32 prev_luma; | ||
181 | u32 prev_enh_luma; | ||
182 | u32 prev_right_luma; | ||
183 | u32 prev_enh_right_luma; | ||
184 | u32 next_luma; | ||
185 | u32 next_enh_luma; | ||
186 | u32 next_right_luma; | ||
187 | u32 next_enh_right_luma; | ||
188 | u32 prev_chroma; | ||
189 | u32 prev_enh_chroma; | ||
190 | u32 prev_right_chroma; | ||
191 | u32 prev_enh_right_chroma; | ||
192 | u32 next_chroma; | ||
193 | u32 next_enh_chroma; | ||
194 | u32 next_right_chroma; | ||
195 | u32 next_enh_right_chroma; | ||
196 | u32 prev_motion; | ||
197 | u32 prev_right_motion; | ||
198 | u32 cur_motion; | ||
199 | u32 cur_right_motion; | ||
200 | u32 next_motion; | ||
201 | u32 next_right_motion; | ||
202 | }; | ||
203 | |||
204 | /* Config for progressive: by pass */ | ||
205 | #define CSDI_CONFIG_PROG 0x00000000 | ||
206 | /* Config for directional deinterlacing without motion */ | ||
207 | #define CSDI_CONFIG_INTER_DIR 0x00000016 | ||
208 | /* Additional configs for fader, blender, motion,... deinterlace algorithms */ | ||
209 | #define CSDI_CONFIG2_DFLT 0x000001B3 | ||
210 | #define CSDI_DCDI_CONFIG_DFLT 0x00203803 | ||
211 | |||
212 | struct sti_hqvdp_hvsrc { | ||
213 | u32 hor_panoramic_ctrl; | ||
214 | u32 output_picture_size; | ||
215 | u32 init_horizontal; | ||
216 | u32 init_vertical; | ||
217 | u32 param_ctrl; | ||
218 | u32 yh_coef[NB_COEF]; | ||
219 | u32 ch_coef[NB_COEF]; | ||
220 | u32 yv_coef[NB_COEF]; | ||
221 | u32 cv_coef[NB_COEF]; | ||
222 | u32 hori_shift; | ||
223 | u32 vert_shift; | ||
224 | }; | ||
225 | |||
226 | /* Default ParamCtrl: all controls enabled */ | ||
227 | #define HVSRC_PARAM_CTRL_DFLT 0xFFFFFFFF | ||
228 | |||
229 | struct sti_hqvdp_iqi { | ||
230 | u32 config; | ||
231 | u32 demo_wind_size; | ||
232 | u32 pk_config; | ||
233 | u32 coeff0_coeff1; | ||
234 | u32 coeff2_coeff3; | ||
235 | u32 coeff4; | ||
236 | u32 pk_lut; | ||
237 | u32 pk_gain; | ||
238 | u32 pk_coring_level; | ||
239 | u32 cti_config; | ||
240 | u32 le_config; | ||
241 | u32 le_lut[64]; | ||
242 | u32 con_bri; | ||
243 | u32 sat_gain; | ||
244 | u32 pxf_conf; | ||
245 | u32 default_color; | ||
246 | }; | ||
247 | |||
248 | /* Default Config : IQI bypassed */ | ||
249 | #define IQI_CONFIG_DFLT 0x00000001 | ||
250 | /* Default Contrast & Brightness gain = 256 */ | ||
251 | #define IQI_CON_BRI_DFLT 0x00000100 | ||
252 | /* Default Saturation gain = 256 */ | ||
253 | #define IQI_SAT_GAIN_DFLT 0x00000100 | ||
254 | /* Default PxfConf : P2I bypassed */ | ||
255 | #define IQI_PXF_CONF_DFLT 0x00000001 | ||
256 | |||
257 | struct sti_hqvdp_top_status { | ||
258 | u32 processing_time; | ||
259 | u32 input_y_crc; | ||
260 | u32 input_uv_crc; | ||
261 | }; | ||
262 | |||
263 | struct sti_hqvdp_fmd_status { | ||
264 | u32 fmd_repeat_move_status; | ||
265 | u32 fmd_scene_count_status; | ||
266 | u32 cfd_sum; | ||
267 | u32 field_sum; | ||
268 | u32 next_y_fmd_crc; | ||
269 | u32 next_next_y_fmd_crc; | ||
270 | u32 next_next_next_y_fmd_crc; | ||
271 | }; | ||
272 | |||
273 | struct sti_hqvdp_csdi_status { | ||
274 | u32 prev_y_csdi_crc; | ||
275 | u32 cur_y_csdi_crc; | ||
276 | u32 next_y_csdi_crc; | ||
277 | u32 prev_uv_csdi_crc; | ||
278 | u32 cur_uv_csdi_crc; | ||
279 | u32 next_uv_csdi_crc; | ||
280 | u32 y_csdi_crc; | ||
281 | u32 uv_csdi_crc; | ||
282 | u32 uv_cup_crc; | ||
283 | u32 mot_csdi_crc; | ||
284 | u32 mot_cur_csdi_crc; | ||
285 | u32 mot_prev_csdi_crc; | ||
286 | }; | ||
287 | |||
288 | struct sti_hqvdp_hvsrc_status { | ||
289 | u32 y_hvsrc_crc; | ||
290 | u32 u_hvsrc_crc; | ||
291 | u32 v_hvsrc_crc; | ||
292 | }; | ||
293 | |||
294 | struct sti_hqvdp_iqi_status { | ||
295 | u32 pxf_it_status; | ||
296 | u32 y_iqi_crc; | ||
297 | u32 u_iqi_crc; | ||
298 | u32 v_iqi_crc; | ||
299 | }; | ||
300 | |||
301 | /* Main commands. We use 2 commands one being processed by the firmware, one | ||
302 | * ready to be fetched upon next Vsync*/ | ||
303 | #define NB_VDP_CMD 2 | ||
304 | |||
305 | struct sti_hqvdp_cmd { | ||
306 | struct sti_hqvdp_top top; | ||
307 | struct sti_hqvdp_vc1re vc1re; | ||
308 | struct sti_hqvdp_fmd fmd; | ||
309 | struct sti_hqvdp_csdi csdi; | ||
310 | struct sti_hqvdp_hvsrc hvsrc; | ||
311 | struct sti_hqvdp_iqi iqi; | ||
312 | struct sti_hqvdp_top_status top_status; | ||
313 | struct sti_hqvdp_fmd_status fmd_status; | ||
314 | struct sti_hqvdp_csdi_status csdi_status; | ||
315 | struct sti_hqvdp_hvsrc_status hvsrc_status; | ||
316 | struct sti_hqvdp_iqi_status iqi_status; | ||
317 | }; | ||
318 | |||
319 | /* | ||
320 | * STI HQVDP structure | ||
321 | * | ||
322 | * @dev: driver device | ||
323 | * @drm_dev: the drm device | ||
324 | * @regs: registers | ||
325 | * @layer: layer structure for hqvdp it self | ||
326 | * @vid_plane: VID plug used as link with compositor IP | ||
327 | * @clk: IP clock | ||
328 | * @clk_pix_main: pix main clock | ||
329 | * @reset: reset control | ||
330 | * @vtg_nb: notifier to handle VTG Vsync | ||
331 | * @btm_field_pending: is there any bottom field (interlaced frame) to display | ||
332 | * @curr_field_count: number of field updates | ||
333 | * @last_field_count: number of field updates since last fps measure | ||
334 | * @hqvdp_cmd: buffer of commands | ||
335 | * @hqvdp_cmd_paddr: physical address of hqvdp_cmd | ||
336 | * @vtg: vtg for main data path | ||
337 | */ | ||
338 | struct sti_hqvdp { | ||
339 | struct device *dev; | ||
340 | struct drm_device *drm_dev; | ||
341 | void __iomem *regs; | ||
342 | struct sti_layer layer; | ||
343 | struct drm_plane *vid_plane; | ||
344 | struct clk *clk; | ||
345 | struct clk *clk_pix_main; | ||
346 | struct reset_control *reset; | ||
347 | struct notifier_block vtg_nb; | ||
348 | bool btm_field_pending; | ||
349 | unsigned int curr_field_count; | ||
350 | unsigned int last_field_count; | ||
351 | void *hqvdp_cmd; | ||
352 | dma_addr_t hqvdp_cmd_paddr; | ||
353 | struct sti_vtg *vtg; | ||
354 | }; | ||
355 | |||
356 | #define to_sti_hqvdp(x) container_of(x, struct sti_hqvdp, layer) | ||
357 | |||
358 | static const uint32_t hqvdp_supported_formats[] = { | ||
359 | DRM_FORMAT_NV12, | ||
360 | }; | ||
361 | |||
362 | static const uint32_t *sti_hqvdp_get_formats(struct sti_layer *layer) | ||
363 | { | ||
364 | return hqvdp_supported_formats; | ||
365 | } | ||
366 | |||
367 | static unsigned int sti_hqvdp_get_nb_formats(struct sti_layer *layer) | ||
368 | { | ||
369 | return ARRAY_SIZE(hqvdp_supported_formats); | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * sti_hqvdp_get_free_cmd | ||
374 | * @hqvdp: hqvdp structure | ||
375 | * | ||
376 | * Look for a hqvdp_cmd that is not being used (or about to be used) by the FW. | ||
377 | * | ||
378 | * RETURNS: | ||
379 | * the offset of the command to be used. | ||
380 | * -1 in error cases | ||
381 | */ | ||
382 | static int sti_hqvdp_get_free_cmd(struct sti_hqvdp *hqvdp) | ||
383 | { | ||
384 | int curr_cmd, next_cmd; | ||
385 | dma_addr_t cmd = hqvdp->hqvdp_cmd_paddr; | ||
386 | int i; | ||
387 | |||
388 | curr_cmd = readl(hqvdp->regs + HQVDP_MBX_CURRENT_CMD); | ||
389 | next_cmd = readl(hqvdp->regs + HQVDP_MBX_NEXT_CMD); | ||
390 | |||
391 | for (i = 0; i < NB_VDP_CMD; i++) { | ||
392 | if ((cmd != curr_cmd) && (cmd != next_cmd)) | ||
393 | return i * sizeof(struct sti_hqvdp_cmd); | ||
394 | cmd += sizeof(struct sti_hqvdp_cmd); | ||
395 | } | ||
396 | |||
397 | return -1; | ||
398 | } | ||
399 | |||
400 | /** | ||
401 | * sti_hqvdp_get_curr_cmd | ||
402 | * @hqvdp: hqvdp structure | ||
403 | * | ||
404 | * Look for the hqvdp_cmd that is being used by the FW. | ||
405 | * | ||
406 | * RETURNS: | ||
407 | * the offset of the command to be used. | ||
408 | * -1 in error cases | ||
409 | */ | ||
410 | static int sti_hqvdp_get_curr_cmd(struct sti_hqvdp *hqvdp) | ||
411 | { | ||
412 | int curr_cmd; | ||
413 | dma_addr_t cmd = hqvdp->hqvdp_cmd_paddr; | ||
414 | unsigned int i; | ||
415 | |||
416 | curr_cmd = readl(hqvdp->regs + HQVDP_MBX_CURRENT_CMD); | ||
417 | |||
418 | for (i = 0; i < NB_VDP_CMD; i++) { | ||
419 | if (cmd == curr_cmd) | ||
420 | return i * sizeof(struct sti_hqvdp_cmd); | ||
421 | |||
422 | cmd += sizeof(struct sti_hqvdp_cmd); | ||
423 | } | ||
424 | |||
425 | return -1; | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * sti_hqvdp_update_hvsrc | ||
430 | * @orient: horizontal or vertical | ||
431 | * @scale: scaling/zoom factor | ||
432 | * @hvsrc: the structure containing the LUT coef | ||
433 | * | ||
434 | * Update the Y and C Lut coef, as well as the shift param | ||
435 | * | ||
436 | * RETURNS: | ||
437 | * None. | ||
438 | */ | ||
439 | static void sti_hqvdp_update_hvsrc(enum sti_hvsrc_orient orient, int scale, | ||
440 | struct sti_hqvdp_hvsrc *hvsrc) | ||
441 | { | ||
442 | const int *coef_c, *coef_y; | ||
443 | int shift_c, shift_y; | ||
444 | |||
445 | /* Get the appropriate coef tables */ | ||
446 | if (scale < SCALE_MAX_FOR_LEG_LUT_F) { | ||
447 | coef_y = coef_lut_f_y_legacy; | ||
448 | coef_c = coef_lut_f_c_legacy; | ||
449 | shift_y = SHIFT_LUT_F_Y_LEGACY; | ||
450 | shift_c = SHIFT_LUT_F_C_LEGACY; | ||
451 | } else if (scale < SCALE_MAX_FOR_LEG_LUT_E) { | ||
452 | coef_y = coef_lut_e_y_legacy; | ||
453 | coef_c = coef_lut_e_c_legacy; | ||
454 | shift_y = SHIFT_LUT_E_Y_LEGACY; | ||
455 | shift_c = SHIFT_LUT_E_C_LEGACY; | ||
456 | } else if (scale < SCALE_MAX_FOR_LEG_LUT_D) { | ||
457 | coef_y = coef_lut_d_y_legacy; | ||
458 | coef_c = coef_lut_d_c_legacy; | ||
459 | shift_y = SHIFT_LUT_D_Y_LEGACY; | ||
460 | shift_c = SHIFT_LUT_D_C_LEGACY; | ||
461 | } else if (scale < SCALE_MAX_FOR_LEG_LUT_C) { | ||
462 | coef_y = coef_lut_c_y_legacy; | ||
463 | coef_c = coef_lut_c_c_legacy; | ||
464 | shift_y = SHIFT_LUT_C_Y_LEGACY; | ||
465 | shift_c = SHIFT_LUT_C_C_LEGACY; | ||
466 | } else if (scale == SCALE_MAX_FOR_LEG_LUT_C) { | ||
467 | coef_y = coef_c = coef_lut_b; | ||
468 | shift_y = shift_c = SHIFT_LUT_B; | ||
469 | } else { | ||
470 | coef_y = coef_c = coef_lut_a_legacy; | ||
471 | shift_y = shift_c = SHIFT_LUT_A_LEGACY; | ||
472 | } | ||
473 | |||
474 | if (orient == HVSRC_HORI) { | ||
475 | hvsrc->hori_shift = (shift_c << 16) | shift_y; | ||
476 | memcpy(hvsrc->yh_coef, coef_y, sizeof(hvsrc->yh_coef)); | ||
477 | memcpy(hvsrc->ch_coef, coef_c, sizeof(hvsrc->ch_coef)); | ||
478 | } else { | ||
479 | hvsrc->vert_shift = (shift_c << 16) | shift_y; | ||
480 | memcpy(hvsrc->yv_coef, coef_y, sizeof(hvsrc->yv_coef)); | ||
481 | memcpy(hvsrc->cv_coef, coef_c, sizeof(hvsrc->cv_coef)); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | /** | ||
486 | * sti_hqvdp_check_hw_scaling | ||
487 | * @layer: hqvdp layer | ||
488 | * | ||
489 | * Check if the HW is able to perform the scaling request | ||
490 | * The firmware scaling limitation is "CEIL(1/Zy) <= FLOOR(LFW)" where: | ||
491 | * Zy = OutputHeight / InputHeight | ||
492 | * LFW = (Tx * IPClock) / (MaxNbCycles * Cp) | ||
493 | * Tx : Total video mode horizontal resolution | ||
494 | * IPClock : HQVDP IP clock (Mhz) | ||
495 | * MaxNbCycles: max(InputWidth, OutputWidth) | ||
496 | * Cp: Video mode pixel clock (Mhz) | ||
497 | * | ||
498 | * RETURNS: | ||
499 | * True if the HW can scale. | ||
500 | */ | ||
501 | static bool sti_hqvdp_check_hw_scaling(struct sti_layer *layer) | ||
502 | { | ||
503 | struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer); | ||
504 | unsigned long lfw; | ||
505 | unsigned int inv_zy; | ||
506 | |||
507 | lfw = layer->mode->htotal * (clk_get_rate(hqvdp->clk) / 1000000); | ||
508 | lfw /= max(layer->src_w, layer->dst_w) * layer->mode->clock / 1000; | ||
509 | |||
510 | inv_zy = DIV_ROUND_UP(layer->src_h, layer->dst_h); | ||
511 | |||
512 | return (inv_zy <= lfw) ? true : false; | ||
513 | } | ||
514 | |||
515 | /** | ||
516 | * sti_hqvdp_prepare_layer | ||
517 | * @layer: hqvdp layer | ||
518 | * @first_prepare: true if it is the first time this function is called | ||
519 | * | ||
520 | * Prepares a command for the firmware | ||
521 | * | ||
522 | * RETURNS: | ||
523 | * 0 on success. | ||
524 | */ | ||
525 | static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare) | ||
526 | { | ||
527 | struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer); | ||
528 | struct sti_hqvdp_cmd *cmd; | ||
529 | int scale_h, scale_v; | ||
530 | int cmd_offset; | ||
531 | |||
532 | dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_layer_to_str(layer)); | ||
533 | |||
534 | /* prepare and commit VID plane */ | ||
535 | hqvdp->vid_plane->funcs->update_plane(hqvdp->vid_plane, | ||
536 | layer->crtc, layer->fb, | ||
537 | layer->dst_x, layer->dst_y, | ||
538 | layer->dst_w, layer->dst_h, | ||
539 | layer->src_x, layer->src_y, | ||
540 | layer->src_w, layer->src_h); | ||
541 | |||
542 | cmd_offset = sti_hqvdp_get_free_cmd(hqvdp); | ||
543 | if (cmd_offset == -1) { | ||
544 | DRM_ERROR("No available hqvdp_cmd now\n"); | ||
545 | return -EBUSY; | ||
546 | } | ||
547 | cmd = hqvdp->hqvdp_cmd + cmd_offset; | ||
548 | |||
549 | if (!sti_hqvdp_check_hw_scaling(layer)) { | ||
550 | DRM_ERROR("Scaling beyond HW capabilities\n"); | ||
551 | return -EINVAL; | ||
552 | } | ||
553 | |||
554 | /* Static parameters, defaulting to progressive mode */ | ||
555 | cmd->top.config = TOP_CONFIG_PROGRESSIVE; | ||
556 | cmd->top.mem_format = TOP_MEM_FORMAT_DFLT; | ||
557 | cmd->hvsrc.param_ctrl = HVSRC_PARAM_CTRL_DFLT; | ||
558 | cmd->csdi.config = CSDI_CONFIG_PROG; | ||
559 | |||
560 | /* VC1RE, FMD bypassed : keep everything set to 0 | ||
561 | * IQI/P2I bypassed */ | ||
562 | cmd->iqi.config = IQI_CONFIG_DFLT; | ||
563 | cmd->iqi.con_bri = IQI_CON_BRI_DFLT; | ||
564 | cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT; | ||
565 | cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT; | ||
566 | |||
567 | /* Buffer planes address */ | ||
568 | cmd->top.current_luma = (u32) layer->paddr + layer->offsets[0]; | ||
569 | cmd->top.current_chroma = (u32) layer->paddr + layer->offsets[1]; | ||
570 | |||
571 | /* Pitches */ | ||
572 | cmd->top.luma_processed_pitch = cmd->top.luma_src_pitch = | ||
573 | layer->pitches[0]; | ||
574 | cmd->top.chroma_processed_pitch = cmd->top.chroma_src_pitch = | ||
575 | layer->pitches[1]; | ||
576 | |||
577 | /* Input / output size | ||
578 | * Align to upper even value */ | ||
579 | layer->dst_w = ALIGN(layer->dst_w, 2); | ||
580 | layer->dst_h = ALIGN(layer->dst_h, 2); | ||
581 | |||
582 | if ((layer->src_w > MAX_WIDTH) || (layer->src_w < MIN_WIDTH) || | ||
583 | (layer->src_h > MAX_HEIGHT) || (layer->src_h < MIN_HEIGHT) || | ||
584 | (layer->dst_w > MAX_WIDTH) || (layer->dst_w < MIN_WIDTH) || | ||
585 | (layer->dst_h > MAX_HEIGHT) || (layer->dst_h < MIN_HEIGHT)) { | ||
586 | DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n", | ||
587 | layer->src_w, layer->src_h, | ||
588 | layer->dst_w, layer->dst_h); | ||
589 | return -EINVAL; | ||
590 | } | ||
591 | cmd->top.input_viewport_size = cmd->top.input_frame_size = | ||
592 | layer->src_h << 16 | layer->src_w; | ||
593 | cmd->hvsrc.output_picture_size = layer->dst_h << 16 | layer->dst_w; | ||
594 | cmd->top.input_viewport_ori = layer->src_y << 16 | layer->src_x; | ||
595 | |||
596 | /* Handle interlaced */ | ||
597 | if (layer->fb->flags & DRM_MODE_FB_INTERLACED) { | ||
598 | /* Top field to display */ | ||
599 | cmd->top.config = TOP_CONFIG_INTER_TOP; | ||
600 | |||
601 | /* Update pitches and vert size */ | ||
602 | cmd->top.input_frame_size = (layer->src_h / 2) << 16 | | ||
603 | layer->src_w; | ||
604 | cmd->top.luma_processed_pitch *= 2; | ||
605 | cmd->top.luma_src_pitch *= 2; | ||
606 | cmd->top.chroma_processed_pitch *= 2; | ||
607 | cmd->top.chroma_src_pitch *= 2; | ||
608 | |||
609 | /* Enable directional deinterlacing processing */ | ||
610 | cmd->csdi.config = CSDI_CONFIG_INTER_DIR; | ||
611 | cmd->csdi.config2 = CSDI_CONFIG2_DFLT; | ||
612 | cmd->csdi.dcdi_config = CSDI_DCDI_CONFIG_DFLT; | ||
613 | } | ||
614 | |||
615 | /* Update hvsrc lut coef */ | ||
616 | scale_h = SCALE_FACTOR * layer->dst_w / layer->src_w; | ||
617 | sti_hqvdp_update_hvsrc(HVSRC_HORI, scale_h, &cmd->hvsrc); | ||
618 | |||
619 | scale_v = SCALE_FACTOR * layer->dst_h / layer->src_h; | ||
620 | sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc); | ||
621 | |||
622 | if (first_prepare) { | ||
623 | /* Prevent VTG shutdown */ | ||
624 | if (clk_prepare_enable(hqvdp->clk_pix_main)) { | ||
625 | DRM_ERROR("Failed to prepare/enable pix main clk\n"); | ||
626 | return -ENXIO; | ||
627 | } | ||
628 | |||
629 | /* Register VTG Vsync callback to handle bottom fields */ | ||
630 | if ((layer->fb->flags & DRM_MODE_FB_INTERLACED) && | ||
631 | sti_vtg_register_client(hqvdp->vtg, | ||
632 | &hqvdp->vtg_nb, layer->mixer_id)) { | ||
633 | DRM_ERROR("Cannot register VTG notifier\n"); | ||
634 | return -ENXIO; | ||
635 | } | ||
636 | } | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static int sti_hqvdp_commit_layer(struct sti_layer *layer) | ||
642 | { | ||
643 | struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer); | ||
644 | int cmd_offset; | ||
645 | |||
646 | dev_dbg(hqvdp->dev, "%s %s\n", __func__, sti_layer_to_str(layer)); | ||
647 | |||
648 | cmd_offset = sti_hqvdp_get_free_cmd(hqvdp); | ||
649 | if (cmd_offset == -1) { | ||
650 | DRM_ERROR("No available hqvdp_cmd now\n"); | ||
651 | return -EBUSY; | ||
652 | } | ||
653 | |||
654 | writel(hqvdp->hqvdp_cmd_paddr + cmd_offset, | ||
655 | hqvdp->regs + HQVDP_MBX_NEXT_CMD); | ||
656 | |||
657 | hqvdp->curr_field_count++; | ||
658 | |||
659 | /* Interlaced : get ready to display the bottom field at next Vsync */ | ||
660 | if (layer->fb->flags & DRM_MODE_FB_INTERLACED) | ||
661 | hqvdp->btm_field_pending = true; | ||
662 | |||
663 | dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n", | ||
664 | __func__, hqvdp->hqvdp_cmd_paddr + cmd_offset); | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | static int sti_hqvdp_disable_layer(struct sti_layer *layer) | ||
670 | { | ||
671 | struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer); | ||
672 | int i; | ||
673 | |||
674 | DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer)); | ||
675 | |||
676 | /* Unregister VTG Vsync callback */ | ||
677 | if ((layer->fb->flags & DRM_MODE_FB_INTERLACED) && | ||
678 | sti_vtg_unregister_client(hqvdp->vtg, &hqvdp->vtg_nb)) | ||
679 | DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); | ||
680 | |||
681 | /* Set next cmd to NULL */ | ||
682 | writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD); | ||
683 | |||
684 | for (i = 0; i < POLL_MAX_ATTEMPT; i++) { | ||
685 | if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70) | ||
686 | & INFO_XP70_FW_READY) | ||
687 | break; | ||
688 | msleep(POLL_DELAY_MS); | ||
689 | } | ||
690 | |||
691 | /* VTG can stop now */ | ||
692 | clk_disable_unprepare(hqvdp->clk_pix_main); | ||
693 | |||
694 | if (i == POLL_MAX_ATTEMPT) { | ||
695 | DRM_ERROR("XP70 could not revert to idle\n"); | ||
696 | return -ENXIO; | ||
697 | } | ||
698 | |||
699 | /* disable VID plane */ | ||
700 | hqvdp->vid_plane->funcs->disable_plane(hqvdp->vid_plane); | ||
701 | |||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | /** | ||
706 | * sti_vdp_vtg_cb | ||
707 | * @nb: notifier block | ||
708 | * @evt: event message | ||
709 | * @data: private data | ||
710 | * | ||
711 | * Handle VTG Vsync event, display pending bottom field | ||
712 | * | ||
713 | * RETURNS: | ||
714 | * 0 on success. | ||
715 | */ | ||
716 | int sti_hqvdp_vtg_cb(struct notifier_block *nb, unsigned long evt, void *data) | ||
717 | { | ||
718 | struct sti_hqvdp *hqvdp = container_of(nb, struct sti_hqvdp, vtg_nb); | ||
719 | int btm_cmd_offset, top_cmd_offest; | ||
720 | struct sti_hqvdp_cmd *btm_cmd, *top_cmd; | ||
721 | |||
722 | if ((evt != VTG_TOP_FIELD_EVENT) && (evt != VTG_BOTTOM_FIELD_EVENT)) { | ||
723 | DRM_DEBUG_DRIVER("Unknown event\n"); | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | if (hqvdp->btm_field_pending) { | ||
728 | /* Create the btm field command from the current one */ | ||
729 | btm_cmd_offset = sti_hqvdp_get_free_cmd(hqvdp); | ||
730 | top_cmd_offest = sti_hqvdp_get_curr_cmd(hqvdp); | ||
731 | if ((btm_cmd_offset == -1) || (top_cmd_offest == -1)) { | ||
732 | DRM_ERROR("Cannot get cmds, skip btm field\n"); | ||
733 | return -EBUSY; | ||
734 | } | ||
735 | |||
736 | btm_cmd = hqvdp->hqvdp_cmd + btm_cmd_offset; | ||
737 | top_cmd = hqvdp->hqvdp_cmd + top_cmd_offest; | ||
738 | |||
739 | memcpy(btm_cmd, top_cmd, sizeof(*btm_cmd)); | ||
740 | |||
741 | btm_cmd->top.config = TOP_CONFIG_INTER_BTM; | ||
742 | btm_cmd->top.current_luma += | ||
743 | btm_cmd->top.luma_src_pitch / 2; | ||
744 | btm_cmd->top.current_chroma += | ||
745 | btm_cmd->top.chroma_src_pitch / 2; | ||
746 | |||
747 | /* Post the command to mailbox */ | ||
748 | writel(hqvdp->hqvdp_cmd_paddr + btm_cmd_offset, | ||
749 | hqvdp->regs + HQVDP_MBX_NEXT_CMD); | ||
750 | |||
751 | hqvdp->curr_field_count++; | ||
752 | hqvdp->btm_field_pending = false; | ||
753 | |||
754 | dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n", | ||
755 | __func__, hqvdp->hqvdp_cmd_paddr); | ||
756 | } | ||
757 | |||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static struct drm_plane *sti_hqvdp_find_vid(struct drm_device *dev, int id) | ||
762 | { | ||
763 | struct drm_plane *plane; | ||
764 | |||
765 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) { | ||
766 | struct sti_layer *layer = to_sti_layer(plane); | ||
767 | |||
768 | if (layer->desc == id) | ||
769 | return plane; | ||
770 | } | ||
771 | |||
772 | return NULL; | ||
773 | } | ||
774 | |||
775 | static void sti_hqvd_init(struct sti_layer *layer) | ||
776 | { | ||
777 | struct sti_hqvdp *hqvdp = to_sti_hqvdp(layer); | ||
778 | int size; | ||
779 | |||
780 | /* find the plane macthing with vid 0 */ | ||
781 | hqvdp->vid_plane = sti_hqvdp_find_vid(hqvdp->drm_dev, STI_VID_0); | ||
782 | if (!hqvdp->vid_plane) { | ||
783 | DRM_ERROR("Cannot find Main video layer\n"); | ||
784 | return; | ||
785 | } | ||
786 | |||
787 | hqvdp->vtg_nb.notifier_call = sti_hqvdp_vtg_cb; | ||
788 | |||
789 | /* Allocate memory for the VDP commands */ | ||
790 | size = NB_VDP_CMD * sizeof(struct sti_hqvdp_cmd); | ||
791 | hqvdp->hqvdp_cmd = dma_alloc_writecombine(hqvdp->dev, size, | ||
792 | &hqvdp->hqvdp_cmd_paddr, | ||
793 | GFP_KERNEL | GFP_DMA); | ||
794 | if (!hqvdp->hqvdp_cmd) { | ||
795 | DRM_ERROR("Failed to allocate memory for VDP cmd\n"); | ||
796 | return; | ||
797 | } | ||
798 | |||
799 | memset(hqvdp->hqvdp_cmd, 0, size); | ||
800 | } | ||
801 | |||
802 | static const struct sti_layer_funcs hqvdp_ops = { | ||
803 | .get_formats = sti_hqvdp_get_formats, | ||
804 | .get_nb_formats = sti_hqvdp_get_nb_formats, | ||
805 | .init = sti_hqvd_init, | ||
806 | .prepare = sti_hqvdp_prepare_layer, | ||
807 | .commit = sti_hqvdp_commit_layer, | ||
808 | .disable = sti_hqvdp_disable_layer, | ||
809 | }; | ||
810 | |||
811 | struct sti_layer *sti_hqvdp_create(struct device *dev) | ||
812 | { | ||
813 | struct sti_hqvdp *hqvdp = dev_get_drvdata(dev); | ||
814 | |||
815 | hqvdp->layer.ops = &hqvdp_ops; | ||
816 | |||
817 | return &hqvdp->layer; | ||
818 | } | ||
819 | |||
820 | static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp) | ||
821 | { | ||
822 | /* Configure Plugs (same for RD & WR) */ | ||
823 | writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE); | ||
824 | writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC); | ||
825 | writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC); | ||
826 | writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK); | ||
827 | writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG); | ||
828 | writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE); | ||
829 | writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL); | ||
830 | |||
831 | writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE); | ||
832 | writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC); | ||
833 | writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC); | ||
834 | writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK); | ||
835 | writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG); | ||
836 | writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE); | ||
837 | writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL); | ||
838 | } | ||
839 | |||
840 | /** | ||
841 | * sti_hqvdp_start_xp70 | ||
842 | * @firmware: firmware found | ||
843 | * @ctxt: hqvdp structure | ||
844 | * | ||
845 | * Run the xP70 initialization sequence | ||
846 | */ | ||
847 | static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt) | ||
848 | { | ||
849 | struct sti_hqvdp *hqvdp = ctxt; | ||
850 | u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem; | ||
851 | u8 *data; | ||
852 | int i; | ||
853 | struct fw_header { | ||
854 | int rd_size; | ||
855 | int wr_size; | ||
856 | int pmem_size; | ||
857 | int dmem_size; | ||
858 | } *header; | ||
859 | |||
860 | DRM_DEBUG_DRIVER("\n"); | ||
861 | /* Check firmware parts */ | ||
862 | if (!firmware) { | ||
863 | DRM_ERROR("Firmware not available\n"); | ||
864 | return; | ||
865 | } | ||
866 | |||
867 | header = (struct fw_header *) firmware->data; | ||
868 | if (firmware->size < sizeof(*header)) { | ||
869 | DRM_ERROR("Invalid firmware size (%d)\n", firmware->size); | ||
870 | goto out; | ||
871 | } | ||
872 | if ((sizeof(*header) + header->rd_size + header->wr_size + | ||
873 | header->pmem_size + header->dmem_size) != firmware->size) { | ||
874 | DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n", | ||
875 | sizeof(*header), header->rd_size, header->wr_size, | ||
876 | header->pmem_size, header->dmem_size, | ||
877 | firmware->size); | ||
878 | goto out; | ||
879 | } | ||
880 | |||
881 | data = (u8 *) firmware->data; | ||
882 | data += sizeof(*header); | ||
883 | fw_rd_plug = (void *) data; | ||
884 | data += header->rd_size; | ||
885 | fw_wr_plug = (void *) data; | ||
886 | data += header->wr_size; | ||
887 | fw_pmem = (void *) data; | ||
888 | data += header->pmem_size; | ||
889 | fw_dmem = (void *) data; | ||
890 | |||
891 | /* Enable clock */ | ||
892 | if (clk_prepare_enable(hqvdp->clk)) | ||
893 | DRM_ERROR("Failed to prepare/enable HQVDP clk\n"); | ||
894 | |||
895 | /* Reset */ | ||
896 | writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL); | ||
897 | |||
898 | for (i = 0; i < POLL_MAX_ATTEMPT; i++) { | ||
899 | if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1) | ||
900 | & STARTUP_CTRL1_RST_DONE) | ||
901 | break; | ||
902 | msleep(POLL_DELAY_MS); | ||
903 | } | ||
904 | if (i == POLL_MAX_ATTEMPT) { | ||
905 | DRM_ERROR("Could not reset\n"); | ||
906 | goto out; | ||
907 | } | ||
908 | |||
909 | /* Init Read & Write plugs */ | ||
910 | for (i = 0; i < header->rd_size / 4; i++) | ||
911 | writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4); | ||
912 | for (i = 0; i < header->wr_size / 4; i++) | ||
913 | writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4); | ||
914 | |||
915 | sti_hqvdp_init_plugs(hqvdp); | ||
916 | |||
917 | /* Authorize Idle Mode */ | ||
918 | writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1); | ||
919 | |||
920 | /* Prevent VTG interruption during the boot */ | ||
921 | writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC); | ||
922 | writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD); | ||
923 | |||
924 | /* Download PMEM & DMEM */ | ||
925 | for (i = 0; i < header->pmem_size / 4; i++) | ||
926 | writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4); | ||
927 | for (i = 0; i < header->dmem_size / 4; i++) | ||
928 | writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4); | ||
929 | |||
930 | /* Enable fetch */ | ||
931 | writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2); | ||
932 | |||
933 | /* Wait end of boot */ | ||
934 | for (i = 0; i < POLL_MAX_ATTEMPT; i++) { | ||
935 | if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70) | ||
936 | & INFO_XP70_FW_READY) | ||
937 | break; | ||
938 | msleep(POLL_DELAY_MS); | ||
939 | } | ||
940 | if (i == POLL_MAX_ATTEMPT) { | ||
941 | DRM_ERROR("Could not boot\n"); | ||
942 | goto out; | ||
943 | } | ||
944 | |||
945 | /* Launch Vsync */ | ||
946 | writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC); | ||
947 | |||
948 | DRM_INFO("HQVDP XP70 started\n"); | ||
949 | out: | ||
950 | release_firmware(firmware); | ||
951 | } | ||
952 | |||
953 | int sti_hqvdp_bind(struct device *dev, struct device *master, void *data) | ||
954 | { | ||
955 | struct sti_hqvdp *hqvdp = dev_get_drvdata(dev); | ||
956 | struct drm_device *drm_dev = data; | ||
957 | struct sti_layer *layer; | ||
958 | int err; | ||
959 | |||
960 | DRM_DEBUG_DRIVER("\n"); | ||
961 | |||
962 | hqvdp->drm_dev = drm_dev; | ||
963 | |||
964 | /* Request for firmware */ | ||
965 | err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
966 | HQVDP_FMW_NAME, hqvdp->dev, | ||
967 | GFP_KERNEL, hqvdp, sti_hqvdp_start_xp70); | ||
968 | if (err) { | ||
969 | DRM_ERROR("Can't get HQVDP firmware\n"); | ||
970 | return err; | ||
971 | } | ||
972 | |||
973 | layer = sti_layer_create(hqvdp->dev, STI_HQVDP_0, hqvdp->regs); | ||
974 | if (!layer) { | ||
975 | DRM_ERROR("Can't create HQVDP plane\n"); | ||
976 | return -ENOMEM; | ||
977 | } | ||
978 | |||
979 | sti_drm_plane_init(drm_dev, layer, 1, DRM_PLANE_TYPE_OVERLAY); | ||
980 | |||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static void sti_hqvdp_unbind(struct device *dev, | ||
985 | struct device *master, void *data) | ||
986 | { | ||
987 | /* do nothing */ | ||
988 | } | ||
989 | |||
990 | static const struct component_ops sti_hqvdp_ops = { | ||
991 | .bind = sti_hqvdp_bind, | ||
992 | .unbind = sti_hqvdp_unbind, | ||
993 | }; | ||
994 | |||
995 | static int sti_hqvdp_probe(struct platform_device *pdev) | ||
996 | { | ||
997 | struct device *dev = &pdev->dev; | ||
998 | struct device_node *vtg_np; | ||
999 | struct sti_hqvdp *hqvdp; | ||
1000 | struct resource *res; | ||
1001 | |||
1002 | DRM_DEBUG_DRIVER("\n"); | ||
1003 | |||
1004 | hqvdp = devm_kzalloc(dev, sizeof(*hqvdp), GFP_KERNEL); | ||
1005 | if (!hqvdp) { | ||
1006 | DRM_ERROR("Failed to allocate HQVDP context\n"); | ||
1007 | return -ENOMEM; | ||
1008 | } | ||
1009 | |||
1010 | hqvdp->dev = dev; | ||
1011 | |||
1012 | /* Get Memory resources */ | ||
1013 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1014 | if (res == NULL) { | ||
1015 | DRM_ERROR("Get memory resource failed\n"); | ||
1016 | return -ENXIO; | ||
1017 | } | ||
1018 | hqvdp->regs = devm_ioremap(dev, res->start, resource_size(res)); | ||
1019 | if (hqvdp->regs == NULL) { | ||
1020 | DRM_ERROR("Register mapping failed\n"); | ||
1021 | return -ENXIO; | ||
1022 | } | ||
1023 | |||
1024 | /* Get clock resources */ | ||
1025 | hqvdp->clk = devm_clk_get(dev, "hqvdp"); | ||
1026 | hqvdp->clk_pix_main = devm_clk_get(dev, "pix_main"); | ||
1027 | if (IS_ERR(hqvdp->clk) || IS_ERR(hqvdp->clk)) { | ||
1028 | DRM_ERROR("Cannot get clocks\n"); | ||
1029 | return -ENXIO; | ||
1030 | } | ||
1031 | |||
1032 | /* Get reset resources */ | ||
1033 | hqvdp->reset = devm_reset_control_get(dev, "hqvdp"); | ||
1034 | if (!IS_ERR(hqvdp->reset)) | ||
1035 | reset_control_deassert(hqvdp->reset); | ||
1036 | |||
1037 | vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0); | ||
1038 | if (vtg_np) | ||
1039 | hqvdp->vtg = of_vtg_find(vtg_np); | ||
1040 | |||
1041 | platform_set_drvdata(pdev, hqvdp); | ||
1042 | |||
1043 | return component_add(&pdev->dev, &sti_hqvdp_ops); | ||
1044 | } | ||
1045 | |||
1046 | static int sti_hqvdp_remove(struct platform_device *pdev) | ||
1047 | { | ||
1048 | component_del(&pdev->dev, &sti_hqvdp_ops); | ||
1049 | return 0; | ||
1050 | } | ||
1051 | |||
1052 | static struct of_device_id hqvdp_of_match[] = { | ||
1053 | { .compatible = "st,stih407-hqvdp", }, | ||
1054 | { /* end node */ } | ||
1055 | }; | ||
1056 | MODULE_DEVICE_TABLE(of, hqvdp_of_match); | ||
1057 | |||
1058 | struct platform_driver sti_hqvdp_driver = { | ||
1059 | .driver = { | ||
1060 | .name = "sti-hqvdp", | ||
1061 | .owner = THIS_MODULE, | ||
1062 | .of_match_table = hqvdp_of_match, | ||
1063 | }, | ||
1064 | .probe = sti_hqvdp_probe, | ||
1065 | .remove = sti_hqvdp_remove, | ||
1066 | }; | ||
1067 | |||
1068 | module_platform_driver(sti_hqvdp_driver); | ||
1069 | |||
1070 | MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); | ||
1071 | MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); | ||
1072 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.h b/drivers/gpu/drm/sti/sti_hqvdp.h new file mode 100644 index 000000000000..cd5ecd0a6dea --- /dev/null +++ b/drivers/gpu/drm/sti/sti_hqvdp.h | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2014 | ||
3 | * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | ||
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | ||
6 | |||
7 | #ifndef _STI_HQVDP_H_ | ||
8 | #define _STI_HQVDP_H_ | ||
9 | |||
10 | struct sti_layer *sti_hqvdp_create(struct device *dev); | ||
11 | |||
12 | #endif | ||
diff --git a/drivers/gpu/drm/sti/sti_hqvdp_lut.h b/drivers/gpu/drm/sti/sti_hqvdp_lut.h new file mode 100644 index 000000000000..619af7f4384e --- /dev/null +++ b/drivers/gpu/drm/sti/sti_hqvdp_lut.h | |||
@@ -0,0 +1,373 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics SA 2014 | ||
3 | * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. | ||
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | ||
6 | |||
7 | #ifndef _STI_HQVDP_LUT_H_ | ||
8 | #define _STI_HQVDP_LUT_H_ | ||
9 | |||
10 | #define NB_COEF 128 | ||
11 | |||
12 | #define SHIFT_LUT_A_LEGACY 8 | ||
13 | #define SHIFT_LUT_B 8 | ||
14 | #define SHIFT_LUT_C_Y_LEGACY 8 | ||
15 | #define SHIFT_LUT_C_C_LEGACY 8 | ||
16 | #define SHIFT_LUT_D_Y_LEGACY 8 | ||
17 | #define SHIFT_LUT_D_C_LEGACY 8 | ||
18 | #define SHIFT_LUT_E_Y_LEGACY 8 | ||
19 | #define SHIFT_LUT_E_C_LEGACY 8 | ||
20 | #define SHIFT_LUT_F_Y_LEGACY 8 | ||
21 | #define SHIFT_LUT_F_C_LEGACY 8 | ||
22 | |||
23 | static const u32 coef_lut_a_legacy[NB_COEF] = { | ||
24 | 0x0000ffff, 0x00010000, 0x000100ff, 0x00000000, | ||
25 | 0x00000000, 0x00050000, 0xfffc00ff, 0x00000000, | ||
26 | 0x00000000, 0x00090000, 0xfff900fe, 0x00000000, | ||
27 | 0x00000000, 0x0010ffff, 0xfff600fb, 0x00000000, | ||
28 | 0x00000000, 0x0017fffe, 0xfff400f7, 0x00000000, | ||
29 | 0x00000000, 0x001ffffd, 0xfff200f2, 0x00000000, | ||
30 | 0x00000000, 0x0027fffc, 0xfff100ec, 0x00000000, | ||
31 | 0x00000000, 0x0030fffb, 0xfff000e5, 0x00000000, | ||
32 | 0x00000000, 0x003afffa, 0xffee00de, 0x00000000, | ||
33 | 0x00000000, 0x0044fff9, 0xffed00d6, 0x00000000, | ||
34 | 0x00000000, 0x004efff8, 0xffed00cd, 0x00000000, | ||
35 | 0x00000000, 0x0059fff6, 0xffed00c4, 0x00000000, | ||
36 | 0x00000000, 0x0064fff5, 0xffed00ba, 0x00000000, | ||
37 | 0x00000000, 0x006ffff3, 0xffee00b0, 0x00000000, | ||
38 | 0x00000000, 0x007afff2, 0xffee00a6, 0x00000000, | ||
39 | 0x00000000, 0x0085fff1, 0xffef009b, 0x00000000, | ||
40 | 0x00000000, 0x0090fff0, 0xfff00090, 0x00000000, | ||
41 | 0x00000000, 0x009bffef, 0xfff10085, 0x00000000, | ||
42 | 0x00000000, 0x00a6ffee, 0xfff2007a, 0x00000000, | ||
43 | 0x00000000, 0x00b0ffee, 0xfff3006f, 0x00000000, | ||
44 | 0x00000000, 0x00baffed, 0xfff50064, 0x00000000, | ||
45 | 0x00000000, 0x00c4ffed, 0xfff60059, 0x00000000, | ||
46 | 0x00000000, 0x00cdffed, 0xfff8004e, 0x00000000, | ||
47 | 0x00000000, 0x00d6ffed, 0xfff90044, 0x00000000, | ||
48 | 0x00000000, 0x00deffee, 0xfffa003a, 0x00000000, | ||
49 | 0x00000000, 0x00e5fff0, 0xfffb0030, 0x00000000, | ||
50 | 0x00000000, 0x00ecfff1, 0xfffc0027, 0x00000000, | ||
51 | 0x00000000, 0x00f2fff2, 0xfffd001f, 0x00000000, | ||
52 | 0x00000000, 0x00f7fff4, 0xfffe0017, 0x00000000, | ||
53 | 0x00000000, 0x00fbfff6, 0xffff0010, 0x00000000, | ||
54 | 0x00000000, 0x00fefff9, 0x00000009, 0x00000000, | ||
55 | 0x00000000, 0x00fffffc, 0x00000005, 0x00000000 | ||
56 | }; | ||
57 | |||
58 | static const u32 coef_lut_b[NB_COEF] = { | ||
59 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
60 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
61 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
62 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
63 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
64 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
65 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
66 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
67 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
68 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
69 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
70 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
71 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
72 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
73 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
74 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
75 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
76 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
77 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
78 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
79 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
80 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
81 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
82 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
83 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
84 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
85 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
86 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
87 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
88 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
89 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, | ||
90 | 0x00000000, 0x00000000, 0x00000100, 0x00000000 | ||
91 | }; | ||
92 | |||
93 | static const u32 coef_lut_c_y_legacy[NB_COEF] = { | ||
94 | 0x00060004, 0x0038ffe1, 0x003800be, 0x0006ffe1, | ||
95 | 0x00050005, 0x0042ffe1, 0x003800b3, 0x0007ffe1, | ||
96 | 0x00040006, 0x0046ffe1, 0x003300b2, 0x0008ffe2, | ||
97 | 0x00030007, 0x004cffe1, 0x002e00b1, 0x0008ffe2, | ||
98 | 0x00020006, 0x0051ffe2, 0x002900b0, 0x0009ffe3, | ||
99 | 0x00010008, 0x0056ffe2, 0x002400ae, 0x0009ffe4, | ||
100 | 0xffff0008, 0x005cffe3, 0x001f00ad, 0x000affe4, | ||
101 | 0xfffe0008, 0x0062ffe4, 0x001a00ab, 0x000affe5, | ||
102 | 0xfffd000a, 0x0066ffe5, 0x001500a8, 0x000bffe6, | ||
103 | 0xfffc0009, 0x006bffe7, 0x001100a5, 0x000bffe8, | ||
104 | 0xfffa000a, 0x0070ffe8, 0x000d00a3, 0x000bffe9, | ||
105 | 0xfff9000b, 0x0076ffea, 0x0008009f, 0x000bffea, | ||
106 | 0xfff7000b, 0x007affec, 0x0005009b, 0x000cffec, | ||
107 | 0xfff6000b, 0x007effef, 0x00010098, 0x000cffed, | ||
108 | 0xfff4000b, 0x0084fff1, 0xfffd0095, 0x000cffee, | ||
109 | 0xfff3000b, 0x0088fff4, 0xfffa0090, 0x000cfff0, | ||
110 | 0xfff1000b, 0x008dfff7, 0xfff7008d, 0x000bfff1, | ||
111 | 0xfff0000c, 0x0090fffa, 0xfff40088, 0x000bfff3, | ||
112 | 0xffee000c, 0x0095fffd, 0xfff10084, 0x000bfff4, | ||
113 | 0xffed000c, 0x00980001, 0xffef007e, 0x000bfff6, | ||
114 | 0xffec000c, 0x009b0005, 0xffec007a, 0x000bfff7, | ||
115 | 0xffea000b, 0x009f0008, 0xffea0076, 0x000bfff9, | ||
116 | 0xffe9000b, 0x00a3000d, 0xffe80070, 0x000afffa, | ||
117 | 0xffe8000b, 0x00a50011, 0xffe7006b, 0x0009fffc, | ||
118 | 0xffe6000b, 0x00a80015, 0xffe50066, 0x000afffd, | ||
119 | 0xffe5000a, 0x00ab001a, 0xffe40062, 0x0008fffe, | ||
120 | 0xffe4000a, 0x00ad001f, 0xffe3005c, 0x0008ffff, | ||
121 | 0xffe40009, 0x00ae0024, 0xffe20056, 0x00080001, | ||
122 | 0xffe30009, 0x00b00029, 0xffe20051, 0x00060002, | ||
123 | 0xffe20008, 0x00b1002e, 0xffe1004c, 0x00070003, | ||
124 | 0xffe20008, 0x00b20033, 0xffe10046, 0x00060004, | ||
125 | 0xffe10007, 0x00b30038, 0xffe10042, 0x00050005 | ||
126 | }; | ||
127 | |||
128 | static const u32 coef_lut_c_c_legacy[NB_COEF] = { | ||
129 | 0x0001fff3, 0x003afffb, 0x003a00a1, 0x0001fffb, | ||
130 | 0x0001fff5, 0x0041fffb, 0x0038009a, 0x0001fffb, | ||
131 | 0x0001fff5, 0x0046fffb, 0x00340099, 0x0001fffb, | ||
132 | 0x0001fff7, 0x0049fffb, 0x00300098, 0x0001fffb, | ||
133 | 0x0001fff9, 0x004cfffb, 0x002d0096, 0x0001fffb, | ||
134 | 0x0001fffa, 0x004ffffc, 0x00290095, 0x0001fffb, | ||
135 | 0x0001fff9, 0x0054fffd, 0x00250093, 0x0001fffc, | ||
136 | 0x0001fffa, 0x0058fffd, 0x00220092, 0x0000fffc, | ||
137 | 0x0001fffb, 0x005bfffe, 0x001f0090, 0x0000fffc, | ||
138 | 0x0001fffd, 0x005effff, 0x001c008c, 0x0000fffd, | ||
139 | 0x0001fffd, 0x00620000, 0x0019008a, 0x0000fffd, | ||
140 | 0x0001fffe, 0x00660001, 0x00160088, 0xfffffffd, | ||
141 | 0x0000fffe, 0x006a0003, 0x00130085, 0xfffffffe, | ||
142 | 0x0000fffe, 0x006e0004, 0x00100083, 0xfffffffe, | ||
143 | 0x0000fffe, 0x00710006, 0x000e007f, 0xffffffff, | ||
144 | 0x0000fffe, 0x00750008, 0x000c007c, 0xfffeffff, | ||
145 | 0xfffffffe, 0x0079000a, 0x000a0079, 0xfffeffff, | ||
146 | 0xfffffffe, 0x007c000c, 0x00080075, 0xfffe0000, | ||
147 | 0xffffffff, 0x007f000e, 0x00060071, 0xfffe0000, | ||
148 | 0xfffeffff, 0x00830010, 0x0004006e, 0xfffe0000, | ||
149 | 0xfffeffff, 0x00850013, 0x0003006a, 0xfffe0000, | ||
150 | 0xfffdffff, 0x00880016, 0x00010066, 0xfffe0001, | ||
151 | 0xfffd0000, 0x008a0019, 0x00000062, 0xfffd0001, | ||
152 | 0xfffd0000, 0x008c001c, 0xffff005e, 0xfffd0001, | ||
153 | 0xfffc0000, 0x0090001f, 0xfffe005b, 0xfffb0001, | ||
154 | 0xfffc0000, 0x00920022, 0xfffd0058, 0xfffa0001, | ||
155 | 0xfffc0001, 0x00930025, 0xfffd0054, 0xfff90001, | ||
156 | 0xfffb0001, 0x00950029, 0xfffc004f, 0xfffa0001, | ||
157 | 0xfffb0001, 0x0096002d, 0xfffb004c, 0xfff90001, | ||
158 | 0xfffb0001, 0x00980030, 0xfffb0049, 0xfff70001, | ||
159 | 0xfffb0001, 0x00990034, 0xfffb0046, 0xfff50001, | ||
160 | 0xfffb0001, 0x009a0038, 0xfffb0041, 0xfff50001 | ||
161 | }; | ||
162 | |||
163 | static const u32 coef_lut_d_y_legacy[NB_COEF] = { | ||
164 | 0xfff80009, 0x0046ffec, 0x004600a3, 0xfff8ffec, | ||
165 | 0xfff70009, 0x004effed, 0x0044009d, 0xfff9ffeb, | ||
166 | 0xfff6000a, 0x0052ffee, 0x003f009d, 0xfffaffea, | ||
167 | 0xfff50009, 0x0057ffef, 0x003b009d, 0xfffbffe9, | ||
168 | 0xfff50008, 0x005bfff0, 0x0037009c, 0xfffcffe9, | ||
169 | 0xfff40008, 0x005ffff2, 0x0033009b, 0xfffcffe9, | ||
170 | 0xfff30007, 0x0064fff3, 0x002f009b, 0xfffdffe8, | ||
171 | 0xfff20007, 0x0068fff5, 0x002b0099, 0xfffeffe8, | ||
172 | 0xfff10008, 0x006bfff7, 0x00270097, 0xffffffe8, | ||
173 | 0xfff00007, 0x006ffff9, 0x00230097, 0xffffffe8, | ||
174 | 0xffef0006, 0x0073fffb, 0x00200095, 0x0000ffe8, | ||
175 | 0xffee0005, 0x0077fffe, 0x001c0093, 0x0000ffe9, | ||
176 | 0xffee0005, 0x007a0000, 0x00180091, 0x0001ffe9, | ||
177 | 0xffed0005, 0x007d0003, 0x0015008e, 0x0002ffe9, | ||
178 | 0xffec0005, 0x00800006, 0x0012008b, 0x0002ffea, | ||
179 | 0xffeb0004, 0x00840008, 0x000e008a, 0x0003ffea, | ||
180 | 0xffeb0003, 0x0087000b, 0x000b0087, 0x0003ffeb, | ||
181 | 0xffea0003, 0x008a000e, 0x00080084, 0x0004ffeb, | ||
182 | 0xffea0002, 0x008b0012, 0x00060080, 0x0005ffec, | ||
183 | 0xffe90002, 0x008e0015, 0x0003007d, 0x0005ffed, | ||
184 | 0xffe90001, 0x00910018, 0x0000007a, 0x0005ffee, | ||
185 | 0xffe90000, 0x0093001c, 0xfffe0077, 0x0005ffee, | ||
186 | 0xffe80000, 0x00950020, 0xfffb0073, 0x0006ffef, | ||
187 | 0xffe8ffff, 0x00970023, 0xfff9006f, 0x0007fff0, | ||
188 | 0xffe8ffff, 0x00970027, 0xfff7006b, 0x0008fff1, | ||
189 | 0xffe8fffe, 0x0099002b, 0xfff50068, 0x0007fff2, | ||
190 | 0xffe8fffd, 0x009b002f, 0xfff30064, 0x0007fff3, | ||
191 | 0xffe9fffc, 0x009b0033, 0xfff2005f, 0x0008fff4, | ||
192 | 0xffe9fffc, 0x009c0037, 0xfff0005b, 0x0008fff5, | ||
193 | 0xffe9fffb, 0x009d003b, 0xffef0057, 0x0009fff5, | ||
194 | 0xffeafffa, 0x009d003f, 0xffee0052, 0x000afff6, | ||
195 | 0xffebfff9, 0x009d0044, 0xffed004e, 0x0009fff7 | ||
196 | }; | ||
197 | |||
198 | static const u32 coef_lut_d_c_legacy[NB_COEF] = { | ||
199 | 0xfffeffff, 0x003fffff, 0x003f0089, 0xfffeffff, | ||
200 | 0xfffe0000, 0x00460000, 0x0042007d, 0xfffffffe, | ||
201 | 0xfffe0000, 0x00490001, 0x003f007d, 0xfffffffd, | ||
202 | 0xfffd0001, 0x004b0002, 0x003c007d, 0x0000fffc, | ||
203 | 0xfffd0001, 0x004e0003, 0x0039007c, 0x0000fffc, | ||
204 | 0xfffc0001, 0x00510005, 0x0036007c, 0x0000fffb, | ||
205 | 0xfffc0001, 0x00540006, 0x0033007b, 0x0001fffa, | ||
206 | 0xfffc0003, 0x00550008, 0x00310078, 0x0001fffa, | ||
207 | 0xfffb0003, 0x00580009, 0x002e0078, 0x0001fffa, | ||
208 | 0xfffb0002, 0x005b000b, 0x002b0077, 0x0002fff9, | ||
209 | 0xfffa0003, 0x005e000d, 0x00280075, 0x0002fff9, | ||
210 | 0xfffa0002, 0x0060000f, 0x00260074, 0x0002fff9, | ||
211 | 0xfffa0004, 0x00610011, 0x00230072, 0x0002fff9, | ||
212 | 0xfffa0004, 0x00640013, 0x00200070, 0x0002fff9, | ||
213 | 0xfff90004, 0x00660015, 0x001e006e, 0x0003fff9, | ||
214 | 0xfff90004, 0x00680017, 0x001c006c, 0x0003fff9, | ||
215 | 0xfff90003, 0x006b0019, 0x0019006b, 0x0003fff9, | ||
216 | 0xfff90003, 0x006c001c, 0x00170068, 0x0004fff9, | ||
217 | 0xfff90003, 0x006e001e, 0x00150066, 0x0004fff9, | ||
218 | 0xfff90002, 0x00700020, 0x00130064, 0x0004fffa, | ||
219 | 0xfff90002, 0x00720023, 0x00110061, 0x0004fffa, | ||
220 | 0xfff90002, 0x00740026, 0x000f0060, 0x0002fffa, | ||
221 | 0xfff90002, 0x00750028, 0x000d005e, 0x0003fffa, | ||
222 | 0xfff90002, 0x0077002b, 0x000b005b, 0x0002fffb, | ||
223 | 0xfffa0001, 0x0078002e, 0x00090058, 0x0003fffb, | ||
224 | 0xfffa0001, 0x00780031, 0x00080055, 0x0003fffc, | ||
225 | 0xfffa0001, 0x007b0033, 0x00060054, 0x0001fffc, | ||
226 | 0xfffb0000, 0x007c0036, 0x00050051, 0x0001fffc, | ||
227 | 0xfffc0000, 0x007c0039, 0x0003004e, 0x0001fffd, | ||
228 | 0xfffc0000, 0x007d003c, 0x0002004b, 0x0001fffd, | ||
229 | 0xfffdffff, 0x007d003f, 0x00010049, 0x0000fffe, | ||
230 | 0xfffeffff, 0x007d0042, 0x00000046, 0x0000fffe | ||
231 | }; | ||
232 | |||
233 | static const u32 coef_lut_e_y_legacy[NB_COEF] = { | ||
234 | 0xfff10001, 0x00490004, 0x00490083, 0xfff10004, | ||
235 | 0xfff10000, 0x00500006, 0x004b007b, 0xfff10002, | ||
236 | 0xfff10000, 0x00530007, 0x0048007b, 0xfff10001, | ||
237 | 0xfff10000, 0x00550009, 0x0046007a, 0xfff10000, | ||
238 | 0xfff1fffe, 0x0058000b, 0x0043007b, 0xfff2fffe, | ||
239 | 0xfff1ffff, 0x005a000d, 0x0040007a, 0xfff2fffd, | ||
240 | 0xfff1fffd, 0x005d000f, 0x003e007a, 0xfff2fffc, | ||
241 | 0xfff1fffd, 0x005f0011, 0x003b0079, 0xfff3fffb, | ||
242 | 0xfff1fffc, 0x00610013, 0x00390079, 0xfff3fffa, | ||
243 | 0xfff1fffb, 0x00640015, 0x00360079, 0xfff3fff9, | ||
244 | 0xfff1fffa, 0x00660017, 0x00340078, 0xfff4fff8, | ||
245 | 0xfff1fffb, 0x00680019, 0x00310077, 0xfff4fff7, | ||
246 | 0xfff2fff9, 0x006a001b, 0x002f0076, 0xfff5fff6, | ||
247 | 0xfff2fff9, 0x006c001e, 0x002c0075, 0xfff5fff5, | ||
248 | 0xfff2fff9, 0x006d0020, 0x002a0073, 0xfff6fff5, | ||
249 | 0xfff3fff7, 0x00700022, 0x00270073, 0xfff6fff4, | ||
250 | 0xfff3fff7, 0x00710025, 0x00250071, 0xfff7fff3, | ||
251 | 0xfff4fff6, 0x00730027, 0x00220070, 0xfff7fff3, | ||
252 | 0xfff5fff6, 0x0073002a, 0x0020006d, 0xfff9fff2, | ||
253 | 0xfff5fff5, 0x0075002c, 0x001e006c, 0xfff9fff2, | ||
254 | 0xfff6fff5, 0x0076002f, 0x001b006a, 0xfff9fff2, | ||
255 | 0xfff7fff4, 0x00770031, 0x00190068, 0xfffbfff1, | ||
256 | 0xfff8fff4, 0x00780034, 0x00170066, 0xfffafff1, | ||
257 | 0xfff9fff3, 0x00790036, 0x00150064, 0xfffbfff1, | ||
258 | 0xfffafff3, 0x00790039, 0x00130061, 0xfffcfff1, | ||
259 | 0xfffbfff3, 0x0079003b, 0x0011005f, 0xfffdfff1, | ||
260 | 0xfffcfff2, 0x007a003e, 0x000f005d, 0xfffdfff1, | ||
261 | 0xfffdfff2, 0x007a0040, 0x000d005a, 0xfffffff1, | ||
262 | 0xfffefff2, 0x007b0043, 0x000b0058, 0xfffefff1, | ||
263 | 0x0000fff1, 0x007a0046, 0x00090055, 0x0000fff1, | ||
264 | 0x0001fff1, 0x007b0048, 0x00070053, 0x0000fff1, | ||
265 | 0x0002fff1, 0x007b004b, 0x00060050, 0x0000fff1 | ||
266 | }; | ||
267 | |||
268 | static const u32 coef_lut_e_c_legacy[NB_COEF] = { | ||
269 | 0xfffa0001, 0x003f0010, 0x003f006d, 0xfffa0010, | ||
270 | 0xfffb0002, 0x00440011, 0x00440062, 0xfffa000e, | ||
271 | 0xfffb0001, 0x00460013, 0x00420062, 0xfffa000d, | ||
272 | 0xfffb0000, 0x00480014, 0x00410062, 0xfffa000c, | ||
273 | 0xfffb0001, 0x00490015, 0x003f0061, 0xfffb000b, | ||
274 | 0xfffb0000, 0x004b0017, 0x003d0061, 0xfffb000a, | ||
275 | 0xfffb0000, 0x004d0018, 0x003b0062, 0xfffb0008, | ||
276 | 0xfffcffff, 0x004f001a, 0x00390061, 0xfffb0007, | ||
277 | 0xfffc0000, 0x004f001c, 0x00380060, 0xfffb0006, | ||
278 | 0xfffcffff, 0x0052001d, 0x00360060, 0xfffb0005, | ||
279 | 0xfffdfffe, 0x0053001f, 0x00340060, 0xfffb0004, | ||
280 | 0xfffdfffe, 0x00540021, 0x0032005e, 0xfffc0004, | ||
281 | 0xfffeffff, 0x00550022, 0x0030005d, 0xfffc0003, | ||
282 | 0xfffeffff, 0x00560024, 0x002f005c, 0xfffc0002, | ||
283 | 0xfffffffd, 0x00580026, 0x002d005c, 0xfffc0001, | ||
284 | 0xfffffffd, 0x005a0027, 0x002b005c, 0xfffc0000, | ||
285 | 0x0000fffd, 0x005a0029, 0x0029005a, 0xfffd0000, | ||
286 | 0x0000fffc, 0x005c002b, 0x0027005a, 0xfffdffff, | ||
287 | 0x0001fffc, 0x005c002d, 0x00260058, 0xfffdffff, | ||
288 | 0x0002fffc, 0x005c002f, 0x00240056, 0xfffffffe, | ||
289 | 0x0003fffc, 0x005d0030, 0x00220055, 0xfffffffe, | ||
290 | 0x0004fffc, 0x005e0032, 0x00210054, 0xfffefffd, | ||
291 | 0x0004fffb, 0x00600034, 0x001f0053, 0xfffefffd, | ||
292 | 0x0005fffb, 0x00600036, 0x001d0052, 0xfffffffc, | ||
293 | 0x0006fffb, 0x00600038, 0x001c004f, 0x0000fffc, | ||
294 | 0x0007fffb, 0x00610039, 0x001a004f, 0xfffffffc, | ||
295 | 0x0008fffb, 0x0062003b, 0x0018004d, 0x0000fffb, | ||
296 | 0x000afffb, 0x0061003d, 0x0017004b, 0x0000fffb, | ||
297 | 0x000bfffb, 0x0061003f, 0x00150049, 0x0001fffb, | ||
298 | 0x000cfffa, 0x00620041, 0x00140048, 0x0000fffb, | ||
299 | 0x000dfffa, 0x00620042, 0x00130046, 0x0001fffb, | ||
300 | 0x000efffa, 0x00620044, 0x00110044, 0x0002fffb | ||
301 | }; | ||
302 | |||
303 | static const u32 coef_lut_f_y_legacy[NB_COEF] = { | ||
304 | 0xfff6fff0, 0x00490012, 0x0049006e, 0xfff60012, | ||
305 | 0xfff7fff1, 0x004e0013, 0x00490068, 0xfff60010, | ||
306 | 0xfff7fff2, 0x004f0015, 0x00470067, 0xfff6000f, | ||
307 | 0xfff7fff5, 0x004f0017, 0x00450065, 0xfff6000e, | ||
308 | 0xfff8fff5, 0x00500018, 0x00440065, 0xfff6000c, | ||
309 | 0xfff8fff6, 0x0051001a, 0x00420064, 0xfff6000b, | ||
310 | 0xfff8fff6, 0x0052001c, 0x00400064, 0xfff6000a, | ||
311 | 0xfff9fff6, 0x0054001d, 0x003e0064, 0xfff60008, | ||
312 | 0xfff9fff8, 0x0054001f, 0x003c0063, 0xfff60007, | ||
313 | 0xfffafff8, 0x00550021, 0x003a0062, 0xfff60006, | ||
314 | 0xfffbfff7, 0x00560022, 0x00390062, 0xfff60005, | ||
315 | 0xfffbfff8, 0x00570024, 0x00370061, 0xfff60004, | ||
316 | 0xfffcfff8, 0x00580026, 0x00350060, 0xfff60003, | ||
317 | 0xfffdfff8, 0x00590028, 0x0033005f, 0xfff60002, | ||
318 | 0xfffdfff7, 0x005b002a, 0x0031005f, 0xfff60001, | ||
319 | 0xfffefff7, 0x005c002c, 0x002f005e, 0xfff60000, | ||
320 | 0xfffffff6, 0x005e002d, 0x002d005e, 0xfff6ffff, | ||
321 | 0x0000fff6, 0x005e002f, 0x002c005c, 0xfff7fffe, | ||
322 | 0x0001fff6, 0x005f0031, 0x002a005b, 0xfff7fffd, | ||
323 | 0x0002fff6, 0x005f0033, 0x00280059, 0xfff8fffd, | ||
324 | 0x0003fff6, 0x00600035, 0x00260058, 0xfff8fffc, | ||
325 | 0x0004fff6, 0x00610037, 0x00240057, 0xfff8fffb, | ||
326 | 0x0005fff6, 0x00620039, 0x00220056, 0xfff7fffb, | ||
327 | 0x0006fff6, 0x0062003a, 0x00210055, 0xfff8fffa, | ||
328 | 0x0007fff6, 0x0063003c, 0x001f0054, 0xfff8fff9, | ||
329 | 0x0008fff6, 0x0064003e, 0x001d0054, 0xfff6fff9, | ||
330 | 0x000afff6, 0x00640040, 0x001c0052, 0xfff6fff8, | ||
331 | 0x000bfff6, 0x00640042, 0x001a0051, 0xfff6fff8, | ||
332 | 0x000cfff6, 0x00650044, 0x00180050, 0xfff5fff8, | ||
333 | 0x000efff6, 0x00650045, 0x0017004f, 0xfff5fff7, | ||
334 | 0x000ffff6, 0x00670047, 0x0015004f, 0xfff2fff7, | ||
335 | 0x0010fff6, 0x00680049, 0x0013004e, 0xfff1fff7 | ||
336 | }; | ||
337 | |||
338 | static const u32 coef_lut_f_c_legacy[NB_COEF] = { | ||
339 | 0x0000fffb, 0x003a001a, 0x003a005d, 0x0000001a, | ||
340 | 0x0001fffb, 0x003f001b, 0x00400051, 0x00000019, | ||
341 | 0x0001fffc, 0x0040001c, 0x003f0051, 0x00000017, | ||
342 | 0x0002fffb, 0x0042001d, 0x003e0051, 0xffff0016, | ||
343 | 0x0002fffb, 0x0043001e, 0x003d0051, 0xffff0015, | ||
344 | 0x0003fffc, 0x00430020, 0x003b0050, 0xffff0014, | ||
345 | 0x0003fffb, 0x00450021, 0x003a0051, 0xfffe0013, | ||
346 | 0x0004fffc, 0x00450022, 0x00390050, 0xfffe0012, | ||
347 | 0x0005fffc, 0x00460023, 0x0038004f, 0xfffe0011, | ||
348 | 0x0005fffb, 0x00480025, 0x00360050, 0xfffd0010, | ||
349 | 0x0006fffc, 0x00480026, 0x0035004f, 0xfffd000f, | ||
350 | 0x0006fffc, 0x00490027, 0x0034004f, 0xfffd000e, | ||
351 | 0x0007fffd, 0x00490028, 0x0033004e, 0xfffd000d, | ||
352 | 0x0008fffc, 0x004a002a, 0x0031004d, 0xfffd000d, | ||
353 | 0x0009fffd, 0x004a002b, 0x0030004d, 0xfffc000c, | ||
354 | 0x0009fffc, 0x004c002c, 0x002f004d, 0xfffc000b, | ||
355 | 0x000afffc, 0x004c002e, 0x002e004c, 0xfffc000a, | ||
356 | 0x000bfffc, 0x004d002f, 0x002c004c, 0xfffc0009, | ||
357 | 0x000cfffc, 0x004d0030, 0x002b004a, 0xfffd0009, | ||
358 | 0x000dfffd, 0x004d0031, 0x002a004a, 0xfffc0008, | ||
359 | 0x000dfffd, 0x004e0033, 0x00280049, 0xfffd0007, | ||
360 | 0x000efffd, 0x004f0034, 0x00270049, 0xfffc0006, | ||
361 | 0x000ffffd, 0x004f0035, 0x00260048, 0xfffc0006, | ||
362 | 0x0010fffd, 0x00500036, 0x00250048, 0xfffb0005, | ||
363 | 0x0011fffe, 0x004f0038, 0x00230046, 0xfffc0005, | ||
364 | 0x0012fffe, 0x00500039, 0x00220045, 0xfffc0004, | ||
365 | 0x0013fffe, 0x0051003a, 0x00210045, 0xfffb0003, | ||
366 | 0x0014ffff, 0x0050003b, 0x00200043, 0xfffc0003, | ||
367 | 0x0015ffff, 0x0051003d, 0x001e0043, 0xfffb0002, | ||
368 | 0x0016ffff, 0x0051003e, 0x001d0042, 0xfffb0002, | ||
369 | 0x00170000, 0x0051003f, 0x001c0040, 0xfffc0001, | ||
370 | 0x00190000, 0x00510040, 0x001b003f, 0xfffb0001 | ||
371 | }; | ||
372 | |||
373 | #endif | ||
diff --git a/drivers/gpu/drm/sti/sti_layer.c b/drivers/gpu/drm/sti/sti_layer.c index 06a587c4f1bb..480ec1c974e2 100644 --- a/drivers/gpu/drm/sti/sti_layer.c +++ b/drivers/gpu/drm/sti/sti_layer.c | |||
@@ -11,7 +11,9 @@ | |||
11 | #include <drm/drm_fb_cma_helper.h> | 11 | #include <drm/drm_fb_cma_helper.h> |
12 | 12 | ||
13 | #include "sti_compositor.h" | 13 | #include "sti_compositor.h" |
14 | #include "sti_cursor.h" | ||
14 | #include "sti_gdp.h" | 15 | #include "sti_gdp.h" |
16 | #include "sti_hqvdp.h" | ||
15 | #include "sti_layer.h" | 17 | #include "sti_layer.h" |
16 | #include "sti_vid.h" | 18 | #include "sti_vid.h" |
17 | 19 | ||
@@ -32,6 +34,8 @@ const char *sti_layer_to_str(struct sti_layer *layer) | |||
32 | return "VID1"; | 34 | return "VID1"; |
33 | case STI_CURSOR: | 35 | case STI_CURSOR: |
34 | return "CURSOR"; | 36 | return "CURSOR"; |
37 | case STI_HQVDP_0: | ||
38 | return "HQVDP0"; | ||
35 | default: | 39 | default: |
36 | return "<UNKNOWN LAYER>"; | 40 | return "<UNKNOWN LAYER>"; |
37 | } | 41 | } |
@@ -50,6 +54,12 @@ struct sti_layer *sti_layer_create(struct device *dev, int desc, | |||
50 | case STI_VID: | 54 | case STI_VID: |
51 | layer = sti_vid_create(dev); | 55 | layer = sti_vid_create(dev); |
52 | break; | 56 | break; |
57 | case STI_CUR: | ||
58 | layer = sti_cursor_create(dev); | ||
59 | break; | ||
60 | case STI_VDP: | ||
61 | layer = sti_hqvdp_create(dev); | ||
62 | break; | ||
53 | } | 63 | } |
54 | 64 | ||
55 | if (!layer) { | 65 | if (!layer) { |
@@ -68,7 +78,9 @@ struct sti_layer *sti_layer_create(struct device *dev, int desc, | |||
68 | return layer; | 78 | return layer; |
69 | } | 79 | } |
70 | 80 | ||
71 | int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, | 81 | int sti_layer_prepare(struct sti_layer *layer, |
82 | struct drm_crtc *crtc, | ||
83 | struct drm_framebuffer *fb, | ||
72 | struct drm_display_mode *mode, int mixer_id, | 84 | struct drm_display_mode *mode, int mixer_id, |
73 | int dest_x, int dest_y, int dest_w, int dest_h, | 85 | int dest_x, int dest_y, int dest_w, int dest_h, |
74 | int src_x, int src_y, int src_w, int src_h) | 86 | int src_x, int src_y, int src_w, int src_h) |
@@ -88,6 +100,7 @@ int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, | |||
88 | return 1; | 100 | return 1; |
89 | } | 101 | } |
90 | 102 | ||
103 | layer->crtc = crtc; | ||
91 | layer->fb = fb; | 104 | layer->fb = fb; |
92 | layer->mode = mode; | 105 | layer->mode = mode; |
93 | layer->mixer_id = mixer_id; | 106 | layer->mixer_id = mixer_id; |
@@ -100,6 +113,7 @@ int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, | |||
100 | layer->src_w = src_w; | 113 | layer->src_w = src_w; |
101 | layer->src_h = src_h; | 114 | layer->src_h = src_h; |
102 | layer->format = fb->pixel_format; | 115 | layer->format = fb->pixel_format; |
116 | layer->vaddr = cma_obj->vaddr; | ||
103 | layer->paddr = cma_obj->paddr; | 117 | layer->paddr = cma_obj->paddr; |
104 | for (i = 0; i < 4; i++) { | 118 | for (i = 0; i < 4; i++) { |
105 | layer->pitches[i] = fb->pitches[i]; | 119 | layer->pitches[i] = fb->pitches[i]; |
diff --git a/drivers/gpu/drm/sti/sti_layer.h b/drivers/gpu/drm/sti/sti_layer.h index 198c3774cc12..ceff497f557e 100644 --- a/drivers/gpu/drm/sti/sti_layer.h +++ b/drivers/gpu/drm/sti/sti_layer.h | |||
@@ -22,7 +22,8 @@ enum sti_layer_type { | |||
22 | STI_GDP = 1 << STI_LAYER_TYPE_SHIFT, | 22 | STI_GDP = 1 << STI_LAYER_TYPE_SHIFT, |
23 | STI_VID = 2 << STI_LAYER_TYPE_SHIFT, | 23 | STI_VID = 2 << STI_LAYER_TYPE_SHIFT, |
24 | STI_CUR = 3 << STI_LAYER_TYPE_SHIFT, | 24 | STI_CUR = 3 << STI_LAYER_TYPE_SHIFT, |
25 | STI_BCK = 4 << STI_LAYER_TYPE_SHIFT | 25 | STI_BCK = 4 << STI_LAYER_TYPE_SHIFT, |
26 | STI_VDP = 5 << STI_LAYER_TYPE_SHIFT | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | enum sti_layer_id_of_type { | 29 | enum sti_layer_id_of_type { |
@@ -39,6 +40,7 @@ enum sti_layer_desc { | |||
39 | STI_GDP_3 = STI_GDP | STI_ID_3, | 40 | STI_GDP_3 = STI_GDP | STI_ID_3, |
40 | STI_VID_0 = STI_VID | STI_ID_0, | 41 | STI_VID_0 = STI_VID | STI_ID_0, |
41 | STI_VID_1 = STI_VID | STI_ID_1, | 42 | STI_VID_1 = STI_VID | STI_ID_1, |
43 | STI_HQVDP_0 = STI_VDP | STI_ID_0, | ||
42 | STI_CURSOR = STI_CUR, | 44 | STI_CURSOR = STI_CUR, |
43 | STI_BACK = STI_BCK | 45 | STI_BACK = STI_BCK |
44 | }; | 46 | }; |
@@ -67,6 +69,7 @@ struct sti_layer_funcs { | |||
67 | * | 69 | * |
68 | * @plane: drm plane it is bound to (if any) | 70 | * @plane: drm plane it is bound to (if any) |
69 | * @fb: drm fb it is bound to | 71 | * @fb: drm fb it is bound to |
72 | * @crtc: crtc it is bound to | ||
70 | * @mode: display mode | 73 | * @mode: display mode |
71 | * @desc: layer type & id | 74 | * @desc: layer type & id |
72 | * @device: driver device | 75 | * @device: driver device |
@@ -82,11 +85,13 @@ struct sti_layer_funcs { | |||
82 | * @format: format | 85 | * @format: format |
83 | * @pitches: pitch of 'planes' (eg: Y, U, V) | 86 | * @pitches: pitch of 'planes' (eg: Y, U, V) |
84 | * @offsets: offset of 'planes' | 87 | * @offsets: offset of 'planes' |
88 | * @vaddr: virtual address of the input buffer | ||
85 | * @paddr: physical address of the input buffer | 89 | * @paddr: physical address of the input buffer |
86 | */ | 90 | */ |
87 | struct sti_layer { | 91 | struct sti_layer { |
88 | struct drm_plane plane; | 92 | struct drm_plane plane; |
89 | struct drm_framebuffer *fb; | 93 | struct drm_framebuffer *fb; |
94 | struct drm_crtc *crtc; | ||
90 | struct drm_display_mode *mode; | 95 | struct drm_display_mode *mode; |
91 | enum sti_layer_desc desc; | 96 | enum sti_layer_desc desc; |
92 | struct device *dev; | 97 | struct device *dev; |
@@ -102,12 +107,15 @@ struct sti_layer { | |||
102 | uint32_t format; | 107 | uint32_t format; |
103 | unsigned int pitches[4]; | 108 | unsigned int pitches[4]; |
104 | unsigned int offsets[4]; | 109 | unsigned int offsets[4]; |
110 | void *vaddr; | ||
105 | dma_addr_t paddr; | 111 | dma_addr_t paddr; |
106 | }; | 112 | }; |
107 | 113 | ||
108 | struct sti_layer *sti_layer_create(struct device *dev, int desc, | 114 | struct sti_layer *sti_layer_create(struct device *dev, int desc, |
109 | void __iomem *baseaddr); | 115 | void __iomem *baseaddr); |
110 | int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, | 116 | int sti_layer_prepare(struct sti_layer *layer, |
117 | struct drm_crtc *crtc, | ||
118 | struct drm_framebuffer *fb, | ||
111 | struct drm_display_mode *mode, | 119 | struct drm_display_mode *mode, |
112 | int mixer_id, | 120 | int mixer_id, |
113 | int dest_x, int dest_y, | 121 | int dest_x, int dest_y, |
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c index 79f369db9fb6..13a4b84deab6 100644 --- a/drivers/gpu/drm/sti/sti_mixer.c +++ b/drivers/gpu/drm/sti/sti_mixer.c | |||
@@ -45,6 +45,7 @@ static const u32 mixerColorSpaceMatIdentity[] = { | |||
45 | #define GAM_CTL_GDP1_MASK BIT(4) | 45 | #define GAM_CTL_GDP1_MASK BIT(4) |
46 | #define GAM_CTL_GDP2_MASK BIT(5) | 46 | #define GAM_CTL_GDP2_MASK BIT(5) |
47 | #define GAM_CTL_GDP3_MASK BIT(6) | 47 | #define GAM_CTL_GDP3_MASK BIT(6) |
48 | #define GAM_CTL_CURSOR_MASK BIT(9) | ||
48 | 49 | ||
49 | const char *sti_mixer_to_str(struct sti_mixer *mixer) | 50 | const char *sti_mixer_to_str(struct sti_mixer *mixer) |
50 | { | 51 | { |
@@ -122,11 +123,15 @@ int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer) | |||
122 | layer_id = GAM_DEPTH_GDP3_ID; | 123 | layer_id = GAM_DEPTH_GDP3_ID; |
123 | break; | 124 | break; |
124 | case STI_VID_0: | 125 | case STI_VID_0: |
126 | case STI_HQVDP_0: | ||
125 | layer_id = GAM_DEPTH_VID0_ID; | 127 | layer_id = GAM_DEPTH_VID0_ID; |
126 | break; | 128 | break; |
127 | case STI_VID_1: | 129 | case STI_VID_1: |
128 | layer_id = GAM_DEPTH_VID1_ID; | 130 | layer_id = GAM_DEPTH_VID1_ID; |
129 | break; | 131 | break; |
132 | case STI_CURSOR: | ||
133 | /* no need to set depth for cursor */ | ||
134 | return 0; | ||
130 | default: | 135 | default: |
131 | DRM_ERROR("Unknown layer %d\n", layer->desc); | 136 | DRM_ERROR("Unknown layer %d\n", layer->desc); |
132 | return 1; | 137 | return 1; |
@@ -185,9 +190,12 @@ static u32 sti_mixer_get_layer_mask(struct sti_layer *layer) | |||
185 | case STI_GDP_3: | 190 | case STI_GDP_3: |
186 | return GAM_CTL_GDP3_MASK; | 191 | return GAM_CTL_GDP3_MASK; |
187 | case STI_VID_0: | 192 | case STI_VID_0: |
193 | case STI_HQVDP_0: | ||
188 | return GAM_CTL_VID0_MASK; | 194 | return GAM_CTL_VID0_MASK; |
189 | case STI_VID_1: | 195 | case STI_VID_1: |
190 | return GAM_CTL_VID1_MASK; | 196 | return GAM_CTL_VID1_MASK; |
197 | case STI_CURSOR: | ||
198 | return GAM_CTL_CURSOR_MASK; | ||
191 | default: | 199 | default: |
192 | return 0; | 200 | return 0; |
193 | } | 201 | } |
@@ -215,6 +223,15 @@ int sti_mixer_set_layer_status(struct sti_mixer *mixer, | |||
215 | return 0; | 223 | return 0; |
216 | } | 224 | } |
217 | 225 | ||
226 | void sti_mixer_clear_all_layers(struct sti_mixer *mixer) | ||
227 | { | ||
228 | u32 val; | ||
229 | |||
230 | DRM_DEBUG_DRIVER("%s clear all layer\n", sti_mixer_to_str(mixer)); | ||
231 | val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL) & 0xFFFF0000; | ||
232 | sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val); | ||
233 | } | ||
234 | |||
218 | void sti_mixer_set_matrix(struct sti_mixer *mixer) | 235 | void sti_mixer_set_matrix(struct sti_mixer *mixer) |
219 | { | 236 | { |
220 | unsigned int i; | 237 | unsigned int i; |
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h index 874372102e52..b97282182908 100644 --- a/drivers/gpu/drm/sti/sti_mixer.h +++ b/drivers/gpu/drm/sti/sti_mixer.h | |||
@@ -23,6 +23,7 @@ | |||
23 | * @id: id of the mixer | 23 | * @id: id of the mixer |
24 | * @drm_crtc: crtc object link to the mixer | 24 | * @drm_crtc: crtc object link to the mixer |
25 | * @pending_event: set if a flip event is pending on crtc | 25 | * @pending_event: set if a flip event is pending on crtc |
26 | * @enabled: to know if the mixer is active or not | ||
26 | */ | 27 | */ |
27 | struct sti_mixer { | 28 | struct sti_mixer { |
28 | struct device *dev; | 29 | struct device *dev; |
@@ -30,6 +31,7 @@ struct sti_mixer { | |||
30 | int id; | 31 | int id; |
31 | struct drm_crtc drm_crtc; | 32 | struct drm_crtc drm_crtc; |
32 | struct drm_pending_vblank_event *pending_event; | 33 | struct drm_pending_vblank_event *pending_event; |
34 | bool enabled; | ||
33 | }; | 35 | }; |
34 | 36 | ||
35 | const char *sti_mixer_to_str(struct sti_mixer *mixer); | 37 | const char *sti_mixer_to_str(struct sti_mixer *mixer); |
@@ -39,6 +41,7 @@ struct sti_mixer *sti_mixer_create(struct device *dev, int id, | |||
39 | 41 | ||
40 | int sti_mixer_set_layer_status(struct sti_mixer *mixer, | 42 | int sti_mixer_set_layer_status(struct sti_mixer *mixer, |
41 | struct sti_layer *layer, bool status); | 43 | struct sti_layer *layer, bool status); |
44 | void sti_mixer_clear_all_layers(struct sti_mixer *mixer); | ||
42 | int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer); | 45 | int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer); |
43 | int sti_mixer_active_video_area(struct sti_mixer *mixer, | 46 | int sti_mixer_active_video_area(struct sti_mixer *mixer, |
44 | struct drm_display_mode *mode); | 47 | struct drm_display_mode *mode); |
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index b8afe490356a..cb924aa2b321 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <drm/drmP.h> | 16 | #include <drm/drmP.h> |
17 | #include <drm/drm_crtc_helper.h> | 17 | #include <drm/drm_crtc_helper.h> |
18 | 18 | ||
19 | #include "sti_drm_crtc.h" | ||
20 | |||
19 | /* glue registers */ | 21 | /* glue registers */ |
20 | #define TVO_CSC_MAIN_M0 0x000 | 22 | #define TVO_CSC_MAIN_M0 0x000 |
21 | #define TVO_CSC_MAIN_M1 0x004 | 23 | #define TVO_CSC_MAIN_M1 0x004 |
@@ -96,7 +98,7 @@ | |||
96 | 98 | ||
97 | #define TVO_SYNC_HD_DCS_SHIFT 8 | 99 | #define TVO_SYNC_HD_DCS_SHIFT 8 |
98 | 100 | ||
99 | #define ENCODER_MAIN_CRTC_MASK BIT(0) | 101 | #define ENCODER_CRTC_MASK (BIT(0) | BIT(1)) |
100 | 102 | ||
101 | /* enum listing the supported output data format */ | 103 | /* enum listing the supported output data format */ |
102 | enum sti_tvout_video_out_type { | 104 | enum sti_tvout_video_out_type { |
@@ -149,14 +151,15 @@ static void tvout_write(struct sti_tvout *tvout, u32 val, int offset) | |||
149 | * Set the clipping mode of a VIP | 151 | * Set the clipping mode of a VIP |
150 | * | 152 | * |
151 | * @tvout: tvout structure | 153 | * @tvout: tvout structure |
154 | * @reg: register to set | ||
152 | * @cr_r: | 155 | * @cr_r: |
153 | * @y_g: | 156 | * @y_g: |
154 | * @cb_b: | 157 | * @cb_b: |
155 | */ | 158 | */ |
156 | static void tvout_vip_set_color_order(struct sti_tvout *tvout, | 159 | static void tvout_vip_set_color_order(struct sti_tvout *tvout, int reg, |
157 | u32 cr_r, u32 y_g, u32 cb_b) | 160 | u32 cr_r, u32 y_g, u32 cb_b) |
158 | { | 161 | { |
159 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 162 | u32 val = tvout_read(tvout, reg); |
160 | 163 | ||
161 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT); | 164 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT); |
162 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT); | 165 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT); |
@@ -165,52 +168,58 @@ static void tvout_vip_set_color_order(struct sti_tvout *tvout, | |||
165 | val |= y_g << TVO_VIP_REORDER_G_SHIFT; | 168 | val |= y_g << TVO_VIP_REORDER_G_SHIFT; |
166 | val |= cb_b << TVO_VIP_REORDER_B_SHIFT; | 169 | val |= cb_b << TVO_VIP_REORDER_B_SHIFT; |
167 | 170 | ||
168 | tvout_write(tvout, val, TVO_VIP_HDMI); | 171 | tvout_write(tvout, val, reg); |
169 | } | 172 | } |
170 | 173 | ||
171 | /** | 174 | /** |
172 | * Set the clipping mode of a VIP | 175 | * Set the clipping mode of a VIP |
173 | * | 176 | * |
174 | * @tvout: tvout structure | 177 | * @tvout: tvout structure |
178 | * @reg: register to set | ||
175 | * @range: clipping range | 179 | * @range: clipping range |
176 | */ | 180 | */ |
177 | static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, u32 range) | 181 | static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, int reg, u32 range) |
178 | { | 182 | { |
179 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 183 | u32 val = tvout_read(tvout, reg); |
180 | 184 | ||
181 | val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT); | 185 | val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT); |
182 | val |= range << TVO_VIP_CLIP_SHIFT; | 186 | val |= range << TVO_VIP_CLIP_SHIFT; |
183 | tvout_write(tvout, val, TVO_VIP_HDMI); | 187 | tvout_write(tvout, val, reg); |
184 | } | 188 | } |
185 | 189 | ||
186 | /** | 190 | /** |
187 | * Set the rounded value of a VIP | 191 | * Set the rounded value of a VIP |
188 | * | 192 | * |
189 | * @tvout: tvout structure | 193 | * @tvout: tvout structure |
194 | * @reg: register to set | ||
190 | * @rnd: rounded val per component | 195 | * @rnd: rounded val per component |
191 | */ | 196 | */ |
192 | static void tvout_vip_set_rnd(struct sti_tvout *tvout, u32 rnd) | 197 | static void tvout_vip_set_rnd(struct sti_tvout *tvout, int reg, u32 rnd) |
193 | { | 198 | { |
194 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 199 | u32 val = tvout_read(tvout, reg); |
195 | 200 | ||
196 | val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT); | 201 | val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT); |
197 | val |= rnd << TVO_VIP_RND_SHIFT; | 202 | val |= rnd << TVO_VIP_RND_SHIFT; |
198 | tvout_write(tvout, val, TVO_VIP_HDMI); | 203 | tvout_write(tvout, val, reg); |
199 | } | 204 | } |
200 | 205 | ||
201 | /** | 206 | /** |
202 | * Select the VIP input | 207 | * Select the VIP input |
203 | * | 208 | * |
204 | * @tvout: tvout structure | 209 | * @tvout: tvout structure |
210 | * @reg: register to set | ||
211 | * @main_path: main or auxiliary path | ||
212 | * @sel_input_logic_inverted: need to invert the logic | ||
205 | * @sel_input: selected_input (main/aux + conv) | 213 | * @sel_input: selected_input (main/aux + conv) |
206 | */ | 214 | */ |
207 | static void tvout_vip_set_sel_input(struct sti_tvout *tvout, | 215 | static void tvout_vip_set_sel_input(struct sti_tvout *tvout, |
216 | int reg, | ||
208 | bool main_path, | 217 | bool main_path, |
209 | bool sel_input_logic_inverted, | 218 | bool sel_input_logic_inverted, |
210 | enum sti_tvout_video_out_type video_out) | 219 | enum sti_tvout_video_out_type video_out) |
211 | { | 220 | { |
212 | u32 sel_input; | 221 | u32 sel_input; |
213 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 222 | u32 val = tvout_read(tvout, reg); |
214 | 223 | ||
215 | if (main_path) | 224 | if (main_path) |
216 | sel_input = TVO_VIP_SEL_INPUT_MAIN; | 225 | sel_input = TVO_VIP_SEL_INPUT_MAIN; |
@@ -232,22 +241,24 @@ static void tvout_vip_set_sel_input(struct sti_tvout *tvout, | |||
232 | 241 | ||
233 | val &= ~TVO_VIP_SEL_INPUT_MASK; | 242 | val &= ~TVO_VIP_SEL_INPUT_MASK; |
234 | val |= sel_input; | 243 | val |= sel_input; |
235 | tvout_write(tvout, val, TVO_VIP_HDMI); | 244 | tvout_write(tvout, val, reg); |
236 | } | 245 | } |
237 | 246 | ||
238 | /** | 247 | /** |
239 | * Select the input video signed or unsigned | 248 | * Select the input video signed or unsigned |
240 | * | 249 | * |
241 | * @tvout: tvout structure | 250 | * @tvout: tvout structure |
251 | * @reg: register to set | ||
242 | * @in_vid_signed: used video input format | 252 | * @in_vid_signed: used video input format |
243 | */ | 253 | */ |
244 | static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, u32 in_vid_fmt) | 254 | static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, |
255 | int reg, u32 in_vid_fmt) | ||
245 | { | 256 | { |
246 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 257 | u32 val = tvout_read(tvout, reg); |
247 | 258 | ||
248 | val &= ~TVO_IN_FMT_SIGNED; | 259 | val &= ~TVO_IN_FMT_SIGNED; |
249 | val |= in_vid_fmt; | 260 | val |= in_vid_fmt; |
250 | tvout_write(tvout, val, TVO_MAIN_IN_VID_FORMAT); | 261 | tvout_write(tvout, val, reg); |
251 | } | 262 | } |
252 | 263 | ||
253 | /** | 264 | /** |
@@ -261,6 +272,7 @@ static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path) | |||
261 | { | 272 | { |
262 | struct device_node *node = tvout->dev->of_node; | 273 | struct device_node *node = tvout->dev->of_node; |
263 | bool sel_input_logic_inverted = false; | 274 | bool sel_input_logic_inverted = false; |
275 | u32 tvo_in_vid_format; | ||
264 | 276 | ||
265 | dev_dbg(tvout->dev, "%s\n", __func__); | 277 | dev_dbg(tvout->dev, "%s\n", __func__); |
266 | 278 | ||
@@ -268,33 +280,36 @@ static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path) | |||
268 | DRM_DEBUG_DRIVER("main vip for hdmi\n"); | 280 | DRM_DEBUG_DRIVER("main vip for hdmi\n"); |
269 | /* select the input sync for hdmi = VTG set 1 */ | 281 | /* select the input sync for hdmi = VTG set 1 */ |
270 | tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL); | 282 | tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL); |
283 | tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; | ||
271 | } else { | 284 | } else { |
272 | DRM_DEBUG_DRIVER("aux vip for hdmi\n"); | 285 | DRM_DEBUG_DRIVER("aux vip for hdmi\n"); |
273 | /* select the input sync for hdmi = VTG set 1 */ | 286 | /* select the input sync for hdmi = VTG set 1 */ |
274 | tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL); | 287 | tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL); |
288 | tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; | ||
275 | } | 289 | } |
276 | 290 | ||
277 | /* set color channel order */ | 291 | /* set color channel order */ |
278 | tvout_vip_set_color_order(tvout, | 292 | tvout_vip_set_color_order(tvout, TVO_VIP_HDMI, |
279 | TVO_VIP_REORDER_CR_R_SEL, | 293 | TVO_VIP_REORDER_CR_R_SEL, |
280 | TVO_VIP_REORDER_Y_G_SEL, | 294 | TVO_VIP_REORDER_Y_G_SEL, |
281 | TVO_VIP_REORDER_CB_B_SEL); | 295 | TVO_VIP_REORDER_CB_B_SEL); |
282 | 296 | ||
283 | /* set clipping mode (Limited range RGB/Y) */ | 297 | /* set clipping mode (Limited range RGB/Y) */ |
284 | tvout_vip_set_clip_mode(tvout, TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y); | 298 | tvout_vip_set_clip_mode(tvout, TVO_VIP_HDMI, |
299 | TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y); | ||
285 | 300 | ||
286 | /* set round mode (rounded to 8-bit per component) */ | 301 | /* set round mode (rounded to 8-bit per component) */ |
287 | tvout_vip_set_rnd(tvout, TVO_VIP_RND_8BIT_ROUNDED); | 302 | tvout_vip_set_rnd(tvout, TVO_VIP_HDMI, TVO_VIP_RND_8BIT_ROUNDED); |
288 | 303 | ||
289 | if (of_device_is_compatible(node, "st,stih407-tvout")) { | 304 | if (of_device_is_compatible(node, "st,stih407-tvout")) { |
290 | /* set input video format */ | 305 | /* set input video format */ |
291 | tvout_vip_set_in_vid_fmt(tvout->regs + TVO_MAIN_IN_VID_FORMAT, | 306 | tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, |
292 | TVO_IN_FMT_SIGNED); | 307 | TVO_IN_FMT_SIGNED); |
293 | sel_input_logic_inverted = true; | 308 | sel_input_logic_inverted = true; |
294 | } | 309 | } |
295 | 310 | ||
296 | /* input selection */ | 311 | /* input selection */ |
297 | tvout_vip_set_sel_input(tvout, main_path, | 312 | tvout_vip_set_sel_input(tvout, TVO_VIP_HDMI, main_path, |
298 | sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB); | 313 | sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB); |
299 | } | 314 | } |
300 | 315 | ||
@@ -309,48 +324,47 @@ static void tvout_hda_start(struct sti_tvout *tvout, bool main_path) | |||
309 | { | 324 | { |
310 | struct device_node *node = tvout->dev->of_node; | 325 | struct device_node *node = tvout->dev->of_node; |
311 | bool sel_input_logic_inverted = false; | 326 | bool sel_input_logic_inverted = false; |
327 | u32 tvo_in_vid_format; | ||
328 | int val; | ||
312 | 329 | ||
313 | dev_dbg(tvout->dev, "%s\n", __func__); | 330 | dev_dbg(tvout->dev, "%s\n", __func__); |
314 | 331 | ||
315 | if (!main_path) { | 332 | if (main_path) { |
316 | DRM_ERROR("HD Analog on aux not implemented\n"); | 333 | val = TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT; |
317 | return; | 334 | val |= TVO_SYNC_MAIN_VTG_SET_3; |
335 | tvout_write(tvout, val, TVO_HD_SYNC_SEL); | ||
336 | tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; | ||
337 | } else { | ||
338 | val = TVO_SYNC_AUX_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT; | ||
339 | val |= TVO_SYNC_AUX_VTG_SET_3; | ||
340 | tvout_write(tvout, val, TVO_HD_SYNC_SEL); | ||
341 | tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; | ||
318 | } | 342 | } |
319 | 343 | ||
320 | DRM_DEBUG_DRIVER("main vip for HDF\n"); | ||
321 | |||
322 | /* set color channel order */ | 344 | /* set color channel order */ |
323 | tvout_vip_set_color_order(tvout->regs + TVO_VIP_HDF, | 345 | tvout_vip_set_color_order(tvout, TVO_VIP_HDF, |
324 | TVO_VIP_REORDER_CR_R_SEL, | 346 | TVO_VIP_REORDER_CR_R_SEL, |
325 | TVO_VIP_REORDER_Y_G_SEL, | 347 | TVO_VIP_REORDER_Y_G_SEL, |
326 | TVO_VIP_REORDER_CB_B_SEL); | 348 | TVO_VIP_REORDER_CB_B_SEL); |
327 | 349 | ||
328 | /* set clipping mode (Limited range RGB/Y) */ | 350 | /* set clipping mode (EAV/SAV clipping) */ |
329 | tvout_vip_set_clip_mode(tvout->regs + TVO_VIP_HDF, | 351 | tvout_vip_set_clip_mode(tvout, TVO_VIP_HDF, TVO_VIP_CLIP_EAV_SAV); |
330 | TVO_VIP_CLIP_LIMITED_RANGE_CB_CR); | ||
331 | 352 | ||
332 | /* set round mode (rounded to 10-bit per component) */ | 353 | /* set round mode (rounded to 10-bit per component) */ |
333 | tvout_vip_set_rnd(tvout->regs + TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED); | 354 | tvout_vip_set_rnd(tvout, TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED); |
334 | 355 | ||
335 | if (of_device_is_compatible(node, "st,stih407-tvout")) { | 356 | if (of_device_is_compatible(node, "st,stih407-tvout")) { |
336 | /* set input video format */ | 357 | /* set input video format */ |
337 | tvout_vip_set_in_vid_fmt(tvout, TVO_IN_FMT_SIGNED); | 358 | tvout_vip_set_in_vid_fmt(tvout, |
359 | tvo_in_vid_format, TVO_IN_FMT_SIGNED); | ||
338 | sel_input_logic_inverted = true; | 360 | sel_input_logic_inverted = true; |
339 | } | 361 | } |
340 | 362 | ||
341 | /* Input selection */ | 363 | /* Input selection */ |
342 | tvout_vip_set_sel_input(tvout->regs + TVO_VIP_HDF, | 364 | tvout_vip_set_sel_input(tvout, TVO_VIP_HDF, main_path, |
343 | main_path, | ||
344 | sel_input_logic_inverted, | 365 | sel_input_logic_inverted, |
345 | STI_TVOUT_VIDEO_OUT_YUV); | 366 | STI_TVOUT_VIDEO_OUT_YUV); |
346 | 367 | ||
347 | /* select the input sync for HD analog = VTG set 3 | ||
348 | * and HD DCS = VTG set 2 */ | ||
349 | tvout_write(tvout, | ||
350 | (TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT) | ||
351 | | TVO_SYNC_MAIN_VTG_SET_3, | ||
352 | TVO_HD_SYNC_SEL); | ||
353 | |||
354 | /* power up HD DAC */ | 368 | /* power up HD DAC */ |
355 | tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF); | 369 | tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF); |
356 | } | 370 | } |
@@ -392,7 +406,7 @@ static void sti_hda_encoder_commit(struct drm_encoder *encoder) | |||
392 | { | 406 | { |
393 | struct sti_tvout *tvout = to_sti_tvout(encoder); | 407 | struct sti_tvout *tvout = to_sti_tvout(encoder); |
394 | 408 | ||
395 | tvout_hda_start(tvout, true); | 409 | tvout_hda_start(tvout, sti_drm_crtc_is_main(encoder->crtc)); |
396 | } | 410 | } |
397 | 411 | ||
398 | static void sti_hda_encoder_disable(struct drm_encoder *encoder) | 412 | static void sti_hda_encoder_disable(struct drm_encoder *encoder) |
@@ -429,7 +443,7 @@ static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev, | |||
429 | 443 | ||
430 | drm_encoder = (struct drm_encoder *) encoder; | 444 | drm_encoder = (struct drm_encoder *) encoder; |
431 | 445 | ||
432 | drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK; | 446 | drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; |
433 | drm_encoder->possible_clones = 1 << 0; | 447 | drm_encoder->possible_clones = 1 << 0; |
434 | 448 | ||
435 | drm_encoder_init(dev, drm_encoder, | 449 | drm_encoder_init(dev, drm_encoder, |
@@ -444,7 +458,7 @@ static void sti_hdmi_encoder_commit(struct drm_encoder *encoder) | |||
444 | { | 458 | { |
445 | struct sti_tvout *tvout = to_sti_tvout(encoder); | 459 | struct sti_tvout *tvout = to_sti_tvout(encoder); |
446 | 460 | ||
447 | tvout_hdmi_start(tvout, true); | 461 | tvout_hdmi_start(tvout, sti_drm_crtc_is_main(encoder->crtc)); |
448 | } | 462 | } |
449 | 463 | ||
450 | static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) | 464 | static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) |
@@ -478,7 +492,7 @@ static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev, | |||
478 | 492 | ||
479 | drm_encoder = (struct drm_encoder *) encoder; | 493 | drm_encoder = (struct drm_encoder *) encoder; |
480 | 494 | ||
481 | drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK; | 495 | drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; |
482 | drm_encoder->possible_clones = 1 << 1; | 496 | drm_encoder->possible_clones = 1 << 1; |
483 | 497 | ||
484 | drm_encoder_init(dev, drm_encoder, | 498 | drm_encoder_init(dev, drm_encoder, |
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c index 740d6e347a62..9564f2568e2c 100644 --- a/drivers/gpu/drm/sti/sti_vtg.c +++ b/drivers/gpu/drm/sti/sti_vtg.c | |||
@@ -51,10 +51,19 @@ | |||
51 | #define VTG_TOP_V_HD_3 0x010C | 51 | #define VTG_TOP_V_HD_3 0x010C |
52 | #define VTG_BOT_V_HD_3 0x0110 | 52 | #define VTG_BOT_V_HD_3 0x0110 |
53 | 53 | ||
54 | #define VTG_H_HD_4 0x0120 | ||
55 | #define VTG_TOP_V_VD_4 0x0124 | ||
56 | #define VTG_BOT_V_VD_4 0x0128 | ||
57 | #define VTG_TOP_V_HD_4 0x012c | ||
58 | #define VTG_BOT_V_HD_4 0x0130 | ||
59 | |||
54 | #define VTG_IRQ_BOTTOM BIT(0) | 60 | #define VTG_IRQ_BOTTOM BIT(0) |
55 | #define VTG_IRQ_TOP BIT(1) | 61 | #define VTG_IRQ_TOP BIT(1) |
56 | #define VTG_IRQ_MASK (VTG_IRQ_TOP | VTG_IRQ_BOTTOM) | 62 | #define VTG_IRQ_MASK (VTG_IRQ_TOP | VTG_IRQ_BOTTOM) |
57 | 63 | ||
64 | /* Delay introduced by the HDMI in nb of pixel */ | ||
65 | #define HDMI_DELAY (6) | ||
66 | |||
58 | /* delay introduced by the Arbitrary Waveform Generator in nb of pixels */ | 67 | /* delay introduced by the Arbitrary Waveform Generator in nb of pixels */ |
59 | #define AWG_DELAY_HD (-9) | 68 | #define AWG_DELAY_HD (-9) |
60 | #define AWG_DELAY_ED (-8) | 69 | #define AWG_DELAY_ED (-8) |
@@ -133,10 +142,10 @@ static void vtg_set_mode(struct sti_vtg *vtg, | |||
133 | writel(tmp, vtg->regs + VTG_VID_TFS); | 142 | writel(tmp, vtg->regs + VTG_VID_TFS); |
134 | writel(tmp, vtg->regs + VTG_VID_BFS); | 143 | writel(tmp, vtg->regs + VTG_VID_BFS); |
135 | 144 | ||
136 | /* prepare VTG set 1 and 2 for HDMI and VTG set 3 for HD DAC */ | 145 | /* prepare VTG set 1 for HDMI */ |
137 | tmp = (mode->hsync_end - mode->hsync_start) << 16; | 146 | tmp = (mode->hsync_end - mode->hsync_start + HDMI_DELAY) << 16; |
147 | tmp |= HDMI_DELAY; | ||
138 | writel(tmp, vtg->regs + VTG_H_HD_1); | 148 | writel(tmp, vtg->regs + VTG_H_HD_1); |
139 | writel(tmp, vtg->regs + VTG_H_HD_2); | ||
140 | 149 | ||
141 | tmp = (mode->vsync_end - mode->vsync_start + 1) << 16; | 150 | tmp = (mode->vsync_end - mode->vsync_start + 1) << 16; |
142 | tmp |= 1; | 151 | tmp |= 1; |
@@ -146,6 +155,11 @@ static void vtg_set_mode(struct sti_vtg *vtg, | |||
146 | writel(0, vtg->regs + VTG_BOT_V_HD_1); | 155 | writel(0, vtg->regs + VTG_BOT_V_HD_1); |
147 | 156 | ||
148 | /* prepare VTG set 2 for for HD DCS */ | 157 | /* prepare VTG set 2 for for HD DCS */ |
158 | tmp = (mode->hsync_end - mode->hsync_start) << 16; | ||
159 | writel(tmp, vtg->regs + VTG_H_HD_2); | ||
160 | |||
161 | tmp = (mode->vsync_end - mode->vsync_start + 1) << 16; | ||
162 | tmp |= 1; | ||
149 | writel(tmp, vtg->regs + VTG_TOP_V_VD_2); | 163 | writel(tmp, vtg->regs + VTG_TOP_V_VD_2); |
150 | writel(tmp, vtg->regs + VTG_BOT_V_VD_2); | 164 | writel(tmp, vtg->regs + VTG_BOT_V_VD_2); |
151 | writel(0, vtg->regs + VTG_TOP_V_HD_2); | 165 | writel(0, vtg->regs + VTG_TOP_V_HD_2); |
@@ -166,6 +180,17 @@ static void vtg_set_mode(struct sti_vtg *vtg, | |||
166 | writel(tmp, vtg->regs + VTG_TOP_V_HD_3); | 180 | writel(tmp, vtg->regs + VTG_TOP_V_HD_3); |
167 | writel(tmp, vtg->regs + VTG_BOT_V_HD_3); | 181 | writel(tmp, vtg->regs + VTG_BOT_V_HD_3); |
168 | 182 | ||
183 | /* Prepare VTG set 4 for DVO */ | ||
184 | tmp = (mode->hsync_end - mode->hsync_start) << 16; | ||
185 | writel(tmp, vtg->regs + VTG_H_HD_4); | ||
186 | |||
187 | tmp = (mode->vsync_end - mode->vsync_start + 1) << 16; | ||
188 | tmp |= 1; | ||
189 | writel(tmp, vtg->regs + VTG_TOP_V_VD_4); | ||
190 | writel(tmp, vtg->regs + VTG_BOT_V_VD_4); | ||
191 | writel(0, vtg->regs + VTG_TOP_V_HD_4); | ||
192 | writel(0, vtg->regs + VTG_BOT_V_HD_4); | ||
193 | |||
169 | /* mode */ | 194 | /* mode */ |
170 | writel(type, vtg->regs + VTG_MODE); | 195 | writel(type, vtg->regs + VTG_MODE); |
171 | } | 196 | } |