Commit 79a44c16 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-sti-next-2015-02-04' of...

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
parents ae6d57d1 cffe1e89
...@@ -60,8 +60,6 @@ static int awg_generate_instr(enum opcode opcode, ...@@ -60,8 +60,6 @@ static int awg_generate_instr(enum opcode opcode,
* pixel. So we transform SKIP into SET * pixel. So we transform SKIP into SET
* instruction */ * instruction */
opcode = SET; opcode = SET;
arg = (arg << 24) >> 24;
arg &= (0x0ff);
break; break;
} }
......
...@@ -14,15 +14,19 @@ ...@@ -14,15 +14,19 @@
#include "sti_layer.h" #include "sti_layer.h"
#include "sti_vtg.h" #include "sti_vtg.h"
#define ALPHASWITCH BIT(6)
#define ENA_COLOR_FILL BIT(8) #define ENA_COLOR_FILL BIT(8)
#define BIGNOTLITTLE BIT(23)
#define WAIT_NEXT_VSYNC BIT(31) #define WAIT_NEXT_VSYNC BIT(31)
/* GDP color formats */ /* GDP color formats */
#define GDP_RGB565 0x00 #define GDP_RGB565 0x00
#define GDP_RGB888 0x01 #define GDP_RGB888 0x01
#define GDP_RGB888_32 0x02 #define GDP_RGB888_32 0x02
#define GDP_XBGR8888 (GDP_RGB888_32 | BIGNOTLITTLE | ALPHASWITCH)
#define GDP_ARGB8565 0x04 #define GDP_ARGB8565 0x04
#define GDP_ARGB8888 0x05 #define GDP_ARGB8888 0x05
#define GDP_ABGR8888 (GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH)
#define GDP_ARGB1555 0x06 #define GDP_ARGB1555 0x06
#define GDP_ARGB4444 0x07 #define GDP_ARGB4444 0x07
#define GDP_CLUT8 0x0B #define GDP_CLUT8 0x0B
...@@ -103,7 +107,9 @@ struct sti_gdp { ...@@ -103,7 +107,9 @@ struct sti_gdp {
static const uint32_t gdp_supported_formats[] = { static const uint32_t gdp_supported_formats[] = {
DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_ARGB4444, DRM_FORMAT_ARGB4444,
DRM_FORMAT_ARGB1555, DRM_FORMAT_ARGB1555,
DRM_FORMAT_RGB565, DRM_FORMAT_RGB565,
...@@ -129,8 +135,12 @@ static int sti_gdp_fourcc2format(int fourcc) ...@@ -129,8 +135,12 @@ static int sti_gdp_fourcc2format(int fourcc)
switch (fourcc) { switch (fourcc) {
case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XRGB8888:
return GDP_RGB888_32; return GDP_RGB888_32;
case DRM_FORMAT_XBGR8888:
return GDP_XBGR8888;
case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ARGB8888:
return GDP_ARGB8888; return GDP_ARGB8888;
case DRM_FORMAT_ABGR8888:
return GDP_ABGR8888;
case DRM_FORMAT_ARGB4444: case DRM_FORMAT_ARGB4444:
return GDP_ARGB4444; return GDP_ARGB4444;
case DRM_FORMAT_ARGB1555: case DRM_FORMAT_ARGB1555:
...@@ -157,6 +167,7 @@ static int sti_gdp_get_alpharange(int format) ...@@ -157,6 +167,7 @@ static int sti_gdp_get_alpharange(int format)
case GDP_ARGB8565: case GDP_ARGB8565:
case GDP_ARGB8888: case GDP_ARGB8888:
case GDP_AYCBR8888: case GDP_AYCBR8888:
case GDP_ABGR8888:
return GAM_GDP_ALPHARANGE_255; return GAM_GDP_ALPHARANGE_255;
} }
return 0; return 0;
......
...@@ -42,8 +42,17 @@ ...@@ -42,8 +42,17 @@
#define HDMI_SW_DI_1_PKT_WORD5 0x0228 #define HDMI_SW_DI_1_PKT_WORD5 0x0228
#define HDMI_SW_DI_1_PKT_WORD6 0x022C #define HDMI_SW_DI_1_PKT_WORD6 0x022C
#define HDMI_SW_DI_CFG 0x0230 #define HDMI_SW_DI_CFG 0x0230
#define HDMI_SW_DI_2_HEAD_WORD 0x0600
#define HDMI_SW_DI_2_PKT_WORD0 0x0604
#define HDMI_SW_DI_2_PKT_WORD1 0x0608
#define HDMI_SW_DI_2_PKT_WORD2 0x060C
#define HDMI_SW_DI_2_PKT_WORD3 0x0610
#define HDMI_SW_DI_2_PKT_WORD4 0x0614
#define HDMI_SW_DI_2_PKT_WORD5 0x0618
#define HDMI_SW_DI_2_PKT_WORD6 0x061C
#define HDMI_IFRAME_SLOT_AVI 1 #define HDMI_IFRAME_SLOT_AVI 1
#define HDMI_IFRAME_SLOT_AUDIO 2
#define XCAT(prefix, x, suffix) prefix ## x ## suffix #define XCAT(prefix, x, suffix) prefix ## x ## suffix
#define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD) #define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
...@@ -99,6 +108,10 @@ ...@@ -99,6 +108,10 @@
#define HDMI_STA_SW_RST BIT(1) #define HDMI_STA_SW_RST BIT(1)
#define HDMI_INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0)
#define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8)
#define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
struct sti_hdmi_connector { struct sti_hdmi_connector {
struct drm_connector drm_connector; struct drm_connector drm_connector;
struct drm_encoder *encoder; struct drm_encoder *encoder;
...@@ -227,6 +240,90 @@ static void hdmi_config(struct sti_hdmi *hdmi) ...@@ -227,6 +240,90 @@ static void hdmi_config(struct sti_hdmi *hdmi)
hdmi_write(hdmi, conf, HDMI_CFG); hdmi_write(hdmi, conf, HDMI_CFG);
} }
/**
* Helper to concatenate infoframe in 32 bits word
*
* @ptr: pointer on the hdmi internal structure
* @data: infoframe to write
* @size: size to write
*/
static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size)
{
unsigned long value = 0;
size_t i;
for (i = size; i > 0; i--)
value = (value << 8) | ptr[i - 1];
return value;
}
/**
* Helper to write info frame
*
* @hdmi: pointer on the hdmi internal structure
* @data: infoframe to write
* @size: size to write
*/
static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi, const u8 *data)
{
const u8 *ptr = data;
u32 val, slot, mode, i;
u32 head_offset, pack_offset;
size_t size;
switch (*ptr) {
case HDMI_INFOFRAME_TYPE_AVI:
slot = HDMI_IFRAME_SLOT_AVI;
mode = HDMI_IFRAME_FIELD;
head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);
pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);
size = HDMI_AVI_INFOFRAME_SIZE;
break;
case HDMI_INFOFRAME_TYPE_AUDIO:
slot = HDMI_IFRAME_SLOT_AUDIO;
mode = HDMI_IFRAME_FRAME;
head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);
pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);
size = HDMI_AUDIO_INFOFRAME_SIZE;
break;
default:
DRM_ERROR("unsupported infoframe type: %#x\n", *ptr);
return;
}
/* Disable transmission slot for updated infoframe */
val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot);
hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
val = HDMI_INFOFRAME_HEADER_TYPE(*ptr++);
val |= HDMI_INFOFRAME_HEADER_VERSION(*ptr++);
val |= HDMI_INFOFRAME_HEADER_LEN(*ptr++);
writel(val, hdmi->regs + head_offset);
/*
* Each subpack contains 4 bytes
* The First Bytes of the first subpacket must contain the checksum
* Packet size in increase by one.
*/
for (i = 0; i < size; i += sizeof(u32)) {
size_t num;
num = min_t(size_t, size - i, sizeof(u32));
val = hdmi_infoframe_subpack(ptr, num);
ptr += sizeof(u32);
writel(val, hdmi->regs + pack_offset + i);
}
/* Enable transmission slot for updated infoframe */
val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, slot);
hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
}
/** /**
* Prepare and configure the AVI infoframe * Prepare and configure the AVI infoframe
* *
...@@ -243,8 +340,6 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi) ...@@ -243,8 +340,6 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
struct drm_display_mode *mode = &hdmi->mode; struct drm_display_mode *mode = &hdmi->mode;
struct hdmi_avi_infoframe infoframe; struct hdmi_avi_infoframe infoframe;
u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
u8 *frame = buffer + HDMI_INFOFRAME_HEADER_SIZE;
u32 val;
int ret; int ret;
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
...@@ -266,47 +361,43 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi) ...@@ -266,47 +361,43 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
return ret; return ret;
} }
/* Disable transmission slot for AVI infoframe */ hdmi_infoframe_write_infopack(hdmi, buffer);
val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, HDMI_IFRAME_SLOT_AVI);
hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
/* Infoframe header */ return 0;
val = buffer[0]; }
val |= buffer[1] << 8;
val |= buffer[2] << 16; /**
hdmi_write(hdmi, val, HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI)); * Prepare and configure the AUDIO infoframe
*
/* Infoframe packet bytes */ * AUDIO infoframe are transmitted once per frame and
val = buffer[3]; * contains information about HDMI transmission mode such as audio codec,
val |= *(frame++) << 8; * sample size, ...
val |= *(frame++) << 16; *
val |= *(frame++) << 24; * @hdmi: pointer on the hdmi internal structure
hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI)); *
* Return negative value if error occurs
val = *(frame++); */
val |= *(frame++) << 8; static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
val |= *(frame++) << 16; {
val |= *(frame++) << 24; struct hdmi_audio_infoframe infofame;
hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI)); u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
int ret;
val = *(frame++);
val |= *(frame++) << 8; ret = hdmi_audio_infoframe_init(&infofame);
val |= *(frame++) << 16; if (ret < 0) {
val |= *(frame++) << 24; DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI)); return ret;
}
val = *(frame++);
val |= *(frame) << 8; infofame.channels = 2;
hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI));
ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer));
/* Enable transmission slot for AVI infoframe if (ret < 0) {
* According to the hdmi specification, AVI infoframe should be DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
* transmitted at least once per two video fields return ret;
*/ }
val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, HDMI_IFRAME_SLOT_AVI); hdmi_infoframe_write_infopack(hdmi, buffer);
hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
return 0; return 0;
} }
...@@ -427,6 +518,10 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge) ...@@ -427,6 +518,10 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
if (hdmi_avi_infoframe_config(hdmi)) if (hdmi_avi_infoframe_config(hdmi))
DRM_ERROR("Unable to configure AVI infoframe\n"); DRM_ERROR("Unable to configure AVI infoframe\n");
/* Program AUDIO infoframe */
if (hdmi_audio_infoframe_config(hdmi))
DRM_ERROR("Unable to configure AUDIO infoframe\n");
/* Sw reset */ /* Sw reset */
hdmi_swreset(hdmi); hdmi_swreset(hdmi);
} }
......
...@@ -1025,7 +1025,7 @@ static int sti_hqvdp_probe(struct platform_device *pdev) ...@@ -1025,7 +1025,7 @@ static int sti_hqvdp_probe(struct platform_device *pdev)
/* Get clock resources */ /* Get clock resources */
hqvdp->clk = devm_clk_get(dev, "hqvdp"); hqvdp->clk = devm_clk_get(dev, "hqvdp");
hqvdp->clk_pix_main = devm_clk_get(dev, "pix_main"); hqvdp->clk_pix_main = devm_clk_get(dev, "pix_main");
if (IS_ERR(hqvdp->clk) || IS_ERR(hqvdp->clk)) { if (IS_ERR(hqvdp->clk) || IS_ERR(hqvdp->clk_pix_main)) {
DRM_ERROR("Cannot get clocks\n"); DRM_ERROR("Cannot get clocks\n");
return -ENXIO; return -ENXIO;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment