aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/sti/Kconfig1
-rw-r--r--drivers/gpu/drm/sti/Makefile4
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c20
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.h2
-rw-r--r--drivers/gpu/drm/sti/sti_cursor.c242
-rw-r--r--drivers/gpu/drm/sti/sti_cursor.h12
-rw-r--r--drivers/gpu/drm/sti/sti_drm_crtc.c23
-rw-r--r--drivers/gpu/drm/sti/sti_drm_drv.c6
-rw-r--r--drivers/gpu/drm/sti/sti_drm_plane.c3
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c62
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c84
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.h6
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c1072
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.h12
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp_lut.h373
-rw-r--r--drivers/gpu/drm/sti/sti_layer.c16
-rw-r--r--drivers/gpu/drm/sti/sti_layer.h12
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.c17
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.h3
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c104
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.c31
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 */
26struct sti_compositor_data stih407_compositor_data = { 26struct 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 */
70struct sti_compositor { 69struct 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 */
36struct 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 */
52struct 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
61static 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
67static const uint32_t *sti_cursor_get_formats(struct sti_layer *layer)
68{
69 return cursor_supported_formats;
70}
71
72static unsigned int sti_cursor_get_nb_formats(struct sti_layer *layer)
73{
74 return ARRAY_SIZE(cursor_supported_formats);
75}
76
77static 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
99static 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
166static 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
186static int sti_cursor_disable_layer(struct sti_layer *layer)
187{
188 return 0;
189}
190
191static 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
208static 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
217struct 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
10struct 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
43static void sti_drm_crtc_commit(struct drm_crtc *crtc) 45static 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
67static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc, 71static 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
239static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { 245static 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}
384EXPORT_SYMBOL(sti_drm_crtc_disable_vblank); 386EXPORT_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}
404EXPORT_SYMBOL(sti_drm_crtc_is_main);
402 405
403int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer, 406int 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
74struct sti_gdp_node_list { 74struct 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 {
88struct sti_gdp { 92struct 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)
168static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer) 174static 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
204struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer) 207struct 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
222end: 222end:
@@ -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
481static int sti_hdmi_connector_get_modes(struct drm_connector *connector) 481static 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:
662err_connector: 669err_connector:
663 drm_bridge_cleanup(bridge); 670 drm_bridge_cleanup(bridge);
664 drm_connector_cleanup(drm_connector); 671 drm_connector_cleanup(drm_connector);
672err_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
789static int sti_hdmi_remove(struct platform_device *pdev) 792static 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
17struct sti_hdmi; 20struct sti_hdmi;
18 21
19struct hdmi_phy_ops { 22struct 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
67u32 hdmi_read(struct sti_hdmi *hdmi, int offset); 69u32 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
97enum sti_hvsrc_orient {
98 HVSRC_HORI,
99 HVSRC_VERT
100};
101
102/* Command structures */
103struct 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
154struct 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
162struct 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
176struct 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
212struct 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
229struct 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
257struct sti_hqvdp_top_status {
258 u32 processing_time;
259 u32 input_y_crc;
260 u32 input_uv_crc;
261};
262
263struct 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
273struct 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
288struct sti_hqvdp_hvsrc_status {
289 u32 y_hvsrc_crc;
290 u32 u_hvsrc_crc;
291 u32 v_hvsrc_crc;
292};
293
294struct 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
305struct 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 */
338struct 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
358static const uint32_t hqvdp_supported_formats[] = {
359 DRM_FORMAT_NV12,
360};
361
362static const uint32_t *sti_hqvdp_get_formats(struct sti_layer *layer)
363{
364 return hqvdp_supported_formats;
365}
366
367static 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 */
382static 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 */
410static 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 */
439static 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 */
501static 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 */
525static 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
641static 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
669static 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 */
716int 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
761static 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
775static 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
802static 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
811struct 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
820static 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 */
847static 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");
949out:
950 release_firmware(firmware);
951}
952
953int 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
984static void sti_hqvdp_unbind(struct device *dev,
985 struct device *master, void *data)
986{
987 /* do nothing */
988}
989
990static const struct component_ops sti_hqvdp_ops = {
991 .bind = sti_hqvdp_bind,
992 .unbind = sti_hqvdp_unbind,
993};
994
995static 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
1046static int sti_hqvdp_remove(struct platform_device *pdev)
1047{
1048 component_del(&pdev->dev, &sti_hqvdp_ops);
1049 return 0;
1050}
1051
1052static struct of_device_id hqvdp_of_match[] = {
1053 { .compatible = "st,stih407-hqvdp", },
1054 { /* end node */ }
1055};
1056MODULE_DEVICE_TABLE(of, hqvdp_of_match);
1057
1058struct 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
1068module_platform_driver(sti_hqvdp_driver);
1069
1070MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
1071MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
1072MODULE_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
10struct 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
23static 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
58static 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
93static 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
128static 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
163static 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
198static 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
233static 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
268static 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
303static 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
338static 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
71int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, 81int 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
28enum sti_layer_id_of_type { 29enum 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 */
87struct sti_layer { 91struct 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
108struct sti_layer *sti_layer_create(struct device *dev, int desc, 114struct sti_layer *sti_layer_create(struct device *dev, int desc,
109 void __iomem *baseaddr); 115 void __iomem *baseaddr);
110int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, 116int 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
49const char *sti_mixer_to_str(struct sti_mixer *mixer) 50const 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
226void 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
218void sti_mixer_set_matrix(struct sti_mixer *mixer) 235void 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 */
27struct sti_mixer { 28struct 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
35const char *sti_mixer_to_str(struct sti_mixer *mixer); 37const 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
40int sti_mixer_set_layer_status(struct sti_mixer *mixer, 42int sti_mixer_set_layer_status(struct sti_mixer *mixer,
41 struct sti_layer *layer, bool status); 43 struct sti_layer *layer, bool status);
44void sti_mixer_clear_all_layers(struct sti_mixer *mixer);
42int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer); 45int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer);
43int sti_mixer_active_video_area(struct sti_mixer *mixer, 46int 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 */
102enum sti_tvout_video_out_type { 104enum 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 */
156static void tvout_vip_set_color_order(struct sti_tvout *tvout, 159static 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 */
177static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, u32 range) 181static 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 */
192static void tvout_vip_set_rnd(struct sti_tvout *tvout, u32 rnd) 197static 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 */
207static void tvout_vip_set_sel_input(struct sti_tvout *tvout, 215static 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 */
244static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, u32 in_vid_fmt) 254static 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
398static void sti_hda_encoder_disable(struct drm_encoder *encoder) 412static 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
450static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) 464static 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}