Quellcode durchsuchen

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
Dave Airlie vor 10 Jahren
Ursprung
Commit
79a44c16b1

+ 0 - 2
drivers/gpu/drm/sti/sti_awg_utils.c

@@ -60,8 +60,6 @@ static int awg_generate_instr(enum opcode opcode,
 				 * pixel. So we transform SKIP into SET
 				 * instruction */
 				opcode = SET;
-				arg = (arg << 24) >> 24;
-				arg &= (0x0ff);
 				break;
 			}
 

+ 11 - 0
drivers/gpu/drm/sti/sti_gdp.c

@@ -14,15 +14,19 @@
 #include "sti_layer.h"
 #include "sti_vtg.h"
 
+#define ALPHASWITCH     BIT(6)
 #define ENA_COLOR_FILL  BIT(8)
+#define BIGNOTLITTLE    BIT(23)
 #define WAIT_NEXT_VSYNC BIT(31)
 
 /* GDP color formats */
 #define GDP_RGB565      0x00
 #define GDP_RGB888      0x01
 #define GDP_RGB888_32   0x02
+#define GDP_XBGR8888    (GDP_RGB888_32 | BIGNOTLITTLE | ALPHASWITCH)
 #define GDP_ARGB8565    0x04
 #define GDP_ARGB8888    0x05
+#define GDP_ABGR8888	(GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH)
 #define GDP_ARGB1555    0x06
 #define GDP_ARGB4444    0x07
 #define GDP_CLUT8       0x0B
@@ -103,7 +107,9 @@ struct sti_gdp {
 
 static const uint32_t gdp_supported_formats[] = {
 	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
 	DRM_FORMAT_ARGB4444,
 	DRM_FORMAT_ARGB1555,
 	DRM_FORMAT_RGB565,
@@ -129,8 +135,12 @@ static int sti_gdp_fourcc2format(int fourcc)
 	switch (fourcc) {
 	case DRM_FORMAT_XRGB8888:
 		return GDP_RGB888_32;
+	case DRM_FORMAT_XBGR8888:
+		return GDP_XBGR8888;
 	case DRM_FORMAT_ARGB8888:
 		return GDP_ARGB8888;
+	case DRM_FORMAT_ABGR8888:
+		return GDP_ABGR8888;
 	case DRM_FORMAT_ARGB4444:
 		return GDP_ARGB4444;
 	case DRM_FORMAT_ARGB1555:
@@ -157,6 +167,7 @@ static int sti_gdp_get_alpharange(int format)
 	case GDP_ARGB8565:
 	case GDP_ARGB8888:
 	case GDP_AYCBR8888:
+	case GDP_ABGR8888:
 		return GAM_GDP_ALPHARANGE_255;
 	}
 	return 0;

+ 137 - 42
drivers/gpu/drm/sti/sti_hdmi.c

@@ -42,8 +42,17 @@
 #define HDMI_SW_DI_1_PKT_WORD5          0x0228
 #define HDMI_SW_DI_1_PKT_WORD6          0x022C
 #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_AUDIO          2
 
 #define  XCAT(prefix, x, suffix)        prefix ## x ## suffix
 #define  HDMI_SW_DI_N_HEAD_WORD(x)      XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
@@ -99,6 +108,10 @@
 
 #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 drm_connector drm_connector;
 	struct drm_encoder *encoder;
@@ -227,6 +240,90 @@ static void hdmi_config(struct sti_hdmi *hdmi)
 	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
  *
@@ -243,8 +340,6 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
 	struct drm_display_mode *mode = &hdmi->mode;
 	struct hdmi_avi_infoframe infoframe;
 	u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
-	u8 *frame = buffer + HDMI_INFOFRAME_HEADER_SIZE;
-	u32 val;
 	int ret;
 
 	DRM_DEBUG_DRIVER("\n");
@@ -266,47 +361,43 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
 		return ret;
 	}
 
-	/* Disable transmission slot for AVI infoframe */
-	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);
+	hdmi_infoframe_write_infopack(hdmi, buffer);
 
-	/* Infoframe header */
-	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));
-
-	/* Infoframe packet bytes */
-	val =  buffer[3];
-	val |= *(frame++) << 8;
-	val |= *(frame++) << 16;
-	val |= *(frame++) << 24;
-	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI));
-
-	val =  *(frame++);
-	val |= *(frame++) << 8;
-	val |= *(frame++) << 16;
-	val |= *(frame++) << 24;
-	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI));
-
-	val =  *(frame++);
-	val |= *(frame++) << 8;
-	val |= *(frame++) << 16;
-	val |= *(frame++) << 24;
-	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI));
-
-	val = *(frame++);
-	val |= *(frame) << 8;
-	hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI));
-
-	/* Enable transmission slot for AVI infoframe
-	 * According to the hdmi specification, AVI infoframe should be
-	 * transmitted at least once per two video fields
-	 */
-	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
-	val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, HDMI_IFRAME_SLOT_AVI);
-	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
+	return 0;
+}
+
+/**
+ * Prepare and configure the AUDIO infoframe
+ *
+ * AUDIO infoframe are transmitted once per frame and
+ * contains information about HDMI transmission mode such as audio codec,
+ * sample size, ...
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * Return negative value if error occurs
+ */
+static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
+{
+	struct hdmi_audio_infoframe infofame;
+	u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
+	int ret;
+
+	ret = hdmi_audio_infoframe_init(&infofame);
+	if (ret < 0) {
+		DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
+		return ret;
+	}
+
+	infofame.channels = 2;
+
+	ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer));
+	if (ret < 0) {
+		DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
+		return ret;
+	}
+
+	hdmi_infoframe_write_infopack(hdmi, buffer);
 
 	return 0;
 }
@@ -427,6 +518,10 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
 	if (hdmi_avi_infoframe_config(hdmi))
 		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 */
 	hdmi_swreset(hdmi);
 }

+ 1 - 1
drivers/gpu/drm/sti/sti_hqvdp.c

@@ -1025,7 +1025,7 @@ static int sti_hqvdp_probe(struct platform_device *pdev)
 	/* Get clock resources */
 	hqvdp->clk = devm_clk_get(dev, "hqvdp");
 	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");
 		return -ENXIO;
 	}