catphish / allwinner-bare-metal

A simple framework to boot an Allwinner H3 SoC and run bare metal code
MIT License
22 stars 8 forks source link

H3: HDMI: Make display.c more generic #1

Closed vanvught closed 3 years ago

vanvught commented 4 years ago

Hi,

I have tried to make the display.c code more generic. However, not successful as I do not have a monitor with the currently hard-coded configuration.

Therefore, I am asking a favor if you can make the display.c more generic by using the struct below.

Many thanks, Arjan

enum display_flags {
    DISPLAY_FLAGS_HSYNC_LOW = 1 << 0,
    DISPLAY_FLAGS_HSYNC_HIGH = 1 << 1,
    DISPLAY_FLAGS_VSYNC_LOW = 1 << 2,
    DISPLAY_FLAGS_VSYNC_HIGH = 1 << 3,

    /* data enable flag */
    DISPLAY_FLAGS_DE_LOW = 1 << 4,
    DISPLAY_FLAGS_DE_HIGH = 1 << 5,
    /* drive data on pos. edge */
    DISPLAY_FLAGS_PIXDATA_POSEDGE = 1 << 6,
    /* drive data on neg. edge */
    DISPLAY_FLAGS_PIXDATA_NEGEDGE = 1 << 7,
    DISPLAY_FLAGS_INTERLACED = 1 << 8,
    DISPLAY_FLAGS_DOUBLESCAN = 1 << 9,
    DISPLAY_FLAGS_DOUBLECLK = 1 << 10,
};

struct timing_entry {
    uint32_t min;
    uint32_t typ;
    uint32_t max;
};

struct display_timing {
    struct timing_entry pixelclock;

    struct timing_entry hactive;        /* hor. active video */
    struct timing_entry hfront_porch;   /* hor. front porch */
    struct timing_entry hback_porch;    /* hor. back porch */
    struct timing_entry hsync_len;      /* hor. sync len */

    struct timing_entry vactive;        /* ver. active video */
    struct timing_entry vfront_porch;   /* ver. front porch */
    struct timing_entry vback_porch;    /* ver. back porch */
    struct timing_entry vsync_len;      /* ver. sync len */

    enum display_flags flags;           /* display flags */
    bool hdmi_monitor;                  /* is hdmi monitor? */
};
#define LCDC_X(x)                           (((x) - 1) << 16)
#define LCDC_Y(y)                           (((y) - 1) << 0)

void lcd_init() {
  // LCD0 feeds mixer0 to HDMI
  LCD0_GCTL         = (1U<<31);
  LCD0_GINT0        = 0;
  LCD0_TCON1_CTL    = (1U<<31) | (30<<4);
  LCD0_TCON1_BASIC0 = LCDC_X(default_timing.hactive.typ) | LCDC_Y(default_timing.vactive.typ);
  LCD0_TCON1_BASIC1 = LCDC_X(default_timing.hactive.typ) | LCDC_Y(default_timing.vactive.typ);
  LCD0_TCON1_BASIC2 = LCDC_X(default_timing.hactive.typ) | LCDC_Y(default_timing.vactive.typ);
vanvught commented 4 years ago

Some work on HDMI_PHY

uint32_t hbl = default_timing.hback_porch.typ + default_timing.hfront_porch.typ + default_timing.hsync_len.typ;
uint32_t vbl = default_timing.vback_porch.typ + default_timing.vfront_porch.typ + default_timing.vsync_len.typ;

  HDMI_FC_INVIDCONF = (1U<<6) | (1U<<5) | (1U<<4) | (1U<<3); // Polarity etc
  HDMI_FC_INHACTIV0 = (default_timing.hactive.typ & 0xff);    // Horizontal pixels
  HDMI_FC_INHACTIV1 = (default_timing.hactive.typ >> 8);      // Horizontal pixels
  HDMI_FC_INHBLANK0 = (hbl & 0xff);     // Horizontal blanking
  HDMI_FC_INHBLANK1 = (hbl >> 8);       // Horizontal blanking

  HDMI_FC_INVACTIV0 = (default_timing.vactive.typ & 0xff);    // Vertical pixels
  HDMI_FC_INVACTIV1 = (default_timing.vactive.typ >> 8);      // Vertical pixels
  HDMI_FC_INVBLANK  = vbl;               // Vertical blanking

  HDMI_FC_HSYNCINDELAY0 = (default_timing.hfront_porch.typ & 0xff);  // Horizontal Front porch
  HDMI_FC_HSYNCINDELAY1 = (default_timing.hfront_porch.typ >> 8);    // Horizontal Front porch
  HDMI_FC_VSYNCINDELAY  = default_timing.vfront_porch.typ;            // Vertical front porch
  HDMI_FC_HSYNCINWIDTH0 = (default_timing.hsync_len.typ & 0xff);  // Horizontal sync pulse
  HDMI_FC_HSYNCINWIDTH1 = (default_timing.hsync_len.typ >> 8);    // Horizontal sync pulse
  HDMI_FC_VSYNCINWIDTH  = default_timing.vsync_len.typ;            // Vertical sync pulse