Merge branch 'master' of git://git.denx.de/u-boot-video

This commit is contained in:
Tom Rini 2017-05-15 20:16:02 -04:00
commit d09ec7f816
18 changed files with 341 additions and 192 deletions

View File

@ -84,7 +84,8 @@ struct sunxi_ccm_reg {
u32 lcd0_ch0_clk_cfg; /* 0x118 LCD0 CH0 module clock */
u32 lcd1_ch0_clk_cfg; /* 0x11c LCD1 CH0 module clock */
#endif
u32 reserved14[3];
u32 tve_clk_cfg; /* 0x120 H3/H5 TVE module clock */
u32 reserved14[2];
u32 lcd0_ch1_clk_cfg; /* 0x12c LCD0 CH1 module clock */
u32 lcd1_ch1_clk_cfg; /* 0x130 LCD1 CH1 module clock */
u32 csi0_clk_cfg; /* 0x134 CSI0 module clock */
@ -307,6 +308,7 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_DE_BE0 12
#define AHB_GATE_OFFSET_DE 12
#define AHB_GATE_OFFSET_HDMI 11
#define AHB_GATE_OFFSET_TVE 9
#ifndef CONFIG_SUNXI_DE2
#define AHB_GATE_OFFSET_LCD1 5
#define AHB_GATE_OFFSET_LCD0 4
@ -415,6 +417,9 @@ struct sunxi_ccm_reg {
#define CCM_HDMI_SLOW_CTRL_DDC_GATE (1 << 31)
#define CCM_TVE_CTRL_GATE (0x1 << 31)
#define CCM_TVE_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
#if defined(CONFIG_MACH_SUN50I)
#define MBUS_CLK_DEFAULT 0x81000002 /* PLL6x2 / 3 */
#elif defined(CONFIG_MACH_SUN8I)
@ -448,6 +453,7 @@ struct sunxi_ccm_reg {
#define AHB_RESET_OFFSET_DE 12
#define AHB_RESET_OFFSET_HDMI 11
#define AHB_RESET_OFFSET_HDMI2 10
#define AHB_RESET_OFFSET_TVE 9
#ifndef CONFIG_SUNXI_DE2
#define AHB_RESET_OFFSET_LCD1 5
#define AHB_RESET_OFFSET_LCD0 4

View File

@ -224,52 +224,6 @@ struct sunxi_hdmi_reg {
#endif
};
/*
* This is based on the A10s User Manual, and the A10s only supports
* composite video and not vga like the A10 / A20 does, still other
* than the removed vga out capability the tvencoder seems to be the same.
* "unknown#" registers are registers which are used in the A10 kernel code,
* but not documented in the A10s User Manual.
*/
struct sunxi_tve_reg {
u32 gctrl; /* 0x000 */
u32 cfg0; /* 0x004 */
u32 dac_cfg0; /* 0x008 */
u32 filter; /* 0x00c */
u32 chroma_freq; /* 0x010 */
u32 porch_num; /* 0x014 */
u32 unknown0; /* 0x018 */
u32 line_num; /* 0x01c */
u32 blank_black_level; /* 0x020 */
u32 unknown1; /* 0x024, seems to be 1 byte per dac */
u8 res0[0x08]; /* 0x028 */
u32 auto_detect_en; /* 0x030 */
u32 auto_detect_int_status; /* 0x034 */
u32 auto_detect_status; /* 0x038 */
u32 auto_detect_debounce; /* 0x03c */
u32 csc_reg0; /* 0x040 */
u32 csc_reg1; /* 0x044 */
u32 csc_reg2; /* 0x048 */
u32 csc_reg3; /* 0x04c */
u8 res1[0xb0]; /* 0x050 */
u32 color_burst; /* 0x100 */
u32 vsync_num; /* 0x104 */
u32 notch_freq; /* 0x108 */
u32 cbr_level; /* 0x10c */
u32 burst_phase; /* 0x110 */
u32 burst_width; /* 0x114 */
u32 unknown2; /* 0x118 */
u32 sync_vbi_level; /* 0x11c */
u32 white_level; /* 0x120 */
u32 active_num; /* 0x124 */
u32 chroma_bw_gain; /* 0x128 */
u32 notch_width; /* 0x12c */
u32 resync_num; /* 0x130 */
u32 slave_para; /* 0x134 */
u32 cfg1; /* 0x138 */
u32 cfg2; /* 0x13c */
};
/*
* DE-FE register constants.
*/
@ -394,67 +348,6 @@ struct sunxi_tve_reg {
#define SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE (1 << 8)
#define SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE (1 << 9)
/*
* TVE register constants.
*/
#define SUNXI_TVE_GCTRL_ENABLE (1 << 0)
/*
* Select input 0 to disable dac, 1 - 4 to feed dac from tve0, 5 - 8 to feed
* dac from tve1. When using tve1 the mux value must be written to both tve0's
* and tve1's gctrl reg.
*/
#define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac) (0xf << (((dac) + 1) * 4))
#define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel) ((sel) << (((dac) + 1) * 4))
#define SUNXI_TVE_CFG0_VGA 0x20000000
#define SUNXI_TVE_CFG0_PAL 0x07030001
#define SUNXI_TVE_CFG0_NTSC 0x07030000
#define SUNXI_TVE_DAC_CFG0_VGA 0x403e1ac7
#ifdef CONFIG_MACH_SUN5I
#define SUNXI_TVE_DAC_CFG0_COMPOSITE 0x433f0009
#else
#define SUNXI_TVE_DAC_CFG0_COMPOSITE 0x403f0008
#endif
#define SUNXI_TVE_FILTER_COMPOSITE 0x00000120
#define SUNXI_TVE_CHROMA_FREQ_PAL_M 0x21e6efe3
#define SUNXI_TVE_CHROMA_FREQ_PAL_NC 0x21f69446
#define SUNXI_TVE_PORCH_NUM_PAL 0x008a0018
#define SUNXI_TVE_PORCH_NUM_NTSC 0x00760020
#define SUNXI_TVE_LINE_NUM_PAL 0x00160271
#define SUNXI_TVE_LINE_NUM_NTSC 0x0016020d
#define SUNXI_TVE_BLANK_BLACK_LEVEL_PAL 0x00fc00fc
#define SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC 0x00f0011a
#define SUNXI_TVE_UNKNOWN1_VGA 0x00000000
#define SUNXI_TVE_UNKNOWN1_COMPOSITE 0x18181818
#define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac) (1 << ((dac) + 0))
#define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac) (1 << ((dac) + 16))
#define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac) (1 << ((dac) + 0))
#define SUNXI_TVE_AUTO_DETECT_STATUS_SHIFT(dac) ((dac) * 8)
#define SUNXI_TVE_AUTO_DETECT_STATUS_MASK(dac) (3 << ((dac) * 8))
#define SUNXI_TVE_AUTO_DETECT_STATUS_NONE 0
#define SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED 1
#define SUNXI_TVE_AUTO_DETECT_STATUS_SHORT_GND 3
#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(d) ((d) * 8)
#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_MASK(d) (0xf << ((d) * 8))
#define SUNXI_TVE_CSC_REG0_ENABLE (1 << 31)
#define SUNXI_TVE_CSC_REG0 0x08440832
#define SUNXI_TVE_CSC_REG1 0x3b6dace1
#define SUNXI_TVE_CSC_REG2 0x0e1d13dc
#define SUNXI_TVE_CSC_REG3 0x00108080
#define SUNXI_TVE_COLOR_BURST_PAL_M 0x00000000
#define SUNXI_TVE_CBR_LEVEL_PAL 0x00002828
#define SUNXI_TVE_CBR_LEVEL_NTSC 0x0000004f
#define SUNXI_TVE_BURST_PHASE_NTSC 0x00000000
#define SUNXI_TVE_BURST_WIDTH_COMPOSITE 0x0016447e
#define SUNXI_TVE_UNKNOWN2_PAL 0x0000e0e0
#define SUNXI_TVE_UNKNOWN2_NTSC 0x0000a0a0
#define SUNXI_TVE_SYNC_VBI_LEVEL_NTSC 0x001000f0
#define SUNXI_TVE_ACTIVE_NUM_COMPOSITE 0x000005a0
#define SUNXI_TVE_CHROMA_BW_GAIN_COMP 0x00000002
#define SUNXI_TVE_NOTCH_WIDTH_COMPOSITE 0x00000101
#define SUNXI_TVE_RESYNC_NUM_PAL 0x800d000c
#define SUNXI_TVE_RESYNC_NUM_NTSC 0x000e000c
#define SUNXI_TVE_SLAVE_PARA_COMPOSITE 0x00000000
int sunxi_simplefb_setup(void *blob);
#endif /* _SUNXI_DISPLAY_H */

View File

@ -0,0 +1,131 @@
/*
* Sunxi TV encoder register and constant defines
*
* (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
* (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _TVE_H
#define _TVE_H
enum tve_mode {
tve_mode_vga,
tve_mode_composite_pal,
tve_mode_composite_ntsc,
tve_mode_composite_pal_m,
tve_mode_composite_pal_nc,
};
/*
* This is based on the A10s User Manual, and the A10s only supports
* composite video and not vga like the A10 / A20 does, still other
* than the removed vga out capability the tvencoder seems to be the same.
* "unknown#" registers are registers which are used in the A10 kernel code,
* but not documented in the A10s User Manual.
*/
struct sunxi_tve_reg {
u32 gctrl; /* 0x000 */
u32 cfg0; /* 0x004 */
u32 dac_cfg0; /* 0x008 */
u32 filter; /* 0x00c */
u32 chroma_freq; /* 0x010 */
u32 porch_num; /* 0x014 */
u32 unknown0; /* 0x018 */
u32 line_num; /* 0x01c */
u32 blank_black_level; /* 0x020 */
u32 unknown1; /* 0x024, seems to be 1 byte per dac */
u8 res0[0x08]; /* 0x028 */
u32 auto_detect_en; /* 0x030 */
u32 auto_detect_int_status; /* 0x034 */
u32 auto_detect_status; /* 0x038 */
u32 auto_detect_debounce; /* 0x03c */
u32 csc_reg0; /* 0x040 */
u32 csc_reg1; /* 0x044 */
u32 csc_reg2; /* 0x048 */
u32 csc_reg3; /* 0x04c */
u8 res1[0xb0]; /* 0x050 */
u32 color_burst; /* 0x100 */
u32 vsync_num; /* 0x104 */
u32 notch_freq; /* 0x108 */
u32 cbr_level; /* 0x10c */
u32 burst_phase; /* 0x110 */
u32 burst_width; /* 0x114 */
u32 unknown2; /* 0x118 */
u32 sync_vbi_level; /* 0x11c */
u32 white_level; /* 0x120 */
u32 active_num; /* 0x124 */
u32 chroma_bw_gain; /* 0x128 */
u32 notch_width; /* 0x12c */
u32 resync_num; /* 0x130 */
u32 slave_para; /* 0x134 */
u32 cfg1; /* 0x138 */
u32 cfg2; /* 0x13c */
};
/*
* TVE register constants.
*/
#define SUNXI_TVE_GCTRL_ENABLE (1 << 0)
/*
* Select input 0 to disable dac, 1 - 4 to feed dac from tve0, 5 - 8 to feed
* dac from tve1. When using tve1 the mux value must be written to both tve0's
* and tve1's gctrl reg.
*/
#define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac) (0xf << (((dac) + 1) * 4))
#define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel) ((sel) << (((dac) + 1) * 4))
#define SUNXI_TVE_CFG0_VGA 0x20000000
#define SUNXI_TVE_CFG0_PAL 0x07030001
#define SUNXI_TVE_CFG0_NTSC 0x07030000
#define SUNXI_TVE_DAC_CFG0_VGA 0x403e1ac7
#ifdef CONFIG_MACH_SUN5I
#define SUNXI_TVE_DAC_CFG0_COMPOSITE 0x433f0009
#else
#define SUNXI_TVE_DAC_CFG0_COMPOSITE 0x403f0008
#endif
#define SUNXI_TVE_FILTER_COMPOSITE 0x00000120
#define SUNXI_TVE_CHROMA_FREQ_PAL_M 0x21e6efe3
#define SUNXI_TVE_CHROMA_FREQ_PAL_NC 0x21f69446
#define SUNXI_TVE_PORCH_NUM_PAL 0x008a0018
#define SUNXI_TVE_PORCH_NUM_NTSC 0x00760020
#define SUNXI_TVE_LINE_NUM_PAL 0x00160271
#define SUNXI_TVE_LINE_NUM_NTSC 0x0016020d
#define SUNXI_TVE_BLANK_BLACK_LEVEL_PAL 0x00fc00fc
#define SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC 0x00f0011a
#define SUNXI_TVE_UNKNOWN1_VGA 0x00000000
#define SUNXI_TVE_UNKNOWN1_COMPOSITE 0x18181818
#define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac) (1 << ((dac) + 0))
#define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac) (1 << ((dac) + 16))
#define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac) (1 << ((dac) + 0))
#define SUNXI_TVE_AUTO_DETECT_STATUS_SHIFT(dac) ((dac) * 8)
#define SUNXI_TVE_AUTO_DETECT_STATUS_MASK(dac) (3 << ((dac) * 8))
#define SUNXI_TVE_AUTO_DETECT_STATUS_NONE 0
#define SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED 1
#define SUNXI_TVE_AUTO_DETECT_STATUS_SHORT_GND 3
#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(d) ((d) * 8)
#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_MASK(d) (0xf << ((d) * 8))
#define SUNXI_TVE_CSC_REG0_ENABLE (1 << 31)
#define SUNXI_TVE_CSC_REG0 0x08440832
#define SUNXI_TVE_CSC_REG1 0x3b6dace1
#define SUNXI_TVE_CSC_REG2 0x0e1d13dc
#define SUNXI_TVE_CSC_REG3 0x00108080
#define SUNXI_TVE_COLOR_BURST_PAL_M 0x00000000
#define SUNXI_TVE_CBR_LEVEL_PAL 0x00002828
#define SUNXI_TVE_CBR_LEVEL_NTSC 0x0000004f
#define SUNXI_TVE_BURST_PHASE_NTSC 0x00000000
#define SUNXI_TVE_BURST_WIDTH_COMPOSITE 0x0016447e
#define SUNXI_TVE_UNKNOWN2_PAL 0x0000e0e0
#define SUNXI_TVE_UNKNOWN2_NTSC 0x0000a0a0
#define SUNXI_TVE_SYNC_VBI_LEVEL_NTSC 0x001000f0
#define SUNXI_TVE_ACTIVE_NUM_COMPOSITE 0x000005a0
#define SUNXI_TVE_CHROMA_BW_GAIN_COMP 0x00000002
#define SUNXI_TVE_NOTCH_WIDTH_COMPOSITE 0x00000101
#define SUNXI_TVE_RESYNC_NUM_PAL 0x800d000c
#define SUNXI_TVE_RESYNC_NUM_NTSC 0x000e000c
#define SUNXI_TVE_SLAVE_PARA_COMPOSITE 0x00000000
void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode);
void tvencoder_enable(struct sunxi_tve_reg * const tve);
#endif /* _TVE_H */

View File

@ -85,6 +85,7 @@ static void decode_timing(u8 *buf, struct display_timing *timing)
uint x_mm, y_mm;
unsigned int ha, hbl, hso, hspw, hborder;
unsigned int va, vbl, vso, vspw, vborder;
struct edid_detailed_timing *t = (struct edid_detailed_timing *)buf;
/* Edid contains pixel clock in terms of 10KHz */
set_entry(&timing->pixelclock, (buf[0] + (buf[1] << 8)) * 10000);
@ -111,6 +112,19 @@ static void decode_timing(u8 *buf, struct display_timing *timing)
set_entry(&timing->vback_porch, vbl - vso - vspw);
set_entry(&timing->vsync_len, vspw);
timing->flags = 0;
if (EDID_DETAILED_TIMING_FLAG_HSYNC_POLARITY(*t))
timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
else
timing->flags |= DISPLAY_FLAGS_HSYNC_LOW;
if (EDID_DETAILED_TIMING_FLAG_VSYNC_POLARITY(*t))
timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
else
timing->flags |= DISPLAY_FLAGS_VSYNC_LOW;
if (EDID_DETAILED_TIMING_FLAG_INTERLACED(*t))
timing->flags = DISPLAY_FLAGS_INTERLACED;
debug("Detailed mode clock %u Hz, %d mm x %d mm\n"
" %04x %04x %04x %04x hborder %x\n"
" %04x %04x %04x %04x vborder %x\n",
@ -122,6 +136,39 @@ static void decode_timing(u8 *buf, struct display_timing *timing)
va + vbl, vborder);
}
/**
* Check if HDMI vendor specific data block is present in CEA block
* @param info CEA extension block
* @return true if block is found
*/
static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info)
{
u8 end, i = 0;
/* check for end of data block */
end = info->dtd_offset;
if (end == 0)
end = 127;
if (end < 4 || end > 127)
return false;
end -= 4;
while (i < end) {
/* Look for vendor specific data block of appropriate size */
if ((EDID_CEA861_DB_TYPE(*info, i) == EDID_CEA861_DB_VENDOR) &&
(EDID_CEA861_DB_LEN(*info, i) >= 5)) {
u8 *db = &info->data[i + 1];
u32 oui = db[0] | (db[1] << 8) | (db[2] << 16);
if (oui == HDMI_IEEE_OUI)
return true;
}
i += EDID_CEA861_DB_LEN(*info, i) + 1;
}
return false;
}
int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
int *panel_bits_per_colourp)
{
@ -167,6 +214,15 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing,
((edid->video_input_definition & 0x70) >> 3) + 4;
}
timing->hdmi_monitor = false;
if (edid->extension_flag && (buf_size >= EDID_EXT_SIZE)) {
struct edid_cea861_info *info =
(struct edid_cea861_info *)(buf + sizeof(*edid));
if (info->extension_tag == EDID_CEA861_EXTENSION_TAG)
timing->hdmi_monitor = cea_is_hdmi_vsdb_present(info);
}
return 0;
}

View File

@ -704,7 +704,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
}
break;
#endif /* CONFIG_BMP_16BPP */
#if defined(CONFIG_BMP_24BMP)
#if defined(CONFIG_BMP_24BPP)
case 24:
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
@ -716,7 +716,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
fb -= lcd_line_length + width * (bpix / 8);
}
break;
#endif /* CONFIG_BMP_24BMP */
#endif /* CONFIG_BMP_24BPP */
#if defined(CONFIG_BMP_32BPP)
case 32:
for (i = 0; i < height; ++i) {

View File

@ -619,4 +619,13 @@ config LCD
CONFIG option. See the README for details. Drives which have been
converted to driver model will instead used CONFIG_DM_VIDEO.
config VIDEO_DW_HDMI
bool
help
Enables the common driver code for the Designware HDMI TX
block found in SoCs from various vendors.
As this does not provide any functionality by itself (but
rather requires a SoC-specific glue driver to call it), it
can not be enabled from the configuration menu.
endmenu

View File

@ -57,6 +57,7 @@ obj-$(CONFIG_VIDEO_VESA) += vesa.o
obj-$(CONFIG_FORMIKE) += formike.o
obj-$(CONFIG_LG4573) += lg4573.o
obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
obj-${CONFIG_EXYNOS_FB} += exynos/

View File

@ -414,13 +414,9 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
/*
* TODO(sjg@chromium.org>: Need to check for HDMI / DVI
* inv_val |= (edid->hdmi_monitor_detected ?
* HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
* HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
*/
inv_val |= HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE;
inv_val |= (edid->hdmi_monitor ?
HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
@ -459,7 +455,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
}
/* hdmi initialization step b.4 */
static void hdmi_enable_video_path(struct dw_hdmi *hdmi)
static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
{
uint clkdis;
@ -484,8 +480,10 @@ static void hdmi_enable_video_path(struct dw_hdmi *hdmi)
clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
if (audio) {
clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
}
}
/* workaround to clear the overflow condition */
@ -716,7 +714,8 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
{
int ret;
debug("hdmi, mode info : clock %d hdis %d vdis %d\n",
debug("%s, mode info : clock %d hdis %d vdis %d\n",
edid->hdmi_monitor ? "hdmi" : "dvi",
edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
hdmi_av_composer(hdmi, edid);
@ -725,11 +724,13 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
if (ret)
return ret;
hdmi_enable_video_path(hdmi);
hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
hdmi_audio_fifo_reset(hdmi);
hdmi_audio_set_format(hdmi);
hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
if (edid->hdmi_monitor) {
hdmi_audio_fifo_reset(hdmi);
hdmi_audio_set_format(hdmi);
hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
}
hdmi_video_packetize(hdmi);
hdmi_video_sample(hdmi);

View File

@ -35,6 +35,7 @@ config DISPLAY_ROCKCHIP_LVDS
config DISPLAY_ROCKCHIP_HDMI
bool "HDMI port"
select VIDEO_DW_HDMI
depends on VIDEO_ROCKCHIP
help
This enables High-Definition Multimedia Interface display support.

View File

@ -9,6 +9,6 @@ ifdef CONFIG_VIDEO_ROCKCHIP
obj-y += rk_vop.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o ../dw_hdmi.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_MIPI) += rk_mipi.o
endif

View File

@ -5,5 +5,5 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o lcdc.o ../videomodes.o
obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o lcdc.o tve.o ../videomodes.o
obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o lcdc.o ../dw_hdmi.o

View File

@ -14,6 +14,7 @@
#include <asm/arch/gpio.h>
#include <asm/arch/lcdc.h>
#include <asm/arch/pwm.h>
#include <asm/arch/tve.h>
#include <asm/global_data.h>
#include <asm/gpio.h>
#include <asm/io.h>
@ -929,63 +930,19 @@ static void sunxi_tvencoder_mode_set(void)
switch (sunxi_display.monitor) {
case sunxi_monitor_vga:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
tvencoder_mode_set(tve, tve_mode_vga);
break;
case sunxi_monitor_composite_pal_nc:
writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
/* Fall through */
tvencoder_mode_set(tve, tve_mode_composite_pal_nc);
break;
case sunxi_monitor_composite_pal:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
tvencoder_mode_set(tve, tve_mode_composite_pal);
break;
case sunxi_monitor_composite_pal_m:
writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
/* Fall through */
tvencoder_mode_set(tve, tve_mode_composite_pal_m);
break;
case sunxi_monitor_composite_ntsc:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
tvencoder_mode_set(tve, tve_mode_composite_ntsc);
break;
case sunxi_monitor_none:
case sunxi_monitor_dvi:
@ -995,14 +952,6 @@ static void sunxi_tvencoder_mode_set(void)
}
}
static void sunxi_tvencoder_enable(void)
{
struct sunxi_tve_reg * const tve =
(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
}
#endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
static void sunxi_drc_init(void)
@ -1080,6 +1029,8 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
int __maybe_unused clk_div, clk_double;
struct sunxi_lcdc_reg * const lcdc =
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
struct sunxi_tve_reg * __maybe_unused const tve =
(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
switch (sunxi_display.monitor) {
case sunxi_monitor_none:
@ -1134,7 +1085,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
sunxi_tvencoder_mode_set();
sunxi_composer_enable();
lcdc_enable(lcdc, sunxi_display.depth);
sunxi_tvencoder_enable();
tvencoder_enable(tve);
#elif defined CONFIG_VIDEO_VGA_VIA_LCD
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon0_mode_set(mode, true);
@ -1153,7 +1104,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
sunxi_tvencoder_mode_set();
sunxi_composer_enable();
lcdc_enable(lcdc, sunxi_display.depth);
sunxi_tvencoder_enable();
tvencoder_enable(tve);
#endif
break;
}

86
drivers/video/sunxi/tve.c Normal file
View File

@ -0,0 +1,86 @@
/*
* TV encoder driver for Allwinner SoCs.
*
* (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
* (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
* (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/tve.h>
#include <asm/io.h>
void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode)
{
switch (mode) {
case tve_mode_vga:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
break;
case tve_mode_composite_pal_nc:
writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
/* Fall through */
case tve_mode_composite_pal:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL,
&tve->blank_black_level);
writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
break;
case tve_mode_composite_pal_m:
writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
/* Fall through */
case tve_mode_composite_ntsc:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC,
&tve->blank_black_level);
writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
break;
}
}
void tvencoder_enable(struct sunxi_tve_reg * const tve)
{
setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
}

View File

@ -316,7 +316,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
break;
#endif /* CONFIG_BMP_16BPP */
#if defined(CONFIG_BMP_24BMP)
#if defined(CONFIG_BMP_24BPP)
case 24:
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
@ -328,7 +328,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
fb -= priv->line_length + width * (bpix / 8);
}
break;
#endif /* CONFIG_BMP_24BMP */
#endif /* CONFIG_BMP_24BPP */
#if defined(CONFIG_BMP_32BPP)
case 32:
for (i = 0; i < height; ++i) {

View File

@ -21,7 +21,7 @@
#define CONFIG_VIDEO_BMP_GZIP
#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (1366*767*4)
#define CONFIG_BMP_24BMP
#define CONFIG_BMP_24BPP
#define CONFIG_BMP_32BPP
/* memory */

View File

@ -19,6 +19,9 @@
#define EDID_SIZE 128
#define EDID_EXT_SIZE 256
/* OUI of HDMI vendor specific data block */
#define HDMI_IEEE_OUI 0x000c03
#define GET_BIT(_x, _pos) \
(((_x) >> (_pos)) & 1)
#define GET_BITS(_x, _pos_msb, _pos_lsb) \
@ -234,6 +237,13 @@ struct edid1_info {
unsigned char checksum;
} __attribute__ ((__packed__));
enum edid_cea861_db_types {
EDID_CEA861_DB_AUDIO = 0x01,
EDID_CEA861_DB_VIDEO = 0x02,
EDID_CEA861_DB_VENDOR = 0x03,
EDID_CEA861_DB_SPEAKER = 0x04,
};
struct edid_cea861_info {
unsigned char extension_tag;
#define EDID_CEA861_EXTENSION_TAG 0x02
@ -251,6 +261,10 @@ struct edid_cea861_info {
#define EDID_CEA861_DTD_COUNT(_x) \
GET_BITS(((_x).dtd_count), 3, 0)
unsigned char data[124];
#define EDID_CEA861_DB_TYPE(_x, offset) \
GET_BITS((_x).data[offset], 7, 5)
#define EDID_CEA861_DB_LEN(_x, offset) \
GET_BITS((_x).data[offset], 4, 0)
} __attribute__ ((__packed__));
/**

View File

@ -967,6 +967,7 @@ struct display_timing {
struct timing_entry vsync_len; /* ver. sync len */
enum display_flags flags; /* display flags */
bool hdmi_monitor; /* is hdmi monitor? */
};
/**

View File

@ -236,7 +236,6 @@ CONFIG_BL1_SIZE
CONFIG_BL2_OFFSET
CONFIG_BL2_SIZE
CONFIG_BMP_16BPP
CONFIG_BMP_24BMP
CONFIG_BMP_24BPP
CONFIG_BMP_32BPP
CONFIG_BOARDDIR