aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Gaignard <benjamin.gaignard@linaro.org>2014-12-11 05:38:59 -0500
committerBenjamin Gaignard <benjamin.gaignard@linaro.org>2014-12-11 08:00:13 -0500
commit4fdbc678fe4dc18cbf1d97e1b45660f91c3089b4 (patch)
tree4938a8517db6034910c99cad241cf8c18c20bc8b
parent96006a770df80d69cbde4802e1e7cdfd70c510b3 (diff)
drm: sti: add HQVDP plane
High Quality Video Data Plane is hardware IP dedicated to video rendering. Compare to GPD (graphic planes) it have better scaler capabilities. HQVDP use VID layer to push data into hardware compositor without going into DDR. From data flow point of view HQVDP and VID are nested so HQVPD update/disable VID. Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/gpu/st,stih4xx.txt26
-rw-r--r--drivers/gpu/drm/sti/Kconfig1
-rw-r--r--drivers/gpu/drm/sti/Makefile3
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c1
-rw-r--r--drivers/gpu/drm/sti/sti_drm_crtc.c6
-rw-r--r--drivers/gpu/drm/sti/sti_drm_plane.c3
-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.c11
-rw-r--r--drivers/gpu/drm/sti/sti_layer.h10
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.c2
12 files changed, 1513 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/gpu/st,stih4xx.txt b/Documentation/devicetree/bindings/gpu/st,stih4xx.txt
index 32cfc7b7631b..c99eb34e640b 100644
--- a/Documentation/devicetree/bindings/gpu/st,stih4xx.txt
+++ b/Documentation/devicetree/bindings/gpu/st,stih4xx.txt
@@ -83,6 +83,22 @@ sti-hda:
83 - clock-names: names of the clocks listed in clocks property in the same 83 - clock-names: names of the clocks listed in clocks property in the same
84 order. 84 order.
85 85
86sti-hqvdp:
87 must be a child of sti-display-subsystem
88 Required properties:
89 - compatible: "st,stih<chip>-hqvdp"
90 - reg: Physical base address of the IP registers and length of memory mapped region.
91 - clocks: from common clock binding: handle hardware IP needed clocks, the
92 number of clocks may depend of the SoC type.
93 See ../clocks/clock-bindings.txt for details.
94 - clock-names: names of the clocks listed in clocks property in the same
95 order.
96 - resets: resets to be used by the device
97 See ../reset/reset.txt for details.
98 - reset-names: names of the resets listed in resets property in the same
99 order.
100 - st,vtg: phandle on vtg main device node.
101
86Example: 102Example:
87 103
88/ { 104/ {
@@ -183,6 +199,16 @@ Example:
183 clocks = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>; 199 clocks = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>;
184 }; 200 };
185 }; 201 };
202
203 sti-hqvdp@9c000000 {
204 compatible = "st,stih407-hqvdp";
205 reg = <0x9C00000 0x100000>;
206 clock-names = "hqvdp", "pix_main";
207 clocks = <&clk_s_c0_flexgen CLK_MAIN_DISP>, <&clk_s_d2_flexgen CLK_PIX_MAIN_DISP>;
208 reset-names = "hqvdp";
209 resets = <&softreset STIH407_HDQVDP_SOFTRESET>;
210 st,vtg = <&vtg_main>;
211 };
186 }; 212 };
187 ... 213 ...
188}; 214};
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 d6128f7fa12c..6ba9d27c1b90 100644
--- a/drivers/gpu/drm/sti/Makefile
+++ b/drivers/gpu/drm/sti/Makefile
@@ -19,4 +19,5 @@ obj-$(CONFIG_DRM_STI) = \
19 sti_hda.o \ 19 sti_hda.o \
20 sti_tvout.o \ 20 sti_tvout.o \
21 sticompositor.o \ 21 sticompositor.o \
22 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 b9415b3f3720..c5cf4aea9694 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -122,6 +122,7 @@ static int sti_compositor_bind(struct device *dev, struct device *master,
122 plane++; 122 plane++;
123 break; 123 break;
124 case STI_BCK: 124 case STI_BCK:
125 case STI_VDP:
125 break; 126 break;
126 } 127 }
127 128
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c
index 928b44fd3717..4c651c200f20 100644
--- a/drivers/gpu/drm/sti/sti_drm_crtc.c
+++ b/drivers/gpu/drm/sti/sti_drm_crtc.c
@@ -148,7 +148,8 @@ sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
148 w = crtc->primary->fb->width - x; 148 w = crtc->primary->fb->width - x;
149 h = crtc->primary->fb->height - y; 149 h = crtc->primary->fb->height - y;
150 150
151 return sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode, 151 return sti_layer_prepare(layer, crtc,
152 crtc->primary->fb, &crtc->mode,
152 mixer->id, 0, 0, w, h, x, y, w, h); 153 mixer->id, 0, 0, w, h, x, y, w, h);
153} 154}
154 155
@@ -175,7 +176,8 @@ static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
175 w = crtc->primary->fb->width - crtc->x; 176 w = crtc->primary->fb->width - crtc->x;
176 h = crtc->primary->fb->height - crtc->y; 177 h = crtc->primary->fb->height - crtc->y;
177 178
178 ret = sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode, 179 ret = sti_layer_prepare(layer, crtc,
180 crtc->primary->fb, &crtc->mode,
179 mixer->id, 0, 0, w, h, 181 mixer->id, 0, 0, w, h,
180 crtc->x, crtc->y, w, h); 182 crtc->x, crtc->y, w, h);
181 if (ret) { 183 if (ret) {
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_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 5051b4cfc46b..480ec1c974e2 100644
--- a/drivers/gpu/drm/sti/sti_layer.c
+++ b/drivers/gpu/drm/sti/sti_layer.c
@@ -13,6 +13,7 @@
13#include "sti_compositor.h" 13#include "sti_compositor.h"
14#include "sti_cursor.h" 14#include "sti_cursor.h"
15#include "sti_gdp.h" 15#include "sti_gdp.h"
16#include "sti_hqvdp.h"
16#include "sti_layer.h" 17#include "sti_layer.h"
17#include "sti_vid.h" 18#include "sti_vid.h"
18 19
@@ -33,6 +34,8 @@ const char *sti_layer_to_str(struct sti_layer *layer)
33 return "VID1"; 34 return "VID1";
34 case STI_CURSOR: 35 case STI_CURSOR:
35 return "CURSOR"; 36 return "CURSOR";
37 case STI_HQVDP_0:
38 return "HQVDP0";
36 default: 39 default:
37 return "<UNKNOWN LAYER>"; 40 return "<UNKNOWN LAYER>";
38 } 41 }
@@ -54,6 +57,9 @@ struct sti_layer *sti_layer_create(struct device *dev, int desc,
54 case STI_CUR: 57 case STI_CUR:
55 layer = sti_cursor_create(dev); 58 layer = sti_cursor_create(dev);
56 break; 59 break;
60 case STI_VDP:
61 layer = sti_hqvdp_create(dev);
62 break;
57 } 63 }
58 64
59 if (!layer) { 65 if (!layer) {
@@ -72,7 +78,9 @@ struct sti_layer *sti_layer_create(struct device *dev, int desc,
72 return layer; 78 return layer;
73} 79}
74 80
75int 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,
76 struct drm_display_mode *mode, int mixer_id, 84 struct drm_display_mode *mode, int mixer_id,
77 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,
78 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)
@@ -92,6 +100,7 @@ int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb,
92 return 1; 100 return 1;
93 } 101 }
94 102
103 layer->crtc = crtc;
95 layer->fb = fb; 104 layer->fb = fb;
96 layer->mode = mode; 105 layer->mode = mode;
97 layer->mixer_id = mixer_id; 106 layer->mixer_id = mixer_id;
diff --git a/drivers/gpu/drm/sti/sti_layer.h b/drivers/gpu/drm/sti/sti_layer.h
index 68bfdca4d738..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
@@ -88,6 +91,7 @@ struct sti_layer_funcs {
88struct sti_layer { 91struct sti_layer {
89 struct drm_plane plane; 92 struct drm_plane plane;
90 struct drm_framebuffer *fb; 93 struct drm_framebuffer *fb;
94 struct drm_crtc *crtc;
91 struct drm_display_mode *mode; 95 struct drm_display_mode *mode;
92 enum sti_layer_desc desc; 96 enum sti_layer_desc desc;
93 struct device *dev; 97 struct device *dev;
@@ -109,7 +113,9 @@ struct sti_layer {
109 113
110struct sti_layer *sti_layer_create(struct device *dev, int desc, 114struct sti_layer *sti_layer_create(struct device *dev, int desc,
111 void __iomem *baseaddr); 115 void __iomem *baseaddr);
112int 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,
113 struct drm_display_mode *mode, 119 struct drm_display_mode *mode,
114 int mixer_id, 120 int mixer_id,
115 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 9a4ce74ac329..13a4b84deab6 100644
--- a/drivers/gpu/drm/sti/sti_mixer.c
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -123,6 +123,7 @@ int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
123 layer_id = GAM_DEPTH_GDP3_ID; 123 layer_id = GAM_DEPTH_GDP3_ID;
124 break; 124 break;
125 case STI_VID_0: 125 case STI_VID_0:
126 case STI_HQVDP_0:
126 layer_id = GAM_DEPTH_VID0_ID; 127 layer_id = GAM_DEPTH_VID0_ID;
127 break; 128 break;
128 case STI_VID_1: 129 case STI_VID_1:
@@ -189,6 +190,7 @@ static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
189 case STI_GDP_3: 190 case STI_GDP_3:
190 return GAM_CTL_GDP3_MASK; 191 return GAM_CTL_GDP3_MASK;
191 case STI_VID_0: 192 case STI_VID_0:
193 case STI_HQVDP_0:
192 return GAM_CTL_VID0_MASK; 194 return GAM_CTL_VID0_MASK;
193 case STI_VID_1: 195 case STI_VID_1:
194 return GAM_CTL_VID1_MASK; 196 return GAM_CTL_VID1_MASK;