aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-02-11 00:34:02 -0500
committerDave Airlie <airlied@redhat.com>2015-02-11 00:34:02 -0500
commit79a44c16b155b799421f5497ae888985a5d7f80c (patch)
tree5c3cef9c504703a5eda86160a227fe367b944329
parentae6d57d12ab3bc833a1a9ca252cc49280713181b (diff)
parentcffe1e89dc9bf541a39d9287ced7c5addff07084 (diff)
Merge branch 'drm-sti-next-2015-02-04' of git://git.linaro.org/people/benjamin.gaignard/kernel into drm-next
Those patches improve audio info frame management, add pixel formats support and fix minor issues. * 'drm-sti-next-2015-02-04' of git://git.linaro.org/people/benjamin.gaignard/kernel: drm: sti: HDMI add audio infoframe drm: sti: add support of XBGR8888 for gdp plane drm: sti: add support of ABGR8888 for gdp plane drm: sti: fix static checker warning in sti_awg_utils drm: sti: fix check for clk_pix_main
-rw-r--r--drivers/gpu/drm/sti/sti_awg_utils.c2
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c11
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c179
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c2
4 files changed, 149 insertions, 45 deletions
diff --git a/drivers/gpu/drm/sti/sti_awg_utils.c b/drivers/gpu/drm/sti/sti_awg_utils.c
index 9fde3ee8b1a5..6029a2e3db1d 100644
--- a/drivers/gpu/drm/sti/sti_awg_utils.c
+++ b/drivers/gpu/drm/sti/sti_awg_utils.c
@@ -60,8 +60,6 @@ static int awg_generate_instr(enum opcode opcode,
60 * pixel. So we transform SKIP into SET 60 * pixel. So we transform SKIP into SET
61 * instruction */ 61 * instruction */
62 opcode = SET; 62 opcode = SET;
63 arg = (arg << 24) >> 24;
64 arg &= (0x0ff);
65 break; 63 break;
66 } 64 }
67 65
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index 32448d1d1e8f..087906fd8846 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -14,15 +14,19 @@
14#include "sti_layer.h" 14#include "sti_layer.h"
15#include "sti_vtg.h" 15#include "sti_vtg.h"
16 16
17#define ALPHASWITCH BIT(6)
17#define ENA_COLOR_FILL BIT(8) 18#define ENA_COLOR_FILL BIT(8)
19#define BIGNOTLITTLE BIT(23)
18#define WAIT_NEXT_VSYNC BIT(31) 20#define WAIT_NEXT_VSYNC BIT(31)
19 21
20/* GDP color formats */ 22/* GDP color formats */
21#define GDP_RGB565 0x00 23#define GDP_RGB565 0x00
22#define GDP_RGB888 0x01 24#define GDP_RGB888 0x01
23#define GDP_RGB888_32 0x02 25#define GDP_RGB888_32 0x02
26#define GDP_XBGR8888 (GDP_RGB888_32 | BIGNOTLITTLE | ALPHASWITCH)
24#define GDP_ARGB8565 0x04 27#define GDP_ARGB8565 0x04
25#define GDP_ARGB8888 0x05 28#define GDP_ARGB8888 0x05
29#define GDP_ABGR8888 (GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH)
26#define GDP_ARGB1555 0x06 30#define GDP_ARGB1555 0x06
27#define GDP_ARGB4444 0x07 31#define GDP_ARGB4444 0x07
28#define GDP_CLUT8 0x0B 32#define GDP_CLUT8 0x0B
@@ -103,7 +107,9 @@ struct sti_gdp {
103 107
104static const uint32_t gdp_supported_formats[] = { 108static const uint32_t gdp_supported_formats[] = {
105 DRM_FORMAT_XRGB8888, 109 DRM_FORMAT_XRGB8888,
110 DRM_FORMAT_XBGR8888,
106 DRM_FORMAT_ARGB8888, 111 DRM_FORMAT_ARGB8888,
112 DRM_FORMAT_ABGR8888,
107 DRM_FORMAT_ARGB4444, 113 DRM_FORMAT_ARGB4444,
108 DRM_FORMAT_ARGB1555, 114 DRM_FORMAT_ARGB1555,
109 DRM_FORMAT_RGB565, 115 DRM_FORMAT_RGB565,
@@ -129,8 +135,12 @@ static int sti_gdp_fourcc2format(int fourcc)
129 switch (fourcc) { 135 switch (fourcc) {
130 case DRM_FORMAT_XRGB8888: 136 case DRM_FORMAT_XRGB8888:
131 return GDP_RGB888_32; 137 return GDP_RGB888_32;
138 case DRM_FORMAT_XBGR8888:
139 return GDP_XBGR8888;
132 case DRM_FORMAT_ARGB8888: 140 case DRM_FORMAT_ARGB8888:
133 return GDP_ARGB8888; 141 return GDP_ARGB8888;
142 case DRM_FORMAT_ABGR8888:
143 return GDP_ABGR8888;
134 case DRM_FORMAT_ARGB4444: 144 case DRM_FORMAT_ARGB4444:
135 return GDP_ARGB4444; 145 return GDP_ARGB4444;
136 case DRM_FORMAT_ARGB1555: 146 case DRM_FORMAT_ARGB1555:
@@ -157,6 +167,7 @@ static int sti_gdp_get_alpharange(int format)
157 case GDP_ARGB8565: 167 case GDP_ARGB8565:
158 case GDP_ARGB8888: 168 case GDP_ARGB8888:
159 case GDP_AYCBR8888: 169 case GDP_AYCBR8888:
170 case GDP_ABGR8888:
160 return GAM_GDP_ALPHARANGE_255; 171 return GAM_GDP_ALPHARANGE_255;
161 } 172 }
162 return 0; 173 return 0;
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index e840ca5de401..1485ade98710 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -42,8 +42,17 @@
42#define HDMI_SW_DI_1_PKT_WORD5 0x0228 42#define HDMI_SW_DI_1_PKT_WORD5 0x0228
43#define HDMI_SW_DI_1_PKT_WORD6 0x022C 43#define HDMI_SW_DI_1_PKT_WORD6 0x022C
44#define HDMI_SW_DI_CFG 0x0230 44#define HDMI_SW_DI_CFG 0x0230
45#define HDMI_SW_DI_2_HEAD_WORD 0x0600
46#define HDMI_SW_DI_2_PKT_WORD0 0x0604
47#define HDMI_SW_DI_2_PKT_WORD1 0x0608
48#define HDMI_SW_DI_2_PKT_WORD2 0x060C
49#define HDMI_SW_DI_2_PKT_WORD3 0x0610
50#define HDMI_SW_DI_2_PKT_WORD4 0x0614
51#define HDMI_SW_DI_2_PKT_WORD5 0x0618
52#define HDMI_SW_DI_2_PKT_WORD6 0x061C
45 53
46#define HDMI_IFRAME_SLOT_AVI 1 54#define HDMI_IFRAME_SLOT_AVI 1
55#define HDMI_IFRAME_SLOT_AUDIO 2
47 56
48#define XCAT(prefix, x, suffix) prefix ## x ## suffix 57#define XCAT(prefix, x, suffix) prefix ## x ## suffix
49#define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD) 58#define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
@@ -99,6 +108,10 @@
99 108
100#define HDMI_STA_SW_RST BIT(1) 109#define HDMI_STA_SW_RST BIT(1)
101 110
111#define HDMI_INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0)
112#define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8)
113#define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
114
102struct sti_hdmi_connector { 115struct sti_hdmi_connector {
103 struct drm_connector drm_connector; 116 struct drm_connector drm_connector;
104 struct drm_encoder *encoder; 117 struct drm_encoder *encoder;
@@ -228,6 +241,90 @@ static void hdmi_config(struct sti_hdmi *hdmi)
228} 241}
229 242
230/** 243/**
244 * Helper to concatenate infoframe in 32 bits word
245 *
246 * @ptr: pointer on the hdmi internal structure
247 * @data: infoframe to write
248 * @size: size to write
249 */
250static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size)
251{
252 unsigned long value = 0;
253 size_t i;
254
255 for (i = size; i > 0; i--)
256 value = (value << 8) | ptr[i - 1];
257
258 return value;
259}
260
261/**
262 * Helper to write info frame
263 *
264 * @hdmi: pointer on the hdmi internal structure
265 * @data: infoframe to write
266 * @size: size to write
267 */
268static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi, const u8 *data)
269{
270 const u8 *ptr = data;
271 u32 val, slot, mode, i;
272 u32 head_offset, pack_offset;
273 size_t size;
274
275 switch (*ptr) {
276 case HDMI_INFOFRAME_TYPE_AVI:
277 slot = HDMI_IFRAME_SLOT_AVI;
278 mode = HDMI_IFRAME_FIELD;
279 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);
280 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);
281 size = HDMI_AVI_INFOFRAME_SIZE;
282 break;
283
284 case HDMI_INFOFRAME_TYPE_AUDIO:
285 slot = HDMI_IFRAME_SLOT_AUDIO;
286 mode = HDMI_IFRAME_FRAME;
287 head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);
288 pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);
289 size = HDMI_AUDIO_INFOFRAME_SIZE;
290 break;
291
292 default:
293 DRM_ERROR("unsupported infoframe type: %#x\n", *ptr);
294 return;
295 }
296
297 /* Disable transmission slot for updated infoframe */
298 val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
299 val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot);
300 hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
301
302 val = HDMI_INFOFRAME_HEADER_TYPE(*ptr++);
303 val |= HDMI_INFOFRAME_HEADER_VERSION(*ptr++);
304 val |= HDMI_INFOFRAME_HEADER_LEN(*ptr++);
305 writel(val, hdmi->regs + head_offset);
306
307 /*
308 * Each subpack contains 4 bytes
309 * The First Bytes of the first subpacket must contain the checksum
310 * Packet size in increase by one.
311 */
312 for (i = 0; i < size; i += sizeof(u32)) {
313 size_t num;
314
315 num = min_t(size_t, size - i, sizeof(u32));
316 val = hdmi_infoframe_subpack(ptr, num);
317 ptr += sizeof(u32);
318 writel(val, hdmi->regs + pack_offset + i);
319 }
320
321 /* Enable transmission slot for updated infoframe */
322 val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
323 val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, slot);
324 hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
325}
326
327/**
231 * Prepare and configure the AVI infoframe 328 * Prepare and configure the AVI infoframe
232 * 329 *
233 * AVI infoframe are transmitted at least once per two video field and 330 * AVI infoframe are transmitted at least once per two video field and
@@ -243,8 +340,6 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
243 struct drm_display_mode *mode = &hdmi->mode; 340 struct drm_display_mode *mode = &hdmi->mode;
244 struct hdmi_avi_infoframe infoframe; 341 struct hdmi_avi_infoframe infoframe;
245 u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; 342 u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
246 u8 *frame = buffer + HDMI_INFOFRAME_HEADER_SIZE;
247 u32 val;
248 int ret; 343 int ret;
249 344
250 DRM_DEBUG_DRIVER("\n"); 345 DRM_DEBUG_DRIVER("\n");
@@ -266,47 +361,43 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
266 return ret; 361 return ret;
267 } 362 }
268 363
269 /* Disable transmission slot for AVI infoframe */ 364 hdmi_infoframe_write_infopack(hdmi, buffer);
270 val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
271 val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, HDMI_IFRAME_SLOT_AVI);
272 hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
273 365
274 /* Infoframe header */ 366 return 0;
275 val = buffer[0]; 367}
276 val |= buffer[1] << 8; 368
277 val |= buffer[2] << 16; 369/**
278 hdmi_write(hdmi, val, HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI)); 370 * Prepare and configure the AUDIO infoframe
279 371 *
280 /* Infoframe packet bytes */ 372 * AUDIO infoframe are transmitted once per frame and
281 val = buffer[3]; 373 * contains information about HDMI transmission mode such as audio codec,
282 val |= *(frame++) << 8; 374 * sample size, ...
283 val |= *(frame++) << 16; 375 *
284 val |= *(frame++) << 24; 376 * @hdmi: pointer on the hdmi internal structure
285 hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI)); 377 *
286 378 * Return negative value if error occurs
287 val = *(frame++); 379 */
288 val |= *(frame++) << 8; 380static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
289 val |= *(frame++) << 16; 381{
290 val |= *(frame++) << 24; 382 struct hdmi_audio_infoframe infofame;
291 hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI)); 383 u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
292 384 int ret;
293 val = *(frame++); 385
294 val |= *(frame++) << 8; 386 ret = hdmi_audio_infoframe_init(&infofame);
295 val |= *(frame++) << 16; 387 if (ret < 0) {
296 val |= *(frame++) << 24; 388 DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
297 hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI)); 389 return ret;
298 390 }
299 val = *(frame++); 391
300 val |= *(frame) << 8; 392 infofame.channels = 2;
301 hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI)); 393
302 394 ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer));
303 /* Enable transmission slot for AVI infoframe 395 if (ret < 0) {
304 * According to the hdmi specification, AVI infoframe should be 396 DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
305 * transmitted at least once per two video fields 397 return ret;
306 */ 398 }
307 val = hdmi_read(hdmi, HDMI_SW_DI_CFG); 399
308 val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, HDMI_IFRAME_SLOT_AVI); 400 hdmi_infoframe_write_infopack(hdmi, buffer);
309 hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
310 401
311 return 0; 402 return 0;
312} 403}
@@ -427,6 +518,10 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
427 if (hdmi_avi_infoframe_config(hdmi)) 518 if (hdmi_avi_infoframe_config(hdmi))
428 DRM_ERROR("Unable to configure AVI infoframe\n"); 519 DRM_ERROR("Unable to configure AVI infoframe\n");
429 520
521 /* Program AUDIO infoframe */
522 if (hdmi_audio_infoframe_config(hdmi))
523 DRM_ERROR("Unable to configure AUDIO infoframe\n");
524
430 /* Sw reset */ 525 /* Sw reset */
431 hdmi_swreset(hdmi); 526 hdmi_swreset(hdmi);
432} 527}
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index f3db05dab0ab..b0eb62de1b2e 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1025,7 +1025,7 @@ static int sti_hqvdp_probe(struct platform_device *pdev)
1025 /* Get clock resources */ 1025 /* Get clock resources */
1026 hqvdp->clk = devm_clk_get(dev, "hqvdp"); 1026 hqvdp->clk = devm_clk_get(dev, "hqvdp");
1027 hqvdp->clk_pix_main = devm_clk_get(dev, "pix_main"); 1027 hqvdp->clk_pix_main = devm_clk_get(dev, "pix_main");
1028 if (IS_ERR(hqvdp->clk) || IS_ERR(hqvdp->clk)) { 1028 if (IS_ERR(hqvdp->clk) || IS_ERR(hqvdp->clk_pix_main)) {
1029 DRM_ERROR("Cannot get clocks\n"); 1029 DRM_ERROR("Cannot get clocks\n");
1030 return -ENXIO; 1030 return -ENXIO;
1031 } 1031 }