mirror of https://gitee.com/openkylin/linux.git
drm/exynos: sending AVI and AUI info frames
This patch adds code for composing AVI and AUI info frames and send them every VSYNC. This patch is important for hdmi certification. v3: - Moved enums, macros to exynos_hdmi.c. - Corrected hex format. - Added static to hdmi_reg_infoframe. v2: - Added few blank lines. - Corrected comments format. - Added comments for 2's Complement calculation for check sum. v1: - Remove un-necessary blank lines. - Change the case of hex constants. Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com> Signed-off-by: Fahad Kunnathadi <fahad.k@samsung.com> Signed-off-by: Shirish S <s.shirish@samsung.com> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
This commit is contained in:
parent
a4d8de5f1b
commit
a144c2e9f1
|
@ -50,6 +50,29 @@
|
|||
#define MAX_HEIGHT 1080
|
||||
#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
|
||||
|
||||
/* AVI header and aspect ratio */
|
||||
#define HDMI_AVI_VERSION 0x02
|
||||
#define HDMI_AVI_LENGTH 0x0D
|
||||
#define AVI_PIC_ASPECT_RATIO_16_9 (2 << 4)
|
||||
#define AVI_SAME_AS_PIC_ASPECT_RATIO 8
|
||||
|
||||
/* AUI header info */
|
||||
#define HDMI_AUI_VERSION 0x01
|
||||
#define HDMI_AUI_LENGTH 0x0A
|
||||
|
||||
/* HDMI infoframe to configure HDMI out packet header, AUI and AVI */
|
||||
enum HDMI_PACKET_TYPE {
|
||||
/* refer to Table 5-8 Packet Type in HDMI specification v1.4a */
|
||||
/* InfoFrame packet type */
|
||||
HDMI_PACKET_TYPE_INFOFRAME = 0x80,
|
||||
/* Vendor-Specific InfoFrame */
|
||||
HDMI_PACKET_TYPE_VSI = HDMI_PACKET_TYPE_INFOFRAME + 1,
|
||||
/* Auxiliary Video information InfoFrame */
|
||||
HDMI_PACKET_TYPE_AVI = HDMI_PACKET_TYPE_INFOFRAME + 2,
|
||||
/* Audio information InfoFrame */
|
||||
HDMI_PACKET_TYPE_AUI = HDMI_PACKET_TYPE_INFOFRAME + 4
|
||||
};
|
||||
|
||||
enum hdmi_type {
|
||||
HDMI_TYPE13,
|
||||
HDMI_TYPE14,
|
||||
|
@ -182,6 +205,7 @@ struct hdmi_v13_conf {
|
|||
int height;
|
||||
int vrefresh;
|
||||
bool interlace;
|
||||
int cea_video_id;
|
||||
const u8 *hdmiphy_data;
|
||||
const struct hdmi_v13_preset_conf *conf;
|
||||
};
|
||||
|
@ -353,15 +377,20 @@ static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
|
|||
};
|
||||
|
||||
static const struct hdmi_v13_conf hdmi_v13_confs[] = {
|
||||
{ 1280, 720, 60, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
|
||||
{ 1280, 720, 50, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
|
||||
{ 720, 480, 60, false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p },
|
||||
{ 1920, 1080, 50, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 },
|
||||
{ 1920, 1080, 50, false, hdmiphy_v13_conf148_5,
|
||||
&hdmi_v13_conf_1080p50 },
|
||||
{ 1920, 1080, 60, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 },
|
||||
{ 1920, 1080, 60, false, hdmiphy_v13_conf148_5,
|
||||
&hdmi_v13_conf_1080p60 },
|
||||
{ 1280, 720, 60, false, 4, hdmiphy_v13_conf74_25,
|
||||
&hdmi_v13_conf_720p60 },
|
||||
{ 1280, 720, 50, false, 19, hdmiphy_v13_conf74_25,
|
||||
&hdmi_v13_conf_720p60 },
|
||||
{ 720, 480, 60, false, 3, hdmiphy_v13_conf27_027,
|
||||
&hdmi_v13_conf_480p },
|
||||
{ 1920, 1080, 50, true, 20, hdmiphy_v13_conf74_25,
|
||||
&hdmi_v13_conf_1080i50 },
|
||||
{ 1920, 1080, 50, false, 31, hdmiphy_v13_conf148_5,
|
||||
&hdmi_v13_conf_1080p50 },
|
||||
{ 1920, 1080, 60, true, 5, hdmiphy_v13_conf74_25,
|
||||
&hdmi_v13_conf_1080i60 },
|
||||
{ 1920, 1080, 60, false, 16, hdmiphy_v13_conf148_5,
|
||||
&hdmi_v13_conf_1080p60 },
|
||||
};
|
||||
|
||||
/* HDMI Version 1.4 */
|
||||
|
@ -479,6 +508,7 @@ struct hdmi_conf {
|
|||
int height;
|
||||
int vrefresh;
|
||||
bool interlace;
|
||||
int cea_video_id;
|
||||
const u8 *hdmiphy_data;
|
||||
const struct hdmi_preset_conf *conf;
|
||||
};
|
||||
|
@ -934,16 +964,21 @@ static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
|
|||
};
|
||||
|
||||
static const struct hdmi_conf hdmi_confs[] = {
|
||||
{ 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 },
|
||||
{ 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 },
|
||||
{ 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 },
|
||||
{ 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
|
||||
{ 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
|
||||
{ 1920, 1080, 30, false, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
|
||||
{ 1920, 1080, 50, false, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
|
||||
{ 1920, 1080, 60, false, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
|
||||
{ 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 },
|
||||
{ 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 },
|
||||
{ 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 },
|
||||
{ 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
|
||||
{ 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
|
||||
{ 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
|
||||
{ 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
|
||||
{ 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
|
||||
};
|
||||
|
||||
struct hdmi_infoframe {
|
||||
enum HDMI_PACKET_TYPE type;
|
||||
u8 ver;
|
||||
u8 len;
|
||||
};
|
||||
|
||||
static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
|
||||
{
|
||||
|
@ -1267,6 +1302,88 @@ static int hdmi_conf_index(struct hdmi_context *hdata,
|
|||
return hdmi_v14_conf_index(mode);
|
||||
}
|
||||
|
||||
static u8 hdmi_chksum(struct hdmi_context *hdata,
|
||||
u32 start, u8 len, u32 hdr_sum)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* hdr_sum : header0 + header1 + header2
|
||||
* start : start address of packet byte1
|
||||
* len : packet bytes - 1 */
|
||||
for (i = 0; i < len; ++i)
|
||||
hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
|
||||
|
||||
/* return 2's complement of 8 bit hdr_sum */
|
||||
return (u8)(~(hdr_sum & 0xff) + 1);
|
||||
}
|
||||
|
||||
static void hdmi_reg_infoframe(struct hdmi_context *hdata,
|
||||
struct hdmi_infoframe *infoframe)
|
||||
{
|
||||
u32 hdr_sum;
|
||||
u8 chksum;
|
||||
u32 aspect_ratio;
|
||||
u32 mod;
|
||||
u32 vic;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
|
||||
if (hdata->dvi_mode) {
|
||||
hdmi_reg_writeb(hdata, HDMI_VSI_CON,
|
||||
HDMI_VSI_CON_DO_NOT_TRANSMIT);
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_CON,
|
||||
HDMI_AVI_CON_DO_NOT_TRANSMIT);
|
||||
hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (infoframe->type) {
|
||||
case HDMI_PACKET_TYPE_AVI:
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type);
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver);
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len);
|
||||
hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
|
||||
|
||||
/* Output format zero hardcoded ,RGB YBCR selection */
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
|
||||
AVI_ACTIVE_FORMAT_VALID |
|
||||
AVI_UNDERSCANNED_DISPLAY_VALID);
|
||||
|
||||
aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9;
|
||||
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio |
|
||||
AVI_SAME_AS_PIC_ASPECT_RATIO);
|
||||
|
||||
if (hdata->type == HDMI_TYPE13)
|
||||
vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id;
|
||||
else
|
||||
vic = hdmi_confs[hdata->cur_conf].cea_video_id;
|
||||
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
|
||||
|
||||
chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
|
||||
infoframe->len, hdr_sum);
|
||||
DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
|
||||
break;
|
||||
case HDMI_PACKET_TYPE_AUI:
|
||||
hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
|
||||
hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type);
|
||||
hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver);
|
||||
hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len);
|
||||
hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
|
||||
chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
|
||||
infoframe->len, hdr_sum);
|
||||
DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
|
||||
hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool hdmi_is_connected(void *ctx)
|
||||
{
|
||||
struct hdmi_context *hdata = ctx;
|
||||
|
@ -1542,6 +1659,8 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
|
|||
|
||||
static void hdmi_conf_init(struct hdmi_context *hdata)
|
||||
{
|
||||
struct hdmi_infoframe infoframe;
|
||||
|
||||
/* disable HPD interrupts */
|
||||
hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
|
||||
HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
|
||||
|
@ -1576,9 +1695,17 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
|
|||
hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
|
||||
hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
|
||||
} else {
|
||||
infoframe.type = HDMI_PACKET_TYPE_AVI;
|
||||
infoframe.ver = HDMI_AVI_VERSION;
|
||||
infoframe.len = HDMI_AVI_LENGTH;
|
||||
hdmi_reg_infoframe(hdata, &infoframe);
|
||||
|
||||
infoframe.type = HDMI_PACKET_TYPE_AUI;
|
||||
infoframe.ver = HDMI_AUI_VERSION;
|
||||
infoframe.len = HDMI_AUI_LENGTH;
|
||||
hdmi_reg_infoframe(hdata, &infoframe);
|
||||
|
||||
/* enable AVI packet every vsync, fixes purple line problem */
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02);
|
||||
hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
|
||||
hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,14 +298,14 @@
|
|||
#define HDMI_AVI_HEADER1 HDMI_CORE_BASE(0x0714)
|
||||
#define HDMI_AVI_HEADER2 HDMI_CORE_BASE(0x0718)
|
||||
#define HDMI_AVI_CHECK_SUM HDMI_CORE_BASE(0x071C)
|
||||
#define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0720 + 4 * (n))
|
||||
#define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0720 + 4 * (n-1))
|
||||
|
||||
#define HDMI_AUI_CON HDMI_CORE_BASE(0x0800)
|
||||
#define HDMI_AUI_HEADER0 HDMI_CORE_BASE(0x0810)
|
||||
#define HDMI_AUI_HEADER1 HDMI_CORE_BASE(0x0814)
|
||||
#define HDMI_AUI_HEADER2 HDMI_CORE_BASE(0x0818)
|
||||
#define HDMI_AUI_CHECK_SUM HDMI_CORE_BASE(0x081C)
|
||||
#define HDMI_AUI_BYTE(n) HDMI_CORE_BASE(0x0820 + 4 * (n))
|
||||
#define HDMI_AUI_BYTE(n) HDMI_CORE_BASE(0x0820 + 4 * (n-1))
|
||||
|
||||
#define HDMI_MPG_CON HDMI_CORE_BASE(0x0900)
|
||||
#define HDMI_MPG_CHECK_SUM HDMI_CORE_BASE(0x091C)
|
||||
|
@ -338,6 +338,19 @@
|
|||
#define HDMI_AN_SEED_2 HDMI_CORE_BASE(0x0E60)
|
||||
#define HDMI_AN_SEED_3 HDMI_CORE_BASE(0x0E64)
|
||||
|
||||
/* AVI bit definition */
|
||||
#define HDMI_AVI_CON_DO_NOT_TRANSMIT (0 << 1)
|
||||
#define HDMI_AVI_CON_EVERY_VSYNC (1 << 1)
|
||||
|
||||
#define AVI_ACTIVE_FORMAT_VALID (1 << 4)
|
||||
#define AVI_UNDERSCANNED_DISPLAY_VALID (1 << 1)
|
||||
|
||||
/* AUI bit definition */
|
||||
#define HDMI_AUI_CON_NO_TRAN (0 << 0)
|
||||
|
||||
/* VSI bit definition */
|
||||
#define HDMI_VSI_CON_DO_NOT_TRANSMIT (0 << 0)
|
||||
|
||||
/* HDCP related registers */
|
||||
#define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n))
|
||||
#define HDMI_HDCP_KSV_LIST(n) HDMI_CORE_BASE(0x7050 + 4 * (n))
|
||||
|
|
Loading…
Reference in New Issue