avafinger / bpi-m64-firmware

Banana Pi M64 firmware (eMMC, Wifi, bluetooth, GbE, OV5640)
27 stars 8 forks source link

WiringPi & RPI.GPIO do not work - on 4.4 Kernel #18

Closed shaddow501 closed 5 years ago

shaddow501 commented 5 years ago

Hello, I was trying your image and I have some issues with it.

following the guide from BPI of installing WiringPi & python GPIO and it doesnt run on the board. the error I get that the application can run only on Raspberry PI board.

When using other image as like Armbian / or other BPI_M64 those applications work without any issue.

What is missing and how to fix that? I like your image since it is small but I need to be able to work with those applications.

Another question: I am using HDMI 5" 800x480 LCD, On Armbian image I can see the display, with yours I have a white screen, what do I need to do in order to get it to work?

avafinger commented 5 years ago

the + is the code you must add.

shaddow501 commented 5 years ago

Yes I know already started to work on it...

shaddow501 commented 5 years ago

linux-sunxi/drivers/gpu/drm/sunxi/subdev/sunxi_hdmi.c

/*
 * Copyright (C) 2016 Allwinnertech Co.Ltd
 * Authors: Jet Cui
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 *
 */
/*HDMI panel ops*/
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include "../sunxi_drm_drv.h"
#include "../sunxi_drm_core.h"
#include "../sunxi_drm_crtc.h"
#include "../sunxi_drm_encoder.h"
#include "../sunxi_drm_connector.h"
#include "../sunxi_drm_plane.h"
#include "../drm_de/drm_al.h"
#include "../subdev/sunxi_common.h"
#include "../sunxi_drm_panel.h"
#include "sunxi_hdmi.h"
#include "hdmi_bsp.h"
#include "de/include.h"
#include <linux/clk-provider.h>

/* vendor specific mode */
static const struct drm_display_mode edid_vsp_modes[] = {
    /* 0 */
    { DRM_MODE("1920x1080@3D", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2558,
        2602, 2750, 0, 1080, 1084, 1089, 2160, 0,
        DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
        .vrefresh = 24, },
    /* 1 */
    { DRM_MODE("1280x720@3D", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
        1760, 1980, 0, 1440, 1445, 1450, 1500, 0,
        DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
        .vrefresh = 50, },
    /* 2 */
    { DRM_MODE("1280x720@3D", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
        1430, 1650, 0, 1440, 1445, 1450, 1500, 0,
        DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
        .vrefresh = 60, },
    /* 3 */
    { DRM_MODE("3840x2160@30", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4010,
        4098, 4400, 0, 2160, 2168, 2178, 2250, 0,
        DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
        .vrefresh = 30, },
    /* 4 */
    { DRM_MODE("3840x2160@25", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
        4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
        DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
        .vrefresh = 25, },
};

static const struct disp_video_timings video_timing[] = {
/* 0 */{HDMI1440_480I,      0, 13500000,  1,  720,   480,   858,
    57,   19,   62,  525,   15,  4,  3,  0,   0,    1,   0,   0},
/* 1 */{HDMI1440_576I,      0, 13500000,  1,  720,   576,   864,
    69,   12,   63,  625,   19,  2,  3,  0,   0,    1,   0,   0},
/* 2 */{HDMI480P,           0, 27000000,  0,  720,   480,   858,
    60,   16,   62,  525,   30,  9,  6,  0,   0,    0,   0,   0},
/* 3 */{HDMI576P,           0, 27000000,  0,  720,   576,   864,
    68,   12,   64,  625,   39,  5,  5,  0,   0,    0,   0,   0},
/* 4 */{HDMI720P_50,        0, 74250000,  0,  1280,  720,   1980,  220,
    440,  40,  750,   20,  5,  5,  1,   1,    0,   0,   0},
/* 5 */{HDMI720P_60,        0, 74250000,  0,  1280,  720,   1650,  220,
    110,  40,  750,   20,  5,  5,  1,   1,    0,   0,   0},
/* 6 */{HDMI1080I_50,       0, 74250000,  0,  1920,  1080,  2640,  148,
    528,  44,  1125,  15,  2,  5,  1,   1,    1,   0,   0},
/* 7 */{HDMI1080I_60,       0, 74250000,  0,  1920,  1080,  2200,  148,
    88,   44,  1125,  15,  2,  5,  1,   1,    1,   0,   0},
/* 8 */{HDMI1080P_50,       0, 148500000, 0,  1920,  1080,  2640,  148,
    528,  44,  1125,  36,  4,  5,  1,   1,    0,   0,   0},
/* 9 */{HDMI1080P_60,       0, 148500000, 0,  1920,  1080,  2200,  148,
    88,   44,  1125,  36,  4,  5,  1,   1,    0,   0,   0},
/* 10*/{HDMI1080P_24,       0, 74250000,  0,  1920,  1080,  2750,  148,
    638,  44,  1125,  36,  4,  5,  1,   1,    0,   0,   0},
/* 11*/{HDMI1080P_25,       0, 74250000,  0,  1920,  1080,  2640,  148,
    528,  44,  1125,  36,  4,  5,  0,   0,    0,   0,   0},
/* 12*/{HDMI1080P_30,       0, 74250000,  0,  1920,  1080,  2200,  148,
    88,   44,  1125,  36,  4,  5,  0,   0,    0,   0,   0},
/* 13*/{HDMI1080P_24_3D_FP, 0, 148500000, 0,  1920,  2160,  2750,  148,
    638,  44,  1125,  36,  4,  5,  1,   1,    0,   45,  1},
/* 14*/{HDMI720P_50_3D_FP,  0, 148500000, 0,  1280,  1440,  1980,  220,
    440,  40,  750,   20,  5,  5,  1,   1,    0,   30,  1},
/* 15*/{HDMI720P_60_3D_FP,  0, 148500000, 0,  1280,  1440,  1650,  220,
    110,  40,  750,   20,  5,  5,  1,   1,    0,   30,  1},
/* 16*/{HDMI3840_2160P_30,  0, 297000000, 0,  3840,  2160,  4400,  296,
    176,  88,  2250,  72,  8, 10,  1,   1,    0,    0,  0},
/* 17*/{HDMI3840_2160P_25,  0, 297000000, 0,  3840,  2160,  5280,  296,
    1056,  88,  2250,  72,  8, 10,  1,   1,    0,    0,  0},
/* 18*/{HDMI800_480P,       0, 27000000,  0,   800,   480,  1028,   88,   
    80,   60,  525,   29, 13,  3,  0,   0,   0,    0,  0},
};

void hdmi_delay_us(unsigned long us)
{
    udelay(us);
}

void hdmi_delay_ms(unsigned long ms)
{
    sunxi_drm_delayed_ms(ms);
}

enum drm_mode_status sunxi_hdmi_check_mode(struct sunxi_panel *sunxi_panel,
    struct drm_display_mode *mode)
{
    struct disp_video_timings hdmi_timing;

    return sunxi_hdmi_mode_timmings(&hdmi_timing, mode);
}

bool default_hdmi_init(struct sunxi_panel *sunxi_panel)
{
    struct sunxi_hdmi_private *sunxi_hdmi_p;
    struct video_para *glb_video_para;
    struct audio_para *glb_audio_para;
    struct disp_video_timings *hdmi_timing;

    sunxi_hdmi_p = (struct sunxi_hdmi_private *)sunxi_panel->private;
    glb_video_para = &sunxi_hdmi_p->video_para;
    glb_audio_para = &sunxi_hdmi_p->audio_para;
    hdmi_timing = sunxi_hdmi_p->timing;

    memcpy(hdmi_timing, &video_timing[4],
        sizeof(struct disp_video_timings));

    glb_video_para->vic = HDMI720P_50;
    glb_video_para->csc = BT601;
    glb_video_para->is_hdmi = 1;
    glb_video_para->is_yuv = 0;
    glb_video_para->is_hcts = 0;
    glb_audio_para->type = 1;
    glb_audio_para->sample_rate = 44100;
    glb_audio_para->sample_bit = 16;
    glb_audio_para->ch_num = 2;
    glb_audio_para->ca = 0;
    glb_audio_para->vic = HDMI720P_50;
    return true;
}

static int hdmi_io_request(struct sunxi_hdmi_private *sunxi_hdmi_p)
{
    int i;

    for (i = 0; i < HDMI_IO_NUM; i++) {
        if (sunxi_hdmi_p->hdmi_io_used[i]) {
            struct disp_gpio_set_t  gpio_info[1];

            memcpy(gpio_info, &(sunxi_hdmi_p->hdmi_io[i]),
                sizeof(struct disp_gpio_set_t));
            sunxi_hdmi_p->gpio_handle[i] =
                sunxi_drm_sys_gpio_request(gpio_info);
        }
    }

    return 0;
}

static int hdmi_io_release(struct sunxi_hdmi_private *sunxi_hdmi_p)
{
    int i;

    for (i = 0; i < HDMI_IO_NUM; i++) {
        if (sunxi_hdmi_p->hdmi_io_used[i] &&
            sunxi_hdmi_p->gpio_handle[i] != 0) {
            struct disp_gpio_set_t  gpio_info[1];

            memcpy(gpio_info, &(sunxi_hdmi_p->hdmi_io[i]),
                sizeof(struct disp_gpio_set_t));
            sunxi_hdmi_p->gpio_handle[i] =
                sunxi_drm_sys_gpio_request(gpio_info);
            gpio_info->mul_sel = 7;
            sunxi_drm_sys_gpio_release(
                sunxi_hdmi_p->gpio_handle[i]);
            sunxi_hdmi_p->gpio_handle[i] = 0;
        }
    }
    return 0;
}

bool default_hdmi_open(struct sunxi_panel *sunxi_panel)
{
    struct sunxi_hdmi_private *sunxi_hdmi_p;

    sunxi_hdmi_p = (struct sunxi_hdmi_private *)sunxi_panel->private;
    hdmi_io_request(sunxi_hdmi_p);

    bsp_hdmi_video(&sunxi_hdmi_p->video_para);
    bsp_hdmi_audio(&sunxi_hdmi_p->audio_para);
    bsp_hdmi_set_video_en(1);
    return true;
}

bool default_hdmi_close(struct sunxi_panel *sunxi_panel)
{
    struct sunxi_hdmi_private *sunxi_hdmi_p;
    sunxi_hdmi_p = (struct sunxi_hdmi_private *)sunxi_panel->private;
    bsp_hdmi_set_video_en(0);
    hdmi_io_release(sunxi_hdmi_p);
    return true;
}

enum drm_mode_status sunxi_hdmi_mode_timmings(void *timing,
    struct drm_display_mode *mode)
{
    struct disp_video_timings *hdmi_timing =
        (struct disp_video_timings *)timing;
    const struct disp_video_timings *fix_timing = NULL;
    int vrefresh;

    if (!hdmi_timing || !mode)
        return MODE_BAD;
    vrefresh = mode->vrefresh;
    if (mode->vrefresh == 0) {
        vrefresh = drm_mode_vrefresh(mode);
        DRM_DEBUG_KMS("vrefresh:%d id:%d (%d x %d) flag:%x\n",
            vrefresh, mode->base.id, mode->hdisplay,
            mode->vdisplay, mode->flags);
    }

    if (vrefresh == 60 || vrefresh == 59 || vrefresh == 61) {
        if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
            if (mode->hdisplay == 1920 &&
                mode->vdisplay == 1080) {
                /* HDMI1080I_60 */
                fix_timing = &video_timing[7];
            }
            if (mode->hdisplay == 720 && mode->vdisplay == 480) {
                /* HDMI1440_480I */
                fix_timing = &video_timing[0];
            }
        } else {
            if (mode->vdisplay == 1080 &&
                mode->hdisplay == 1920) {
                /* HDMI1080P_60 */
                fix_timing = &video_timing[9];
            }
            if (mode->vdisplay == 720 &&
                mode->hdisplay == 1280) {
                /* HDMI720P_60 */
                fix_timing = &video_timing[5];
            }
            if (mode->vdisplay == 480 &&
                mode->hdisplay == 720) {
                /* HDMI480P */
                fix_timing = &video_timing[2];
            }
            if (mode->vdisplay == 576 &&
                mode->hdisplay == 720) {
                /* HDMI576P */
                fix_timing = &video_timing[3];
            }
            if (mode->vdisplay == 1440 &&
                mode->hdisplay == 1280) {
                /* HDMI720P_60_3D_FP */
                fix_timing = &video_timing[15];
            }
            if (mode->vdisplay == 480 &&
                mode->hdisplay == 800) {
                /* HDMI800_480P */
                fix_timing = &video_timing[18];
            }
        }
    } else if (vrefresh == 50 || vrefresh == 49 || vrefresh == 51) {
        if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
            if (mode->hdisplay == 1920 &&
                mode->vdisplay == 1080) {
                fix_timing = &video_timing[6];
                /* HDMI1080I_50 */
            }
            if (mode->hdisplay == 720 &&
                mode->vdisplay == 576) {
                /* HDMI1440_576I */
                fix_timing = &video_timing[1];
            }
        } else {
            if (mode->vdisplay == 1080 &&
                mode->hdisplay == 1920) {
                /* HDMI1080P_50 */
                fix_timing = &video_timing[8];
            }
            if (mode->vdisplay == 720 &&
                mode->hdisplay == 1280) {
                /* HDMI720P_50 */
                fix_timing = &video_timing[4];
            }
            if (mode->vdisplay == 1440 &&
                mode->hdisplay == 1280) {
                /* HDMI720P_50_3D_FP */
                fix_timing = &video_timing[14];
            }
        }
    } else if (vrefresh == 30 || vrefresh == 29 || vrefresh == 31) {
        if (mode->vdisplay == 1080 && mode->hdisplay == 1920) {
            /* HDMI1080P_30 */
            fix_timing = &video_timing[12];
        }
        if (mode->vdisplay == 2160 && mode->hdisplay == 3840) {
            /* HDMI3840_2160P_30 */
            fix_timing = &video_timing[16];
        }
    } else if (vrefresh == 23 || vrefresh == 24 ||
        vrefresh == 25 || vrefresh == 26) {
        if (mode->vdisplay == 2160 && mode->hdisplay == 1920) {
            /* HDMI1080P_24_3D_FP */
            fix_timing = &video_timing[13];
        }
        if (mode->vdisplay == 1080 && mode->hdisplay == 1920 &&
            mode->htotal == 2640) {
            /* HDMI1080P_25 */
            fix_timing = &video_timing[11];
        }
        if (mode->vdisplay == 1080 && mode->hdisplay == 1920 &&
            mode->htotal == 2750) {
            /* HDMI1080P_24 */
            fix_timing = &video_timing[10];
        }
        if (mode->vdisplay == 2160 && mode->hdisplay == 3840) {
            /* HDMI3840_2160P_25 */
            fix_timing = &video_timing[17];
        }
    }

    if (fix_timing == NULL)
        return MODE_ERROR;

    memcpy(hdmi_timing, fix_timing, sizeof(struct disp_video_timings));
    DRM_DEBUG_KMS("[%d]vrefresh:%d id:%d(%d x %d)flag:%x vic:%d  %d\n",
            __LINE__,
        vrefresh, mode->base.id, mode->hdisplay, mode->vdisplay,
        mode->flags, fix_timing->vic, hdmi_timing->vic);

    return MODE_OK;
}

static void edid_read_data(u8 block, struct edid *buf)
{
    int ret;
    u8 *pbuf = ((u8 *)(buf)) + 128*block;
    u8 offset = (block&0x01) ? 128:0;
    int i;

    ret = bsp_hdmi_ddc_read(Explicit_Offset_Address_E_DDC_Read,
            block>>1, offset, 128, pbuf);
    DRM_DEBUG_KMS("Sink : EDID bank %d:\n", block);

    DRM_DEBUG_KMS(
        " 0   1   2   3   4   5   6   7   8   9   A   B   \
        C   D   E   F\n");
    DRM_DEBUG_KMS(
        " ========================================\n");

    for (i = 0; i < 8; i++) {
        DRM_DEBUG_KMS(" %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  \
            %2.2x  %2.2x \
            %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x \
            %2.2x  %2.2x\n",
            pbuf[i * 16 + 0], pbuf[i * 16 + 1], pbuf[i * 16 + 2],
            pbuf[i * 16 + 3], pbuf[i * 16 + 4], pbuf[i * 16 + 5],
            pbuf[i * 16 + 6], pbuf[i * 16 + 7], pbuf[i * 16 + 8],
            pbuf[i * 16 + 9], pbuf[i * 16 + 10],
            pbuf[i * 16 + 11],
            pbuf[i * 16 + 12], pbuf[i * 16 + 13],
            pbuf[i * 16 + 14], pbuf[i * 16 + 15]);
    }
    DRM_DEBUG_KMS(
        " ==========================================\n");

}
/* drm does not add the vendor specific mode, so we add it */
int sunxi_vendor_specific_mode(struct drm_connector *connector,
    unsigned char *edid, int size)
{
    struct drm_display_mode *newmode;

    u8 index = 8;
    u8 vic_len = 0;
    u8 i;
    int cout = 0;

    /* check if it's HDMI VSDB */
    if (!((edid[0] == 0x03) && (edid[1] == 0x0c) &&
        (edid[2] == 0x00))) {
        return 0;
    }

    if (size <= 8)
        return 0;

    if ((edid[7]&0x20) == 0)
        return 0;
    if ((edid[7]&0x40) == 0x40)
        index = index + 2;
    if ((edid[7]&0x80) == 0x80)
        index = index + 2;

    /* mandatary format support */
    if (edid[index]&0x80) {
        i = 3;
        while (i--) {
            newmode = drm_mode_duplicate(connector->dev,
                    &edid_vsp_modes[i]);
            if (newmode) {
                cout++;
                drm_mode_probed_add(connector, newmode);
            } else {
                DRM_ERROR("kmzalloc edid for sunxi \
                    failed.\n");
            }
        }
    }
    DRM_INFO("3D_multi_present   %d.\n", cout);
    if (((edid[index]&0x60) == 1) || ((edid[index]&0x60) == 2))
        DRM_INFO("3D_multi_present.\n");

    vic_len = edid[index+1]>>5;
    for (i = 0; i < vic_len; i++) {
        /* HDMI_VIC for extended resolution transmission */
        if ((edid[index+1+1+i] + 0x100) == HDMI3840_2160P_30)
            newmode = drm_mode_duplicate(connector->dev,
                    &edid_vsp_modes[3]);
        if (newmode) {
            cout++;
            drm_mode_probed_add(connector, newmode);
        }
        if (HDMI3840_2160P_25 == (edid[index+1+1+i] + 0x100))
            newmode = drm_mode_duplicate(connector->dev,
                &edid_vsp_modes[4]);
        if (newmode) {
            cout++;
            drm_mode_probed_add(connector, newmode);
        }
        DRM_INFO("edid_parse_vsdb: VIC %d support.\n",
            edid[index+1+1+i]);
    }
    DRM_INFO("4k  _multi_present   %d.\n", cout);

    index += (edid[index+1]&0xe0) + 2;
    if (index > (size+1))
        return cout;

    DRM_INFO("3D_multi_present byte(%2.2x,%2.2x).\n",
        edid[index], edid[index+1]);

    return cout;
}

static int sunxi_load_cea_db(struct drm_connector *connector,
    struct edid *pedid)
{
    unsigned int offset;
    struct sunxi_hdmi_private *sunxi_hdmi_p;
    struct sunxi_drm_connector *sunxi_connector =
        to_sunxi_connector(connector);
    unsigned char *edid;
    int count = 0;

    sunxi_hdmi_p = sunxi_connector->panel->private;
    edid = (unsigned char *)pedid;
    /* must cea */
    if (edid[0] != 2) {
        DRM_INFO("edid not cea :%d.\n", edid[0]);

        return 0;
    }
    if (edid[1] >= 1) {
        sunxi_hdmi_p->can_YCbCr444 = !!(edid[3] & 0x20);
        sunxi_hdmi_p->can_YCbCr422 = !!(edid[3] & 0x10);
    }

    offset = edid[2];
    if (offset > 4) {
        u8 bsum = 4;

        while (bsum < offset) {
            u8 tag = edid[bsum]>>5;
            u8 len = edid[bsum]&0x1f;

            if ((len > 0) && ((bsum + len + 1) > offset)) {
                goto out;

                if (tag == 3) {
                    count += sunxi_vendor_specific_mode(
                        connector, edid+bsum+1, len);
                }
            }
            bsum += (len + 1);
        }
    }

out:
    return count;
}

void swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
    size_t size, enum dma_data_direction dir);

unsigned int sunxi_hdmi_get_edid(struct sunxi_panel *panel)
{
    struct drm_connector *connector = panel->drm_connector;
    int i = 0, block = 0;
    unsigned int count = 0;
    struct edid *sunxi_deid;
    struct sunxi_hdmi_private *sunxi_hdmi_p;

    sunxi_hdmi_p = (struct sunxi_hdmi_private *)panel->private;
    sunxi_deid = kzalloc(sizeof(struct edid), GFP_KERNEL);
    if (!sunxi_deid) {
        DRM_ERROR("kzalloc edid for sunxi failed.\n");
        goto out;
    }

    edid_read_data(0, sunxi_deid);
    block = sunxi_deid->extensions;
    if (block > 0 && block < 8) {
        kfree(sunxi_deid);
        sunxi_deid = kzalloc(sizeof(struct edid) * (block+1),
            GFP_KERNEL);
        if (!sunxi_deid) {
            DRM_ERROR("kzalloc edid for sunxi failed.\n");
            goto out;
        }
        for (i = 0; i < (block+1); i++) {
            edid_read_data(i, sunxi_deid);
#if 0
            swiotlb_sync_single_for_device(NULL,
                virt_to_phys((sunxi_deid+i)),
                128, DMA_BIDIRECTIONAL);
#endif
            if (i > 0)
                count += sunxi_load_cea_db(connector,
                    sunxi_deid+i);
        }
        sunxi_hdmi_p->nr_sad = drm_edid_to_sad(sunxi_deid,
            &sunxi_hdmi_p->hdmi_sads);
        drm_edid_to_eld(connector, sunxi_deid);
    }

    count += drm_add_edid_modes(connector, sunxi_deid);
    if (!count) {
        DRM_ERROR("Add edid modes failed %d\n", count);
        kfree(sunxi_deid);
        goto out;
    }

    drm_mode_connector_update_edid_property(connector, sunxi_deid);
    kfree(sunxi_deid);

    DRM_INFO("%s:add %d cout modes.\n", __func__, count);

out:
    return count;
}

enum drm_connector_status sunxi_hdmi_detect(struct sunxi_panel *panel)
{
    enum drm_connector_status status = connector_status_disconnected;
    int on_sure = 0, off_sure = 0, time = 5;

    (void)panel;

    DRM_DEBUG_KMS("%s:line:%d  status:  %d\n", __func__, __LINE__,
        bsp_hdmi_get_hpd());

    while (time--) {
        if (bsp_hdmi_get_hpd()) {
            on_sure++;
            off_sure = 0;
        } else {
            off_sure++;
            on_sure = 0;
        }
        if (off_sure == 3) {
            status = connector_status_disconnected;
            break;
        }
        if (on_sure == 3) {
            status = connector_status_connected;
            break;
        }
        hdmi_delay_us(100);
    }
    return status;
}

static struct panel_ops  default_panel = {
    .init = default_hdmi_init,
    .open = default_hdmi_open,
    .close = default_hdmi_close,
    .reset = NULL,
    .bright_light = NULL,
    .detect = sunxi_hdmi_detect,
    .change_mode_to_timming = sunxi_hdmi_mode_timmings,
    .check_valid_mode = sunxi_hdmi_check_mode,
    .get_modes = sunxi_hdmi_get_edid

};

void sunxi_hdmi_get_sys_info(struct sunxi_panel *sunxi_panel)
{
    struct sunxi_hdmi_private *sunxi_hdmi_p;
    struct device_node *node;
    unsigned int value;
    struct disp_gpio_set_t  *gpio_info;
    int i;
    char io_name[32];

    sunxi_hdmi_p = (struct sunxi_hdmi_private *)sunxi_panel->private;
    node = sunxi_drm_get_name_node("sunxi-hdmi");
    if (!node) {
        DRM_ERROR("get sunxi-hdmi node err.\n");
        return;
    }

    sunxi_drm_get_sys_item_char(node, "hdmi_power",
        sunxi_hdmi_p->hdmi_power);
    if (sunxi_drm_get_sys_item_int(node, "hdmi_cts_compatibility",
        &value) == 0) {
        sunxi_hdmi_p->cts_compat = !!value;
    }
    if (sunxi_drm_get_sys_item_int(node, "hdmi_hdcp_enable",
        &value) == 0) {
        sunxi_hdmi_p->hdcp_enable = !!value;
    }
    if (sunxi_drm_get_sys_item_int(node, "hdmi_cec_support",
        &value) == 0) {
        sunxi_hdmi_p->cec_support = !!value;
    }

    for (i = 0; i < HDMI_IO_NUM; i++) {
        gpio_info = &(sunxi_hdmi_p->hdmi_io[i]);
        sprintf(io_name, "hdmi_io_%d", i);
        if (0 == sunxi_drm_get_sys_item_gpio(node, io_name,
            gpio_info))
            sunxi_hdmi_p->hdmi_io_used[i] = 1;
        else
            sunxi_hdmi_p->hdmi_io_used[i] = 0;
    }
}

int sunxi_hdmi_set_audio_mode(struct sunxi_panel *sunxi_panel)
{
    return 0;
}

unsigned char  sunxi_hdmi_yuv_output(struct sunxi_hdmi_private *sunxi_hdmi_p)
{
    if (!sunxi_hdmi_p->can_YCbCr444)
        return 0;
    switch (sunxi_hdmi_p->timing->vic) {
    case HDMI1080P_24:
    case HDMI1080P_24_3D_FP:
    case HDMI3840_2160P_24:
    case HDMI3840_2160P_30:
    case HDMI3840_2160P_25:
        return 0;
    }
    /* 1 is can_YCbCr444 */
    return 1;
}

int sunxi_hdmi_set_timing(void *data, struct drm_display_mode *mode)
{
    struct sunxi_drm_connector *sunxi_connector =
                to_sunxi_connector(data);
    struct sunxi_panel *sunxi_panel = sunxi_connector->panel;
    struct sunxi_hdmi_private *sunxi_hdmi_p =
        (struct sunxi_hdmi_private *)sunxi_panel->private;
    struct sunxi_hardware_res *hw_res = sunxi_connector->hw_res;
    enum drm_mode_status status;

    if (!mode)
        return 0;

    status = sunxi_panel->panel_ops->change_mode_to_timming(
        sunxi_hdmi_p->timing, mode);
    if (status != MODE_OK) {
        DRM_ERROR("sunxi hdmi set timmings err status:%d.\n", status);
        return  -EINVAL;
    }
    DRM_DEBUG_KMS("[%d] con_id:%d  vic:%d, mode_id:%d\n", __LINE__,
        sunxi_connector->connector_id, sunxi_hdmi_p->timing->vic,
        mode->base.id);

    sunxi_hdmi_p->video_para.vic = sunxi_hdmi_p->timing->vic;
    /* sunxi_hdmi_yuv_output(sunxi_hdmi_p); */
    sunxi_hdmi_p->video_para.is_yuv = 0;
    sunxi_hdmi_p->video_para.is_hdmi = 1;
    sunxi_hdmi_p->video_para.csc = BT601;
    sunxi_hdmi_p->audio_para.vic = sunxi_hdmi_p->timing->vic;
    hw_res->clk_rate = sunxi_hdmi_p->timing->pixel_clk;

    return 0;
}

bool sunxi_hdmi_disable(void *data)
{
    struct sunxi_drm_connector *sunxi_connector =
        to_sunxi_connector(data);
    struct sunxi_hardware_res  *hw_res = sunxi_connector->hw_res;
    struct sunxi_panel *sunxi_panel = sunxi_connector->panel;

    sunxi_panel->panel_ops->close(sunxi_panel);
    sunxi_irq_free(hw_res);
    return true;
}

bool sunxi_hdmi_enable(void *data)
{
    struct sunxi_drm_connector *sunxi_connector =
        to_sunxi_connector(data);
    struct sunxi_panel *sunxi_panel = sunxi_connector->panel;
        sunxi_panel->panel_ops->open(sunxi_panel);
    return true;
}

bool sunxi_hdmi_reset(void *data)
{
    struct drm_connector *connector = (struct drm_connector *)data;
    struct sunxi_drm_connector *sunxi_connector =
        to_sunxi_connector(data);
    struct sunxi_drm_encoder *sunxi_encoder;
    struct sunxi_drm_crtc *sunxi_crtc;

    if (!connector || !connector->encoder
            || !connector->encoder->crtc)
        return false;

    sunxi_encoder = to_sunxi_encoder(connector->encoder);
    sunxi_crtc = to_sunxi_crtc(connector->encoder->crtc);
    sunxi_clk_set(sunxi_connector->hw_res);
    sunxi_clk_enable(sunxi_connector->hw_res);

    return true;
}

bool sunxi_hdmi_init(void *data)
{
    struct sunxi_drm_connector *sunxi_connector =
        to_sunxi_connector(data);
    struct sunxi_hdmi_private *sunxi_hdmi_p;
    hdmi_bsp_func hdmi_func;
    struct sunxi_panel *sunxi_panel;

    sunxi_panel = sunxi_connector->panel;
    sunxi_hdmi_p = (struct sunxi_hdmi_private *)sunxi_panel->private;

    hdmi_func.delay_ms = hdmi_delay_ms;
    hdmi_func.delay_us = hdmi_delay_us;
    bsp_hdmi_set_func(&hdmi_func);
    sunxi_hdmi_get_sys_info(sunxi_connector->panel);
    /* hdmi must all open */
    sunxi_connector->hw_res->clk_rate =
        sunxi_hdmi_p->timing->pixel_clk;
    DRM_DEBUG_KMS("sunxi_hdmi_init, hdmi connector clk:%lu\n",
        sunxi_connector->hw_res->clk_rate);
    sunxi_drm_sys_power_enable(sunxi_hdmi_p->hdmi_power);

    sunxi_clk_set(sunxi_connector->hw_res);
    sunxi_clk_enable(sunxi_connector->hw_res);
    clk_prepare_enable(sunxi_panel->clk);
    msleep(200);
    bsp_hdmi_set_version(0);
    bsp_hdmi_init();
    bsp_hdmi_hrst();
    bsp_hdmi_standby();
    msleep(200);

    return true;
}

void sunxi_hdmi_delayed_work(void *data)
{
    /* get cec msg */
    unsigned char msg;
    bsp_hdmi_cec_get_simple_msg(&msg);
}

static struct sunxi_hardware_ops hdmi_con_ops = {
    .init = sunxi_hdmi_init,
    .reset = sunxi_hdmi_reset,
    .enable = sunxi_hdmi_enable,
    .disable = sunxi_hdmi_disable,
    .updata_reg = NULL,
    .vsync_proc = NULL,
    .irq_query = NULL,
    /* whether check the cec ctl info in vysnc delayed work?
    * or other place better?.
    */
    .vsync_delayed_do = sunxi_hdmi_delayed_work,
    .set_timming = sunxi_hdmi_set_timing,

};

static int sunxi_hdmi_hwres_init(struct sunxi_hardware_res *hw_res,
    struct sunxi_panel *sunxi_panel, struct device_node *hdmi_node)
{
    hw_res->reg_base = (uintptr_t __force)of_iomap(hdmi_node, 0);
    if (hw_res->reg_base == 0) {
        DRM_ERROR("unable to map hdmi registers\n");
        return -EINVAL;
    }
    bsp_hdmi_set_addr(hw_res->reg_base);
#if defined(CONFIG_COMMON_CLK)
    /* get clk */
    hw_res->clk = of_clk_get(hdmi_node, 0);
    if (IS_ERR(hw_res->clk)) {
        DRM_ERROR("fail to get clk for hdmi\n");
        return -EINVAL;
    }

    /* here we use panel clk for ddc clock*/
    sunxi_panel->clk = of_clk_get(hdmi_node, 1);
    if (IS_ERR(sunxi_panel->clk)) {
        DRM_ERROR("fail to get clk for hdmi ddc\n");
        return -EINVAL;
    }
    hw_res->ops = &hdmi_con_ops;
#endif
    return 0;
}

static int sunxi_hdmi_private_init(struct sunxi_panel *sunxi_panel,
    int hdmi_id)
{
    struct sunxi_hdmi_private *sunxi_hdmi_p;

    sunxi_hdmi_p = kzalloc(sizeof(struct sunxi_hdmi_private),
        GFP_KERNEL);
    if (!sunxi_hdmi_p) {
        DRM_ERROR("failed to allocate sunxi_hdmi_private.\n");
        return -EINVAL;
    }
    sunxi_hdmi_p->timing = kzalloc(sizeof(struct disp_video_timings),
        GFP_KERNEL);
    if (!sunxi_hdmi_p->timing) {
        DRM_ERROR("failed to allocate disp_video_timings.\n");
        kfree(sunxi_hdmi_p);
        return -EINVAL;
    }
    sunxi_panel->private = sunxi_hdmi_p;
    sunxi_hdmi_p->hdmi_id = hdmi_id;

    return 0;
}

void sunxi_hdmi_private_destroy(struct sunxi_hdmi_private *sunxi_hdmi_p)
{
    kfree(sunxi_hdmi_p->timing);
    kfree(sunxi_hdmi_p);
}

static inline int sunxi_hdmi_panel_ops_init(struct sunxi_panel *sunxi_panel)
{
    sunxi_panel->panel_ops = &default_panel;
    if (sunxi_panel->panel_ops->init) {
        if (!sunxi_panel->panel_ops->init(sunxi_panel))
            return -EINVAL;
    }
    return 0;
}

struct sunxi_panel *sunxi_hdmi_pan_init(struct sunxi_hardware_res *hw_res,
    int pan_id, int hdmi_id)
{
    char primary_key[20];
    int value = 0, ret;
    struct sunxi_panel *sunxi_panel = NULL;
    struct device_node *node;

    sprintf(primary_key, "sunxi-hdmi");
    node = sunxi_drm_get_name_node(primary_key);
    if (!node) {
        DRM_ERROR("get device [%s] node fail.\n", primary_key);
        return NULL;
    }

    sunxi_panel = sunxi_panel_creat(value, pan_id);
    if (!sunxi_panel) {
        DRM_ERROR("creat sunxi panel fail.\n");
        goto err_false;
    }

    ret = sunxi_hdmi_hwres_init(hw_res, sunxi_panel, node);
    if (ret) {
        DRM_ERROR("creat hw_res fail.\n");
        sunxi_panel_destroy(sunxi_panel);
        goto err_false;
    }

    ret = sunxi_hdmi_private_init(sunxi_panel, hdmi_id);
    if (ret) {
        DRM_ERROR("creat hw_res fail.\n");
        sunxi_panel_destroy(sunxi_panel);
        goto err_false;
    }

    ret = sunxi_hdmi_panel_ops_init(sunxi_panel);
    if (ret) {
        sunxi_panel_destroy(sunxi_panel);
        DRM_ERROR("creat panel_ops fail.\n");
        goto err_false;
    }
    return sunxi_panel;
err_false:
    return NULL;
}

void sunxi_hdmi_pan_destroy(struct sunxi_panel *sunxi_panel,
    struct sunxi_hardware_res *hw_res)
{
    struct sunxi_hdmi_private *sunxi_hdmi_p;

    sunxi_hdmi_p = (struct sunxi_hdmi_private *)sunxi_panel->private;
    sunxi_hdmi_private_destroy(sunxi_hdmi_p);
    sunxi_hwres_destroy(hw_res);
}

/linux-sunxi/drivers/gpu/drm/sunxi/subdev/sunxi_hdmi.h

/*
 * Copyright (C) 2016 Allwinnertech Co.Ltd
 * Authors: Jet Cui
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 *
 */
/*HDMI panel ops*/
#ifndef _SUNXI_HDMI_H_
#define _SUNXI_HDMI_H_
#include "hdmi_bsp.h"
#define Abort_Current_Operation             0
#define Special_Offset_Address_Read         1
#define Explicit_Offset_Address_Write       2
#define Implicit_Offset_Address_Write       3
#define Explicit_Offset_Address_Read        4
#define Implicit_Offset_Address_Read        5
#define Explicit_Offset_Address_E_DDC_Read  6
#define Implicit_Offset_Address_E_DDC_Read  7

#define HDMI1440_480I       6
#define HDMI1440_576I       21
#define HDMI480P            2
#define HDMI576P            17
#define HDMI720P_50         19
#define HDMI720P_60         4
#define HDMI1080I_50        20
#define HDMI1080I_60        5
#define HDMI1080P_50        31
#define HDMI1080P_60        16
#define HDMI1080P_24        32
#define HDMI1080P_25        33
#define HDMI1080P_30        34
#define HDMI800_480P        35
#define HDMI1080P_24_3D_FP  (HDMI1080P_24 + 0x80)
#define HDMI720P_50_3D_FP   (HDMI720P_50  + 0x80)
#define HDMI720P_60_3D_FP   (HDMI720P_60  + 0x80)
#define HDMI3840_2160P_30   (1+0x100)
#define HDMI3840_2160P_25   (2+0x100)
#define HDMI3840_2160P_24   (3+0x100)
#define HDMI_EDID_LEN 1024

#define HDMI_State_Idle          0x00
#define HDMI_State_Wait_Hpd          0x02
#define HDMI_State_Rx_Sense          0x03
#define HDMI_State_EDID_Parse        0x04
#define HDMI_State_HPD_Done          0x05

#define HDMI_IO_NUM 5

struct sunxi_hdmi_private {
    int hdmi_id;
    struct sunxi_panel *sunxi_panel;
    struct disp_video_timings *timing;
    bool    hdmi_io_used[HDMI_IO_NUM];
    bool    power_on;
    bool    can_YCbCr444;
    bool    can_YCbCr422;
    bool    cts_compat;
    bool    hdcp_enable;
    bool    cec_support;
    bool    exp;
    struct disp_gpio_set_t hdmi_io[HDMI_IO_NUM];
    int             gpio_handle[HDMI_IO_NUM];
    char    hdmi_power[25];
    struct cea_sad    *hdmi_sads;
    int   nr_sad;
    struct video_para video_para;
    struct audio_para audio_para;
};

struct sunxi_panel *sunxi_hdmi_pan_init(struct sunxi_hardware_res *hw_res,
    int pan_id, int hdmi_id);

void sunxi_hdmi_pan_destroy(struct sunxi_panel *sunxi_panel,
    struct sunxi_hardware_res *hw_res);
enum drm_mode_status
    sunxi_hdmi_mode_timmings(void *timing, struct drm_display_mode *mode);
#endif

/linux-sunxi/drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.c

/*
 * Allwinner SoCs display driver.
 *
 * Copyright (C) 2016 Allwinner.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include "disp_display.h"

struct disp_dev_t gdisp;

s32 bsp_disp_init(struct disp_bsp_init_para *para)
{
    u32 num_screens, disp;

    memset(&gdisp, 0x00, sizeof(struct disp_dev_t));
    memcpy(&gdisp.init_para, para, sizeof(struct disp_bsp_init_para));
    para->shadow_protect = bsp_disp_shadow_protect;
    disp_init_feat();

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        spin_lock_init(&gdisp.screen[disp].flag_lock);
        tasklet_init(&gdisp.screen[disp].tasklet, disp_tasklet,
                 (unsigned long)disp);
    }

    bsp_disp_set_print_level(DEFAULT_PRINT_LEVLE);
    disp_init_al(para);
    disp_init_lcd(para);
#if defined(SUPPORT_HDMI)
    disp_init_hdmi(para);
#endif
#if defined(SUPPORT_TV)
    disp_init_tv_para(para);
#endif

#if defined(SUPPORT_EDP)
    disp_init_edp(para);
#endif /*endif SUPPORT_EDP */

#if defined(SUPPORT_VDPO)
    disp_init_vdpo(para);
#endif
    disp_init_mgr(para);
    disp_init_enhance(para);
    disp_init_smbl(para);
    disp_init_capture(para);

#if defined(SUPPORT_WB)
    disp_init_format_convert_manager(para);
#endif
#if defined SUPPORT_EINK
    disp_init_eink(para);
#endif

    disp_init_connections(para);

    return DIS_SUCCESS;
}

s32 bsp_disp_exit(u32 mode)
{
#if defined SUPPORT_EINK
    disp_exit_eink();
#endif
#if defined(SUPPORT_WB)
    disp_exit_format_convert_manager();
#endif
    disp_exit_capture();
    disp_exit_smbl();
    disp_exit_enhance();
    disp_exit_mgr();
#if defined(SUPPORT_HDMI)
    disp_exit_hdmi();
#endif

#if defined(SUPPORT_VDPO)
    disp_exit_vdpo();
#endif
    disp_exit_lcd();
    disp_exit_al();

    disp_exit_feat();

    return DIS_SUCCESS;
}

s32 bsp_disp_open(void)
{
    return DIS_SUCCESS;
}

s32 bsp_disp_close(void)
{
    return DIS_SUCCESS;
}

s32 disp_device_attached(int disp_mgr, int disp_dev,
             enum disp_output_type output_type,
             enum disp_output_type mode)
{
    struct disp_manager *mgr = NULL;
    struct disp_device *dispdev = NULL;

    mgr = disp_get_layer_manager(disp_mgr);
    if (!mgr)
        return -1;

    /* no need to attch */
    if (mgr->device && (output_type == mgr->device->type))
        return 0;

    /* detach manager and device first */
    if (mgr->device) {
        dispdev = mgr->device;
        if (dispdev->is_enabled && dispdev->is_enabled(dispdev)
            && dispdev->disable)
            dispdev->disable(dispdev);
        if (dispdev->unset_manager)
            dispdev->unset_manager(dispdev);
    }

    dispdev = disp_device_get(disp_dev, output_type);
    if (dispdev && dispdev->set_manager) {
        dispdev->set_manager(dispdev, mgr);
        DE_WRN("attached ok, mgr%d<-->device%d, type=%d\n", disp_mgr,
               disp_dev, (u32) output_type);
        if (dispdev->set_mode)
            dispdev->set_mode(dispdev, mode);
        return 0;
    }

    return -1;
}

s32 disp_device_attached_and_enable(int disp_mgr, int disp_dev,
                    enum disp_output_type output_type,
                    enum disp_output_type mode)
{
    struct disp_manager *mgr = NULL;
    struct disp_device *dispdev = NULL;

    mgr = disp_get_layer_manager(disp_mgr);
    if (!mgr)
        return -1;
    /* disable device */
    if (output_type == DISP_OUTPUT_TYPE_NONE) {
        if (mgr->device && mgr->device->is_enabled
            && mgr->device->disable) {
            if (mgr->device->is_enabled(mgr->device))
                mgr->device->disable(mgr->device);
            dispdev = mgr->device;
            if (dispdev->unset_manager)
                dispdev->unset_manager(dispdev);
        }
        return 0;
    }

    /* no need to attch */
    if (mgr->device && (output_type == mgr->device->type)) {
        if (mgr->device->is_enabled
            && mgr->device->is_enabled(mgr->device)) {
            u32 output_mode;

            if (mgr->device->get_mode) {
                output_mode =
                    mgr->device->get_mode(mgr->device);
                if (output_mode == mode)
                    return 0;
            }
            if (mgr->device->disable)
                mgr->device->disable(mgr->device);
        }
        if (output_type == DISP_OUTPUT_TYPE_TV)
            disp_delay_ms(300);
        if (mgr->device->set_mode)
            mgr->device->set_mode(mgr->device, mode);
        if (mgr->device->enable)
            mgr->device->enable(mgr->device);
        return 0;
    }

    /* detach manager and device first */
    if (mgr->device) {
        dispdev = mgr->device;
        if (dispdev->is_enabled && dispdev->is_enabled(dispdev)
            && dispdev->disable)
            dispdev->disable(dispdev);
        if (dispdev->unset_manager)
            dispdev->unset_manager(dispdev);
    }

    dispdev = disp_device_get(disp_dev, output_type);
    if (dispdev && dispdev->set_manager) {
        dispdev->set_manager(dispdev, mgr);
        DE_WRN("attached ok, mgr%d<-->device%d, type=%d, mode=%d\n",
               disp_mgr, disp_dev, (u32) output_type, (u32) mode);
        if (dispdev->set_mode)
            dispdev->set_mode(dispdev, mode);
        if (dispdev->enable)
            dispdev->enable(dispdev);
        return 0;
    }

    return -1;
}

s32 disp_device_detach(int disp_mgr, int disp_dev,
               enum disp_output_type output_type)
{
    struct disp_manager *mgr = NULL;
    struct disp_device *dispdev = NULL;

    mgr = disp_get_layer_manager(disp_mgr);
    if (!mgr) {
        DE_WRN("get mgr%d fail\n", disp_mgr);
        return -1;
    }

    dispdev = disp_device_get(disp_dev, output_type);
    if (!dispdev) {
        DE_WRN("get device%d fail\n", disp_dev);
        return -1;
    }

    if (mgr->device == dispdev) {
        if (dispdev->disable)
            dispdev->disable(dispdev);
        if (dispdev->unset_manager)
            dispdev->unset_manager(dispdev);
    }

    return 0;
}

s32 bsp_disp_device_switch(int disp, enum disp_output_type output_type,
               enum disp_output_type mode)
{
    int num_screens = 0;
    int disp_dev;
    int ret = -1;

    DE_INF("%s, disp%d try switch to device(type%d,mode%d)\n", __func__,
           disp, output_type, mode);

    ret = disp_device_attached_and_enable(disp, disp, output_type, mode);
    if (ret != 0) {
        num_screens = bsp_disp_feat_get_num_screens();
        for (disp_dev = 0; disp_dev < num_screens; disp_dev++) {
            ret =
                disp_device_attached_and_enable(disp, disp_dev,
                                output_type, mode);
            if (ret == 0)
                break;
        }
    }

    return ret;
}

s32 bsp_disp_eink_update(struct disp_eink_manager *manager,
            struct disp_layer_config_inner *config,
            unsigned int layer_num,
            enum eink_update_mode mode,
            struct area_info *update_area)
{
    int ret = -1;
    struct area_info area;

    memcpy(&area, update_area, sizeof(struct area_info));

    if (manager)
        ret = manager->eink_update(manager, config, layer_num,
                       mode, area);
    else
        __debug("eink manager is NULL!\n");

    return ret;
}

s32 bsp_disp_eink_set_temperature(struct disp_eink_manager *manager,
                  unsigned int temp)
{
    s32 ret = -1;

    if (manager)
        ret = manager->set_temperature(manager, temp);
    else
        pr_err("eink manager is NULL!\n");

    return ret;
}

s32 bsp_disp_eink_get_temperature(struct disp_eink_manager *manager)
{
    s32 ret = -1;

    if (manager)
        ret = manager->get_temperature(manager);
    else
        pr_err("eink manager is NULL!\n");

    return ret;
}

s32 bsp_disp_eink_op_skip(struct disp_eink_manager *manager, unsigned int skip)
{
    s32 ret = -1;

    if (manager)
        ret = manager->op_skip(manager, skip);
    else
        pr_err("eink manager is NULL!\n");

    return ret;
}

s32 disp_init_connections(struct disp_bsp_init_para *para)
{
    u32 disp = 0;
    u32 num_screens = 0;
    u32 num_layers = 0, layer_id = 0;
    u32 i = 0;

    DE_INF("disp_init_connections\n");

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        struct disp_manager *mgr;
        struct disp_layer *lyr;
        struct disp_device *dispdev = NULL;
        struct disp_enhance *enhance = NULL;
        struct disp_smbl *smbl = NULL;
        struct disp_capture *cptr = NULL;

        mgr = disp_get_layer_manager(disp);
        if (!mgr)
            continue;

        /* connect layer & it's manager */
        num_layers = bsp_disp_feat_get_num_layers(disp);
        for (layer_id = 0; layer_id < num_layers; layer_id++) {
            lyr = disp_get_layer_1(disp, layer_id);
            if (lyr != NULL)
                lyr->set_manager(lyr, mgr);
        }

        if ((para->boot_info.sync == 1)
            && (disp == para->boot_info.disp)
            && (para->boot_info.type == DISP_OUTPUT_TYPE_LCD)) {
            /* connect device & it's manager */
            dispdev = disp_device_get(disp, DISP_OUTPUT_TYPE_LCD);
            if ((dispdev) && (dispdev->set_manager)) {
                dispdev->set_manager(dispdev, mgr);
            } else {
                for (i = 0; i < num_screens; i++) {
                    dispdev =
                        disp_device_get(i,
                            DISP_OUTPUT_TYPE_LCD);
                    if ((dispdev)
                        && (dispdev->set_manager)) {
                        dispdev->set_manager(dispdev,
                                     mgr);
                        break;
                    }
                }
            }
        } else if (para->boot_info.sync == 0) {
            dispdev = disp_device_get(disp, DISP_OUTPUT_TYPE_LCD);
            if ((dispdev) && (dispdev->set_manager))
                dispdev->set_manager(dispdev, mgr);
        }

        enhance = disp_get_enhance(disp);
        if (enhance && (enhance->set_manager))
            enhance->set_manager(enhance, mgr);

        smbl = disp_get_smbl(disp);
        if (smbl && (smbl->set_manager))
            smbl->set_manager(smbl, mgr);

        cptr = disp_get_capture(disp);
        if (cptr && (cptr->set_manager))
            cptr->set_manager(cptr, mgr);
    }

    return 0;
}

s32 bsp_disp_check_device_enabled(struct disp_bsp_init_para *para)
{
    int ret = 0;
    int enabled = 0;

    if ((para->boot_info.sync == 1)
        && (para->boot_info.type != DISP_OUTPUT_TYPE_NONE)) {
        int num_screens = 0;
        int disp = para->boot_info.disp;
        int disp_dev = disp;
        enum disp_output_type type =
            (enum disp_output_type)para->boot_info.type;
        enum disp_output_type mode =
            (enum disp_output_type)para->boot_info.mode;
        struct disp_manager *mgr = NULL;

        mgr = disp_get_layer_manager(disp);
        if (!mgr) {
            enabled = 0;
            goto exit;
        }

        /* attach manager and display device */
        ret = disp_device_attached(disp, disp_dev, type, mode);
        if (ret != 0) {
            num_screens = bsp_disp_feat_get_num_screens();
            for (disp_dev = 0; disp_dev < num_screens; disp_dev++) {
                ret =
                    disp_device_attached(disp, disp_dev, type,
                             mode);
                if (ret == 0)
                    break;
            }
        }

        /* enable display device(only software) */
        if (ret != 0) {
            /* attach fail */
            DE_WRN("Can't find device(%d) for manager %d\n",
                 (int)type, disp);
            goto exit;
        }

        if (mgr->device->check_if_enabled &&
            mgr->device->check_if_enabled(mgr->device)) {
            enabled = 1;
        }
    }

exit:
    return enabled;
}

s32 bsp_disp_sync_with_hw(struct disp_bsp_init_para *para)
{
    if ((para->boot_info.sync == 1)
        && (para->boot_info.type != DISP_OUTPUT_TYPE_NONE)) {
        int num_screens = 0;
        int disp = para->boot_info.disp;
        int disp_dev = disp;
        enum disp_output_type type =
            (enum disp_output_type)para->boot_info.type;
        enum disp_output_type mode =
            (enum disp_output_type)para->boot_info.mode;
        int ret = -1;
        struct disp_manager *mgr = NULL;

        mgr = disp_get_layer_manager(disp);
        if (!mgr)
            return -1;

        /* attach manager and display device */
        ret = disp_device_attached(disp, disp_dev, type, mode);
        if (ret != 0) {
            num_screens = bsp_disp_feat_get_num_screens();
            for (disp_dev = 0; disp_dev < num_screens; disp_dev++) {
                ret =
                    disp_device_attached(disp, disp_dev, type,
                             mode);
                if (ret == 0)
                    break;
            }
        }

        /* enable display device(only software) */
        if (ret != 0) {
            /* attach fail */
            DE_WRN("Can't find device(%d) for manager %d\n",
                 (int)type, disp);
            return -1;
        }
        if (mgr->device && mgr->device->sw_enable) {
            if (mgr->device->set_mode)
                mgr->device->set_mode(mgr->device, mode);
            return mgr->device->sw_enable(mgr->device);
        }
    }

    return -1;
}

/***********************************************************
 *
 * interrupt proc
 *
 ***********************************************************/
static s32 bsp_disp_cfg_get(u32 disp)
{
    return gdisp.screen[disp].cfg_cnt;
}

s32 bsp_disp_shadow_protect(u32 disp, bool protect)
{
    s32 ret = -1;
    u32 cnt = 0;
    u32 max_cnt = 50;
    u32 delay = 10;     /* us */
    unsigned long flags;

    if (protect) {
        while ((ret != 0) && (cnt < max_cnt)) {
            spin_lock_irqsave(&gdisp.screen[disp].flag_lock, flags);
            cnt++;
            if (gdisp.screen[disp].have_cfg_reg == false) {
                gdisp.screen[disp].cfg_cnt++;
                ret = 0;
            }
            spin_unlock_irqrestore(&gdisp.screen[disp].flag_lock,
                           flags);
            if (ret != 0)
                disp_delay_us(delay);
        }

        if (ret != 0) {
            DE_INF("wait for reg load finish time out\n");
            spin_lock_irqsave(&gdisp.screen[disp].flag_lock, flags);
            gdisp.screen[disp].cfg_cnt++;
            spin_unlock_irqrestore(&gdisp.screen[disp].flag_lock,
                           flags);
        }
    } else {
        spin_lock_irqsave(&gdisp.screen[disp].flag_lock, flags);
        gdisp.screen[disp].cfg_cnt--;
        spin_unlock_irqrestore(&gdisp.screen[disp].flag_lock, flags);
    }
    __inf("sel=%d, protect:%d,  cnt=%d\n", disp, protect,
          gdisp.screen[disp].cfg_cnt);
    return DIS_SUCCESS;
}

s32 bsp_disp_vsync_event_enable(u32 disp, bool enable)
{
    gdisp.screen[disp].vsync_event_en = enable;

    return DIS_SUCCESS;
}

static s32 disp_sync_all(u32 disp, bool sync)
{
    struct disp_manager *mgr;
    struct disp_device *dispdev;

    mgr = disp_get_layer_manager(disp);
    if (!mgr) {
        DE_WRN("get mgr%d fail\n", disp);
    } else {
        dispdev = mgr->device;
        if (mgr->sync)
            mgr->sync(mgr, sync);
        if (dispdev && dispdev->get_status) {
            if (dispdev->get_status(dispdev) != 0)
                gdisp.screen[disp].health_info.error_cnt++;
        }
    }

    return 0;
}

#if defined(__LINUX_PLAT__)
/* return 10fps */
s32 bsp_disp_get_fps(u32 disp)
{
    u32 pre_time_index, cur_time_index;
    u32 pre_time, cur_time;
    u32 fps = 0xff;

    pre_time_index = gdisp.screen[disp].health_info.sync_time_index;
    cur_time_index =
        (pre_time_index == 0) ?
        (DEBUG_TIME_SIZE - 1) : (pre_time_index - 1);

    pre_time = gdisp.screen[disp].health_info.sync_time[pre_time_index];
    cur_time = gdisp.screen[disp].health_info.sync_time[cur_time_index];

     /* HZ:timer interrupt times in 1 sec */
     /* jiffies:increase 1 when timer interrupt occur. */
     /* jiffies/HZ:current kernel boot time(second). */
     /* 1000MS / ((cur_time_jiffies/HZ - pre_time_jiffes/HZ)*1000) */

    if (pre_time != cur_time)
        fps = MSEC_PER_SEC * HZ / (cur_time - pre_time);

    return fps;
}

static void disp_sync_checkin(u32 disp)
{
    u32 index = gdisp.screen[disp].health_info.sync_time_index;

    gdisp.screen[disp].health_info.sync_time[index] = jiffies;
    index++;
    index = (index >= DEBUG_TIME_SIZE) ? 0 : index;
    gdisp.screen[disp].health_info.sync_time_index = index;
}

s32 bsp_disp_get_health_info(u32 disp, struct disp_health_info *info)
{
    if (info)
        memcpy(info, &gdisp.screen[disp].health_info,
               sizeof(struct disp_health_info));
    return 0;
}
#endif

void sync_event_proc(u32 disp, bool timeout)
{
    int ret;
    unsigned long flags;

    if (!timeout)
        disp_sync_checkin(disp);
    else
        gdisp.screen[disp].health_info.skip_cnt++;

    gdisp.screen[disp].health_info.irq_cnt++;

    spin_lock_irqsave(&gdisp.screen[disp].flag_lock, flags);
    if ((bsp_disp_cfg_get(disp) == 0) && (!timeout)) {
        gdisp.screen[disp].have_cfg_reg = true;
        spin_unlock_irqrestore(&gdisp.screen[disp].flag_lock, flags);

        disp_sync_all(disp, true);
        gdisp.screen[disp].have_cfg_reg = false;
        if (gdisp.init_para.disp_int_process)
            gdisp.init_para.disp_int_process(disp);

    } else {
        spin_unlock_irqrestore(&gdisp.screen[disp].flag_lock, flags);
        disp_sync_all(disp, false);
    }

    if (gdisp.screen[disp].vsync_event_en && gdisp.init_para.vsync_event) {
        ret = gdisp.init_para.vsync_event(disp);
        if (ret == 0)
            gdisp.screen[disp].health_info.vsync_cnt++;
        else
            gdisp.screen[disp].health_info.vsync_skip_cnt++;

    }
    tasklet_schedule(&gdisp.screen[disp].tasklet);
}

s32 bsp_disp_get_output_type(u32 disp)
{
    struct disp_manager *mgr = disp_get_layer_manager(disp);

    if (mgr) {
        struct disp_device *dispdev = mgr->device;

        if (dispdev && dispdev->is_enabled
            && dispdev->is_enabled(dispdev))
            return dispdev->type;
    }

    return DISP_OUTPUT_TYPE_NONE;
}

void disp_tasklet(unsigned long data)
{
    struct disp_manager *mgr;
    u32 disp = (u32)data;

    mgr = disp_get_layer_manager(disp);
    if (!mgr) {
        DE_WRN("get mgr%d fail\n", disp);
    } else {
        if (mgr->tasklet)
            mgr->tasklet(mgr);
    }
}

#ifdef CONFIG_DEVFREQ_DRAM_FREQ_IN_VSYNC
s32 bsp_disp_get_vb_time(void)
{
    u32 num_screens, screen_id;
    struct disp_video_timings tt;
    u32 vb_time = 0;

    num_screens = bsp_disp_feat_get_num_screens();
    for (screen_id = 0; screen_id < num_screens; screen_id++) {
        if (bsp_disp_get_output_type(screen_id)
            == DISP_OUTPUT_TYPE_LCD) {
            struct disp_device *lcd;
            u32 time_per_line = 0;
            u32 start_delay = 0;

            lcd = disp_get_lcd(screen_id);
            if (!lcd)
                DE_WRN("get lcd%d fail\n", screen_id);

            if (lcd && lcd->get_timings) {
                u32 fps = 0;

                lcd->get_timings(lcd, &tt);
                if ((tt.ver_total_time != 0)
                    && (tt.hor_total_time != 0))
                    fps =
                        tt.pixel_clk * 1000 /
                        (tt.ver_total_time *
                         tt.hor_total_time);
                start_delay = tt.ver_total_time - tt.y_res - 10;
                fps = (fps == 0) ? 60 : fps;
                time_per_line =
                    1000000 / fps / tt.ver_total_time;
                vb_time = (start_delay) * time_per_line;
            }
        }
        /* add hdmi support ? */
    }
    return vb_time;
}

/* returns: us */
s32 bsp_disp_get_next_vb_time(void)
{
    u32 cur_line;
    u32 num_screens, screen_id;
    struct disp_video_timings tt;
    u32 next_time = 16000;

    num_screens = bsp_disp_feat_get_num_screens();
    for (screen_id = 0; screen_id < num_screens; screen_id++) {
        if (bsp_disp_get_output_type(screen_id)
            == DISP_OUTPUT_TYPE_LCD) {
            struct disp_device *lcd;
            u32 time_per_line = 0;
            struct disp_panel_para info;

            memset(&info, 0, sizeof(struct disp_panel_para));
            lcd = disp_get_lcd(screen_id);
            if (lcd && lcd->get_panel_info)
                lcd->get_panel_info(lcd, &info);
            cur_line = disp_al_lcd_get_cur_line(screen_id, &info);
            if (!lcd)
                DE_WRN("get lcd%d fail\n", screen_id);

            if (info.lcd_if != LCD_IF_EDP) {
                if (lcd && lcd->get_timings) {
                    u32 fps = 0;

                    lcd->get_timings(lcd, &tt);
                    if ((tt.ver_total_time != 0)
                        && (tt.hor_total_time != 0))
                        fps =
                            tt.pixel_clk * 1000 /
                            (tt.ver_total_time *
                             tt.hor_total_time);
                    fps = (fps == 0) ? 60 : fps;
                    time_per_line =
                        1000000 / fps / tt.ver_total_time;
                    next_time =
                        (tt.ver_total_time -
                         cur_line) * time_per_line;
                }
            }
        }
        /* add hdmi support ? */
    }
    return next_time;
}

s32 bsp_disp_is_in_vb(void)
{
    u32 num_screens, screen_id;
    s32 ret = 1;

    num_screens = bsp_disp_feat_get_num_screens();
    for (screen_id = 0; screen_id < num_screens; screen_id++) {
        if (bsp_disp_get_output_type(screen_id)
            == DISP_OUTPUT_TYPE_LCD) {
            struct disp_device *lcd;
            struct disp_panel_para info;

            lcd = disp_get_lcd(screen_id);
            if (!lcd)
                DE_WRN("get lcd%d fail\n", screen_id);

            memset(&info, 0, sizeof(struct disp_panel_para));
            if (lcd && lcd->get_panel_info)
                lcd->get_panel_info(lcd, &info);
            ret =
                disp_al_lcd_query_irq(screen_id, LCD_IRQ_TCON0_VBLK,
                          &info);
        } else if (bsp_disp_get_output_type(screen_id) ==
               DISP_OUTPUT_TYPE_HDMI) {
            /* FIXME: add hdmi */
        }
    }
    return ret;
}
#endif

s32 bsp_disp_set_print_level(u32 print_level)
{
    gdisp.print_level = print_level;

    return 0;
}

s32 bsp_disp_get_print_level(void)
{
    return gdisp.print_level;
}

s32 bsp_disp_get_screen_physical_width(u32 disp)
{
    s32 width = 0, height = 0;
    struct disp_manager *mgr = NULL;

    mgr = disp_get_layer_manager(disp);
    if (mgr && mgr->device && mgr->device->get_dimensions)
        mgr->device->get_dimensions(mgr->device, &width, &height);

    return width;
}

s32 bsp_disp_get_screen_physical_height(u32 disp)
{
    s32 width = 0, height = 0;
    struct disp_manager *mgr = NULL;

    mgr = disp_get_layer_manager(disp);
    if (mgr && mgr->device && mgr->device->get_dimensions)
        mgr->device->get_dimensions(mgr->device, &width, &height);

    return height;
}

s32 bsp_disp_get_screen_width(u32 disp)
{
    s32 width = 0;
    /* FIXME */
    return width;
}

s32 bsp_disp_get_screen_height(u32 disp)
{
    s32 height = 0;
    /* FIXME */

    return height;
}

s32 bsp_disp_get_screen_width_from_output_type(u32 disp, u32 output_type,
                           u32 output_mode)
{
    u32 width = 800, height = 480;
    struct disp_device *dispdev;

    if (output_type == DISP_OUTPUT_TYPE_LCD) {
        struct disp_manager *mgr;

        mgr = disp_get_layer_manager(disp);
        if (mgr && mgr->device && mgr->device->get_resolution) {
            mgr->device->get_resolution(mgr->device, &width,
                            &height);
        }
    } else if (output_type == DISP_OUTPUT_TYPE_EDP) {
        dispdev = disp_device_get(disp, DISP_OUTPUT_TYPE_EDP);
        if (dispdev)
            dispdev->get_resolution(dispdev, &width, &height);
    } else if ((output_type == DISP_OUTPUT_TYPE_HDMI)
           || (output_type == DISP_OUTPUT_TYPE_TV)
           || (output_type == DISP_OUTPUT_TYPE_VGA)
           || (output_type == DISP_OUTPUT_TYPE_VDPO)) {
        switch (output_mode) {
        case DISP_TV_MOD_NTSC:
        case DISP_TV_MOD_480I:
        case DISP_TV_MOD_480P:
            width = 720;
            height = 480;
            break;
        case DISP_TV_MOD_800_480P:
            width = 800;
            height = 480;
            break;
        case DISP_TV_MOD_PAL:
        case DISP_TV_MOD_576I:
        case DISP_TV_MOD_576P:
            width = 720;
            height = 576;
            break;
        case DISP_TV_MOD_1024_600P:
            width = 1024;
            height = 600;
            break;
        case DISP_TV_MOD_720P_50HZ:
        case DISP_TV_MOD_720P_60HZ:
            width = 1280;
            height = 720;
            break;
        case DISP_TV_MOD_1280_800P:
            width = 1280;
            height = 800;
            break;
        case DISP_TV_MOD_1080P_50HZ:
        case DISP_TV_MOD_1080P_60HZ:
        case DISP_TV_MOD_1080P_30HZ:
        case DISP_TV_MOD_1080P_25HZ:
        case DISP_TV_MOD_1080P_24HZ:
        case DISP_TV_MOD_1080I_50HZ:
        case DISP_TV_MOD_1080I_60HZ:
            width = 1920;
            height = 1080;
            break;
        case DISP_TV_MOD_3840_2160P_30HZ:
        case DISP_TV_MOD_3840_2160P_25HZ:
        case DISP_TV_MOD_3840_2160P_24HZ:
            width = 3840;
            height = 2160;
            break;
        case DISP_TV_MOD_4096_2160P_24HZ:
            width = 4096;
            height = 2160;
            break;
        case DISP_VGA_MOD_800_600P_60:
            width = 800;
            height = 600;
            break;
        case DISP_VGA_MOD_1024_768P_60:
            width = 1024;
            height = 768;
            break;
        case DISP_VGA_MOD_1280_768P_60:
            width = 1280;
            height = 768;
            break;
        case DISP_VGA_MOD_1280_800P_60:
            width = 1280;
            height = 800;
            break;
        case DISP_VGA_MOD_1366_768P_60:
            width = 1366;
            height = 768;
            break;
        case DISP_VGA_MOD_1440_900P_60:
            width = 1440;
            height = 900;
            break;
        case DISP_VGA_MOD_1920_1080P_60:
            width = 1920;
            height = 1080;
            break;
        case DISP_VGA_MOD_1920_1200P_60:
            width = 1920;
            height = 1200;
            break;
        case DISP_TV_MOD_3840_1080P_30:
            width = 3840;
            height = 1080;
            break;
        }
    }
    /* FIXME: add other output device res */

    return width;
}

s32 bsp_disp_get_screen_height_from_output_type(u32 disp, u32 output_type,
                        u32 output_mode)
{
    u32 width = 800, height = 480;
    struct disp_device *dispdev;

    if (output_type == DISP_OUTPUT_TYPE_LCD) {
        struct disp_manager *mgr;

        mgr = disp_get_layer_manager(disp);
        if (mgr && mgr->device && mgr->device->get_resolution) {
            mgr->device->get_resolution(mgr->device, &width,
                            &height);
        }
    } else if (output_type == DISP_OUTPUT_TYPE_EDP) {
        dispdev = disp_device_get(disp, DISP_OUTPUT_TYPE_EDP);
        if (dispdev)
            dispdev->get_resolution(dispdev, &width, &height);
    } else if ((output_type == DISP_OUTPUT_TYPE_HDMI)
           || (output_type == DISP_OUTPUT_TYPE_TV)
           || (output_type == DISP_OUTPUT_TYPE_VGA)
           || (output_type == DISP_OUTPUT_TYPE_VDPO)) {
        switch (output_mode) {
        case DISP_TV_MOD_NTSC:
        case DISP_TV_MOD_480I:
        case DISP_TV_MOD_480P:
            width = 720;
            height = 480;
            break;
        case DISP_TV_MOD_PAL:
        case DISP_TV_MOD_576I:
        case DISP_TV_MOD_576P:
            width = 720;
            height = 576;
            break;
       case DISP_TV_MOD_800_480P:
            width = 800;
            height = 480;
            break;
        case DISP_TV_MOD_1024_600P:
            width = 1024;
            height = 600;
            break;
        case DISP_TV_MOD_720P_50HZ:
        case DISP_TV_MOD_720P_60HZ:
            width = 1280;
            height = 720;
            break;
        case DISP_TV_MOD_1280_800P:
            width = 1280;
            height = 800;
            break;
        case DISP_TV_MOD_1080P_50HZ:
        case DISP_TV_MOD_1080P_60HZ:
        case DISP_TV_MOD_1080P_30HZ:
        case DISP_TV_MOD_1080P_25HZ:
        case DISP_TV_MOD_1080P_24HZ:
        case DISP_TV_MOD_1080I_50HZ:
        case DISP_TV_MOD_1080I_60HZ:
            width = 1920;
            height = 1080;
            break;
        case DISP_TV_MOD_3840_2160P_30HZ:
        case DISP_TV_MOD_3840_2160P_25HZ:
        case DISP_TV_MOD_3840_2160P_24HZ:
            width = 3840;
            height = 2160;
            break;
        case DISP_TV_MOD_4096_2160P_24HZ:
            width = 4096;
            height = 2160;
            break;
        case DISP_VGA_MOD_800_600P_60:
            width = 800;
            height = 600;
            break;
        case DISP_VGA_MOD_1024_768P_60:
            width = 1024;
            height = 768;
            break;
        case DISP_VGA_MOD_1280_768P_60:
            width = 1280;
            height = 768;
            break;
        case DISP_VGA_MOD_1280_800P_60:
            width = 1280;
            height = 800;
            break;
        case DISP_VGA_MOD_1366_768P_60:
            width = 1366;
            height = 768;
            break;
        case DISP_VGA_MOD_1440_900P_60:
            width = 1440;
            height = 900;
            break;
        case DISP_VGA_MOD_1920_1080P_60:
            width = 1920;
            height = 1080;
            break;
        case DISP_VGA_MOD_1920_1200P_60:
            width = 1920;
            height = 1200;
            break;
        case DISP_TV_MOD_3840_1080P_30:
            width = 3840;
            height = 1080;
            break;
        }
    }
    /* FIXME: add other output device res */

    return height;
}

s32 bsp_disp_set_hdmi_func(struct disp_device_func *func)
{
    u32 disp = 0;
    u32 num_screens = 0;
    s32 ret = 0, registered_cnt = 0;

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        struct disp_device *hdmi;

        hdmi = disp_device_find(disp, DISP_OUTPUT_TYPE_HDMI);
        if (hdmi) {
            ret = hdmi->set_func(hdmi, func);
            if (ret == 0)
                registered_cnt++;
        }
    }

    if (registered_cnt != 0) {
        DE_INF("registered!!\n");
        gdisp.hdmi_registered = 1;
        if (gdisp.init_para.start_process)
            gdisp.init_para.start_process();

        return 0;
    }

    return -1;
}

s32 bsp_disp_set_vdpo_func(struct disp_tv_func *func)
{
    u32 disp = 0;
    u32 num_screens = 0;
    s32 ret = 0, registered_cnt = 0;

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        struct disp_device *vdpo;

        vdpo = disp_device_find(disp, DISP_OUTPUT_TYPE_VDPO);
        if (vdpo) {
            if (vdpo->set_tv_func)
                ret = vdpo->set_tv_func(vdpo, func);
            if (ret == 0)
                registered_cnt++;
        }
    }

    if (registered_cnt != 0) {
        DE_INF("registered!!\n");
        gdisp.vdpo_registered = 1;
        if (gdisp.init_para.start_process)
            gdisp.init_para.start_process();

        return 0;
    }

    return -1;
}

s32 bsp_disp_set_edp_func(struct disp_tv_func *func)
{
    u32 disp = 0;
    u32 num_screens = 0;
    s32 ret = 0, registered_cnt = 0;

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        struct disp_device *edp;

        edp = disp_device_find(disp, DISP_OUTPUT_TYPE_EDP);
        if (edp) {
            if (edp->set_tv_func)
                ret = edp->set_tv_func(edp, func);
            if (ret == 0)
                registered_cnt++;
        }
    }

    if (registered_cnt != 0) {
        DE_INF("edp registered!!\n");
        gdisp.edp_registered = 1;
        if (gdisp.init_para.start_process)
            gdisp.init_para.start_process();

        return 0;
    }

    return -1;
}

s32 bsp_disp_hdmi_check_support_mode(u32 disp, enum disp_output_type mode)
{
    u32 num_screens = 0;
    s32 ret = 0;

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        struct disp_device *hdmi;

        hdmi = disp_device_find(disp, DISP_OUTPUT_TYPE_HDMI);
        if (hdmi && hdmi->check_support_mode) {
            ret = hdmi->check_support_mode(hdmi, (u32) mode);
            break;
        }
    }

    return ret;
}

s32 bsp_disp_hdmi_set_detect(bool hpd)
{
    u32 num_screens = 0;
    u32 disp;
    s32 ret = 0;

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        struct disp_device *hdmi;

        hdmi = disp_device_find(disp, DISP_OUTPUT_TYPE_HDMI);
        if (hdmi && hdmi->set_detect) {
            ret = hdmi->set_detect(hdmi, hpd);
            break;
        }
    }

    return ret;
}

s32 bsp_disp_tv_set_hpd(u32 state)
{
#if defined SUPPORT_TV

    u32 disp = 0, num_screens = 0;
    s32 ret = 0;
    struct disp_device *ptv = NULL;

    num_screens = bsp_disp_feat_get_num_screens();
    for (disp = 0; disp < num_screens; disp++) {
        ptv = disp_device_find(disp, DISP_OUTPUT_TYPE_TV);
        if (ptv) {
            ret = disp_tv_set_hpd(ptv, state);
        } else {
            ret &= ret;
            /* DE_WRN("'ptv is null\n"); */
            continue;
        }
    }

    if (ret != 0) {
        DE_WRN("'tv set hpd is fail!\n");
        return -1;
    }
#endif

    return 0;
}

s32 bsp_disp_tv_register(struct disp_tv_func *func)
{
#if defined SUPPORT_TV
    u32 disp = 0;
    u32 num_screens = 0;
    s32 ret = 0, registered_cnt = 0;
    struct disp_device *dispdev = NULL;

    num_screens = bsp_disp_feat_get_num_screens();
    disp_init_tv();
    for (disp = 0; disp < num_screens; disp++) {
        dispdev = disp_device_find(disp, DISP_OUTPUT_TYPE_TV);
        if (dispdev && dispdev->set_tv_func) {
            ret = dispdev->set_tv_func(dispdev, func);
            if (ret == 0)
                registered_cnt++;
        }
    }

#if defined(SUPPORT_VGA)
    disp_init_vga();
    for (disp = 0; disp < num_screens; disp++) {
        dispdev = disp_device_find(disp, DISP_OUTPUT_TYPE_VGA);
        if (dispdev && dispdev->set_tv_func) {
            ret = dispdev->set_tv_func(dispdev, func);
            if (ret == 0)
                registered_cnt++;
        }
    }
#endif
    if (registered_cnt != 0) {
        gdisp.tv_registered = 1;
        if (gdisp.init_para.start_process)
            gdisp.init_para.start_process();
    }
#endif
    return 0;
}

s32 bsp_disp_lcd_set_panel_funs(char *name, struct disp_lcd_panel_fun *lcd_cfg)
{
    struct disp_device *lcd;
    u32 num_screens;
    u32 screen_id;
    u32 registered_cnt = 0;

    num_screens = bsp_disp_feat_get_num_screens();
    for (screen_id = 0; screen_id < num_screens; screen_id++) {
        lcd = disp_get_lcd(screen_id);
        if (lcd && (lcd->set_panel_func)) {
            if (!lcd->set_panel_func(lcd, name, lcd_cfg)) {
                gdisp.lcd_registered[screen_id] = 1;
                registered_cnt++;
                DE_INF("panel driver %s register\n", name);
            }
        }
    }

    return 0;
}

void LCD_OPEN_FUNC(u32 disp, LCD_FUNC func, u32 delay)
{
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);

    if (lcd && lcd->set_open_func)
        lcd->set_open_func(lcd, func, delay);
}

void LCD_CLOSE_FUNC(u32 disp, LCD_FUNC func, u32 delay)
{
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);

    if (lcd && lcd->set_close_func)
        lcd->set_close_func(lcd, func, delay);
}

s32 bsp_disp_get_lcd_registered(u32 disp)
{
    return gdisp.lcd_registered[disp];
}

s32 bsp_disp_get_hdmi_registered(void)
{
    return gdisp.hdmi_registered;
}

s32 bsp_disp_get_tv_registered(void)
{
    return gdisp.tv_registered;
}

s32 bsp_disp_lcd_backlight_enable(u32 disp)
{
    s32 ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        return ret;

    if (lcd->backlight_enable)
        ret = lcd->backlight_enable(lcd);

    return ret;
}

s32 bsp_disp_lcd_backlight_disable(u32 disp)
{
    s32 ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        return ret;

    if (lcd && lcd->backlight_disable)
        ret = lcd->backlight_disable(lcd);

    return ret;
}

s32 bsp_disp_lcd_pwm_enable(u32 disp)
{
    s32 ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        return ret;

    if (lcd && lcd->pwm_enable)
        ret = lcd->pwm_enable(lcd);

    return ret;
}

s32 bsp_disp_lcd_pwm_disable(u32 disp)
{
    s32 ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        return ret;

    if (lcd && lcd->pwm_disable)
        ret = lcd->pwm_disable(lcd);

    return ret;
}

s32 bsp_disp_lcd_power_enable(u32 disp, u32 power_id)
{
    s32 ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        return ret;

    if (lcd && lcd->power_enable)
        ret = lcd->power_enable(lcd, power_id);

    return ret;
}

s32 bsp_disp_lcd_power_disable(u32 disp, u32 power_id)
{
    s32 ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        return ret;

    if (lcd && lcd->power_disable)
        ret = lcd->power_disable(lcd, power_id);

    return ret;
}

s32 bsp_disp_lcd_set_bright(u32 disp, u32 bright)
{
    s32 ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        return ret;

    if (lcd && lcd->set_bright)
        ret = lcd->set_bright(lcd, bright);

    return ret;
}

s32 bsp_disp_lcd_get_bright(u32 disp)
{
    u32 bright = 0;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd && lcd->get_bright)
        bright = lcd->get_bright(lcd);

    return bright;
}

s32 bsp_disp_lcd_tcon_enable(u32 disp)
{
    int ret = -1;
    struct disp_device *lcd;
    struct disp_device *lcd_slave;

    struct disp_panel_para *panel_info =
        kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);

    if (panel_info == NULL)
        goto OUT;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        goto FREE_INFO;

    if (lcd && lcd->get_panel_info)
        ret = lcd->get_panel_info(lcd, panel_info);

    if (ret != 0)
        goto FREE_INFO;

    if (panel_info->lcd_tcon_mode == DISP_TCON_SLAVE_MODE) {
        ret = 0;
        goto FREE_INFO;
    }

    if (lcd && lcd->tcon_enable)
        ret = lcd->tcon_enable(lcd);

    if (panel_info->lcd_tcon_mode <= DISP_TCON_MASTER_SYNC_EVERY_FRAME &&
        panel_info->lcd_tcon_mode >= DISP_TCON_MASTER_SYNC_AT_FIRST_TIME) {
        lcd_slave = disp_get_lcd(panel_info->lcd_slave_tcon_num);
        if (lcd_slave == NULL)
            goto FREE_INFO;
        if (lcd_slave && lcd_slave->tcon_enable)
            ret = lcd_slave->tcon_enable(lcd_slave);
    }

FREE_INFO:
    if (panel_info != NULL)
        kfree(panel_info);
OUT:
    return ret;
}

s32 bsp_disp_lcd_tcon_disable(u32 disp)
{
    int ret = -1;
    struct disp_device *lcd;
    struct disp_device *lcd_slave;

    struct disp_panel_para *panel_info =
        kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);

    if (panel_info == NULL)
        goto OUT;

    lcd = disp_get_lcd(disp);
    if (lcd == NULL)
        goto FREE_INFO;

    if (lcd && lcd->get_panel_info)
        ret = lcd->get_panel_info(lcd, panel_info);

    if (ret != 0)
        goto FREE_INFO;

    if (lcd && lcd->tcon_disable)
        ret = lcd->tcon_disable(lcd);

    if (panel_info->lcd_tcon_mode <= DISP_TCON_MASTER_SYNC_EVERY_FRAME &&
        panel_info->lcd_tcon_mode >= DISP_TCON_MASTER_SYNC_AT_FIRST_TIME) {
        lcd_slave = disp_get_lcd(panel_info->lcd_slave_tcon_num);
        if (lcd_slave == NULL)
            goto FREE_INFO;
        if (lcd_slave && lcd_slave->tcon_disable)
            ret = lcd_slave->tcon_disable(lcd_slave);
    }

FREE_INFO:
    if (panel_info != NULL)
        kfree(panel_info);
OUT:
    return ret;
}

s32 bsp_disp_lcd_pin_cfg(u32 disp, u32 en)
{
    int ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd && lcd->pin_cfg)
        ret = lcd->pin_cfg(lcd, en);

    return ret;
}

s32 bsp_disp_lcd_gpio_set_value(u32 disp, u32 io_index, u32 value)
{
    int ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd && lcd->gpio_set_value)
        ret = lcd->gpio_set_value(lcd, io_index, value);

    return ret;
}

s32 bsp_disp_lcd_gpio_set_direction(u32 disp, unsigned int io_index,
                    u32 direction)
{
    int ret = -1;
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (lcd && lcd->gpio_set_direction)
        ret = lcd->gpio_set_direction(lcd, io_index, direction);

    return ret;
}

s32 bsp_disp_get_panel_info(u32 disp, struct disp_panel_para *info)
{
    struct disp_device *lcd;

    lcd = disp_get_lcd(disp);
    if (!lcd)
        DE_WRN("get lcd%d fail\n", disp);

    if (lcd && lcd->get_panel_info)
        return lcd->get_panel_info(lcd, info);

    return DIS_FAIL;
}

int bsp_disp_get_display_size(u32 disp, unsigned int *width,
                  unsigned int *height)
{
    return disp_al_get_display_size(disp, width, height);
}
#if defined(SUPPORT_DSI)
s32 bsp_disp_lcd_dsi_open(u32 disp)
{
    s32 ret = -1;
    struct disp_panel_para *panel_info =
        kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);

    ret = bsp_disp_get_panel_info(disp, panel_info);
    if (ret == DIS_FAIL) {
        DE_WRN("%s:Get panel info failed\n", __func__);
        goto OUT;
    }

    if (panel_info->lcd_tcon_mode == DISP_TCON_SLAVE_MODE)
        goto OUT;

    ret = dsi_mode_switch(disp, 1);
    if (panel_info->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
        disp + 1 < DEVICE_DSI_NUM)
        ret = dsi_mode_switch(disp + 1, 1);
    else if (panel_info->lcd_tcon_mode != DISP_TCON_NORMAL_MODE &&
         panel_info->lcd_tcon_mode != DISP_TCON_DUAL_DSI)
        ret = dsi_mode_switch(panel_info->lcd_slave_tcon_num, 1);

OUT:
    kfree(panel_info);
    return ret;
}

s32 bsp_disp_lcd_dsi_close(u32 disp)
{
    s32 ret = -1;
    struct disp_panel_para *panel_info =
        kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);

    ret = bsp_disp_get_panel_info(disp, panel_info);
    if (ret == DIS_FAIL) {
        DE_WRN("%s:Get panel info failed\n", __func__);
        goto OUT;
    }

    if (panel_info->lcd_tcon_mode == DISP_TCON_SLAVE_MODE)
        goto OUT;

    ret = dsi_mode_switch(disp, 0);
    if (panel_info->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
        disp + 1 < DEVICE_DSI_NUM)
        ret = dsi_mode_switch(disp + 1, 0);
    else if (panel_info->lcd_tcon_mode != DISP_TCON_NORMAL_MODE &&
         panel_info->lcd_tcon_mode != DISP_TCON_DUAL_DSI)
        ret = dsi_mode_switch(panel_info->lcd_slave_tcon_num, 0);
OUT:
    kfree(panel_info);
    return ret;
}

s32 bsp_disp_lcd_dsi_clk_enable(u32 disp, u32 en)
{
    s32 ret = -1;
    struct disp_panel_para *panel_info =
        kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);

    ret = bsp_disp_get_panel_info(disp, panel_info);
    if (ret == DIS_FAIL) {
        DE_WRN("%s:Get panel info failed\n", __func__);
        goto OUT;
    }

    if (panel_info->lcd_tcon_mode == DISP_TCON_SLAVE_MODE)
        goto OUT;

    ret = dsi_clk_enable(disp, en);
    if (panel_info->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
        disp + 1 < DEVICE_DSI_NUM)
        ret = dsi_clk_enable(disp + 1, en);
    else if (panel_info->lcd_tcon_mode != DISP_TCON_NORMAL_MODE &&
         panel_info->lcd_tcon_mode != DISP_TCON_DUAL_DSI)
        ret = dsi_clk_enable(panel_info->lcd_slave_tcon_num, en);
OUT:
    kfree(panel_info);
    return ret;
}

s32 bsp_disp_lcd_dsi_dcs_wr(u32 disp, u8 command, u8 *para, u32 para_num)
{
    s32 ret = -1;
    struct disp_panel_para *panel_info =
        kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);

    ret = bsp_disp_get_panel_info(disp, panel_info);
    if (ret == DIS_FAIL) {
        DE_WRN("%s:Get panel info failed\n", __func__);
        goto OUT;
    }

    if (panel_info->lcd_tcon_mode == DISP_TCON_SLAVE_MODE)
        goto OUT;

    ret = dsi_dcs_wr(disp, command, para, para_num);
    if (panel_info->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
        disp + 1 < DEVICE_DSI_NUM &&
        panel_info->lcd_dsi_port_num == DISP_LCD_DSI_SINGLE_PORT)
        ret = dsi_dcs_wr(disp + 1, command, para, para_num);
    else if (panel_info->lcd_tcon_mode != DISP_TCON_NORMAL_MODE &&
         panel_info->lcd_tcon_mode != DISP_TCON_DUAL_DSI)
        ret = dsi_dcs_wr(panel_info->lcd_slave_tcon_num, command, para,
                 para_num);
OUT:
    kfree(panel_info);
    return ret;
}

s32 bsp_disp_lcd_dsi_gen_wr(u32 disp, u8 command, u8 *para, u32 para_num)
{
    s32 ret = -1;
    struct disp_panel_para *panel_info =
        kmalloc(sizeof(struct disp_panel_para), GFP_KERNEL | __GFP_ZERO);

    ret = bsp_disp_get_panel_info(disp, panel_info);
    if (ret == DIS_FAIL) {
        DE_WRN("%s:Get panel info failed\n", __func__);
        goto OUT;
    }

    if (panel_info->lcd_tcon_mode == DISP_TCON_SLAVE_MODE)
        goto OUT;

    ret = dsi_gen_wr(disp, command, para, para_num);
    if (panel_info->lcd_tcon_mode == DISP_TCON_DUAL_DSI &&
        disp + 1 < DEVICE_DSI_NUM &&
        panel_info->lcd_dsi_port_num == DISP_LCD_DSI_SINGLE_PORT)
        ret = dsi_gen_wr(disp + 1, command, para, para_num);
    else if (panel_info->lcd_tcon_mode != DISP_TCON_NORMAL_MODE &&
         panel_info->lcd_tcon_mode != DISP_TCON_DUAL_DSI)
        ret = dsi_gen_wr(panel_info->lcd_slave_tcon_num, command, para,
                 para_num);
OUT:
    kfree(panel_info);
    return ret;
}
#endif /*endif SUPPORT_DSI */

/linux-sunxi/drivers/video/fbdev/sunxi/disp2/disp/de/disp_hdmi.h

/*
 * Allwinner SoCs display driver.
 *
 * Copyright (C) 2016 Allwinner.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#ifndef __DISP_HDMI_H__
#define __DISP_HDMI_H__

#include "disp_private.h"

#define HDMI1440_480I 6
#define HDMI1440_576I 21
#define HDMI480P 2
#define HDMI576P 17
#define HDMI720P_50 19
#define HDMI720P_60 4
#define HDMI1080I_50 20
#define HDMI1080I_60 5
#define HDMI1080P_50 31
#define HDMI1080P_60 16
#define HDMI1080P_24 32
#define HDMI1080P_25 33
#define HDMI1080P_30 34
#define HDMI800_480P 35
#define HDMI1080P_24_3D_FP (HDMI1080P_24 + 0x80)
#define HDMI720P_50_3D_FP (HDMI720P_50 + 0x80)
#define HDMI720P_60_3D_FP (HDMI720P_60 + 0x80)
#define HDMI3840_2160P_30 (0x01 + 0x100)
#define HDMI3840_2160P_25 (0x02 + 0x100)
#define HDMI3840_2160P_24 (0x03 + 0x100)
#define HDMI4096_2160P_24 (0x04 + 0x100)
#define HDMI1024_600      (0x05 + 0x100)
#define HDMI1280_800      (0x06 + 0x100)

s32 disp_init_hdmi(struct disp_bsp_init_para *para);

struct disp_device *disp_get_hdmi(u32 disp);

#endif

/linux-sunxi/drivers/video/fbdev/sunxi/disp2/disp/de/include.h

/*
 * Allwinner SoCs display driver.
 *
 * Copyright (C) 2016 Allwinner.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#ifndef _DISP_INCLUDE_H_
#define _DISP_INCLUDE_H_

#define __LINUX_PLAT__
/* #define __UBOOT_PLAT__ */

#if defined(__LINUX_PLAT__)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
#include <asm/memory.h>
#include <asm/unistd.h>
#include "linux/semaphore.h"
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/dma-mapping.h>
#include <linux/fb.h>
#include <linux/sched.h>    /* wake_up_process() */
#include <linux/kthread.h>  /* kthread_create()??kthread_run() */
#include <linux/err.h>      /* IS_ERR()??PTR_ERR() */
#include <linux/delay.h>
#include <linux/platform_device.h>
#include "asm-generic/int-ll64.h"
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/pwm.h>
#include <asm/div64.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_iommu.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/compat.h>
#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
#include <asm/barrier.h>
#include <linux/clk-provider.h>

#include <video/sunxi_display2.h>
#include <video/sunxi_metadata.h>
#include "../disp_sys_intf.h"
#include "disp_features.h"

/* #include "disp_format_convert.h" */
s32 bsp_disp_get_print_level(void);

#if 1
#define __inf(msg...) do { \
        if (bsp_disp_get_print_level()) { \
            pr_warn("[DISP] %s,line:%d:", __func__, __LINE__); \
            pr_warn(msg); \
        } \
    } while (0)
#define __msg(msg...) do { \
        if (bsp_disp_get_print_level()) { \
            pr_warn("[DISP] %s,line:%d:", __func__, __LINE__); \
            pr_warn(msg); \
        } \
    } while (0)
#define __wrn(msg...) do { \
            pr_warn("[DISP] %s,line:%d:", __func__, __LINE__); \
            pr_warn(msg); \
        } while (0)
#define __here__ do { \
        if (bsp_disp_get_print_level() == 2) { \
            pr_warn("[DISP] %s,line:%d\n", __func__, __LINE__);\
        } \
    } while (0)
#define __debug(msg...)  do { \
        if (bsp_disp_get_print_level() == 2) { \
            pr_warn("[DISP] %s,line:%d:", __func__, __LINE__); \
            pr_warn(msg); \
        } \
    } while (0)
#else
#define __inf(msg...)  printk(msg)
#define __msg(msg...)  printk(msg)
#define __wrn(msg...)  printk(msg)
#define __here__
#define __debug(msg...)
#endif

#endif              /* end of define __LINUX_PLAT__ */

#ifdef __UBOOT_PLAT__
#include <common.h>
#include <malloc.h>
#include <sunxi_display2.h>
#include <sys_config.h>
#include <asm/arch/intc.h>
#include <pwm.h>
#include <asm/arch/timer.h>
#include <asm/arch/platform.h>
#include <linux/list.h>
#include <asm/memory.h>
#include <div64.h>
#include <fdt_support.h>
#include <power/sunxi/pmu.h>
#include "asm/io.h"
#include "../disp_sys_intf.h"

#define OSAL_PRINTF
#define __inf(msg...)
#define __msg(msg...)
#define __wrn(msg...) printf(msg)
#define __here
#define __debug

#define false 0
#define true 1
#endif

#if defined(__LINUX_PLAT__)
#define DE_INF __inf
#define DE_MSG __msg
#define DE_WRN __wrn
#define DE_DBG __debug
#define DISP_IRQ_RETURN IRQ_HANDLED
#else
#define DE_INF(msg...)
#define DE_MSG __msg
#define DE_WRN __wrn
#define DE_DBG __debug
#ifndef DISP_IRQ_RETURN
#define DISP_IRQ_RETURN DIS_SUCCESS
#endif
#endif

#define DEFAULT_PRINT_LEVLE 2
#if defined(CONFIG_FPGA_V4_PLATFORM) \
    || defined(CONFIG_FPGA_V7_PLATFORM) \
    || defined(CONFIG_A67_FPGA)
#define __FPGA_DEBUG__
#endif

#define SETMASK(width, shift)   ((width?((-1U) >> (32-width)):0)  << (shift))
#define CLRMASK(width, shift)   (~(SETMASK(width, shift)))
#define GET_BITS(shift, width, reg)     \
    (((reg) & SETMASK(width, shift)) >> (shift))
#define SET_BITS(shift, width, reg, val) \
    (((reg) & CLRMASK(width, shift)) | (val << (shift)))

#define DISPALIGN(value, align) ((align == 0) ? \
                value : \
                (((value) + ((align) - 1)) & ~((align) - 1)))

#ifndef abs
#define abs(x) (((x)&0x80000000) ? (0-(x)):(x))
#endif

#define LCD_GAMMA_TABLE_SIZE (256 * sizeof(unsigned int))

#define ONE_SEC 1000000000ull
struct panel_extend_para {
    unsigned int lcd_gamma_en;
    unsigned int lcd_gamma_tbl[256];
    unsigned int lcd_cmap_en;
    unsigned int lcd_cmap_tbl[2][3][4];
    unsigned int lcd_bright_curve_tbl[256];
};

enum disp_return_value {
    DIS_SUCCESS = 0,
    DIS_FAIL = -1,
    DIS_PARA_FAILED = -2,
    DIS_PRIO_ERROR = -3,
    DIS_OBJ_NOT_INITED = -4,
    DIS_NOT_SUPPORT = -5,
    DIS_NO_RES = -6,
    DIS_OBJ_COLLISION = -7,
    DIS_DEV_NOT_INITED = -8,
    DIS_DEV_SRAM_COLLISION = -9,
    DIS_TASK_ERROR = -10,
    DIS_PRIO_COLLSION = -11
};

/*basic data information definition*/
enum disp_layer_feat {
    DISP_LAYER_FEAT_GLOBAL_ALPHA = 1 << 0,
    DISP_LAYER_FEAT_PIXEL_ALPHA = 1 << 1,
    DISP_LAYER_FEAT_GLOBAL_PIXEL_ALPHA = 1 << 2,
    DISP_LAYER_FEAT_PRE_MULT_ALPHA = 1 << 3,
    DISP_LAYER_FEAT_COLOR_KEY = 1 << 4,
    DISP_LAYER_FEAT_ZORDER = 1 << 5,
    DISP_LAYER_FEAT_POS = 1 << 6,
    DISP_LAYER_FEAT_3D = 1 << 7,
    DISP_LAYER_FEAT_SCALE = 1 << 8,
    DISP_LAYER_FEAT_DE_INTERLACE = 1 << 9,
    DISP_LAYER_FEAT_COLOR_ENHANCE = 1 << 10,
    DISP_LAYER_FEAT_DETAIL_ENHANCE = 1 << 11,
};

enum disp_pixel_type {
    DISP_PIXEL_TYPE_RGB = 0x0,
    DISP_PIXEL_TYPE_YUV = 0x1,
};

enum disp_layer_dirty_flags {
    LAYER_ATTR_DIRTY = 0x00000001,
    LAYER_VI_FC_DIRTY = 0x00000002,
    LAYER_HADDR_DIRTY = 0x00000004,
    LAYER_SIZE_DIRTY = 0x00000008,
    BLEND_ENABLE_DIRTY = 0x00000010,
    BLEND_ATTR_DIRTY = 0x00000020,
    BLEND_CTL_DIRTY        = 0x00000040,
    BLEND_OUT_DIRTY        = 0x00000080,
    LAYER_ATW_DIRTY        = 0x00000100,
    LAYER_HDR_DIRTY        = 0x00000200,
    LAYER_ALL_DIRTY        = 0x000003ff,
};

enum disp_manager_dirty_flags {
    MANAGER_ENABLE_DIRTY = 0x00000001,
    MANAGER_CK_DIRTY = 0x00000002,
    MANAGER_BACK_COLOR_DIRTY = 0x00000004,
    MANAGER_SIZE_DIRTY = 0x00000008,
    MANAGER_COLOR_RANGE_DIRTY = 0x00000010,
    MANAGER_COLOR_SPACE_DIRTY = 0x00000020,
    MANAGER_BLANK_DIRTY = 0x00000040,
    MANAGER_ALL_DIRTY = 0x0000007f,
};

/* disp_atw_info_inner - asynchronous time wrap infomation
 *
 * @used: indicate if the atw funtion is used
 * @mode: atw mode
 * @b_row: the row number of the micro block
 * @b_col: the column number of the micro block
 * @cof_fd: dma_buf fd for the buffer contaied coefficient for atw
 */
struct disp_atw_info_inner {
    bool used;
    enum disp_atw_mode mode;
    unsigned int b_row;
    unsigned int b_col;
    int cof_fd;
    unsigned long long cof_addr;
};

/* disp_fb_info_inner - image buffer info on the inside
 *
 * @addr: buffer address for each plane
 * @size: size<width,height> for each buffer, unit:pixels
 * @align: align for each buffer, unit:bytes
 * @format: pixel format
 * @color_space: color space
 * @trd_right_addr: the right-eye buffer address for each plane,
 *                  valid when frame-packing 3d buffer input
 * @pre_multiply: indicate the pixel use premultiplied alpha
 * @crop: crop rectangle for buffer to be display
 * @flag: indicate stereo/non-stereo buffer
 * @scan: indicate interleave/progressive scan type, and the scan order
 * @metadata_buf: the phy_address to the buffer contained metadata for fbc/hdr
 * @metadata_size: the size of metadata buffer, unit:bytes
 * @metadata_flag: the flag to indicate the type of metadata buffer
 *  0     : no metadata
 *  1 << 0: hdr static metadata
 *  1 << 1: hdr dynamic metadata
 *  1 << 4: frame buffer compress(fbc) metadata
 *  x     : all type could be "or" together
 */
struct disp_fb_info_inner {
    int fd;
    struct dma_buf           *dmabuf;
    unsigned long long       addr[3];
    struct disp_rectsz       size[3];
    unsigned int             align[3];
    enum disp_pixel_format   format;
    enum disp_color_space    color_space;
    int                      trd_right_fd;
    unsigned int             trd_right_addr[3];
    bool                     pre_multiply;
    struct disp_rect64       crop;
    enum disp_buffer_flags   flags;
    enum disp_scan_flags     scan;
    enum disp_eotf           eotf;
    int                      depth;
    unsigned int             fbd_en;
    int                      metadata_fd;
    unsigned long long       metadata_buf;
    unsigned int             metadata_size;
    unsigned int             metadata_flag;
};

/* disp_layer_info_inner - layer info on the inside
 *
 * @mode: buffer/clolor mode, when in color mode, the layer is widthout buffer
 * @zorder: the zorder of layer, 0~max-layer-number
 * @alpha_mode:
 *  0: pixel alpha;
 *  1: global alpha
 *  2: mixed alpha, compositing width pixel alpha before global alpha
 * @alpha_value: global alpha value, valid when alpha_mode is not pixel alpha
 * @screen_win: the rectangle on the screen for fb to be display
 * @b_trd_out: indicate if 3d display output
 * @out_trd_mode: 3d output mode, valid when b_trd_out is true
 * @color: the color value to be display, valid when layer is in color mode
 * @fb: the framebuffer info related width the layer, valid when in buffer mode
 * @id: frame id, the user could get the frame-id display currently by
 *  DISP_LAYER_GET_FRAME_ID ioctl
 * @atw: asynchronous time wrap information
 */
struct disp_layer_info_inner {
    enum disp_layer_mode      mode;
    unsigned char             zorder;
    unsigned char             alpha_mode;
    unsigned char             alpha_value;
    struct disp_rect          screen_win;
    bool                      b_trd_out;
    enum disp_3d_out_mode     out_trd_mode;
    union {
        unsigned int               color;
        struct disp_fb_info_inner  fb;
    };

    unsigned int              id;
    struct disp_atw_info_inner atw;
};

/* disp_layer_config_inner - layer config on the inside
 *
 * @info: layer info
 * @enable: indicate to enable/disable the layer
 * @channel: the channel index of the layer, 0~max-channel-number
 * @layer_id: the layer index of the layer widthin it's channel
 */
struct disp_layer_config_inner {
    struct disp_layer_info_inner info;
    bool enable;
    unsigned int channel;
    unsigned int layer_id;
};

/* disp_layer_config_ops - operations for layer config
 *
 * @vmap:vmap a block contigous phys memory into virtual space
 * @vunmap: release virtual mapping obtained by vmap()
 */
struct disp_layer_config_ops {
    void *(*vmap)(unsigned long phys_addr, unsigned long size);
    void (*vunmap)(const void *vaddr);
};
struct disp_layer_config_data {
    struct disp_layer_config_inner config;
    enum disp_layer_dirty_flags flag;
    struct disp_layer_config_ops ops;
};

struct disp_manager_info {
    struct disp_color back_color;
    struct disp_colorkey ck;
    struct disp_rect size;
    enum disp_csc_type cs;
    enum disp_color_space color_space;
    u32 color_range;
    u32 interlace;
    bool enable;
    /* index of device */
    u32 disp_device;
    /* indicate the index of timing controller */
    u32 hwdev_index;
    /* true: disable all layer; false: enable layer if requested */
    bool blank;
    u32 de_freq;
    enum disp_eotf eotf; /* sdr/hdr10/hlg */
    enum disp_data_bits data_bits;
};

struct disp_manager_data {
    struct disp_manager_info config;
    enum disp_manager_dirty_flags flag;
};

struct disp_clk_info {
    u32 clk;
    u32 clk_div;
    u32 h_clk;
    u32 clk_src;
    u32 clk_div2;

    u32 clk_p;
    u32 clk_div_p;
    u32 h_clk_p;
    u32 clk_src_p;

    u32 ahb_clk;
    u32 h_ahb_clk;
    u32 dram_clk;
    u32 h_dram_clk;

    bool enabled;
};

struct disp_enhance_info {
    /* basic adjust */
    /*
     * enhance parameters : 0~10, bigger value, stronger enhance level
     * mode : combination of enhance_mode and dev_type
     * enhance_mode : bit31~bit16 of mode
     *              : 0-disable; 1-enable; 2-demo(enable half window)
     * dev_type : bit15~bit0 of mode
     *          : 0-lcd; 1-tv(hdmi, cvbs, vga, ypbpr)
     */
    u32 bright;
    u32 contrast;
    u32 saturation;
    u32 hue;
    u32         edge;
    u32         detail;
    u32         denoise;
    u32 mode;
    /* ehnance */
    u32 sharp;      /* 0-off; 1~3-on. */
    u32 auto_contrast;  /* 0-off; 1~3-on. */
    u32 auto_color;     /* 0-off; 1-on. */
    u32 fancycolor_red; /* 0-Off; 1-2-on. */
    u32 fancycolor_green;   /* 0-Off; 1-2-on. */
    u32 fancycolor_blue;    /* 0-Off; 1-2-on. */
    struct disp_rect window;
    u32 enable;
    struct disp_rect size;
    u32 demo_enable;    /* 1: enable demo mode */
};

enum disp_enhance_dirty_flags {
    ENHANCE_NONE_DIRTY = 0x0,
    ENHANCE_ENABLE_DIRTY = 0x1 << 0,
    ENHANCE_BRIGHT_DIRTY = 0x1 << 1,
    ENHANCE_SHARP_DIRTY = 0x1 << 2,
    ENHANCE_SIZE_DIRTY = 0x1 << 3,
    ENHANCE_MODE_DIRTY = 0X1 << 4,
    ENHANCE_DEMO_DIRTY = 0x1 << 5,
    ENHANCE_FORMAT_DIRTY    = 0x1 << 6,
    ENHANCE_BYPASS_DIRTY    = 0x1 << 7,
    ENHANCE_INIT_DIRTY      = 0x1 << 8,
    ENHANCE_CONTRAST_DIRTY  = 0x1 << 9,
    ENHANCE_EDGE_DIRTY      = 0x1 << 10,
    ENHANCE_DETAIL_DIRTY    = 0x1 << 11,
    ENHANCE_SAT_DIRTY       = 0x1 << 12,
    ENHANCE_DNS_DIRTY       = 0x1 << 13,
    ENHANCE_USER_DIRTY      = 0xff00,
    ENHANCE_ALL_DIRTY = 0xffff,
};

struct disp_enhance_config {
    struct disp_enhance_info info;
    enum disp_enhance_dirty_flags flags;
};

enum disp_smbl_dirty_flags {
    SMBL_DIRTY_NONE = 0x00000000,
    SMBL_DIRTY_ENABLE = 0x00000001,
    SMBL_DIRTY_WINDOW = 0x00000002,
    SMBL_DIRTY_SIZE = 0x00000004,
    SMBL_DIRTY_BL = 0x00000008,
    SMBL_DIRTY_ALL = 0x0000000F,
};

struct disp_smbl_info {
    struct disp_rect window;
    u32 enable;
    struct disp_rect size;
    u32 backlight;
    u32 backlight_dimming;
    enum disp_smbl_dirty_flags flags;
};

struct disp_csc_config {
    u32 in_fmt;
    u32 in_mode;
    u32 in_color_range;
    u32 out_fmt;
    u32 out_mode;
    u32 out_color_range;
    u32 brightness;
    u32 contrast;
    u32 saturation;
    u32 hue;
    u32 enhance_mode;
    u32 color;
    u32 in_eotf;
    u32 out_eotf;
};

enum {
    DE_RGB = 0,
    DE_YUV = 1,
};

enum disp_capture_dirty_flags {
    CAPTURE_DIRTY_ADDRESS = 0x00000001,
    CAPTURE_DIRTY_WINDOW = 0x00000002,
    CAPTURE_DIRTY_SIZE = 0x00000004,
    CAPTURE_DIRTY_ALL = 0x00000007,
};
/* disp_s_frame_inner - display simple frame buffer
 *
 * @format: pixel format of fb
 * @size: size for each plane
 * @crop: crop zone to be fill image data
 * @fd: dma_buf fd
 * @addr: buffer addr for each plane
 */
struct disp_s_frame_inner {
    enum disp_pixel_format format;
    struct disp_rectsz size[3];
    struct disp_rect crop;
    unsigned long long addr[3];
    int fd;
};

/* disp_capture_info_inner - display capture information
 *
 * @window: the rectange on the screen to be capture
 * @out_frame: the framebuffer to be restore capture image data
 */
struct disp_capture_info_inner {
    struct disp_rect window;
    struct disp_s_frame_inner out_frame;
};
/* disp_capture_config - configuration for capture function
 *
 * @in_frame: input frame information
 * @out_frame: output framebuffer infomation
 * @disp: indicate which disp channel to be capture
 * @flags: caputre flags
 */
struct disp_capture_config {
    struct disp_s_frame in_frame;   /* only format/size/crop valid */
    struct disp_s_frame out_frame;
    u32 disp;       /* which disp channel to be capture */
    enum disp_capture_dirty_flags flags;
};

enum disp_lcd_if {
    LCD_IF_HV = 0,
    LCD_IF_CPU = 1,
    LCD_IF_LVDS = 3,
    LCD_IF_DSI = 4,
    LCD_IF_EDP = 5,
    LCD_IF_EXT_DSI = 6,
    LCD_IF_VDPO = 7,
};

enum disp_lcd_hv_if {
    LCD_HV_IF_PRGB_1CYC = 0,    /* parallel hv */
    LCD_HV_IF_SRGB_3CYC = 8,    /* serial hv */
    LCD_HV_IF_DRGB_4CYC = 10,   /* Dummy RGB */
    LCD_HV_IF_RGBD_4CYC = 11,   /* RGB Dummy */
    LCD_HV_IF_CCIR656_2CYC = 12,
};

enum disp_lcd_hv_srgb_seq {
    LCD_HV_SRGB_SEQ_RGB_RGB = 0,
    LCD_HV_SRGB_SEQ_RGB_BRG = 1,
    LCD_HV_SRGB_SEQ_RGB_GBR = 2,
    LCD_HV_SRGB_SEQ_BRG_RGB = 4,
    LCD_HV_SRGB_SEQ_BRG_BRG = 5,
    LCD_HV_SRGB_SEQ_BRG_GBR = 6,
    LCD_HV_SRGB_SEQ_GRB_RGB = 8,
    LCD_HV_SRGB_SEQ_GRB_BRG = 9,
    LCD_HV_SRGB_SEQ_GRB_GBR = 10,
};

enum disp_lcd_hv_syuv_seq {
    LCD_HV_SYUV_SEQ_YUYV = 0,
    LCD_HV_SYUV_SEQ_YVYU = 1,
    LCD_HV_SYUV_SEQ_UYUV = 2,
    LCD_HV_SYUV_SEQ_VYUY = 3,
};

enum disp_lcd_hv_syuv_fdly {
    LCD_HV_SYUV_FDLY_0LINE = 0,
    LCD_HV_SRGB_FDLY_2LINE = 1, /* ccir ntsc */
    LCD_HV_SRGB_FDLY_3LINE = 2, /* ccir pal */
};

enum disp_lcd_cpu_if {
    LCD_CPU_IF_RGB666_18PIN = 0,
    LCD_CPU_IF_RGB666_9PIN = 10,
    LCD_CPU_IF_RGB666_6PIN = 12,
    LCD_CPU_IF_RGB565_16PIN = 8,
    LCD_CPU_IF_RGB565_8PIN = 14,
};

enum disp_lcd_cpu_mode {
    LCD_CPU_AUTO_MODE = 0,
    LCD_CPU_TRIGGER_MODE = 1,
};

enum disp_lcd_te {
    LCD_TE_DISABLE = 0,
    LCD_TE_RISING = 1,
    LCD_TE_FALLING = 2,
};

enum disp_lcd_lvds_if {
    LCD_LVDS_IF_SINGLE_LINK = 0,
    LCD_LVDS_IF_DUAL_LINK = 1,
};

enum disp_lcd_lvds_colordepth {
    LCD_LVDS_8bit = 0,
    LCD_LVDS_6bit = 1,
};

enum disp_lcd_lvds_mode {
    LCD_LVDS_MODE_NS = 0,
    LCD_LVDS_MODE_JEIDA = 1,
};

enum disp_lcd_dsi_if {
    LCD_DSI_IF_VIDEO_MODE = 0,
    LCD_DSI_IF_COMMAND_MODE = 1,
    LCD_DSI_IF_BURST_MODE = 2,
};

enum disp_lcd_dsi_lane {
    LCD_DSI_1LANE = 1,
    LCD_DSI_2LANE = 2,
    LCD_DSI_3LANE = 3,
    LCD_DSI_4LANE = 4,
};

enum disp_lcd_dsi_format {
    LCD_DSI_FORMAT_RGB888 = 0,
    LCD_DSI_FORMAT_RGB666 = 1,
    LCD_DSI_FORMAT_RGB666P = 2,
    LCD_DSI_FORMAT_RGB565 = 3,
};

enum disp_lcd_frm {
    LCD_FRM_BYPASS = 0,
    LCD_FRM_RGB666 = 1,
    LCD_FRM_RGB565 = 2,
};

enum disp_lcd_cmap_color {
    LCD_CMAP_B0 = 0x0,
    LCD_CMAP_G0 = 0x1,
    LCD_CMAP_R0 = 0x2,
    LCD_CMAP_B1 = 0x4,
    LCD_CMAP_G1 = 0x5,
    LCD_CMAP_R1 = 0x6,
    LCD_CMAP_B2 = 0x8,
    LCD_CMAP_G2 = 0x9,
    LCD_CMAP_R2 = 0xa,
    LCD_CMAP_B3 = 0xc,
    LCD_CMAP_G3 = 0xd,
    LCD_CMAP_R3 = 0xe,
};

struct __disp_dsi_dphy_timing_t {
    unsigned int lp_clk_div;
    unsigned int hs_prepare;
    unsigned int hs_trail;
    unsigned int clk_prepare;
    unsigned int clk_zero;
    unsigned int clk_pre;
    unsigned int clk_post;
    unsigned int clk_trail;
    unsigned int hs_dly_mode;
    unsigned int hs_dly;
    unsigned int lptx_ulps_exit;
    unsigned int hstx_ana0;
    unsigned int hstx_ana1;
};

/**
 * lcd tcon mode(dual tcon drive dual dsi)
 */
enum disp_lcd_tcon_mode {
    DISP_TCON_NORMAL_MODE = 0,
    DISP_TCON_MASTER_SYNC_AT_FIRST_TIME,
    DISP_TCON_MASTER_SYNC_EVERY_FRAME,
    DISP_TCON_SLAVE_MODE,
    DISP_TCON_DUAL_DSI,
};

enum disp_lcd_dsi_port {
    DISP_LCD_DSI_SINGLE_PORT = 0,
    DISP_LCD_DSI_DUAL_PORT,
};

struct disp_panel_para {
    enum disp_lcd_if lcd_if;

    enum disp_lcd_hv_if lcd_hv_if;
    enum disp_lcd_hv_srgb_seq lcd_hv_srgb_seq;
    enum disp_lcd_hv_syuv_seq lcd_hv_syuv_seq;
    enum disp_lcd_hv_syuv_fdly lcd_hv_syuv_fdly;

    enum disp_lcd_lvds_if lcd_lvds_if;
    enum disp_lcd_lvds_colordepth lcd_lvds_colordepth;
    enum disp_lcd_lvds_mode lcd_lvds_mode;
    unsigned int lcd_lvds_io_polarity;

    enum disp_lcd_cpu_if lcd_cpu_if;
    enum disp_lcd_te lcd_cpu_te;
    enum disp_lcd_dsi_port lcd_dsi_port_num;
    enum disp_lcd_tcon_mode  lcd_tcon_mode;
    unsigned int             lcd_slave_stop_pos;
    unsigned int             lcd_sync_pixel_num;
    unsigned int             lcd_sync_line_num;
    unsigned int             lcd_slave_tcon_num;
    enum disp_lcd_cpu_mode lcd_cpu_mode;

    enum disp_lcd_dsi_if lcd_dsi_if;
    enum disp_lcd_dsi_lane lcd_dsi_lane;
    enum disp_lcd_dsi_format lcd_dsi_format;
    unsigned int lcd_dsi_eotp;
    unsigned int lcd_dsi_vc;
    enum disp_lcd_te lcd_dsi_te;

    unsigned int             lcd_tcon_en_odd_even;

    unsigned int lcd_dsi_dphy_timing_en;
    struct __disp_dsi_dphy_timing_t *lcd_dsi_dphy_timing_p;

    unsigned int lcd_edp_rate;  /* 1(1.62G); 2(2.7G); 3(5.4G) */
    unsigned int lcd_edp_lane;  /* 1/2/4lane */
    unsigned int lcd_edp_colordepth;/* color depth, 0:8bit; 1:6bit */
    unsigned int lcd_edp_fps;

    unsigned int lcd_dclk_freq;
    unsigned int lcd_x; /* horizontal resolution */
    unsigned int lcd_y; /* vertical resolution */
    unsigned int lcd_width; /* width of lcd in mm */
    unsigned int lcd_height;    /* height of lcd in mm */
    unsigned int lcd_xtal_freq;

    unsigned int lcd_pwm_used;
    unsigned int lcd_pwm_ch;
    unsigned int lcd_pwm_freq;
    unsigned int lcd_pwm_pol;

    unsigned int lcd_rb_swap;
    unsigned int lcd_rgb_endian;

    unsigned int lcd_vt;
    unsigned int lcd_ht;
    unsigned int lcd_vbp;
    unsigned int lcd_hbp;
    unsigned int lcd_vspw;
    unsigned int lcd_hspw;

    unsigned int lcd_interlace;
    unsigned int lcd_hv_clk_phase;
    unsigned int lcd_hv_sync_polarity;

    unsigned int lcd_frm;
    unsigned int lcd_gamma_en;
    unsigned int lcd_cmap_en;
    unsigned int lcd_bright_curve_en;

    char lcd_size[8];   /* e.g. 7.9, 9.7 */
    char lcd_model_name[32];

    unsigned int tcon_index;    /* not need to config for user */
    unsigned int lcd_fresh_mode;    /* not need to config for user */
    unsigned int lcd_dclk_freq_original;/* not need to config for user */
    unsigned int ccir_clk_div;/*not need to config for user*/
    unsigned int input_csc;/*not need to config for user*/

};

enum disp_mod_id {
    DISP_MOD_DE = 0,
    DISP_MOD_DEVICE,    /* for timing controller common module */
    DISP_MOD_LCD0,
    DISP_MOD_LCD1,
    DISP_MOD_LCD2,
    DISP_MOD_LCD3,
    DISP_MOD_DSI0,
    DISP_MOD_DSI1,
    DISP_MOD_DSI2,
    DISP_MOD_DSI3,
    DISP_MOD_HDMI,
    DISP_MOD_LVDS,
    DISP_MOD_EINK,
    DISP_MOD_EDMA,
    DISP_MOD_VDPO,
    DISP_MOD_NUM,
};

struct bootlogo_info {
    unsigned long fb_base; /*physical address of bootlogo*/
};

struct disp_bootloader_info {
    int sync;       /* 1: sync width bootloader */
    int disp;       /* output disp at bootloader period */
    int type;       /* output type at bootloader period */
    int mode; /* output mode at bootloader period */
    int format;/* YUV or RGB */
    int bits; /* color deep */
    int eotf;
    int cs; /* color space */
};

#define DEBUG_TIME_SIZE 100
struct disp_health_info {
    unsigned long sync_time[DEBUG_TIME_SIZE];   /* for_debug */
    unsigned int sync_time_index;   /* for_debug */
    unsigned int skip_cnt;
    unsigned int          skip_cnt_timeout;
    unsigned int error_cnt; /* under flow .ect */
    unsigned long long    irq_cnt;
    unsigned int vsync_cnt;
    unsigned int          vsync_skip_cnt;
};

struct disp_bsp_init_para {
    uintptr_t reg_base[DISP_MOD_NUM];
    u32 irq_no[DISP_MOD_NUM];
    struct clk *mclk[DISP_MOD_NUM];

    s32 (*disp_int_process)(u32 sel);
    s32 (*vsync_event)(u32 sel);
    s32 (*start_process)(void);
    s32 (*capture_event)(u32 sel);
    s32 (*shadow_protect)(u32 sel, bool protect);
    struct disp_bootloader_info boot_info;
    struct bootlogo_info bootlogo;
};

typedef void (*LCD_FUNC) (unsigned int sel);
struct disp_lcd_function {
    LCD_FUNC func;
    unsigned int delay; /* ms */
};

#define LCD_MAX_SEQUENCES 7
struct disp_lcd_flow {
    struct disp_lcd_function func[LCD_MAX_SEQUENCES];
    unsigned int func_num;
    unsigned int cur_step;
};

struct disp_lcd_panel_fun {
    void (*cfg_panel_info)(struct panel_extend_para *info);
    int (*cfg_open_flow)(unsigned int sel);
    int (*cfg_close_flow)(unsigned int sel);
    int (*lcd_user_defined_func)(unsigned int sel, unsigned int para1,
                      unsigned int para2, unsigned int para3);
    int (*set_bright)(unsigned int sel, unsigned int bright);
};

struct disp_enhance_para {
    /* basic adjust */
    u32 bright;
    u32 contrast;
    u32 saturation;
    u32 hue;
    u32 mode;
    /* ehnance */
    u32 sharp;      /* 0-off; 1~3-on. */
    u32 auto_contrast;  /* 0-off; 1~3-on. */
    u32 auto_color;     /* 0-off; 1-on. */
    u32 fancycolor_red; /* 0-Off; 1-2-on. */
    u32 fancycolor_green;   /* 0-Off; 1-2-on. */
    u32 fancycolor_blue;    /* 0-Off; 1-2-on. */
    struct disp_rect window;
    u32 enable;
};

struct disp_device {
    struct list_head list;
    /* data fields */
    char name[32];
    u32 disp;
    /* indicate the index of hw device(timing controller) */
    u32 hwdev_index;
    u32 fix_timing;
    enum disp_output_type type;
    struct disp_manager *manager;
    struct disp_video_timings timings;
    struct work_struct close_eink_panel_work;
    void *priv_data;

    /* function fileds  */
    /* init: script init && clock init && pwm init && register irq
     * exit: clock exit && unregister irq
     */
    s32 (*init)(struct disp_device *dispdev);
    s32 (*exit)(struct disp_device *dispdev);

    s32 (*set_manager)(struct disp_device *dispdev,
               struct disp_manager *mgr);
    s32 (*unset_manager)(struct disp_device *dispdev);

    s32 (*enable)(struct disp_device *dispdev);
    s32 (*fake_enable)(struct disp_device *dispdev);
    s32 (*sw_enable)(struct disp_device *dispdev);
    s32 (*disable)(struct disp_device *dispdev);
    s32 (*is_enabled)(struct disp_device *dispdev);
    s32 (*check_if_enabled)(struct disp_device *dispdev);
    s32 (*is_used)(struct disp_device *dispdev);
    s32 (*get_resolution)(struct disp_device *dispdev, u32 *xres,
                  u32 *yres);
    s32 (*get_dimensions)(struct disp_device *dispdev, u32 *width,
                  u32 *height);
    s32 (*set_timings)(struct disp_device *dispdev,
               struct disp_video_timings *timings);
    s32 (*get_timings)(struct disp_device *dispdev,
               struct disp_video_timings *timings);
    s32 (*check_timings)(struct disp_device *dispdev,
                 struct disp_video_timings *timings);
    s32 (*detect)(struct disp_device *dispdev);
    s32 (*set_detect)(struct disp_device *dispdev, bool hpd);
    s32 (*get_status)(struct disp_device *dispdev);
    s32 (*get_fps)(struct disp_device *dispdev);
    /*
     * check if be in the safe period now,
     * safe period means the current line is less than the start_delay
     */
    bool (*is_in_safe_period)(struct disp_device *dispdev);
    u32 (*usec_before_vblank)(struct disp_device *dispdev);

    s32 (*get_input_csc)(struct disp_device *dispdev);
    s32 (*get_input_color_range)(struct disp_device *dispdev);
    s32 (*is_interlace)(struct disp_device *dispdev);

    /* power manager */
    s32 (*early_suspend)(struct disp_device *dispdev);
    s32 (*late_resume)(struct disp_device *dispdev);
    s32 (*suspend)(struct disp_device *dispdev);
    s32 (*resume)(struct disp_device *dispdev);

    s32 (*dump)(struct disp_device *dispdev, char *buf);

    /* HDMI /TV */
    s32 (*set_mode)(struct disp_device *dispdev, u32 mode);
    s32 (*get_mode)(struct disp_device *dispdev);
    s32 (*set_static_config)(struct disp_device *dispdev,
              struct disp_device_config *config);
    s32 (*get_static_config)(struct disp_device *dispdev,
              struct disp_device_config *config);
    s32 (*set_dynamic_config)(struct disp_device *dispdev,
              struct disp_device_dynamic_config *config);
    s32 (*get_dynamic_config)(struct disp_device *dispdev,
              struct disp_device_dynamic_config *config);
    /*
     * check_config_dirty
     * check if the config is not the same with current one
     */
    bool (*check_config_dirty)(struct disp_device *dispdev,
                   struct disp_device_config *config);
    s32 (*check_support_mode)(struct disp_device *dispdev, u32 mode);
    s32 (*set_func)(struct disp_device *dispdev,
            struct disp_device_func *func);
    s32 (*set_tv_func)(struct disp_device *dispdev,
               struct disp_tv_func *func);
    s32 (*set_enhance_mode)(struct disp_device *dispdev, u32 mode);

    /* LCD */
    s32 (*set_bright)(struct disp_device *dispdev, u32 bright);
    s32 (*get_bright)(struct disp_device *dispdev);
    s32 (*backlight_enable)(struct disp_device *dispdev);
    s32 (*backlight_disable)(struct disp_device *dispdev);
    s32 (*pwm_enable)(struct disp_device *dispdev);
    s32 (*pwm_disable)(struct disp_device *dispdev);
    s32 (*power_enable)(struct disp_device *dispdev, u32 power_id);
    s32 (*power_disable)(struct disp_device *dispdev, u32 power_id);
    s32 (*tcon_enable)(struct disp_device *dispdev);
    s32 (*tcon_disable)(struct disp_device *dispdev);
    s32 (*set_bright_dimming)(struct disp_device *dispdev, u32 dimming);

    struct disp_lcd_flow *(*get_open_flow)(struct disp_device *dispdev);
    struct disp_lcd_flow *(*get_close_flow)(struct disp_device *dispdev);
    s32 (*pin_cfg)(struct disp_device *dispdev, u32 bon);
    s32 (*set_gamma_tbl)(struct disp_device *dispdev, u32 *tbl,
                  u32 size);
    s32 (*enable_gamma)(struct disp_device *dispdev);
    s32 (*disable_gamma)(struct disp_device *dispdev);
    s32 (*set_color_temperature)(struct disp_device *dispdev, s32 color_temperature);
    s32 (*get_color_temperature)(struct disp_device *dispdev);
    s32 (*set_panel_func)(struct disp_device *lcd, char *name,
                  struct disp_lcd_panel_fun *lcd_cfg);
    s32 (*set_open_func)(struct disp_device *lcd, LCD_FUNC func,
                 u32 delay);
    s32 (*set_close_func)(struct disp_device *lcd, LCD_FUNC func,
                  u32 delay);
    int (*gpio_set_value)(struct disp_device *dispdev,
                  unsigned int io_index, u32 value);
    int (*gpio_set_direction)(struct disp_device *dispdev,
                  unsigned int io_index, u32 direction);
    int (*get_panel_info)(struct disp_device *dispdev,
                   struct disp_panel_para *info);
};

/* manager */
struct disp_manager {
    /* data fields */
    char name[32];
    u32 disp;
    u32 num_chns;
    u32 num_layers;
    struct disp_device *device;
    struct disp_smbl *smbl;
    struct disp_enhance *enhance;
    struct disp_capture *cptr;

    struct list_head lyr_list;

#ifdef SUPPORT_WB
    wait_queue_head_t write_back_queue;
    u32 write_back_finish;
#endif

    /* function fields */
    s32 (*enable)(struct disp_manager *mgr);
    s32 (*sw_enable)(struct disp_manager *mgr);
    s32 (*disable)(struct disp_manager *mgr);
    s32 (*is_enabled)(struct disp_manager *mgr);
    s32 (*blank)(struct disp_manager *mgr, bool blank);

    /* init: clock init && reg init && register irq
     * exit: clock exit && unregister irq
     */
    s32 (*init)(struct disp_manager *mgr);
    s32 (*exit)(struct disp_manager *mgr);

    s32 (*set_back_color)(struct disp_manager *mgr,
                  struct disp_color *bk_color);
    s32 (*get_back_color)(struct disp_manager *mgr,
                  struct disp_color *bk_color);
    s32 (*set_color_key)(struct disp_manager *mgr,
                 struct disp_colorkey *ck);
    s32 (*get_color_key)(struct disp_manager *mgr,
                 struct disp_colorkey *ck);

    s32 (*get_screen_size)(struct disp_manager *mgr, u32 *width,
                u32 *height);
    s32 (*set_screen_size)(struct disp_manager *mgr, u32 width,
                u32 height);
    s32 (*get_clk_rate)(struct disp_manager *mgr);

    /* layer mamage */
    s32 (*check_layer_zorder)(struct disp_manager *mgr,
                  struct disp_layer_config *config,
                  u32 layer_num);
    s32 (*set_layer_config)(struct disp_manager *mgr,
                struct disp_layer_config *config,
                unsigned int layer_num);
    s32 (*get_layer_config)(struct disp_manager *mgr,
                struct disp_layer_config *config,
                unsigned int layer_num);
    s32 (*set_layer_config2)(struct disp_manager *mgr,
                 struct disp_layer_config2 *config,
                 unsigned int layer_num);
    s32 (*get_layer_config2)(struct disp_manager *mgr,
                 struct disp_layer_config2 *config,
                 unsigned int layer_num);
    s32 (*extend_layer_config)(struct disp_manager *mgr,
                   struct disp_layer_config *info,
                   unsigned int layer_num);
    s32 (*set_output_color_range)(struct disp_manager *mgr,
                      u32 color_range);
    s32 (*get_output_color_range)(struct disp_manager *mgr);
    s32 (*update_color_space)(struct disp_manager *mgr);

    s32 (*apply)(struct disp_manager *mgr);
    s32 (*force_apply)(struct disp_manager *mgr);
    s32 (*update_regs)(struct disp_manager *mgr);
    s32 (*sync)(struct disp_manager *mgr, bool sync);
    s32 (*tasklet)(struct disp_manager *mgr);

    /* debug interface, dump manager info */
    s32 (*dump)(struct disp_manager *mgr, char *buf);
};

struct disp_layer {
    /* data fields */
    char name[32];
    u32 disp;
    u32 chn;
    u32 id;

    /* enum disp_layer_feat caps; */
    struct disp_manager *manager;
    struct list_head list;
    void *data;

    /* function fileds */
    s32 (*is_support_format)(struct disp_layer *layer,
                  enum disp_pixel_format fmt);
    s32 (*set_manager)(struct disp_layer *layer,
                struct disp_manager *mgr);
    s32 (*unset_manager)(struct disp_layer *layer);
    s32 (*check)(struct disp_layer *layer,
              struct disp_layer_config *config);
    s32 (*check2)(struct disp_layer *layer,
              struct disp_layer_config2 *config);
    s32 (*save_and_dirty_check)(struct disp_layer *layer,
                     struct disp_layer_config *config);
    s32 (*save_and_dirty_check2)(struct disp_layer *layer,
                     struct disp_layer_config2 *config);
    s32 (*get_config)(struct disp_layer *layer,
               struct disp_layer_config *config);
    s32 (*get_config2)(struct disp_layer *layer,
               struct disp_layer_config2 *config);
    s32 (*apply)(struct disp_layer *layer);
    s32 (*force_apply)(struct disp_layer *layer);
    s32 (*is_dirty)(struct disp_layer *layer);
    s32 (*dirty_clear)(struct disp_layer *layer);
    /* init: NULL
     * exit: NULL
     */
    s32 (*init)(struct disp_layer *layer);
    s32 (*exit)(struct disp_layer *layer);
    s32 (*get_frame_id)(struct disp_layer *layer);
    s32 (*dump)(struct disp_layer *layer, char *buf);
};

struct disp_smbl {
    /* static fields */
    char *name;
    u32 disp;
    u32 backlight;
    struct disp_manager *manager;

    /*
     * The following functions do not block:
     *
     * is_enabled
     * set_layer_info
     * get_layer_info
     *
     * The rest of the functions may block and cannot be called from
     * interrupt context
     */

    s32 (*enable)(struct disp_smbl *smbl);
    s32 (*disable)(struct disp_smbl *smbl);
    bool (*is_enabled)(struct disp_smbl *smbl);
    s32 (*set_manager)(struct disp_smbl *smbl, struct disp_manager *mgr);
    s32 (*unset_manager)(struct disp_smbl *smbl);
    s32 (*update_backlight)(struct disp_smbl *smbl, unsigned int bl);

    /* init: NULL
     * exit: NULL
     */
    s32 (*init)(struct disp_smbl *smbl);
    s32 (*exit)(struct disp_smbl *smbl);

    s32 (*apply)(struct disp_smbl *smbl);
    s32 (*update_regs)(struct disp_smbl *smbl);
    s32 (*force_apply)(struct disp_smbl *smbl);
    s32 (*sync)(struct disp_smbl *smbl);
    s32 (*tasklet)(struct disp_smbl *smbl);

    s32 (*set_window)(struct disp_smbl *smbl, struct disp_rect *window);
    s32 (*get_window)(struct disp_smbl *smbl, struct disp_rect *window);
    s32 (*dump)(struct disp_smbl *smbl, char *buf);
};

struct disp_enhance {
    /* static fields */
    char *name;
    u32 disp;
    struct disp_manager *manager;

    /*
     * The following functions do not block:
     *
     * is_enabled
     * set_layer_info
     * get_layer_info
     *
     * The rest of the functions may block and cannot be called from
     * interrupt context
     */

    s32 (*enable)(struct disp_enhance *enhance);
    s32 (*disable)(struct disp_enhance *enhance);
    bool (*is_enabled)(struct disp_enhance *enhance);
    s32 (*set_manager)(struct disp_enhance *enhance,
                struct disp_manager *mgr);
    s32 (*unset_manager)(struct disp_enhance *enhance);

    /* init: NULL
     * exit: NULL
     */
    s32 (*init)(struct disp_enhance *enhance);
    s32 (*exit)(struct disp_enhance *enhance);

    s32 (*apply)(struct disp_enhance *enhance);
    s32 (*update_regs)(struct disp_enhance *enhance);
    s32 (*force_apply)(struct disp_enhance *enhance);
    s32 (*sync)(struct disp_enhance *enhance);
    s32 (*tasklet)(struct disp_enhance *enhance);

    /* power manager */
    s32 (*early_suspend)(struct disp_enhance *enhance);
    s32 (*late_resume)(struct disp_enhance *enhance);
    s32 (*suspend)(struct disp_enhance *enhance);
    s32 (*resume)(struct disp_enhance *enhance);

    s32 (*set_bright)(struct disp_enhance *enhance, u32 val);
    s32 (*set_saturation)(struct disp_enhance *enhance, u32 val);
    s32 (*set_contrast)(struct disp_enhance *enhance, u32 val);
    s32 (*set_hue)(struct disp_enhance *enhance, u32 val);
    s32 (*set_edge)(struct disp_enhance *enhance, u32 val);
    s32 (*set_detail)(struct disp_enhance *enhance, u32 val);
    s32 (*set_denoise)(struct disp_enhance *enhance, u32 val);
    s32 (*set_mode)(struct disp_enhance *enhance, u32 val);
    s32 (*set_window)(struct disp_enhance *enhance,
              struct disp_rect *window);
    s32 (*get_bright)(struct disp_enhance *enhance);
    s32 (*get_saturation)(struct disp_enhance *enhance);
    s32 (*get_contrast)(struct disp_enhance *enhance);
    s32 (*get_hue)(struct disp_enhance *enhance);
    s32 (*get_edge)(struct disp_enhance *enhance);
    s32 (*get_detail)(struct disp_enhance *enhance);
    s32 (*get_denoise)(struct disp_enhance *enhance);
    s32 (*get_mode)(struct disp_enhance *enhance);
    s32 (*get_window)(struct disp_enhance *enhance,
              struct disp_rect *window);
    s32 (*set_para)(struct disp_enhance *enhance,
            struct disp_enhance_para *para);
    s32 (*demo_enable)(struct disp_enhance *enhance);
    s32 (*demo_disable)(struct disp_enhance *enhance);
    s32 (*dump)(struct disp_enhance *enhance, char *buf);
};

struct disp_capture {
    char *name;
    u32 disp;
    struct disp_manager *manager;

    s32 (*set_manager)(struct disp_capture *cptr,
                struct disp_manager *mgr);
    s32 (*unset_manager)(struct disp_capture *cptr);
    s32 (*start)(struct disp_capture *cptr);
    s32 (*commmit)(struct disp_capture *cptr,
            struct disp_capture_info *info);
    s32 (*commmit2)(struct disp_capture *cptr,
            struct disp_capture_info2 *info);
    s32 (*stop)(struct disp_capture *cptr);
    s32 (*sync)(struct disp_capture *cptr);
    s32 (*tasklet)(struct disp_capture *cptr);
    s32 (*init)(struct disp_capture *cptr);
    s32 (*exit)(struct disp_capture *cptr);
    /* 0: finish, other: fail/err */
    s32 (*query)(struct disp_capture *cptr);

    /* debug interface, dump capture info */
    s32 (*dump)(struct disp_capture *cptr, char *buf);
    /* inner interface */
    s32 (*apply)(struct disp_capture *cptr);
};

struct ee_img {
    unsigned long addr;
    unsigned int pitch;
    unsigned int w;     /* image width */
    unsigned int h;     /* image height */
};

struct rect_size {
    u32 width;
    u32 height;
    u32 align;
};

struct area_info {
    unsigned int x_top;
    unsigned int y_top;
    unsigned int x_bottom;
    unsigned int y_bottom;
};

struct eink_timing_param {
    unsigned int lbl;   /*  */
    unsigned int lel;   /*  */
    unsigned int lsl;
    unsigned int fbl;   /*  */
    unsigned int fel;   /*  */
    unsigned int fsl;   /*  */
    unsigned int width; /* image width */
    unsigned int height;    /* image height */
};

enum eink_flash_mode {
    LOCAL,
    GLOBAL,
    INIT
};

enum buf_use_state {
    FREE,
    USED
};

enum eink_update_mode {
    /* GLOBAL */
    EINK_INIT_MODE = 0x01,
    EINK_DU_MODE = 0x02,
    EINK_GC16_MODE = 0x04,
    EINK_A2_MODE = 0x10,
    EINK_GC16_LOCAL_MODE = 0x84,

    /* LOCAL */
    EINK_DU_RECT_MODE = 0x402,
    EINK_GC16_RECT_MODE = 0x404,
    EINK_A2_RECT_MODE = 0x410,
    EINK_GC16_LOCAL_RECT_MODE = 0x484,
};

struct eink_8bpp_image {
    enum eink_update_mode update_mode;
    enum eink_flash_mode flash_mode;
    enum buf_use_state state;
    void *vaddr;
    void *paddr;
    bool window_calc_enable;
    struct rect_size size;
    struct area_info update_area;
};

struct eink_init_param {
    bool used;
    u8 eink_moudule_type;
    u8 eink_version_type;
    u8 eink_ctrl_data_type;
    u8 eink_bits;       /*0->3bits,1->4bits,2->5bits */
    u8 eink_mode;       /*0->8data,1->16data */
    struct eink_timing_param timing;
    char wavefile_path[32];
};

enum eink_bit_num {
    EINK_BIT_1 = 0x01,
    EINK_BIT_2 = 0x02,
    EINK_BIT_3 = 0x03,
    EINK_BIT_4 = 0x04,
    EINK_BIT_5 = 0x05
};

/* #define EINK_FLUSH_TIME_TEST */

struct disp_eink_manager {
    unsigned int disp;
    unsigned int test;
    int tcon_flag;
    int eink_panel_temperature;

    unsigned int flush_continue_flag;
    struct tasklet_struct sync_tasklet;
    struct tasklet_struct decode_tasklet;
    wait_queue_head_t decode_taske_queue;
    struct work_struct decode_work;
    struct eink_private *private_data;
    struct disp_manager *mgr;
    struct eink_buffer_manager *buffer_mgr;
    struct pipeline_manager *pipeline_mgr;
    struct format_manager *convert_mgr;
    struct task_struct *detect_fresh_task;
    struct task_struct *debug_task;
    struct mutex standby_lock;
    int (*eink_update)(struct disp_eink_manager *manager,
                struct disp_layer_config_inner *config,
                unsigned int layer_num,
                enum eink_update_mode mode,
                struct area_info update_area);
    int (*enable)(struct disp_eink_manager *);
    int (*disable)(struct disp_eink_manager *);
    int (*op_skip)(struct disp_eink_manager *manager, u32 skip);
    int (*suspend)(struct disp_eink_manager *);
    int (*resume)(struct disp_eink_manager *);
    void (*clearwd)(struct disp_eink_manager *, int);
    /*for debug */
    int (*decode)(struct disp_eink_manager *, int);
    int (*set_temperature)(struct disp_eink_manager *manager,
                unsigned int temp);
    unsigned int (*get_temperature)(struct disp_eink_manager *manager);
};

struct image_format {
    enum disp_pixel_format format;
    unsigned int width;
    unsigned int height;
    unsigned long addr1;
    unsigned long addr2;
    unsigned long addr3;
};

struct format_manager {
    unsigned int disp;
    unsigned int irq_num;
    unsigned int write_back_finish;
    wait_queue_head_t write_back_queue;
    struct clk *clk;
    int (*enable)(unsigned int id);
    int (*disable)(unsigned int id);
    int (*start_convert)(unsigned int id,
                  struct disp_layer_config_inner *config,
                  unsigned int layer_num,
                  struct image_format *dest);
};

#endif

/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/drv_hdmi.c

/*
 * Allwinner SoCs hdmi driver.
 *
 * Copyright (C) 2016 Allwinner.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include "drv_hdmi_i.h"
#include "hdmi_core.h"
#include "../disp/disp_sys_intf.h"
#include "../disp/dev_disp.h"
#include <linux/regulator/consumer.h>
#include <linux/clk-provider.h>
#include <linux/clk/sunxi.h>
#include <linux/sunxi-clk-prepare.h>
#if defined(CONFIG_EXTCON)
#include <linux/extcon.h>
#endif
#include <linux/sunxi-sid.h>

static u32 io_enable_count;

static struct semaphore *run_sem;
static struct task_struct *HDMI_task;
static struct task_struct *cec_task;
static bool hdmi_cec_support;
static char hdmi_power[25];
static char hdmi_io_regulator[25];
static int hdmi_io_regulator_val;
static bool hdmi_power_used;
static bool hdmi_io_regulator_used;
static bool hdmi_used;
static bool boot_hdmi;
#if defined(CONFIG_COMMON_CLK)
static struct clk *hdmi_clk;
static struct clk *hdmi_ddc_clk;
static struct clk *hdmi_clk_parent;
#if defined(CONFIG_ARCH_SUN8IW12)
static struct clk *hdmi_cec_clk;
#endif
#endif
static u32 power_enable_count;
static u32 io_regulator_enable_count;
static u32 clk_enable_count;
static struct mutex mlock;
#if defined(CONFIG_SND_SUNXI_SOC_SUNXI_HDMIAUDIO)
static bool audio_enable;
#endif
static bool b_hdmi_suspend;
static bool b_hdmi_suspend_pre;

static struct cdev *my_cdev;
static dev_t devid;
static struct class *hdmi_class;
hdmi_info_t ghdmi;

void hdmi_delay_ms(unsigned long ms)
{
    u32 timeout = ms*HZ/1000;

    set_current_state(TASK_INTERRUPTIBLE);
    schedule_timeout(timeout);
}

void hdmi_delay_us(unsigned long us)
{
    udelay(us);
}

unsigned int hdmi_get_soc_version(void)
{
    unsigned int version = 0;
#if defined(CONFIG_ARCH_SUN8IW7)
#if defined(SUN8IW7P1_REV_A) || defined(SUN8IW7P2_REV_B)
    unsigned int chip_ver = sunxi_get_soc_ver();

    switch (chip_ver) {
    case SUN8IW7P1_REV_A:
    case SUN8IW7P2_REV_A:
        version = 0;
        break;
    case SUN8IW7P1_REV_B:
    case SUN8IW7P2_REV_B:
        version = 1;
    }
#else
    version = 1;
#endif /*endif  SUN8IW7P1_REV_A*/
#endif
    return version;
}

static int hdmi_parse_io_config(void)
{
    disp_sys_pin_set_state("hdmi", DISP_PIN_STATE_ACTIVE);
    return 0;
}

static int hdmi_io_config(u32 bon)
{
    return disp_sys_pin_set_state(
        "hdmi", (bon == 1) ? DISP_PIN_STATE_ACTIVE : DISP_PIN_STATE_SLEEP);
}

#if defined(CONFIG_COMMON_CLK)
static int hdmi_clk_enable(void)
{
    int ret = 0;

    if (hdmi_clk)
        ret = clk_prepare_enable(hdmi_clk);
    if (ret != 0)
        return ret;

    if (hdmi_ddc_clk)
        ret = clk_prepare_enable(hdmi_ddc_clk);

#if defined(CONFIG_ARCH_SUN8IW12)
    if (hdmi_cec_clk)
        ret = clk_prepare_enable(hdmi_cec_clk);
#endif /*endif CONFIG_ARCH_SUN8IW12 */

    if (ret != 0)
        clk_disable(hdmi_clk);

    return ret;
}

static int hdmi_clk_disable(void)
{
    if (hdmi_clk)
        clk_disable(hdmi_clk);
    if (hdmi_ddc_clk)
        clk_disable(hdmi_ddc_clk);

#if defined(CONFIG_ARCH_SUN8IW12)
    if (hdmi_cec_clk)
        clk_disable(hdmi_cec_clk);
#endif /*endif CONFIG_ARCH_SUN8IW12 */

    return 0;
}

static int hdmi_clk_config(u32 vic)
{
    int index = 0;

    index = hdmi_core_get_video_info(vic);

    if (hdmi_clk) {
        clk_set_rate(hdmi_clk, video_timing[index].pixel_clk);
        pr_info("pixel_clk:%d\n", video_timing[index].pixel_clk);
    }

    return 0;
}
#else
static int hdmi_clk_enable(void){}
static int hdmi_clk_disable(void){}
static int hdmi_clk_config(u32 vic) {}
#endif

/* hdmi_clk_enable_prepare - prepare for hdmi enable
 * if there is some other clk will affect hdmi module,
 * should enable these clk before enable hdmi
 */
int hdmi_clk_enable_prepare(void)
{
    int ret = 0;

    pr_warn("%s()L%d\n", __func__, __LINE__);
    if (hdmi_clk)
        ret = sunxi_clk_enable_prepare(hdmi_clk);
    if (ret != 0)
        return ret;

    return ret;
}

/* hdmi_clk_disable_prepare - prepare for hdmi disable
 * if there is some other clk will affect hdmi module,
 * should disable these clk after disable hdmi
 */
int hdmi_clk_disable_prepare(void)
{
    pr_warn("%s()L%d\n", __func__, __LINE__);
    if (hdmi_clk)
        sunxi_clk_disable_prepare(hdmi_clk);

    return 0;
}

unsigned int hdmi_clk_get_div(void)
{
    unsigned long rate = 1, rate_parent = 1;
    unsigned int div = 4;

    if (!hdmi_clk || !hdmi_clk_parent) {
        pr_warn("%s, get clk div fail\n", __func__);
        goto exit;
    }

    if (hdmi_clk)
        rate = clk_get_rate(hdmi_clk);
    if (hdmi_clk_parent)
        rate_parent = clk_get_rate(hdmi_clk_parent);

    if (rate != 0)
        div = rate_parent / rate;
    else
        pr_warn("%s, hdmi clk rate is ZERO!\n", __func__);

exit:
    return div;
}

#ifdef CONFIG_AW_AXP
static int hdmi_set_io_regulator_val(char *name, int value)
{
    struct regulator *regu = NULL;
    int ret = -1;

    regu = regulator_get(NULL, name);
    if (IS_ERR(regu)) {
        pr_err("%s: some error happen, fail to get regulator %s\n",
                __func__, name);
        goto exit;
    }

    ret = regulator_set_voltage(regu, value * 1000, value * 1000);
    if (ret != 0) {
        pr_err("%s: some error happen, fail to enable regulator %s!\n",
                __func__, name);
        goto exit1;
    } else {
        hdmi_inf("suceess to enable regulator %s!\n", name);
    }

exit1:
    /* put regulater, when module exit */
    regulator_put(regu);
exit:
    return ret;
}

static int hdmi_power_enable(char *name)
{
    struct regulator *regu = NULL;
    int ret = -1;

    regu = regulator_get(NULL, name);
    if (IS_ERR(regu)) {
        pr_err("%s: some error happen, fail to get regulator %s\n",
                __func__, name);
        goto exit;
    }

    /* enalbe regulator */
    ret = regulator_enable(regu);
    if (ret != 0) {
        pr_err("%s: some error happen, fail to enable regulator %s!\n",
                __func__, name);
        goto exit1;
    } else {
        hdmi_inf("suceess to enable regulator %s!\n", name);
    }

exit1:
    /* put regulater, when module exit */
    regulator_put(regu);
exit:
    return ret;
}

static int hdmi_power_disable(char *name)
{
    struct regulator *regu = NULL;
    int ret = 0;

    regu = regulator_get(NULL, name);
    if (IS_ERR(regu)) {
        hdmi_wrn("%s: some error happen, fail to get regulator %s\n",
                __func__, name);
        goto exit;
    }

    /* disalbe regulator */
    ret = regulator_disable(regu);
    if (ret != 0) {
        hdmi_wrn(
            "%s: some error happen, fail to disable regulator %s!\n",
            __func__, name);
        goto exit1;
    } else {
        hdmi_inf("suceess to disable regulator %s!\n", name);
    }

exit1:
    /* put regulater, when module exit */
    regulator_put(regu);
exit:
    return ret;
}
#else
static int hdmi_set_io_regulator_val(char *name, int value) {return 0; }
static int hdmi_power_enable(char *name) {return 0; }
static int hdmi_power_disable(char *name) {return 0; }
#endif

static s32 hdmi_enable(void)
{
    hdmi_inf("[hdmi_enable]\n");

    mutex_lock(&mlock);
    if (ghdmi.bopen != 1) {
        hdmi_clk_config(ghdmi.mode);
        hdmi_core_set_video_enable(1);
        ghdmi.bopen = 1;
    }
    mutex_unlock(&mlock);
    return 0;
}

static s32 hdmi_disable(void)
{
    hdmi_inf("[hdmi_disable]\n");

    mutex_lock(&mlock);
    if (ghdmi.bopen != 0) {
        hdmi_core_set_video_enable(0);
        ghdmi.bopen = 0;
    }
    mutex_unlock(&mlock);
    return 0;
}

static struct disp_hdmi_mode hdmi_mode_tbl[] = {
    {DISP_TV_MOD_480I,                HDMI1440_480I,     },
    {DISP_TV_MOD_576I,                HDMI1440_576I,     },
    {DISP_TV_MOD_480P,                HDMI480P,          },
    {DISP_TV_MOD_576P,                HDMI576P,          },
    {DISP_TV_MOD_720P_50HZ,           HDMI720P_50,       },
    {DISP_TV_MOD_720P_60HZ,           HDMI720P_60,       },
    {DISP_TV_MOD_1080I_50HZ,          HDMI1080I_50,      },
    {DISP_TV_MOD_1080I_60HZ,          HDMI1080I_60,      },
    {DISP_TV_MOD_1080P_24HZ,          HDMI1080P_24,      },
    {DISP_TV_MOD_1080P_50HZ,          HDMI1080P_50,      },
    {DISP_TV_MOD_1080P_60HZ,          HDMI1080P_60,      },
    {DISP_TV_MOD_1080P_25HZ,          HDMI1080P_25,      },
    {DISP_TV_MOD_1080P_30HZ,          HDMI1080P_30,      },
    {DISP_TV_MOD_1080P_24HZ_3D_FP,    HDMI1080P_24_3D_FP,},
    {DISP_TV_MOD_720P_50HZ_3D_FP,     HDMI720P_50_3D_FP, },
    {DISP_TV_MOD_720P_60HZ_3D_FP,     HDMI720P_60_3D_FP, },
    {DISP_TV_MOD_3840_2160P_30HZ,     HDMI3840_2160P_30, },
    {DISP_TV_MOD_3840_2160P_25HZ,     HDMI3840_2160P_25, },
    {DISP_TV_MOD_3840_2160P_24HZ,     HDMI3840_2160P_24, },
    {DISP_TV_MOD_4096_2160P_24HZ,     HDMI4096_2160P_24, },
    {DISP_TV_MOD_1024_600P,           HDMI1024_600,      },
    {DISP_TV_MOD_1280_800P,           HDMI1280_800,      },
    {DISP_TV_MOD_800_480P,            HDMI800_480P,      },
};

static u32 hdmi_get_vic(u32 mode)
{
    u32 hdmi_mode = DISP_TV_MOD_720P_50HZ;
    u32 i;
    bool find = false;

    for (i = 0; i < sizeof(hdmi_mode_tbl)/sizeof(struct disp_hdmi_mode);
            i++) {
        if (hdmi_mode_tbl[i].mode == mode) {
            hdmi_mode = hdmi_mode_tbl[i].hdmi_mode;
            find = true;
            break;
        }
    }

    if (false == find)
        pr_warn("[HDMI]can't find vic for mode(%d)\n", mode);

    return hdmi_mode;
}

static s32 hdmi_set_display_mode(u32 mode)
{
    u32 hdmi_mode;
    u32 i;
    bool find = false;

    hdmi_inf("[hdmi_set_display_mode],mode:%d\n", mode);

    for (i = 0; i < sizeof(hdmi_mode_tbl)/sizeof(struct disp_hdmi_mode);
            i++) {
        if (hdmi_mode_tbl[i].mode == (enum disp_tv_mode)mode) {
            hdmi_mode = hdmi_mode_tbl[i].hdmi_mode;
            find = true;
            break;
        }
    }

    if (find) {
        ghdmi.mode = hdmi_mode;
        return hdmi_core_set_video_mode(hdmi_mode);
    }
    hdmi_wrn("unsupported video mode %d when set display mode\n", mode);
    return -1;

}

#if defined(CONFIG_SND_SUNXI_SOC_SUNXI_HDMIAUDIO)
static s32 hdmi_audio_enable(u8 mode, u8 channel)
{
    hdmi_inf("[hdmi_audio_enable],mode:%d,ch:%d\n", mode, channel);
    mutex_lock(&mlock);
    audio_enable = mode;
    mutex_unlock(&mlock);
    return hdmi_core_set_audio_enable(audio_enable);
}

static s32 hdmi_set_audio_para(hdmi_audio_t *audio_para)
{
    hdmi_inf("[hdmi_set_audio_para]\n");
    return hdmi_core_audio_config(audio_para);
}
#endif

static s32 hdmi_mode_support(u32 mode)
{
    u32 hdmi_mode;
    u32 i;
    bool find = false;

    for (i = 0; i < sizeof(hdmi_mode_tbl)/sizeof(struct disp_hdmi_mode);
            i++) {
        if (hdmi_mode_tbl[i].mode == (enum disp_tv_mode)mode) {
            hdmi_mode = hdmi_mode_tbl[i].hdmi_mode;
            find = true;
            break;
        }
    }

    if (find)
        return hdmi_core_mode_support(hdmi_mode);
    else
        return 0;
}

static s32 hdmi_get_HPD_status(void)
{
    return hdmi_core_hpd_check();
}

static s32 hdmi_get_hdcp_enable(void)
{
    return hdmi_core_get_hdcp_enable();
}

static s32 hdmi_get_video_timming_info(struct disp_video_timings **video_info)
{
    struct disp_video_timings *info;
    int ret = -1;
    int i, list_num;

    info = video_timing;
    list_num = hdmi_core_get_list_num();
    for (i = 0; i < list_num; i++) {
        if (info->vic == ghdmi.mode) {
            *video_info = info;
            ret = 0;
            break;
        }
        info++;
    }
    return ret;
}

static s32 hdmi_get_input_csc(void)
{
    return hdmi_core_get_csc_type();
}

static int hdmi_run_thread(void *parg)
{
    while (1) {
        if (kthread_should_stop())
            break;

        mutex_lock(&mlock);
        if (false == b_hdmi_suspend) {
            /* normal state */
            b_hdmi_suspend_pre = b_hdmi_suspend;
            mutex_unlock(&mlock);
            hdmi_core_loop();

            if (false == b_hdmi_suspend) {
                if (hdmi_get_hdcp_enable() == 1)
                    hdmi_delay_ms(100);
                else
                    hdmi_delay_ms(200);
            }
        } else {
            /* suspend state */
            if (false == b_hdmi_suspend_pre) {
                /* first time after enter suspend state */
                /* hdmi_core_enter_lp(); */
            }
            b_hdmi_suspend_pre = b_hdmi_suspend;
            mutex_unlock(&mlock);
        }
    }

    return 0;
}

void cec_msg_sent(char *buf)
{
    char *envp[2];

    envp[0] = buf;
    envp[1] = NULL;
    kobject_uevent_env(&ghdmi.dev->kobj, KOBJ_CHANGE, envp);
}

#define CEC_BUF_SIZE 32
static int cec_thread(void *parg)
{
    int ret = 0;
    char buf[CEC_BUF_SIZE];
    unsigned char msg;

    while (1) {
        if (kthread_should_stop())
            break;

        mutex_lock(&mlock);
        ret = -1;
        if (false == b_hdmi_suspend)
            ret = hdmi_core_cec_get_simple_msg(&msg);
        mutex_unlock(&mlock);
        if (ret == 0) {
            memset(buf, 0, CEC_BUF_SIZE);
            snprintf(buf, sizeof(buf), "CEC_MSG=0x%x", msg);
            cec_msg_sent(buf);
        }
        hdmi_delay_ms(10);
    }

    return 0;
}

#if defined(CONFIG_EXTCON)
static const unsigned int hdmi_cable[] = {
    EXTCON_DISP_HDMI,
    EXTCON_NONE,
};
static struct extcon_dev extcon_hdmi = {
    .name = "hdmi",
};

/* s32 disp_set_hdmi_detect(bool hpd); */
static void hdmi_report_hpd_work(struct work_struct *work)
{
    if (hdmi_get_HPD_status()) {
        extcon_set_state(&extcon_hdmi, STATUE_OPEN);
        disp_set_hdmi_detect(1);
        hdmi_inf("switch_set_state 1\n");
    } else {
        extcon_set_state(&extcon_hdmi, STATUE_CLOSE);
        disp_set_hdmi_detect(0);
        hdmi_inf("switch_set_state 0\n");
    }
}

s32 hdmi_hpd_state(u32 state)
{
    if (state == 0)
        extcon_set_state(&extcon_hdmi, STATUE_CLOSE);
    else
        extcon_set_state(&extcon_hdmi, STATUE_OPEN);

    return 0;
}
#else
static void hdmi_report_hpd_work(struct work_struct *work)
{
}

s32 hdmi_hpd_state(u32 state)
{
    return 0;
}
#endif
/**
 * hdmi_hpd_report - report hdmi hot plug state to user space
 * @hotplug:    0: hdmi plug out;   1:hdmi plug in
 *
 * always return success.
 */
s32 hdmi_hpd_event(void)
{
    schedule_work(&ghdmi.hpd_work);
    return 0;
}

static s32 hdmi_suspend(void)
{
    hdmi_core_update_detect_time(0);
    if (hdmi_used && (false == b_hdmi_suspend)) {
        if (HDMI_task) {
            kthread_stop(HDMI_task);
            HDMI_task = NULL;
        }
        if (hdmi_cec_support && cec_task) {
            kthread_stop(cec_task);
            cec_task = NULL;
        }
        mutex_lock(&mlock);
        b_hdmi_suspend = true;
        hdmi_core_enter_lp();
        if (clk_enable_count != 0) {
            hdmi_clk_disable();
            clk_enable_count--;
        }
        if (io_enable_count != 0) {
            hdmi_io_config(0);
            io_enable_count--;
        }
        if ((hdmi_power_used) && (power_enable_count != 0)) {
            hdmi_power_disable(hdmi_power);
            power_enable_count--;
        }
        if (hdmi_io_regulator_used && io_regulator_enable_count) {
            hdmi_power_disable(hdmi_io_regulator);
            --io_regulator_enable_count;
        }
        mutex_unlock(&mlock);
        pr_info("[HDMI]hdmi suspend\n");
    }

    return 0;
}

static s32 hdmi_resume(void)
{
    int ret;

    mutex_lock(&mlock);
    if (hdmi_used && (true == b_hdmi_suspend)) {
        /* normal state */
        if (clk_enable_count == 0) {
            ret = hdmi_clk_enable();
            if (ret == 0)
                clk_enable_count++;
            else {
                pr_warn("fail to enable hdmi's clock\n");
                goto exit;
            }
        }
        if (hdmi_io_regulator_used && !io_regulator_enable_count) {
            hdmi_set_io_regulator_val(hdmi_io_regulator,
                        hdmi_io_regulator_val);
            hdmi_power_enable(hdmi_io_regulator);
            ++io_regulator_enable_count;
        }
        if ((hdmi_power_used) && (power_enable_count == 0)) {
            hdmi_power_enable(hdmi_power);
            power_enable_count++;
        }
        if (io_enable_count == 0) {
            hdmi_io_config(1);
            io_enable_count++;
        }
        /* first time after exit suspend state */
        hdmi_core_exit_lp();

        HDMI_task = kthread_create(hdmi_run_thread,
                (void *)0, "hdmi proc");
        if (IS_ERR(HDMI_task)) {
            s32 err = 0;

            pr_warn("Unable to start kernel thread %s.\n\n",
                "hdmi proc");
            err = PTR_ERR(HDMI_task);
            HDMI_task = NULL;
        } else
            wake_up_process(HDMI_task);

        if (hdmi_cec_support) {
            cec_task = kthread_create(cec_thread, (void *)0,
                "cec proc");
            if (IS_ERR(cec_task)) {
                s32 err = 0;

                pr_warn("Unable to start kernel thread %s.\n\n",
                    "cec proc");
                err = PTR_ERR(cec_task);
                cec_task = NULL;
            } else
                wake_up_process(cec_task);
        }

        pr_info("[HDMI]hdmi resume\n");
    }

exit:
    mutex_unlock(&mlock);

    hdmi_core_update_detect_time(200);/* 200ms */
    b_hdmi_suspend = false;

    return  0;
}

#if defined(CONFIG_SND_SUNXI_SOC_SUNXI_HDMIAUDIO)
extern void audio_set_hdmi_func(__audio_hdmi_func *hdmi_func);
#endif
/* extern s32 disp_set_hdmi_func(struct disp_device_func *func); */
/* extern unsigned int disp_boot_para_parse(const char *name); */

s32 hdmi_init(struct platform_device *pdev)
{
#if defined(CONFIG_SND_SUNXI_SOC_SUNXI_HDMIAUDIO)
    __audio_hdmi_func audio_func;
#if defined(CONFIG_SND_SUNXI_SOC_AUDIOHUB_INTERFACE)
    __audio_hdmi_func audio_func_muti;
#endif
#endif
    unsigned int value, output_type0, output_mode0;
    unsigned int output_type1, output_mode1;
    struct disp_device_func disp_func;
    int ret = 0;
    uintptr_t reg_base;

    hdmi_used = 0;
    b_hdmi_suspend_pre = b_hdmi_suspend = false;
    hdmi_power_used = 0;
    hdmi_used = 1;

    /*  parse boot para */
    value = disp_boot_para_parse("boot_disp");
    output_type0 = (value >> 8) & 0xff;
    output_mode0 = (value) & 0xff;

    output_type1 = (value >> 24) & 0xff;
    output_mode1 = (value >> 16) & 0xff;
    if ((output_type0 == DISP_OUTPUT_TYPE_HDMI) ||
        (output_type1 == DISP_OUTPUT_TYPE_HDMI)) {
        boot_hdmi = true;
        ghdmi.bopen = 1;
        ghdmi.mode = (output_type0 ==
            DISP_OUTPUT_TYPE_HDMI) ? output_mode0:output_mode1;
        ghdmi.mode = hdmi_get_vic(ghdmi.mode);
    }
    /* iomap */
    reg_base = (uintptr_t __force)of_iomap(pdev->dev.of_node, 0);
    if (reg_base == 0) {
        dev_err(&pdev->dev, "unable to map hdmi registers\n");
        ret = -EINVAL;
        goto err_iomap;
    }
    hdmi_core_set_base_addr(reg_base);

    /* get clk */
    hdmi_clk = of_clk_get(pdev->dev.of_node, 0);
    if (IS_ERR(hdmi_clk)) {
        dev_err(&pdev->dev, "fail to get clk for hdmi\n");
        goto err_clk_get;
    }

    hdmi_clk_parent = clk_get_parent(hdmi_clk);
    if (IS_ERR(hdmi_clk_parent)) {
        dev_err(&pdev->dev, "fail to get clk parent for hdmi\n");
        goto err_power;
    }

    clk_enable_count = __clk_get_enable_count(hdmi_clk);
    hdmi_ddc_clk = of_clk_get(pdev->dev.of_node, 1);
    if (IS_ERR(hdmi_ddc_clk)) {
        dev_err(&pdev->dev, "fail to get clk for hdmi ddc\n");
        goto err_power;
    }

#if defined(CONFIG_ARCH_SUN8IW12)
    hdmi_cec_clk = of_clk_get(pdev->dev.of_node, 2);
    if (IS_ERR_OR_NULL(hdmi_cec_clk)) {
        dev_err(&pdev->dev, "fail to get hdmi_cec_clk\n");
        goto err_power;
    }
#endif /*endif CONFIG_ARCH_SUN8IW12 */
    /* parse io config */
    hdmi_parse_io_config();
    mutex_init(&mlock);

    if (io_enable_count == 0) {
        hdmi_io_config(1);
        io_enable_count++;
    }
    mutex_lock(&mlock);
    if (clk_enable_count == 0) {
        hdmi_wrn("hdmi_clk_enable\n");
        ret = hdmi_clk_enable();
        clk_enable_count++;
    }
    mutex_unlock(&mlock);
    if (ret != 0) {
        clk_enable_count--;
        dev_err(&pdev->dev, "fail to enable hdmi clk\n");
        goto err_clk_enable;
    }

    INIT_WORK(&ghdmi.hpd_work, hdmi_report_hpd_work);

#if defined(CONFIG_EXTCON)
    extcon_hdmi.supported_cable = hdmi_cable;
    extcon_dev_register_attr(&extcon_hdmi, &pdev->dev);
#endif
    ret = disp_sys_script_get_item("hdmi", "hdmi_io_regulator",
                       (int *)hdmi_io_regulator, 2);
    if (ret == 2) {
        ret = disp_sys_script_get_item("hdmi", "hdmi_io_regulator_val",
                    &value, 1);
        if (ret == 1) {
            mutex_lock(&mlock);
            hdmi_io_regulator_val = value;
            hdmi_set_io_regulator_val(hdmi_io_regulator, value);
            mutex_unlock(&mlock);
        }

        mutex_lock(&mlock);
        ret = hdmi_power_enable(hdmi_io_regulator);
        mutex_unlock(&mlock);
        if (ret) {
            dev_err(&pdev->dev, "fail to enable hdmi io power %s\n",
                hdmi_io_regulator);
        } else {
            ++io_regulator_enable_count;
            hdmi_io_regulator_used = 1;
        }
    }

    ret = disp_sys_script_get_item("hdmi", "hdmi_power",
            (int *)hdmi_power, 2);
    if (ret == 2) {
        hdmi_power_used = 1;
        if (hdmi_power_used) {
            pr_info("[HDMI] power %s\n", hdmi_power);
            mutex_lock(&mlock);
            ret = hdmi_power_enable(hdmi_power);
            power_enable_count++;
            mutex_unlock(&mlock);
            if (ret != 0) {
                power_enable_count--;
                dev_err(&pdev->dev,
                "fail to enable hdmi power %s\n", hdmi_power);
                goto err_power;
            }
        }
    }

    ret = disp_sys_script_get_item("hdmi", "hdmi_cts_compatibility",
                    &value, 1);
    if (ret == 1)
        hdmi_core_set_cts_enable(value);
    ret = disp_sys_script_get_item("hdmi", "hdmi_hdcp_enable", &value, 1);
    if (ret == 1)
        hdmi_core_set_hdcp_enable(value);

    ret = disp_sys_script_get_item("hdmi", "hdmi_hpd_mask", &value, 1);
    if (ret == 1)
        hdmi_hpd_mask = value;

    ret = disp_sys_script_get_item("hdmi", "hdmi_cec_support", &value, 1);
    if ((ret == 1) && (value == 1))
        hdmi_cec_support = true;
    hdmi_core_cec_enable(hdmi_cec_support);
    pr_info("[HDMI] cec support = %d\n", hdmi_cec_support);

    hdmi_core_initial(boot_hdmi);

    run_sem = kmalloc(sizeof(struct semaphore), GFP_KERNEL | __GFP_ZERO);
    if (!run_sem) {
        dev_err(&pdev->dev, "fail to kmalloc memory for run_sem\n");
        goto err_sem;
    }
    sema_init((struct semaphore *)run_sem, 0);

    HDMI_task = kthread_create(hdmi_run_thread, (void *)0, "hdmi proc");
    if (IS_ERR(HDMI_task)) {
        s32 err = 0;

        dev_err(&pdev->dev, "Unable to start kernel thread %s.\n\n",
            "hdmi proc");
        err = PTR_ERR(HDMI_task);
        HDMI_task = NULL;
        goto err_thread;
    }
    wake_up_process(HDMI_task);

    if (hdmi_cec_support) {
        cec_task = kthread_create(cec_thread, (void *)0, "cec proc");
        if (IS_ERR(cec_task)) {
            s32 err = 0;

            dev_err(&pdev->dev,
                "Unable to start kernel thread %s.\n\n",
                "cec proc");
            err = PTR_ERR(cec_task);
            cec_task = NULL;
            goto err_thread;
        }
        wake_up_process(cec_task);
    }

#if defined(CONFIG_SND_SUNXI_SOC_SUNXI_HDMIAUDIO)
    audio_func.hdmi_audio_enable = hdmi_audio_enable;
    audio_func.hdmi_set_audio_para = hdmi_set_audio_para;
    audio_set_hdmi_func(&audio_func);
#if defined(CONFIG_SND_SUNXI_SOC_AUDIOHUB_INTERFACE)
    audio_func_muti.hdmi_audio_enable = hdmi_audio_enable;
    audio_func_muti.hdmi_set_audio_para = hdmi_set_audio_para;
    audio_set_muti_hdmi_func(&audio_func_muti);
#endif
#endif
    memset(&disp_func, 0, sizeof(struct disp_device_func));
    disp_func.enable = hdmi_enable;
    disp_func.disable = hdmi_disable;
    disp_func.set_mode = hdmi_set_display_mode;
    disp_func.mode_support = hdmi_mode_support;
    disp_func.get_HPD_status = hdmi_get_HPD_status;
    disp_func.get_input_csc = hdmi_get_input_csc;
    disp_func.get_video_timing_info = hdmi_get_video_timming_info;
    disp_func.suspend = hdmi_suspend;
    disp_func.resume = hdmi_resume;
    disp_set_hdmi_func(&disp_func);

    return 0;

err_thread:
    kfree(run_sem);
err_sem:
    hdmi_power_disable(hdmi_power);
err_power:
    hdmi_clk_disable();
err_clk_enable:
err_clk_get:
    iounmap((char __iomem *)reg_base);
err_iomap:
    return -1;
}

s32 hdmi_exit(void)
{
    if (hdmi_used) {
        hdmi_core_exit();

        kfree(run_sem);

        run_sem = NULL;
        if (HDMI_task) {
            kthread_stop(HDMI_task);
            HDMI_task = NULL;
        }

        if (hdmi_cec_support && cec_task) {
            kthread_stop(cec_task);
            cec_task = NULL;
        }

        if ((hdmi_power_used == 1) && (power_enable_count != 0))
            hdmi_power_disable(hdmi_power);

        if (hdmi_io_regulator_used && io_regulator_enable_count)
            hdmi_power_disable(hdmi_io_regulator);
        if (clk_enable_count != 0) {
            hdmi_clk_disable();
            clk_enable_count--;
        }
    }

    return 0;
}

#ifndef CONFIG_OF
static struct resource hdmi_resource[1] = {

    [0] = {
        .start = 0x01c16000,
        .end   = 0x01c165ff,
        .flags = IORESOURCE_MEM,
    },
};

static struct platform_device hdmi_device = {

    .name          = "hdmi",
    .id             = -1,
    .num_resources  = ARRAY_SIZE(hdmi_resource),
    .resource       = hdmi_resource,
    .dev            = {}
};
#else
static const struct of_device_id sunxi_hdmi_match[] = {
    { .compatible = "allwinner,sunxi-hdmi", },
    {},
};
#endif

static ssize_t hdmi_debug_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
    return sprintf(buf, "debug=%s\n", hdmi_print?"on" : "off");
}

static ssize_t hdmi_debug_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{
    if (count < 1)
        return -EINVAL;

    if (strncasecmp(buf, "on", 2) == 0 || strncasecmp(buf, "1", 1) == 0)
        hdmi_print = 1;
    else if (strncasecmp(buf, "off", 3) == 0 ||
            strncasecmp(buf, "0", 1) == 0)
        hdmi_print = 0;
    else
        return -EINVAL;

    return count;
}

#if defined(HDMI_ENABLE_DUMP_WRITE)

static ssize_t hdmi_dump_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{

    static long long val;
    long long reg, num, i = 0;
    unsigned char value_r[128];
    s32 ret = -1;

    ret = kstrtoll(buf, 0, &val);
    reg = (val >> 8);
    num = val & 0xff;
    pr_alert("\n");
    pr_alert("read:start add:0x%llx,count:0x%llx\n", reg, num);
    do {
        bsp_hdmi_read(reg, &value_r[i]);
        pr_alert("0x%llx: 0x%04x ", reg, value_r[i]);
        reg += 1;
        i++;
        if (i == num)
            pr_alert("\n");
        if (i % 4 == 0)
            pr_alert("\n");
    } while (i < num);

    return count;
    return count;
}

static ssize_t hdmi_write_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{
    static long long val;
    long long reg;
    long long value_w;
    s32 ret = -1;

    ret = kstrtoll(buf, 0, &val);
    if (ret != 0) {
        pr_alert("convert string fail!\n");
        return 0;
    }

    reg = (val >> 16);
    value_w =  val & 0xFFFF;
    bsp_hdmi_write(reg, value_w);
    pr_alert("write 0x%llx to reg:0x%llx\n", value_w, reg);
    return count;
}

static ssize_t hdmi_dump_show(struct device *dev, struct device_attribute *attr,
                  char *buf)
{
    pr_alert("echo reg|count > dump\n");
    pr_alert("eg read star address=0x0006,count 0x10:echo 0x610 > dump\n");
    pr_alert(
        "eg read star address=0x2000,count 0x10:echo 0x200010 > dump\n");

    return 0;
}

static ssize_t hdmi_write_show(struct device *dev,
                   struct device_attribute *attr, char *buf)
{
    pr_alert("echo reg|val > write\n");
    pr_alert(
        "eg write value:0x13fe to address:0x0004 :echo 0x413fe > write\n");
    pr_alert(
        "eg write value:0x6 to address:0x2000 :echo 0x20000006 > write\n");

    return 0;
}

#endif /*endif HDMI_ENABLE_DUMP_WRITE */
static DEVICE_ATTR(debug, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_debug_show, hdmi_debug_store);

#if defined(HDMI_ENABLE_DUMP_WRITE)
static DEVICE_ATTR(dump, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_dump_show, hdmi_dump_store);

static DEVICE_ATTR(write, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_write_show, hdmi_write_store);
#endif

/* s32 hdmi_hpd_state(u32 state); */
static ssize_t hdmi_state_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
    return sprintf(buf, "nothing\n");
}

static ssize_t hdmi_state_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{
    if (count < 1)
        return -EINVAL;

    if (strncasecmp(buf, "1", 1) == 0)
        hdmi_hpd_state(1);
    else
        hdmi_hpd_state(0);

    return count;
}

static DEVICE_ATTR(state, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_state_show, hdmi_state_store);

static ssize_t hdmi_rgb_only_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
    return sprintf(buf, "rgb_only=%s\n", rgb_only?"on" : "off");
}

static ssize_t hdmi_rgb_only_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{
    if (count < 1)
        return -EINVAL;

    if (strncasecmp(buf, "on", 2) == 0 || strncasecmp(buf, "1", 1) == 0)
        rgb_only = 1;
    else if (strncasecmp(buf, "off", 3) == 0 ||
            strncasecmp(buf, "0", 1) == 0)
        rgb_only = 0;
    else
        return -EINVAL;

    return count;
}

static DEVICE_ATTR(rgb_only, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_rgb_only_show, hdmi_rgb_only_store);

static ssize_t hdmi_hpd_mask_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
    return sprintf(buf, "0x%x\n", hdmi_hpd_mask);
}

static ssize_t hdmi_hpd_mask_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{
    int err;
    unsigned long val;

    if (count < 1)
        return -EINVAL;

    err = kstrtoul(buf, 16, &val);
    if (err) {
        pr_err("Invalid size\n");
        return err;
    }

    pr_info("val=0x%x\n", (u32)val);
    hdmi_hpd_mask = val;

    return count;
}

static DEVICE_ATTR(hpd_mask, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_hpd_mask_show, hdmi_hpd_mask_store);

static ssize_t hdmi_edid_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
    void *pedid = (void *)hdmi_edid_get_data();

    memcpy(buf, pedid, HDMI_EDID_LEN);
    return HDMI_EDID_LEN;
}

static ssize_t hdmi_edid_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{
    return count;
}

static DEVICE_ATTR(edid, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_edid_show, hdmi_edid_store);

static ssize_t hdmi_hdcp_enable_show(struct device *dev,
        struct device_attribute *attr, char *buf)
{
    return sprintf(buf, "%d\n", hdmi_core_get_hdcp_enable());
}

static ssize_t hdmi_hdcp_enable_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t count)
{
    if (count < 1)
        return -EINVAL;

    if (strncasecmp(buf, "1", 1) == 0) {
        if (hdmi_core_get_hdcp_enable() != 1)
            hdmi_core_set_hdcp_enable(1);
    } else {
        if (hdmi_core_get_hdcp_enable() != 0)
            hdmi_core_set_hdcp_enable(0);
    }

    return count;
}

static DEVICE_ATTR(hdcp_enable, S_IRUGO|S_IWUSR|S_IWGRP,
        hdmi_hdcp_enable_show, hdmi_hdcp_enable_store);

static int hdmi_probe(struct platform_device *pdev)
{
    hdmi_inf("hdmi_probe call\n");
    memset(&ghdmi, 0, sizeof(hdmi_info_t));
    ghdmi.dev = &pdev->dev;
    hdmi_init(pdev);
    return 0;
}

static int hdmi_remove(struct platform_device *pdev)
{
    hdmi_inf("hdmi_remove call\n");
    hdmi_exit();
    return 0;
}

static struct platform_driver hdmi_driver = {

    .probe    = hdmi_probe,
    .remove  = hdmi_remove,
    .driver = {

        .name   = "hdmi",
        .owner  = THIS_MODULE,
        .of_match_table = sunxi_hdmi_match,
    },
};

static int hdmi_open(struct inode *inode, struct file *file)
{
    return 0;
}

static int hdmi_release(struct inode *inode, struct file *file)
{
    return 0;
}

static ssize_t hdmi_read(struct file *file, char __user *buf,
            size_t count, loff_t *ppos)
{
    return -EINVAL;
}

static ssize_t hdmi_write(struct file *file, const char __user *buf,
            size_t count, loff_t *ppos)
{
    return -EINVAL;
}

static int hdmi_mmap(struct file *file, struct vm_area_struct *vma)
{
    return 0;
}

static long hdmi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    return 0;
}

static const struct file_operations hdmi_fops = {

    .owner      = THIS_MODULE,
    .open       = hdmi_open,
    .release    = hdmi_release,
    .write    = hdmi_write,
    .read       = hdmi_read,
    .unlocked_ioctl = hdmi_ioctl,
    .mmap      = hdmi_mmap,
};

static struct attribute *hdmi_attributes[] = {

    &dev_attr_debug.attr,
    &dev_attr_state.attr,
    &dev_attr_rgb_only.attr,
    &dev_attr_hpd_mask.attr,
    &dev_attr_edid.attr,
    &dev_attr_hdcp_enable.attr,
#if defined(HDMI_ENABLE_DUMP_WRITE)
    &dev_attr_dump.attr,
    &dev_attr_write.attr,
#endif
    NULL
};

static struct attribute_group hdmi_attribute_group = {
    .name = "attr",
    .attrs = hdmi_attributes
};

static int __init hdmi_module_init(void)
{
    int ret = 0, err;

    alloc_chrdev_region(&devid, 0, 1, "hdmi");
    my_cdev = cdev_alloc();
    cdev_init(my_cdev, &hdmi_fops);
    my_cdev->owner = THIS_MODULE;
    err = cdev_add(my_cdev, devid, 1);
    if (err) {
        hdmi_wrn("cdev_add fail.\n");
        return -1;
    }

    hdmi_class = class_create(THIS_MODULE, "hdmi");
    if (IS_ERR(hdmi_class)) {
        hdmi_wrn("class_create fail\n");
        return -1;
    }

    ghdmi.dev = device_create(hdmi_class, NULL, devid, NULL, "hdmi");

    ret = sysfs_create_group(&ghdmi.dev->kobj, &hdmi_attribute_group);

#ifndef CONFIG_OF
    ret = platform_device_register(&hdmi_device);
#endif
    if (ret == 0)
        ret = platform_driver_register(&hdmi_driver);

    hdmi_inf("hdmi_module_init\n");
    return ret;
}

static void __exit hdmi_module_exit(void)
{
    hdmi_inf("hdmi_module_exit\n");
    platform_driver_unregister(&hdmi_driver);
#ifndef CONFIG_OF
    platform_device_unregister(&hdmi_device);
#endif
    class_destroy(hdmi_class);
    cdev_del(my_cdev);
}

late_initcall(hdmi_module_init);
module_exit(hdmi_module_exit);

MODULE_AUTHOR("tyle");
MODULE_DESCRIPTION("hdmi driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:hdmi");

/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.h

/*
 * Allwinner SoCs hdmi driver.
 *
 * Copyright (C) 2016 Allwinner.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#ifndef __HDMI_CORE_H__
#define __HDMI_CORE_H__

#include "drv_hdmi_i.h"
#include "hdmi_edid.h"
#include "hdmi_bsp.h"

#define HDMI1440_480I       6
#define HDMI1440_576I       21
#define HDMI480P            2
#define HDMI576P            17
#define HDMI720P_50         19
#define HDMI720P_60     4
#define HDMI1080I_50        20
#define HDMI1080I_60        5
#define HDMI1080P_50        31
#define HDMI1080P_60        16
#define HDMI1080P_24        32
#define HDMI1080P_25        33
#define HDMI1080P_30        34
#define HDMI800_480P        35
#define HDMI1080P_24_3D_FP  (HDMI1080P_24 + 0x80)
#define HDMI720P_50_3D_FP   (HDMI720P_50 + 0x80)
#define HDMI720P_60_3D_FP   (HDMI720P_60 + 0x80)
#define HDMI3840_2160P_30   (0x01 + 0x100)
#define HDMI3840_2160P_25   (0x02 + 0x100)
#define HDMI3840_2160P_24   (0x03 + 0x100)
#define HDMI4096_2160P_24   (0x04 + 0x100)
#define HDMI1024_600        (0x05 + 0x100)
#define HDMI1280_800        (0x06 + 0x100)
#define HDMI_EDID_LEN 1024

#define HDMI_State_Idle          0x00
#define HDMI_State_Wait_Hpd          0x02
#define HDMI_State_Rx_Sense          0x03
#define HDMI_State_EDID_Parse        0x04
#define HDMI_State_HPD_Done          0x05
#define HDMI_STATE_SMOOTH_DISPLAY 0x06

/*
*typedef struct video_timing
*{
*    s32 VIC;
*    s32 PCLK;
*    s32 AVI_PR;
*    s32 INPUTX;
*    s32 INPUTY;
*    s32 HT;
*    s32 HBP;
*    s32 HFP;
*    s32 HPSW;
*    s32 VT;
*    s32 VBP;
*    s32 VFP;
*    s32 VPSW;
*}HDMI_VIDE_INFO;
*/

typedef struct audio_timing {
    s32   CTS;
    s32   ACR_N;
    s32   CH_STATUS0;
    s32   CH_STATUS1;
} HDMI_AUDIO_INFO;

extern s32 hdmi_core_initial(bool sw_only);
extern void hdmi_core_exit(void);
extern void hdmi_core_set_base_addr(uintptr_t base_addr);
extern s32 hdmi_core_loop(void);
extern s32 hdmi_core_hpd_check(void);
extern s32 hdmi_core_get_video_info(s32 vic);
extern s32 hdmi_core_get_audio_info(s32 sample_rate);
extern s32 hdmi_core_set_video_mode(u32 vic);
extern u32 hdmi_core_get_video_mode(void);
extern s32 hdmi_core_mode_support(u32 mode);
extern s32 hdmi_core_dvi_support(void);
extern s32 hdmi_core_audio_config(hdmi_audio_t *audio_param);
extern s32 hdmi_core_set_video_enable(bool enable);
extern bool hdmi_core_get_video_enable(void);
extern s32 hdmi_core_set_audio_enable(bool enable);
extern bool hdmi_core_get_audio_enable(void);
extern s32 hdmi_core_set_hdcp_enable(u32 mode);
extern u32 hdmi_core_get_hdcp_enable(void);
extern s32 hdmi_core_set_cts_enable(u32 enable);
extern u32 hdmi_core_get_cts_enable(void);
extern s32 hdmi_core_enter_lp(void);
extern s32 hdmi_core_exit_lp(void);
extern u32 hdmi_core_get_csc_type(void);
extern s32 hdmi_core_update_detect_time(u32 time_val);
extern s32 hdmi_core_cec_enable(bool enable);
extern int hdmi_core_cec_get_simple_msg(unsigned char *msg);

s32 hdmi_core_get_list_num(void);

extern u32 hdmi_print;
extern u32 hdmi_hpd_mask;/* 0x10: force unplug; 0x11: force plug */
extern u32 is_exp;
/* extern disp_video_timing video_timing[]; */

extern void hdmi_delay_ms(unsigned long ms);
extern void hdmi_delay_us(unsigned long us);
extern int hdmi_clk_enable_prepare(void);
extern int hdmi_clk_disable_prepare(void);
extern unsigned int hdmi_get_soc_version(void);
extern unsigned int hdmi_clk_get_div(void);

#endif

/linux-sunxi/include/video/sunxi_display2.h


/*
 * Allwinner SoCs display driver.
 *
 * Copyright (C) 2016 Allwinner.
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#ifndef __SUNXI_DISPLAY2_H__
#define __SUNXI_DISPLAY2_H__

struct disp_manager;
struct disp_device;
struct disp_smbl;
struct disp_enhance;
struct disp_capture;

struct disp_color {
    unsigned char alpha;
    unsigned char red;
    unsigned char green;
    unsigned char blue;
};

struct disp_rect {
    int x;
    int y;
    unsigned int width;
    unsigned int height;
};

struct disp_rectsz {
    unsigned int width;
    unsigned int height;
};

struct disp_position {
    int x;
    int y;
};

enum disp_pixel_format {
    DISP_FORMAT_ARGB_8888 = 0x00,   /* MSB  A-R-G-B  LSB */
    DISP_FORMAT_ABGR_8888 = 0x01,
    DISP_FORMAT_RGBA_8888 = 0x02,
    DISP_FORMAT_BGRA_8888 = 0x03,
    DISP_FORMAT_XRGB_8888 = 0x04,
    DISP_FORMAT_XBGR_8888 = 0x05,
    DISP_FORMAT_RGBX_8888 = 0x06,
    DISP_FORMAT_BGRX_8888 = 0x07,
    DISP_FORMAT_RGB_888 = 0x08,
    DISP_FORMAT_BGR_888 = 0x09,
    DISP_FORMAT_RGB_565 = 0x0a,
    DISP_FORMAT_BGR_565 = 0x0b,
    DISP_FORMAT_ARGB_4444 = 0x0c,
    DISP_FORMAT_ABGR_4444 = 0x0d,
    DISP_FORMAT_RGBA_4444 = 0x0e,
    DISP_FORMAT_BGRA_4444 = 0x0f,
    DISP_FORMAT_ARGB_1555 = 0x10,
    DISP_FORMAT_ABGR_1555 = 0x11,
    DISP_FORMAT_RGBA_5551 = 0x12,
    DISP_FORMAT_BGRA_5551 = 0x13,
    DISP_FORMAT_A2R10G10B10                  = 0x14,
    DISP_FORMAT_A2B10G10R10                  = 0x15,
    DISP_FORMAT_R10G10B10A2                  = 0x16,
    DISP_FORMAT_B10G10R10A2                  = 0x17,

    /*
     * SP: semi-planar
     * P:planar
     * I:interleaved
     * UVUV: U in the LSBs;
     * VUVU: V in the LSBs
     */
    DISP_FORMAT_YUV444_I_AYUV = 0x40,   /* MSB  A-Y-U-V  LSB */
    DISP_FORMAT_YUV444_I_VUYA = 0x41,   /* MSB  V-U-Y-A  LSB */
    DISP_FORMAT_YUV422_I_YVYU = 0x42,   /* MSB  Y-V-Y-U  LSB */
    DISP_FORMAT_YUV422_I_YUYV = 0x43,   /* MSB  Y-U-Y-V  LSB */
    DISP_FORMAT_YUV422_I_UYVY = 0x44,   /* MSB  U-Y-V-Y  LSB */
    DISP_FORMAT_YUV422_I_VYUY = 0x45,   /* MSB  V-Y-U-Y  LSB */
    DISP_FORMAT_YUV444_P = 0x46,    /* MSB  P3-2-1-0 LSB,  YYYY UUUU VVVV */
    DISP_FORMAT_YUV422_P = 0x47,    /* MSB  P3-2-1-0 LSB   YYYY UU   VV */
    DISP_FORMAT_YUV420_P = 0x48,    /* MSB  P3-2-1-0 LSB   YYYY U    V */
    DISP_FORMAT_YUV411_P = 0x49,    /* MSB  P3-2-1-0 LSB   YYYY U    V */
    DISP_FORMAT_YUV422_SP_UVUV = 0x4a,  /* MSB  V-U-V-U  LSB */
    DISP_FORMAT_YUV422_SP_VUVU = 0x4b,  /* MSB  U-V-U-V  LSB */
    DISP_FORMAT_YUV420_SP_UVUV = 0x4c,
    DISP_FORMAT_YUV420_SP_VUVU = 0x4d,
    DISP_FORMAT_YUV411_SP_UVUV = 0x4e,
    DISP_FORMAT_YUV411_SP_VUVU = 0x4f,
    DISP_FORMAT_8BIT_GRAY = 0x50,
    DISP_FORMAT_YUV444_I_AYUV_10BIT          = 0x51,
    DISP_FORMAT_YUV444_I_VUYA_10BIT          = 0x52,
    DISP_FORMAT_YUV422_I_YVYU_10BIT          = 0x53,
    DISP_FORMAT_YUV422_I_YUYV_10BIT          = 0x54,
    DISP_FORMAT_YUV422_I_UYVY_10BIT          = 0x55,
    DISP_FORMAT_YUV422_I_VYUY_10BIT          = 0x56,
    DISP_FORMAT_YUV444_P_10BIT               = 0x57,
    DISP_FORMAT_YUV422_P_10BIT               = 0x58,
    DISP_FORMAT_YUV420_P_10BIT               = 0x59,
    DISP_FORMAT_YUV411_P_10BIT               = 0x5a,
    DISP_FORMAT_YUV422_SP_UVUV_10BIT         = 0x5b,
    DISP_FORMAT_YUV422_SP_VUVU_10BIT         = 0x5c,
    DISP_FORMAT_YUV420_SP_UVUV_10BIT         = 0x5d,
    DISP_FORMAT_YUV420_SP_VUVU_10BIT         = 0x5e,
    DISP_FORMAT_YUV411_SP_UVUV_10BIT         = 0x5f,
    DISP_FORMAT_YUV411_SP_VUVU_10BIT         = 0x60,
    DISP_FORMAT_MAX,
};

enum disp_3d_out_mode {
    DISP_3D_OUT_MODE_CI_1 = 0x5,    /* column interlaved 1 */
    DISP_3D_OUT_MODE_CI_2 = 0x6,    /* column interlaved 2 */
    DISP_3D_OUT_MODE_CI_3 = 0x7,    /* column interlaved 3 */
    DISP_3D_OUT_MODE_CI_4 = 0x8,    /* column interlaved 4 */
    DISP_3D_OUT_MODE_LIRGB = 0x9,   /* line interleaved rgb */

    DISP_3D_OUT_MODE_TB = 0x0,  /* top bottom */
    DISP_3D_OUT_MODE_FP = 0x1,  /* frame packing */
    DISP_3D_OUT_MODE_SSF = 0x2, /* side by side full */
    DISP_3D_OUT_MODE_SSH = 0x3, /* side by side half */
    DISP_3D_OUT_MODE_LI = 0x4,  /* line interleaved */
    DISP_3D_OUT_MODE_FA = 0xa,  /* field alternative */
};

enum disp_color_space {
    DISP_UNDEF = 0x00,
    DISP_UNDEF_F = 0x01,
    DISP_GBR = 0x100,
    DISP_BT709 = 0x101,
    DISP_FCC = 0x102,
    DISP_BT470BG = 0x103,
    DISP_BT601 = 0x104,
    DISP_SMPTE240M = 0x105,
    DISP_YCGCO = 0x106,
    DISP_BT2020NC = 0x107,
    DISP_BT2020C = 0x108,
    DISP_GBR_F = 0x200,
    DISP_BT709_F = 0x201,
    DISP_FCC_F = 0x202,
    DISP_BT470BG_F = 0x203,
    DISP_BT601_F = 0x204,
    DISP_SMPTE240M_F = 0x205,
    DISP_YCGCO_F = 0x206,
    DISP_BT2020NC_F = 0x207,
    DISP_BT2020C_F = 0x208,
    DISP_RESERVED = 0x300,
    DISP_RESERVED_F = 0x301,
};

enum disp_csc_type {
    DISP_CSC_TYPE_RGB        = 0,
    DISP_CSC_TYPE_YUV444     = 1,
    DISP_CSC_TYPE_YUV422     = 2,
    DISP_CSC_TYPE_YUV420     = 3,
};

enum disp_data_bits {
    DISP_DATA_8BITS    = 0,
    DISP_DATA_10BITS   = 1,
    DISP_DATA_12BITS   = 2,
    DISP_DATA_16BITS   = 3,
};
enum disp_dvi_hdmi {
    DISP_DVI_HDMI_UNDEFINED = 0,
    DISP_DVI = 1,
    DISP_HDMI = 2,
};
enum disp_scan_info {
    DISP_SCANINFO_NO_DATA = 0,
    OVERSCAN = 1,
    UNDERSCAN = 2,
};
enum disp_color_range {
    DISP_COLOR_RANGE_DEFAULT = 0, /*default*/
    DISP_COLOR_RANGE_0_255 = 1,
    DISP_COLOR_RANGE_16_235 = 2,
};

enum disp_output_type {
    DISP_OUTPUT_TYPE_NONE = 0,
    DISP_OUTPUT_TYPE_LCD = 1,
    DISP_OUTPUT_TYPE_TV = 2,
    DISP_OUTPUT_TYPE_HDMI = 4,
    DISP_OUTPUT_TYPE_VGA = 8,
    DISP_OUTPUT_TYPE_VDPO = 16,
    DISP_OUTPUT_TYPE_EDP    = 32, /*16 for vdpo*/
};

enum disp_tv_mode {
    DISP_TV_MOD_480I = 0,
    DISP_TV_MOD_576I = 1,
    DISP_TV_MOD_480P = 2,
    DISP_TV_MOD_576P = 3,
    DISP_TV_MOD_720P_50HZ = 4,
    DISP_TV_MOD_720P_60HZ = 5,
    DISP_TV_MOD_1080I_50HZ = 6,
    DISP_TV_MOD_1080I_60HZ = 7,
    DISP_TV_MOD_1080P_24HZ = 8,
    DISP_TV_MOD_1080P_50HZ = 9,
    DISP_TV_MOD_1080P_60HZ = 0xa,
    DISP_TV_MOD_1080P_24HZ_3D_FP = 0x17,
    DISP_TV_MOD_720P_50HZ_3D_FP = 0x18,
    DISP_TV_MOD_720P_60HZ_3D_FP = 0x19,
    DISP_TV_MOD_1080P_25HZ = 0x1a,
    DISP_TV_MOD_1080P_30HZ = 0x1b,
    DISP_TV_MOD_800_480P = 0x45,
    DISP_TV_MOD_PAL = 0xb,
    DISP_TV_MOD_PAL_SVIDEO = 0xc,
    DISP_TV_MOD_NTSC = 0xe,
    DISP_TV_MOD_NTSC_SVIDEO = 0xf,
    DISP_TV_MOD_PAL_M = 0x11,
    DISP_TV_MOD_PAL_M_SVIDEO = 0x12,
    DISP_TV_MOD_PAL_NC = 0x14,
    DISP_TV_MOD_PAL_NC_SVIDEO = 0x15,
    DISP_TV_MOD_3840_2160P_30HZ = 0x1c,
    DISP_TV_MOD_3840_2160P_25HZ = 0x1d,
    DISP_TV_MOD_3840_2160P_24HZ = 0x1e,
    DISP_TV_MOD_4096_2160P_24HZ     = 0x1f,
    DISP_TV_MOD_4096_2160P_25HZ     = 0x20,
    DISP_TV_MOD_4096_2160P_30HZ     = 0x21,
    DISP_TV_MOD_3840_2160P_60HZ     = 0x22,
    DISP_TV_MOD_4096_2160P_60HZ     = 0x23,
    DISP_TV_MOD_3840_2160P_50HZ     = 0x24,
    DISP_TV_MOD_4096_2160P_50HZ     = 0x25,
    DISP_TV_MOD_1280_1024P_60HZ     = 0x41,
    DISP_TV_MOD_1024_768P_60HZ      = 0x42,
    DISP_TV_MOD_900_540P_60HZ       = 0x43,
    DISP_TV_MOD_1920_720P_60HZ      = 0x44,
    DISP_TV_MOD_1024_600P           = 0x45,
    DISP_TV_MOD_1280_800P           = 0x46,
    /* vga */
    DISP_VGA_MOD_640_480P_60 = 0x50,
    DISP_VGA_MOD_800_600P_60 = 0x51,
    DISP_VGA_MOD_1024_768P_60 = 0x52,
    DISP_VGA_MOD_1280_768P_60 = 0x53,
    DISP_VGA_MOD_1280_800P_60 = 0x54,
    DISP_VGA_MOD_1366_768P_60 = 0x55,
    DISP_VGA_MOD_1440_900P_60 = 0x56,
    DISP_VGA_MOD_1920_1080P_60 = 0x57,
    DISP_VGA_MOD_1920_1200P_60 = 0x58,
    DISP_TV_MOD_3840_1080P_30 = 0x59,
    DISP_VGA_MOD_1280_720P_60        = 0x5a,
    DISP_VGA_MOD_MAX_NUM             = 0x5b,
    DISP_TV_MODE_NUM,
};

enum disp_exit_mode {
    DISP_EXIT_MODE_CLEAN_ALL = 0,
    DISP_EXIT_MODE_CLEAN_PARTLY = 1, /* only clean interrupt temply */
};

enum disp_buffer_flags {
    DISP_BF_NORMAL = 0, /* non-stereo */
    DISP_BF_STEREO_TB = 1 << 0, /* stereo top-bottom */
    DISP_BF_STEREO_FP = 1 << 1, /* stereo frame packing */
    DISP_BF_STEREO_SSH = 1 << 2,    /* stereo side by side half */
    DISP_BF_STEREO_SSF = 1 << 3,    /* stereo side by side full */
    DISP_BF_STEREO_LI = 1 << 4, /* stereo line interlace */
    /*
     * 2d plus depth to convert into 3d,
     * left and right image using the same frame buffer
     */
    DISP_BF_STEREO_2D_DEPTH  = 1 << 5,
};

enum disp_layer_mode {
    LAYER_MODE_BUFFER = 0,
    LAYER_MODE_COLOR = 1,
};

enum disp_scan_flags {
    DISP_SCAN_PROGRESSIVE = 0,
    DISP_SCAN_INTERLACED_ODD_FLD_FIRST = 1 << 0,
    DISP_SCAN_INTERLACED_EVEN_FLD_FIRST = 1 << 1,
};

enum disp_eotf {
    DISP_EOTF_RESERVED = 0x000,
    DISP_EOTF_BT709 = 0x001,
    DISP_EOTF_UNDEF = 0x002,
    DISP_EOTF_GAMMA22 = 0x004, /* SDR */
    DISP_EOTF_GAMMA28 = 0x005,
    DISP_EOTF_BT601 = 0x006,
    DISP_EOTF_SMPTE240M = 0x007,
    DISP_EOTF_LINEAR = 0x008,
    DISP_EOTF_LOG100 = 0x009,
    DISP_EOTF_LOG100S10 = 0x00a,
    DISP_EOTF_IEC61966_2_4 = 0x00b,
    DISP_EOTF_BT1361 = 0x00c,
    DISP_EOTF_IEC61966_2_1 = 0X00d,
    DISP_EOTF_BT2020_0 = 0x00e,
    DISP_EOTF_BT2020_1 = 0x00f,
    DISP_EOTF_SMPTE2084 = 0x010, /* HDR10 */
    DISP_EOTF_SMPTE428_1 = 0x011,
    DISP_EOTF_ARIB_STD_B67 = 0x012, /* HLG */
};
/* disp_atw_mode - mode for asynchronous time warp
 *
 * @NORMAL_MODE: dual buffer, left eye and right eye buffer is individual
 * @LEFT_RIGHT_MODE: single buffer, the left half of each line buffer
 *           is for left eye, the right half is for the right eye
 * @UP_DOWN_MODE: single buffer, the first half of the total buffer
 *        is for the left eye, the second half is for the right eye
 */
enum disp_atw_mode {
    NORMAL_MODE,
    LEFT_RIGHT_MODE,
    UP_DOWN_MODE,
};
struct disp_output {
    unsigned int type;
    unsigned int mode;
};

struct disp_rect64 {
    long long x;
    long long y;
    long long width;
    long long height;
};

struct disp_fb_info {
    /* address of frame buffer,
     * single addr for interleaved fomart,
     * double addr for semi-planar fomart
     * triple addr for planar format
     */
    unsigned long long addr[3];
    struct disp_rectsz size[3];
    /* align for 3 comonent,unit: bytes */
    unsigned int align[3];
    enum disp_pixel_format format;
    enum disp_color_space color_space;  /* color space */
    unsigned int trd_right_addr[3]; /* right address of 3d fb */
    bool pre_multiply;  /* true: pre-multiply fb */
    struct disp_rect64 crop;    /* crop rectangle boundaries */
    enum disp_buffer_flags flags;
    enum disp_scan_flags scan;
};

struct disp_layer_info {
    enum disp_layer_mode mode;
    unsigned char zorder;
    /* 0: pixel alpha;  1: global alpha;  2: global pixel alpha */
    unsigned char alpha_mode;
    unsigned char alpha_value;  /* global alpha value */
    struct disp_rect screen_win;    /* display window on the screen */
    bool b_trd_out;     /* 3d display */
    enum disp_3d_out_mode out_trd_mode; /* 3d display mode */
    union {
        unsigned int color; /* valid when LAYER_MODE_COLOR */
        struct disp_fb_info fb; /* valid when LAYER_MODE_BUFFER */
    };

    unsigned int id; /* frame id, the id of frame display currently */
};

struct disp_layer_config {
    struct disp_layer_info info;
    bool enable;
    unsigned int channel;
    unsigned int layer_id;
};

/* disp_atw_info - asynchronous time wrap infomation
 *
 * @used: indicate if the atw funtion is used
 * @mode: atw mode
 * @b_row: the row number of the micro block
 * @b_col: the column number of the micro block
 * @cof_fd: dma_buf fd for the buffer contaied coefficient for atw
 */
struct disp_atw_info {
    bool used;
    enum disp_atw_mode mode;
    unsigned int b_row;
    unsigned int b_col;
    int cof_fd;
};
/**
 * disp_vdpo_config
 */
struct disp_vdpo_config {
    unsigned int data_seq_sel;
    unsigned int dclk_invt;
    unsigned int dclk_dly_num;
    unsigned int spl_type_u;
    unsigned int spl_type_v;
};
/* disp_fb_info2 - image buffer info v2
 *
 * @fd: dma_buf  fd for frame buffer
 * @size: size<width,height> for each buffer, unit:pixels
 * @align: align for each buffer, unit:bytes
 * @format: pixel format
 * @color_space: color space
 * @trd_right_fd: dma_buf fd for the right-eye frame buffer,
 *                  valid when frame-packing 3d buffer input
 * @pre_multiply: indicate the pixel use premultiplied alpha
 * @crop: crop rectangle for buffer to be display
 * @flag: indicate stereo/non-stereo buffer
 * @scan: indicate interleave/progressive scan type, and the scan order
 * @depth: depth perception for stereo image, only valid when stereo image input
 *            unit: pixel
 * @fbd_en: indicate if enable fbd function
 * @metadata_fd: dma_buf fd for the buffer contained metadata for fbc/hdr
 * @metadata_size: the size of metadata buffer, unit:bytes
 * @metadata_flag: the flag to indicate the type of metadata buffer
 *  0     : no metadata
 *  1 << 0: hdr static metadata
 *  1 << 1: hdr dynamic metadata
 *  1 << 4: frame buffer compress(fbc) metadata
 *  x     : all type could be "or" together
 */
struct disp_fb_info2 {
    int                      fd;
    struct disp_rectsz       size[3];
    unsigned int             align[3];
    enum disp_pixel_format   format;
    enum disp_color_space    color_space;
    int                      trd_right_fd;
    bool                     pre_multiply;
    struct disp_rect64       crop;
    enum disp_buffer_flags   flags;
    enum disp_scan_flags     scan;
    enum disp_eotf           eotf;
    int                      depth;
    unsigned int             fbd_en;
    int                      metadata_fd;
    unsigned int             metadata_size;
    unsigned int             metadata_flag;
};

/* disp_layer_info2 - layer info v2
 *
 * @mode: buffer/clolor mode, when in color mode, the layer is widthout buffer
 * @zorder: the zorder of layer, 0~max-layer-number
 * @alpha_mode:
 *  0: pixel alpha;
 *  1: global alpha
 *  2: mixed alpha, compositing width pixel alpha before global alpha
 * @alpha_value: global alpha value, valid when alpha_mode is not pixel alpha
 * @screen_win: the rectangle on the screen for fb to be display
 * @b_trd_out: indicate if 3d display output
 * @out_trd_mode: 3d output mode, valid when b_trd_out is true
 * @color: the color value to be display, valid when layer is in color mode
 * @fb: the framebuffer info related width the layer, valid when in buffer mode
 * @id: frame id, the user could get the frame-id display currently by
 *  DISP_LAYER_GET_FRAME_ID ioctl
 * @atw: asynchronous time wrap information
 */
struct disp_layer_info2 {
    enum disp_layer_mode      mode;
    unsigned char             zorder;
    unsigned char             alpha_mode;
    unsigned char             alpha_value;
    struct disp_rect          screen_win;
    bool                      b_trd_out;
    enum disp_3d_out_mode     out_trd_mode;
    union {
        unsigned int            color;
        struct disp_fb_info2    fb;
    };

    unsigned int              id;
    struct disp_atw_info      atw;
};

/* disp_layer_config2 - layer config v2
 *
 * @info: layer info
 * @enable: indicate to enable/disable the layer
 * @channel: the channel index of the layer, 0~max-channel-number
 * @layer_id: the layer index of the layer widthin it's channel
 */
struct disp_layer_config2 {
    struct disp_layer_info2 info;
    bool enable;
    unsigned int channel;
    unsigned int layer_id;
};

/**
 * match rule: 0/1:always match;
 *             2:match if min<=color<=max;
 *             3:match if color>max or color<min
 */
struct disp_colorkey {
    struct disp_color ck_max;
    struct disp_color ck_min;
    unsigned int red_match_rule;
    unsigned int green_match_rule;
    unsigned int blue_match_rule;
};

struct disp_s_frame {
    enum disp_pixel_format format;
    struct disp_rectsz size[3];
    struct disp_rect crop;
    unsigned long long addr[3];
};

struct disp_capture_info {
    /* capture the whole screen if window eq ZERO */
    struct disp_rect window;
    struct disp_s_frame out_frame;
};

/* disp_s_frame2 - display simple frame buffer
 *
 * @format: pixel format of fb
 * @size: size for each plane
 * @crop: crop zone to be fill image data
 * @fd: dma_buf fd
 */
struct disp_s_frame2 {
    enum disp_pixel_format format;
    struct disp_rectsz size[3];
    struct disp_rect crop;
    int fd;
};

/* disp_capture_info2 - display capture information
 *
 * @window: the rectange on the screen to be capture
 * @out_frame: the framebuffer to be restore capture image data
 */
struct disp_capture_info2 {
    struct disp_rect window;
    struct disp_s_frame2 out_frame;
};

struct disp_capture_fmt {
    enum disp_pixel_format format;   /* write-back ouput format, doson't support YUV ouput yet */
    struct disp_rect window;         /* source crop */
    struct disp_rect crop;           /* output crop */
};

struct disp_capture_buffer {
    int handle;                      /* Unique integer id represent this buffer */
    enum disp_pixel_format format;   /* write-back ouput format */
    struct disp_rect window;         /* source crop */
    struct disp_rect crop;           /* output crop */
    struct disp_rectsz size[3];

    int fd;
    int width;                       /* buffer width  in pixels */
    int height;                      /* buffer height in pixels */
};

struct disp_capture_handle {
    int handle;    /* unique integer id represent a capture buffer */
    int fencefd;   /* fence fd for this buffer */
};

enum disp_capture_extend_cmd {
    DISP_CAPTURE_E_SET_FMT,
    DISP_CAPTURE_E_BUFFER_LIST_INIT,
    DISP_CAPTURE_E_BUFFER_LIST_CLEAR,
    DISP_CAPTURE_E_ACQUIRE_BUFFER,
    DISP_CAPTURE_E_RELEASE_BUFFER,
    DISP_CAPTURE_E_CTRL,
};

/* disp_device_config - display deivce config
 *
 * @type: output type
 * @mode: output mode
 * @format: data format
 * @bits:   data bits
 * @eotf:   electro-optical transfer function
 *      SDR  : DISP_EOTF_GAMMA22
 *      HDR10: DISP_EOTF_SMPTE2084
 *      HLG  : DISP_EOTF_ARIB_STD_B67
 * @cs:     color space type
 *      DISP_BT601: SDR for SD resolution(< 720P)
 *      DISP_BT709: SDR for HD resolution(>= 720P)
 *      DISP_BT2020NC: HDR10 or HLG or wide-color-gamut
 * @dvi_hdmi: output mode
 *        DVI: DISP_DVI
 *        HDMI: DISP_HDMI
 * @range:    RGB/YUV quantization range
 *          DEFUALT: limited range when sending a CE video format
 *                   full range when sending an IT video format
 *          LIMITED: color limited range from 16 to 235
 *          FULL: color full range from 0 to 255
 * @scan info:
 *        DISP_SCANINFO_NO_DATA: overscan if it is a CE format,
 *                               underscan if it is an IT format
 *        OVERSCAN: composed for overscan display
 *        UNDERSCAN: composed for underscan display
 * @aspect_ratio: active format aspect ratio
 */
struct disp_device_config {
    enum disp_output_type       type;
    enum disp_tv_mode           mode;
    enum disp_csc_type          format;
    enum disp_data_bits         bits;
    enum disp_eotf              eotf;
    enum disp_color_space       cs;
    enum disp_dvi_hdmi          dvi_hdmi;
    enum disp_color_range       range;
    enum disp_scan_info         scan;
    unsigned int                aspect_ratio;
    unsigned int                reserve1;
};

/* disp_device_dynamic_config - display deivce dynamic config
 *
 * @metadata_fd: dma_buf fd for the buffer contained metadata for fbc/hdr
 * @metadata_size: the size of metadata buffer, unit:bytes
 * @metadata_flag: the flag to indicate the type of metadata buffer
 *  0     : no metadata
 *  1 << 0: hdr static metadata
 *  1 << 1: hdr dynamic metadata
 *  1 << 4: frame buffer compress(fbc) metadata
 *  x     : all type could be "or" together
 * @vmap:vmap a block contigous phys memory into virtual space
 * @vunmap: release virtual mapping obtained by vmap()
 */
struct disp_device_dynamic_config {
    int          metadata_fd;
    unsigned int             metadata_size;
    unsigned int             metadata_flag;
    void *(*vmap)(unsigned long phys_addr, unsigned long size);
    void (*vunmap)(const void *vaddr);
};
struct disp_video_timings {
    unsigned int vic;   /* video information code */
    unsigned int tv_mode;
    unsigned int pixel_clk;
    unsigned int pixel_repeat; /* pixel repeat (pixel_repeat+1) times */
    unsigned int x_res;
    unsigned int y_res;
    unsigned int hor_total_time;
    unsigned int hor_back_porch;
    unsigned int hor_front_porch;
    unsigned int hor_sync_time;
    unsigned int ver_total_time;
    unsigned int ver_back_porch;
    unsigned int ver_front_porch;
    unsigned int ver_sync_time;
    unsigned int hor_sync_polarity; /* 0: negative, 1: positive */
    unsigned int ver_sync_polarity; /* 0: negative, 1: positive */
    bool b_interlace;
    unsigned int vactive_space;
    unsigned int trd_mode;
    unsigned long      dclk_rate_set; /*unit: hz */
    unsigned long long frame_period; /* unit: ns */
    int                start_delay; /* unit: line */
};

enum disp_fb_mode {
    FB_MODE_SCREEN0 = 0,
    FB_MODE_SCREEN1 = 1,
    FB_MODE_SCREEN2 = 2,
    FB_MODE_DUAL_SAME_SCREEN_TB = 3,/* two screen, top buffer for screen0, bottom buffer for screen1 */
    FB_MODE_DUAL_DIFF_SCREEN_SAME_CONTENTS = 4,/* two screen, they have same contents; */
};

struct disp_fb_create_info {
    enum disp_fb_mode fb_mode;
    enum disp_layer_mode mode;
    unsigned int buffer_num;
    unsigned int width;
    unsigned int height;

    unsigned int output_width;  /* used when scaler mode */
    unsigned int output_height; /* used when scaler mode */
};

enum disp_init_mode {
    DISP_INIT_MODE_SCREEN0 = 0, /* fb0 for screen0 */
    DISP_INIT_MODE_SCREEN1 = 1, /* fb0 for screen1 */
    DISP_INIT_MODE_SCREEN2 = 2, /* fb0 for screen1 */
    DISP_INIT_MODE_TWO_DIFF_SCREEN = 3,/* fb0 for screen0 and fb1 for screen1 */
    DISP_INIT_MODE_TWO_SAME_SCREEN = 4,/* fb0(up buffer for screen0, down buffer for screen1) */
    DISP_INIT_MODE_TWO_DIFF_SCREEN_SAME_CONTENTS = 5,/* fb0 for two different screen(screen0 layer is normal layer, screen1 layer is scaler layer); */
};

struct disp_tv_func {
    int (*tv_enable)(u32 sel);
    int (*tv_disable)(u32 sel);
    int (*tv_suspend)(u32 sel);
    int (*tv_resume)(u32 sel);
    int (*tv_get_mode)(u32 sel);
    int (*tv_set_mode)(u32 sel, enum disp_tv_mode tv_mod);
    int (*tv_get_input_csc)(u32 sel);
    int (*tv_get_video_timing_info)(u32 sel,
                     struct disp_video_timings **
                     video_info);
    int (*tv_mode_support)(u32 sel, enum disp_tv_mode mode);
    int (*tv_hot_plugging_detect)(u32 state);
    int (*tv_set_enhance_mode)(u32 sel, u32 mode);
    int (*tv_irq_enable)(u32 sel, u32 irq_id, u32 en);
    int (*tv_irq_query)(u32 sel);
    unsigned int (*tv_get_cur_line)(u32 sel);
    int (*vdpo_set_config)(u32 sel, struct disp_vdpo_config *p_cfg);
    int (*tv_get_startdelay)(u32 sel);
};

/* disp_vdevice_interface_para - vdevice interaface parameter
 *
 * @intf:interface
 *  0:hv, 1:cpu, 3:lvds, 4:dsi
 * @sub_intf:  sub interface
 *  rgb interface: 0:parallel hv, 8:serial hv, 10:dummy rgb
 *                     11: rgb dummy, 12: ccir656
 *  cpu interface: 0:18 pin, 10:9pin, 12:6pin, 8:16pin, 14:8pin
 *  lvds interface:0:single link, 1:dual link
 *  dsi inerafce:   0:video mode, 1:command mode, 2: video burst mode
 * @sequence:output sequence
 *  rgb output: 0:rgb rgb, 1:rgb brg, 2:rgb gbr, 4:brg rgb
 *                  5:brg brg, 6:brg gbr
 *  8:grb rgb, 9:grb brg, 10:grb gbr
 *  yuv output:0:yuyv, 1: yvyu, 2:uyvy, 3:vyuy
 * @fdelay:yuv eav/sav F line delay
 *  0: F toggle right after active video line
 *  1: delay 2 line(CCIR NTSC)
 *  2: delay 3 line(CCIR PAL)
 * @clk_phase:clk phase
 *  0: 0 degree, 1:90 degree, 2: 180 degree, 3:270 degree
 * @sync_polarity:sync signals polarity
 *  0: vsync active low,hsync active low
 *  1: vsync active high,hsync active low
 *  2: vsync active low,hsync active high
 *  3: vsync active high,hsync active high
 */
struct disp_vdevice_interface_para {
    unsigned int intf;
    unsigned int sub_intf;
    unsigned int sequence;
    unsigned int fdelay;
    unsigned int clk_phase;
    unsigned int sync_polarity;
    unsigned int ccir_clk_div;
    unsigned int input_csc;/*not need to config for user*/
};

struct disp_vdevice_source_ops {
    int (*tcon_enable)(struct disp_device *dispdev);
    int (*tcon_disable)(struct disp_device *dispdev);
    int (*tcon_simple_enable)(struct disp_device *dispdev);
    int (*tcon_simple_disable)(struct disp_device *dispdev);
};

struct disp_device_func {
    int (*enable)(void);
    int (*disable)(void);
    int (*set_mode)(u32 mode);
    int (*mode_support)(u32 mode);
    int (*get_HPD_status)(void);
    int (*get_input_csc)(void);
    int (*get_video_timing_info)(struct disp_video_timings **video_info);
    int (*suspend)(void);
    int (*resume)(void);
    int (*early_suspend)(void);
    int (*late_resume)(void);
    int (*get_interface_para)(void *para);
    int (*set_static_config)(struct disp_device_config *config);
    int (*get_static_config)(struct disp_device_config *config);
    int (*set_dynamic_config)(struct disp_device_dynamic_config *config);
    int (*get_dynamic_config)(struct disp_device_dynamic_config *config);
};

struct disp_vdevice_init_data {
    char name[32];
    u32 disp;
    u32 fix_timing;
    enum disp_output_type type;
    struct disp_device_func func;
};

enum disp_tv_dac_source {
    DISP_TV_DAC_SRC_COMPOSITE = 0,
    DISP_TV_DAC_SRC_LUMA = 1,
    DISP_TV_DAC_SRC_CHROMA = 2,
    DISP_TV_DAC_SRC_Y = 4,
    DISP_TV_DAC_SRC_PB = 5,
    DISP_TV_DAC_SRC_PR = 6,
    DISP_TV_DAC_SRC_NONE = 7,
};

enum disp_tv_output {
    DISP_TV_NONE = 0,
    DISP_TV_CVBS = 1,
    DISP_TV_YPBPR = 2,
    DISP_TV_SVIDEO = 4,
    DISP_VGA = 5,
};

enum tag_DISP_CMD {
    /* ----disp global---- */
    DISP_RESERVE0 = 0x00,
    DISP_RESERVE1 = 0x01,
    DISP_SET_BKCOLOR = 0x03,
    DISP_GET_BKCOLOR = 0x04,
    DISP_SET_COLORKEY = 0x05,
    DISP_GET_COLORKEY = 0x06,
    DISP_GET_SCN_WIDTH = 0x07,
    DISP_GET_SCN_HEIGHT = 0x08,
    DISP_GET_OUTPUT_TYPE = 0x09,
    DISP_SET_EXIT_MODE = 0x0A,
    DISP_VSYNC_EVENT_EN = 0x0B,
    DISP_BLANK = 0x0C,
    DISP_SHADOW_PROTECT = 0x0D,
    DISP_HWC_COMMIT = 0x0E,
    DISP_DEVICE_SWITCH = 0x0F,
    DISP_GET_OUTPUT = 0x10,
    DISP_SET_COLOR_RANGE = 0x11,
    DISP_GET_COLOR_RANGE = 0x12,
    DISP_HWC_CUSTOM = 0x13,
    DISP_DEVICE_SET_CONFIG = 0x14,
    DISP_DEVICE_GET_CONFIG = 0x15,

    /* ----layer---- */
    DISP_LAYER_ENABLE = 0x40,
    DISP_LAYER_DISABLE = 0x41,
    DISP_LAYER_SET_INFO = 0x42,
    DISP_LAYER_GET_INFO = 0x43,
    DISP_LAYER_TOP = 0x44,
    DISP_LAYER_BOTTOM = 0x45,
    DISP_LAYER_GET_FRAME_ID = 0x46,
    DISP_LAYER_SET_CONFIG = 0x47,
    DISP_LAYER_GET_CONFIG = 0x48,
    /*
     * LAYER_S(G)ET_CONFIG2 takes disp_layer_config2,
     * it will support more featuras
     */
    DISP_LAYER_SET_CONFIG2 = 0x49,
    DISP_LAYER_GET_CONFIG2 = 0x4a,

    /* ----hdmi---- */
    DISP_HDMI_SUPPORT_MODE = 0xc4,
    DISP_SET_TV_HPD = 0xc5,
    DISP_HDMI_GET_EDID = 0xc6,

    /* ----lcd---- */
    DISP_LCD_ENABLE = 0x100,
    DISP_LCD_DISABLE = 0x101,
    DISP_LCD_SET_BRIGHTNESS = 0x102,
    DISP_LCD_GET_BRIGHTNESS = 0x103,
    DISP_LCD_BACKLIGHT_ENABLE = 0x104,
    DISP_LCD_BACKLIGHT_DISABLE = 0x105,
    DISP_LCD_SET_SRC = 0x106,
    DISP_LCD_SET_FPS = 0x107,
    DISP_LCD_GET_FPS = 0x108,
    DISP_LCD_GET_SIZE = 0x109,
    DISP_LCD_GET_MODEL_NAME = 0x10a,
    DISP_LCD_SET_GAMMA_TABLE = 0x10b,
    DISP_LCD_GAMMA_CORRECTION_ENABLE = 0x10c,
    DISP_LCD_GAMMA_CORRECTION_DISABLE = 0x10d,
    DISP_LCD_USER_DEFINED_FUNC = 0x10e,
    DISP_LCD_CHECK_OPEN_FINISH = 0x10f,
    DISP_LCD_CHECK_CLOSE_FINISH = 0x110,

    /*tv*/
    DISP_TV_SET_GAMMA_TABLE = 0x111,
    /* ---- capture --- */
    DISP_CAPTURE_START = 0x140,/* caputre screen and scaler to dram */
    DISP_CAPTURE_STOP = 0x141,
    DISP_CAPTURE_COMMIT = 0x142,
    DISP_CAPTURE_COMMIT2 = 0x143,
    DISP_CAPTURE_QUERY = 0x144,
    DISP_CAPTURE_EXTEND = 0x145,

    /* ---enhance --- */
    DISP_ENHANCE_ENABLE = 0x180,
    DISP_ENHANCE_DISABLE = 0x181,
    DISP_ENHANCE_GET_EN = 0x182,
    DISP_ENHANCE_SET_WINDOW = 0x183,
    DISP_ENHANCE_GET_WINDOW = 0x184,
    DISP_ENHANCE_SET_MODE = 0x185,
    DISP_ENHANCE_GET_MODE = 0x186,
    DISP_ENHANCE_DEMO_ENABLE = 0x187,
    DISP_ENHANCE_DEMO_DISABLE = 0x188,

    /* ---smart backlight --- */
    DISP_SMBL_ENABLE = 0x200,
    DISP_SMBL_DISABLE = 0x201,
    DISP_SMBL_GET_EN = 0x202,
    DISP_SMBL_SET_WINDOW = 0x203,
    DISP_SMBL_GET_WINDOW = 0x204,

    /* ---- for test */
    DISP_FB_REQUEST = 0x280,
    DISP_FB_RELEASE = 0x281,

    DISP_MEM_REQUEST = 0x2c0,
    DISP_MEM_RELEASE = 0x2c1,
    DISP_MEM_GETADR = 0x2c2,
    DISP_VDPO_SET_CONFIG = 0x2c3,

    DISP_EINK_UPDATE = 0x402,
    DISP_EINK_SET_TEMP = 0x403,
    DISP_EINK_GET_TEMP = 0x404,
    DISP_EINK_OVERLAP_SKIP = 0x405,
    DISP_EINK_UPDATE2 = 0x406,
};

#define FBIOGET_LAYER_HDL_0 0x4700
#define FBIOGET_LAYER_HDL_1 0x4701

#endif

and it wont compile:

drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.c: In function 'bsp_disp_get_screen_width_from_output_type':
drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.c:897:3: error: duplicate case value
   case DISP_TV_MOD_1024_600P:
   ^
drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.c:887:9: error: previously used here
         case DISP_TV_MOD_800_480P:
         ^
drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.c: In function 'bsp_disp_get_screen_height_from_output_type':
drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.c:1012:3: error: duplicate case value
   case DISP_TV_MOD_1024_600P:
   ^
drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.c:1008:8: error: previously used here
        case DISP_TV_MOD_800_480P:
        ^
In file included from drivers/video/fbdev/sunxi/disp2/disp/de/disp_private.c:12:0:
drivers/video/fbdev/sunxi/disp2/disp/de/../dev_disp.h:247:44: warning: 'struct dramfreq_vb_time_ops' declared inside parameter list
 extern int dramfreq_set_vb_time_ops(struct dramfreq_vb_time_ops *ops);
                                            ^
drivers/video/fbdev/sunxi/disp2/disp/de/../dev_disp.h:247:44: warning: its scope is only this definition or declaration, which is probably not what you want
scripts/Makefile.build:258: recipe for target 'drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.o' failed
make[6]: *** [drivers/video/fbdev/sunxi/disp2/disp/de/disp_display.o] Error 1
make[6]: *** Waiting for unfinished jobs....
scripts/Makefile.build:403: recipe for target 'drivers/video/fbdev/sunxi/disp2/disp' failed
make[5]: *** [drivers/video/fbdev/sunxi/disp2/disp] Error 2
scripts/Makefile.build:403: recipe for target 'drivers/video/fbdev/sunxi' failed
make[4]: *** [drivers/video/fbdev/sunxi] Error 2
scripts/Makefile.build:403: recipe for target 'drivers/video/fbdev' failed
make[3]: *** [drivers/video/fbdev] Error 2
scripts/Makefile.build:403: recipe for target 'drivers/video' failed
make[2]: *** [drivers/video] Error 2
Makefile:964: recipe for target 'drivers' failed
make[1]: *** [drivers] Error 2
make[1]: Leaving directory '/home/ilan/BPI-M64-bsp-4.4/linux-sunxi'
Makefile:31: recipe for target 'kernel' failed
make: *** [kernel] Error 2
avafinger commented 5 years ago

Change this:

enum disp_tv_mode { DISP_TV_MOD_480I = 0, DISP_TV_MOD_576I = 1, DISP_TV_MOD_480P = 2, DISP_TV_MOD_576P = 3, DISP_TV_MOD_720P_50HZ = 4, DISP_TV_MOD_720P_60HZ = 5, DISP_TV_MOD_1080I_50HZ = 6, DISP_TV_MOD_1080I_60HZ = 7, DISP_TV_MOD_1080P_24HZ = 8, DISP_TV_MOD_1080P_50HZ = 9, DISP_TV_MOD_1080P_60HZ = 0xa, DISP_TV_MOD_1080P_24HZ_3D_FP = 0x17, DISP_TV_MOD_720P_50HZ_3D_FP = 0x18, DISP_TV_MOD_720P_60HZ_3D_FP = 0x19, DISP_TV_MOD_1080P_25HZ = 0x1a, DISP_TV_MOD_1080P_30HZ = 0x1b, DISP_TV_MOD_800_480P = 0x45, <=== remove DISP_TV_MOD_PAL = 0xb, DISP_TV_MOD_PAL_SVIDEO = 0xc, DISP_TV_MOD_NTSC = 0xe, DISP_TV_MOD_NTSC_SVIDEO = 0xf, DISP_TV_MOD_PAL_M = 0x11, DISP_TV_MOD_PAL_M_SVIDEO = 0x12, DISP_TV_MOD_PAL_NC = 0x14, DISP_TV_MOD_PAL_NC_SVIDEO = 0x15, DISP_TV_MOD_3840_2160P_30HZ = 0x1c, DISP_TV_MOD_3840_2160P_25HZ = 0x1d, DISP_TV_MOD_3840_2160P_24HZ = 0x1e, DISP_TV_MOD_4096_2160P_24HZ = 0x1f, DISP_TV_MOD_4096_2160P_25HZ = 0x20, DISP_TV_MOD_4096_2160P_30HZ = 0x21, DISP_TV_MOD_3840_2160P_60HZ = 0x22, DISP_TV_MOD_4096_2160P_60HZ = 0x23, DISP_TV_MOD_3840_2160P_50HZ = 0x24, DISP_TV_MOD_4096_2160P_50HZ = 0x25, DISP_TV_MOD_1280_1024P_60HZ = 0x41, DISP_TV_MOD_1024_768P_60HZ = 0x42, DISP_TV_MOD_900_540P_60HZ = 0x43, DISP_TV_MOD_1920_720P_60HZ = 0x44, DISP_TV_MOD_1024_600P = 0x45, DISP_TV_MOD_1280_800P = 0x46, DISP_TV_MOD_800_480P = 0x47,

shaddow501 commented 5 years ago

I just removed case DISP_TV_MOD_1024_600P: since I dont use it anyway

Should I get it back?

avafinger commented 5 years ago

yes

shaddow501 commented 5 years ago

Ok got it back and changed 0x45 to 0x47, trying to compile compile finish successfully now uploading to the SD card.

shaddow501 commented 5 years ago

After uploading the kernel it is stuck here:

** Unrecognized filesystem type **
load file(ULI/factory/snum.txt) error
Hit any key to stop autoboot:  2 [1.822][cpu1]fetch script data boot_disp.output_full fail
 0 
** Bad device mmc 2 **
reading bananapi/bpi-m64/linux4.4/720p/bpiEnv.txt
** Unable to read file bananapi/bpi-m64/linux4.4/720p/bpiEnv.txt **
reading bananapi/bpi-m64/linux4.4/bpiEnv.txt
** Unable to read file bananapi/bpi-m64/linux4.4/bpiEnv.txt **
reading bpiEnv.txt
** Unable to read file bpiEnv.txt **
reading bananapi/bpi-m64/linux4.4/720p/uEnv.txt
1891 bytes read in 14 ms (131.8 KiB/s)
Loaded environment from uEnv.txt
Running uenvcmd ...
Banana Pi bpi-m64 chip: r18 Service: linux4.4 bpiuser: 720p
reading bananapi/bpi-m64/linux4.4/uImage
7674233 bytes read in 341 ms (21.5 MiB/s)
reading bananapi/bpi-m64/linux4.4/uInitrd
5166907 bytes read in 231 ms (21.3 MiB/s)
## Booting kernel from Legacy Image at 45000000 ...
   Image Name:   AARCH64 Banana Pi Linux-4.4.89
   Image Type:   AArch64 Linux Kernel Image (gzip compressed)
   Data Size:    7674169 Bytes = 7.3 MiB
   Load Address: 40080000
   Entry Point:  40080000
   Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 49000000 ...
   Image Name:   uInitrd
   Image Type:   AArch64 Linux RAMDisk Image (gzip compressed)
   Data Size:    5166843 Bytes = 4.9 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
   reserving fdt memory region: addr=40020000 size=800
   reserving fdt memory region: addr=48000000 size=1000000
   reserving fdt memory region: addr=48100000 size=4000
   reserving fdt memory region: addr=48104000 size=1000
   reserving fdt memory region: addr=48105000 size=1000
   Loading Ramdisk to 5fb12000, end 5ffff6fb ... OK
   Using Device Tree in place at 44000000, end 44016c7f

Starting kernel ...

INFO:    BL3-1: Next image address = 0x40080000
INFO:    BL3-1: Next image spsr = 0x3c5

Could it be because of that?

define DEFAULT_PRINT_LEVLE 2

avafinger commented 5 years ago

Hmm, looks like broken... You have two choices: a) Restore screen0_output_mode = 5 and

define DEFAULT_PRINT_LEVLE 0

and Rebuild b) Restore to previous position and rebuild

The code

define DEFAULT_PRINT_LEVLE 2

Is just to print info and warnings

shaddow501 commented 5 years ago

I have changed it back to #define DEFAULT_PRINT_LEVLE 0 and it booted. but... screen is white again, interested with a picture?

I see in the first boot that the boot logo of the BPI is not centered, that means that it still do not get the resolution...

avafinger commented 5 years ago

screen0_output_mode = 5 ( = 720p) screen0_output_mode = 18 ( = 800x480P)

Ok, attach the picture.

avafinger commented 5 years ago

can you gz your /lib/firmware/edid/800x480.bin?

shaddow501 commented 5 years ago

I can do everything if you tell me how... Where is it? i dont see it on the current image are you referring to armbian?

avafinger commented 5 years ago

I tested here with #define DEFAULT_PRINT_LEVLE 2 and it freeze, weird thing.

Try again with screen0_output_mode = 18 ( = 800x480P)

define DEFAULT_PRINT_LEVLE 0

shaddow501 commented 5 years ago

Yes I did change it back to #define DEFAULT_PRINT_LEVLE 0 and it loaded at parameter 18. but white screen after u- 20190702_205023 boot.

shaddow501 commented 5 years ago

I really dont know what is harder to set the screen or fixing the battery issue in Armbian I dont care what image to use just that all will work :) edid.zip

Basically I prefer armbian since it is again light weight image and booting very fast, but no one can answer about the battery support....

avafinger commented 5 years ago

The Screen Image is different from the previous Image. Looks like the timings are wrong. You should search the internet and change the Timings. Maybe grab the timings from RPI forum and try again. If you find the right timings i recompile my IMG with that. If you don't get an answer in Armbian chances are no one got it working.

Free support is expensive in any place... ;)

avafinger commented 5 years ago

Read this: https://www.instructables.com/id/Orange-PI-HowTo-Set-It-Up-to-Use-With-a-5-HDMI-TFT/

avafinger commented 5 years ago

Did you set hdmi_cts_compatibility = 1 in the fex?

shaddow501 commented 5 years ago

yes I did

I also seen the post you mention and already tried it, but with banana Pi it just doesnt work...

avafinger commented 5 years ago

but with banana Pi it just doesnt work...

Actually is not the BananaPi the issue, is the Kernel version. Open this issue in BPI (https://github.com/BPI-SINOVOIP/BPI-M64-bsp-4.4), ask Dangku maybe he can help.

shaddow501 commented 5 years ago

I did open but you are the first one that takes this matter seriously :)

avafinger commented 5 years ago

Can you make this changes and give another try?

diff --git a/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.c b/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.c
index ed20de5..084c71a 100644
--- a/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.c
+++ b/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.c
@@ -98,6 +98,27 @@ struct disp_video_timings video_timing[] = {
            .trd_mode = 0,
        },
        {
+           .vic = HDMI800_480P,
+           .tv_mode = 0,
+           .pixel_clk = 27000000,
+           .pixel_repeat = 0,
+           .x_res = 800,
+           .y_res = 480,
+           .hor_total_time = 1028,
+           .hor_back_porch = 88,
+           .hor_front_porch = 80,
+           .hor_sync_time = 60,
+           .ver_total_time = 525,
+           .ver_back_porch = 29,
+           .ver_front_porch = 13,
+           .ver_sync_time = 3,
+           .hor_sync_polarity = 0,
+           .ver_sync_polarity = 0,
+           .b_interlace = 0,
+           .vactive_space = 0,
+           .trd_mode = 0,
+       },
+       {
            .vic = HDMI576P,
            .tv_mode = 0,
            .pixel_clk = 27000000,
diff --git a/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.h b/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.h
index 11f538e..d803c63 100644
--- a/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.h
+++ b/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.h
@@ -28,6 +28,7 @@
 #define HDMI1080P_24       32
 #define HDMI1080P_25       33
 #define HDMI1080P_30       34
+#define HDMI800_480P        35
 #define HDMI1080P_24_3D_FP  (HDMI1080P_24 + 0x80)
 #define HDMI720P_50_3D_FP   (HDMI720P_50 + 0x80)
 #define HDMI720P_60_3D_FP   (HDMI720P_60 + 0x80)
diff --git a/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_edid.c b/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_edid.c
index 1c4bc94..653735f 100644
--- a/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_edid.c
+++ b/linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_edid.c
@@ -150,6 +150,8 @@ static s32 edid_parse_dtd_block(u8 *pbuf)
            Device_Support_VIC[HDMI1440_480I] = 1;
        if ((sizex == 720) && (sizey == 480))
            /* Device_Support_VIC[HDMI480P] = 1; */
+        if ((sizex == 800) && (sizey == 480))
+           Device_Support_VIC[HDMI800_480P] = 1;
        if ((sizex == 1280) && (sizey == 720))
            Device_Support_VIC[HDMI720P_60] = 1;
        if ((sizex == 1920) && (sizey == 540))
avafinger commented 5 years ago

Also try without this:

shaddow501 commented 5 years ago

How? where?

avafinger commented 5 years ago

linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_edid.c and linux-sunxi/drivers/video/fbdev/sunxi/disp2/hdmi/hdmi_core.c

avafinger commented 5 years ago

Add the code with the PLUS (+)

avafinger commented 5 years ago

Worked?

shaddow501 commented 5 years ago

Ok, I did both of the options with the: if ((sizex == 800) && (sizey == 480)) Device_Support_VIC[HDMI800_480P] = 1;

and without, at boot I get the BPI logo ( not centered ) and when the kernel is loading I get white screen... same as before.

shaddow501 commented 5 years ago

Something strange, when I convert the sun50i-a64-bpi-m64-720p.dtb to dts file, I see even though before compilation I have set the screen0 mode to 18, in the dtb file it is on 5... I have no clue why it didnt change it.. I have changed this file:

sunxi-pack/allwinner/tulip-m64/configs/BPI-M64-720P/sys_config.fex

and when I compile I compile the 720P version...

avafinger commented 5 years ago

Right.

If i recall correctly, the BSP embed sunxi.dtb in the FAT partition. Check the file ./out/tulip-m64/image/sunxi.dtb , decompile and see what is the value.

Try also with the value of 69 instead of 18.

I get the BPI logo ( not centered )

We have some progress here, the kernel is switching to wrong display mode. Try with 69.

shaddow501 commented 5 years ago

Well I always did have the u boot first boot logo, the problem was after the kernel started to load than the screen went white and loose the signal.

I now instead of building kernel I first do clear all build so now I build it again

avafinger commented 5 years ago

Any news? I will put some effort to make it works only today.

shaddow501 commented 5 years ago

Well I think I recompile more than 100 times already but no change.

what do you mean to try 69? instead of 18, what 69 stands for?

avafinger commented 5 years ago

The last change you made to the sources, perhaps this is the correct video mode.

shaddow501 commented 5 years ago

Well i didnt see anything that related to 69 in the sources...

avafinger commented 5 years ago

Please, change it and see the results.

avafinger commented 5 years ago

try also 35.

shaddow501 commented 5 years ago

lol, you know that every change takes lots of time.. so it will take time to test it...

if i need to add it to the dtb file i need to change it to hex means that 69=0x45 , 18=0x12, 35= 0x23

avafinger commented 5 years ago

not to worry, you are the one that can test the changes, hopefully, 35 will work.

shaddow501 commented 5 years ago

I dont know why when I change in sys_config.fex to the right parameters and than compile again by pressing "1" than write use key number "7" to push it all to the SD, when I load and de- compile the dtb file to dts and enter it to see the values I see that that it is still on screen0 mode 5... I really dont know what am i missing here...

avafinger commented 5 years ago

sunxi.dtb?

shaddow501 commented 5 years ago

it is sun50i-a64-bpi-m64-720p.dtb located in the boot folder

avafinger commented 5 years ago

Then edit the dts (from decompile) and change it manually. Last time (year ago) i used tee BSP the resulting file was sunxi.dtb.

shaddow501 commented 5 years ago

but there i am not sure if I need to change to to HEX or just a number, any way both didnt work for me, not 18 & nor 35

avafinger commented 5 years ago

can you search for the files: sun50i-a64-bpi-m64-720p.dtb and sunxi.dtb

Check the date and time after a full build.

HEX or number i think does not matter.

shaddow501 commented 5 years ago

Yes but 18 in hex is 12 & 35 in hex is 23... so what to put lol anyway tried both without success.

shaddow501 commented 5 years ago

this is the sys_config.fex file:

;A64 PAD application
;---------------------------------------------------------------------------------------------------------
; 说明: 脚本中的字符串区分大小写,用户可以修改"="后面的数值,但是不要修改前面的字符串
; 描述gpio的形式:Port:端口+组内序号<功能分配><内部电阻状态><驱动能力><输出电平状态>
;---------------------------------------------------------------------------------------------------------

[product]
version = "100"
machine = "bpi-m64"

;---------------------------------------------------------------------------------------------------------
; eraseflag - 1 erase data partition, 0 - do not erase data partition
; next_work - action after burn, 0x0 by config, 0x1 normal, 0x2 reboot, 0x3 shutdown,0x4 reupdate ,0x5 boot
; debug_mode = 0 : do not print any message,debug_mode = 1 ,print debug message
;---------------------------------------------------------------------------------------------------------
[platform]
eraseflag   = 0
next_work   = 3
debug_mode  = 1

;---------------------------------------------------------------------------------------------------------
; dragonboard_test default is 0,only in dragonboard card boot mode must be set 1
; If you modified dragonboard_test flag,before you pack imgage, you must be build kernel again.
;---------------------------------------------------------------------------------------------------------
[target]
boot_clock       = 1008
storage_type     = -1
burn_key         = 1
dragonboard_test = 0

;----------------------------------------------------------------------------------
;   system configuration
;   ?
;dcdc1_vol                                                     ---set dcdc1 voltage,mV,1600-3400,100mV/step
;dcdc2_vol                                                     ---set dcdc2 voltage,mV,600-1540,20mV/step
;dcdc3_vol                                                     ---set dcdc3 voltage,mV,600-1860,20mV/step
;dcdc4_vol                                                     ---set dcdc4 voltage,mV,600-1540,20mV/step
;dcdc5_vol                                                     ---set dcdc5 voltage,mV,1000-2550,50mV/step
;aldo2_vol                                                     ---set aldo2 voltage,mV,700-3300,100mV/step
;aldo3_vol                                                     ---set aldo3 voltage,mV,700-3300,100mV/step
;----------------------------------------------------------------------------------

[power_sply]
dcdc1_vol                  = 1003300
dcdc2_vol                  = 1001100
dcdc3_vol                  = 1001100
dcdc4_vol                  = 1100
dcdc5_vol                  = 1001500
dcdc6_vol                  = 1001100
aldo1_vol                  = 1002800
aldo2_vol                  = 1003300
aldo3_vol                  = 1003000
dldo1_vol                  = 1003300
dldo2_vol                  = 1003300
dldo3_vol                  = 1002800
dldo4_vol                  = 1003300
eldo1_vol                  = 1001800
eldo2_vol                  = 1800
eldo3_vol                  = 1001500
fldo2_vol                  = 1001100
gpio0_vol                  = 1003300
gpio1_vol                  = 2800
dc1sw_vol                  = 1002500

[card_boot]
logical_start   = 40960
sprite_gpio0    =

;---------------------------------------------------------------------------------------------------------
; if 1 == standby_mode, then support super standby;
; else, support normal standby.
;---------------------------------------------------------------------------------------------------------
[pm_para]
standby_mode           = 1

[card0_boot_para]
card_ctrl       = 0
card_high_speed = 1
card_line       = 4
sdc_d1          = port:PF0<2><1><2><default>
sdc_d0          = port:PF1<2><1><2><default>
sdc_clk         = port:PF2<2><1><2><default>
sdc_cmd         = port:PF3<2><1><2><default>
sdc_d3          = port:PF4<2><1><2><default>
sdc_d2          = port:PF5<2><1><2><default>

[card2_boot_para]
;sdc_io_1v8      = 1
card_ctrl       = 2
card_high_speed = 1
card_line       = 8
sdc_ds          = port:PC1<3><1><3><default>
sdc_clk         = port:PC5<3><1><3><default>
sdc_cmd         = port:PC6<3><1><3><default>
sdc_d0          = port:PC8<3><1><3><default>
sdc_d1          = port:PC9<3><1><3><default>
sdc_d2          = port:PC10<3><1><3><default>
sdc_d3          = port:PC11<3><1><3><default>
sdc_d4          = port:PC12<3><1><3><default>
sdc_d5          = port:PC13<3><1><3><default>
sdc_d6          = port:PC14<3><1><3><default>
sdc_d7          = port:PC15<3><1><3><default>
sdc_emmc_rst    = port:PC16<3><1><3><default>
sdc_ex_dly_used = 2

[twi_para]
twi_port        = 0
twi_scl         = port:PH0<2><default><default><default>
twi_sda         = port:PH1<2><default><default><default>

[uart_para]
uart_debug_port = 0
uart_debug_tx   = port:PB8<4><1><default><default>
uart_debug_rx   = port:PB9<4><1><default><default>

[jtag_para]
jtag_enable     = 0
jtag_ms         = port:PB0<4><default><default><default>
jtag_ck         = port:PB1<4><default><default><default>
jtag_do         = port:PB2<4><default><default><default>
jtag_di         = port:PB3<4><default><default><default>

;----------------------------------------------------------------------------------
;
;LED support
;----------------------------------------------------------------------------------
[led_para]
compatible              = "allwinner,sunxi-leds"
led_used        = 1
led_num         = 3
led1            = port:PD24<1><default><default><default>
led1_trigger        = "default-on"
led2            = port:PE14<1><default><default><default>
led2_trigger        = "heartbeat"
led3            = port:PE15<1><default><default><default>
led3_trigger        = "default-on"

[clock]
pll4            = 300
pll6            = 600
pll8            = 360
pll9            = 297
pll10           = 264

;*****************************************************************************
;sdram configuration
;
;*****************************************************************************
[dram_para]

dram_clk        = 576
dram_type       = 3
dram_zq         = 0x3b3bbb
dram_odt_en     = 0x1
dram_para1      = 0x10E410E4
dram_para2      = 0x1000
dram_mr0        = 0x1840
dram_mr1        = 0x40
dram_mr2        = 0x18
dram_mr3        = 0x2
dram_tpr0       = 0x004A2195
dram_tpr1       = 0x02424190
dram_tpr2       = 0x0008B060
dram_tpr3       = 0x050005dc
dram_tpr4       = 0x0
dram_tpr5       = 0x0
dram_tpr6       = 0x0
dram_tpr7       = 0x2a066198
dram_tpr8       = 0x0
dram_tpr9       = 0x0
dram_tpr10      = 0x8808
dram_tpr11      = 0x00004444
dram_tpr12      = 0x55550000
dram_tpr13      = 0x04000900

;----------------------------------------------------------------------------------
;os life cycle para configuration
;----------------------------------------------------------------------------------

;------------------------------------------------------------------------------;
; 10/100/100Mbps Ethernet MAC Controller Configure                             ;
;------------------------------------------------------------------------------;
;   配置选项:                                                                 ;
;   gmac_used  ---  1: gmac used, 0: not used                                  ;
;   gmac_powerx --  A[:B] A: axp channel, B: voltage value                     ;
;   phy-mode    --  rgmii, rmii, mii                                           ;
;   tx-delay    --  transmit clock delay: 0~7                                  ;
;   rx-delay    --  receive clock delay:  0~31                                 ;
;------------------------------------------------------------------------------;
;         MII        RGMII        MII        RGMII        MII        RGMII     ;
;PD02~05  *            *    PD15   *                PD22   *           *       ;
;   PD06  *            *    PD16                    PD23   *           *       ;
;   PD07  *            *    PD17                    PD24                       ;
;   PD08                    PD18   *           *    PD25                       ;
;   PD09                    PD19   *           *    PD26                       ;
;   PD10  *                 PD20   *                PD26                       ;
;PD11~14  *            *    PD21   *           *    PD28                       ;
;------------------------------------------------------------------------------;
[gmac0]
gmac0_used         = 1
phy-mode           = "rgmii"
gmac_rxd3          = port:PD08<4><default><3><default>
gmac_rxd2          = port:PD09<4><default><3><default>
gmac_rxd1          = port:PD10<4><default><3><default>
gmac_rxd0          = port:PD11<4><default><3><default>
gmac_rxclk         = port:PD12<4><default><3><default>
gmac_rxdv          = port:PD13<4><default><3><default>
gmac_rxerr         = port:PD14<4><default><3><default>
gmac_txd3          = port:PD15<4><default><3><default>
gmac_txd2          = port:PD16<4><default><3><default>
gmac_txd1          = port:PD17<4><default><3><default>
gmac_txd0          = port:PD18<4><default><3><default>
gmac_txclk         = port:PD19<4><default><3><default>
gmac_txen          = port:PD20<4><default><3><default>
gmac_clkin         = port:PD21<4><default><3><default>
gmac_mdc           = port:PD22<4><default><3><default>
gmac_mdio          = port:PD23<4><default><3><default>
gmac-power0        = "vcc-ephy0"
gmac-power1        = "vcc-ephy1"
gmac-power2        = ""
tx-delay           = 4
rx-delay           = 0

;----------------------------------------------------------------------------------
;i2c configuration
;----------------------------------------------------------------------------------
[twi0]
twi0_used        = 1
twi0_scl         = port:PH0<2><default><default><default>
twi0_sda         = port:PH1<2><default><default><default>

[twi1]
twi1_used        = 1
twi1_scl         = port:PH2<2><default><default><default>
twi1_sda         = port:PH3<2><default><default><default>

[twi2]
twi2_used        = 1
twi2_scl         = port:PE14<3><default><default><default>
twi2_sda         = port:PE15<3><default><default><default>

;----------------------------------------------------------------------------------
;TWI device configuration
;compatible        --- device name
;reg               --- device address
;----------------------------------------------------------------------------------
;[twi0/twi_board0]
;compatible        =
;reg               =

;----------------------------------------------------------------------------------
;uart configuration
;uart_port ---  x (/dev/ttySx, x=0,1,2,...)
;uart_type ---  2 (2 wire), 4 (4 wire), 8 (8 wire, full function)
;----------------------------------------------------------------------------------
[uart0]
uart0_used       = 1
uart0_port       = 0
uart0_type       = 2
uart0_tx         = port:PB8<4><1><default><default>
uart0_rx         = port:PB9<4><1><default><default>

[uart1]
uart1_used       = 1
uart1_port       = 1
uart1_type       = 4
uart1_tx         = port:PG6<2><1><default><default>
uart1_rx         = port:PG7<2><1><default><default>
uart1_rts        = port:PG8<2><1><default><default>
uart1_cts        = port:PG9<2><1><default><default>

[uart2]
uart2_used       = 1
uart2_port       = 2
uart2_type       = 4
uart2_tx         = port:PB0<2><1><default><default>
uart2_rx         = port:PB1<2><1><default><default>
uart2_rts        = port:PB2<2><1><default><default>
uart2_cts        = port:PB3<2><1><default><default>

[uart3]
uart3_used       = 0
uart3_port       = 3
uart3_type       = 4
uart3_tx         = port:PH4<2><1><default><default>
uart3_rx         = port:PH5<2><1><default><default>
uart3_rts        = port:PH6<2><1><default><default>
uart3_cts        = port:PH7<2><1><default><default>

[uart4]
uart4_used       = 0
uart4_port       = 4
uart4_type       = 4
uart4_tx         = port:PD2<3><1><default><default>
uart4_rx         = port:PD3<3><1><default><default>
uart4_rts        = port:PD4<3><1><default><default>
uart4_cts        = port:PD5<3><1><default><default>

;----------------------------------------------------------------------------------
;SPI controller configuration
;----------------------------------------------------------------------------------
[spi0]
spi0_used       = 0
spi0_cs_number  = 1
spi0_cs_bitmap  = 1
spi0_cs0        = port:PC3<4><1><default><default>
spi0_sclk       = port:PC2<4><default><default><default>
spi0_mosi       = port:PC0<4><default><default><default>
spi0_miso       = port:PC1<4><default><default><default>

[spi1]
spi1_used       = 1
spi1_cs_number  = 1
spi1_cs_bitmap  = 1
spi1_cs0        = port:PD0<4><1><default><default>
spi1_sclk       = port:PD1<4><default><default><default>
spi1_mosi       = port:PD2<4><default><default><default>
spi1_miso       = port:PD3<4><default><default><default>

;----------------------------------------------------------------------------------
;SPI device configuration
;compatible        --- device name
;spi-max-frequency --- work frequency
;reg               --- chip select
;optional properties: spi-cpha, spi-cpol, spi-cs-high
;----------------------------------------------------------------------------------
;[spi0/spi_board0]
compatible        = spidev
;spi-max-frequency =
;reg               =
;spi-cpha
;spi-cpol
;spi-cs-high

;----------------------------------------------------------------------------------
;resistance tp configuration
;----------------------------------------------------------------------------------
[rtp_para]
rtp_used      = 0
rtp_screen_size = 5
rtp_regidity_level = 5
rtp_press_threshold_enable = 0
rtp_press_threshold = 0x1f40
rtp_sensitive_level = 0xf
rtp_exchange_x_y_flag = 0

;----------------------------------------------------------------------------------
;capacitor tp configuration
;external int function
;wakeup output function
;notice ---    tp_int_port &  tp_io_port use the same port
;----------------------------------------------------------------------------------
[ctp]
compatible      = "allwinner,sun50i-ctp-para"
ctp_used            = 0
ctp_name        = "bpi_lcd7"
ctp_twi_id          = 0
ctp_twi_addr        = 0x5d
ctp_screen_max_x    = 800
ctp_screen_max_y    = 480
ctp_revert_x_flag   = 0
ctp_revert_y_flag   = 0
ctp_exchange_x_y_flag = 0

ctp_int_port        = port:PH04<6><default><default><default>
ctp_wakeup          = port:PH08<1><default><default><default>
ctp_power_ldo       = ""
ctp_power_ldo_vol   = 3300
ctp_power_io        =

;--------------------------------------------------------------------------------
; CTP automatic detection configuration
;ctp_detect_used  --- Whether startup automatic inspection function. 1:used,0:unused
;Module name postposition 1 said detection, 0 means no detection.
;--------------------------------------------------------------------------------
[ctp_list]
compatible        = "allwinner,sun50i-ctp-list"
ctp_list_used             = 1
ft5x16_ts                 = 1
gslX680new        = 0
gt9xx_ts                  = 1
gt9xxnew_ts       = 1
gt82x                     = 0
zet622x                   = 0
aw5306_ts                 = 0

;----------------------------------------------------------------------------------
;touch key configuration
;----------------------------------------------------------------------------------
[tkey_para]
tkey_used           = 0
tkey_twi_id         =
tkey_twi_addr       =
tkey_int            =

;----------------------------------------------------------------------------------
;motor configuration
;----------------------------------------------------------------------------------
[motor_para]
motor_used          = 0
motor_shake         = port:power3<1><default><default><1>

;----------------------------------------------------------------------------------
; nand0_dragonboard  default is 0,only in dragonboard card boot mode must be set 1
;----------------------------------------------------------------------------------
[nand0_para]
nand0_dragonboard = 0
nand0_support_2ch    = 0

nand0_used          = 1
nand0_we            = port:PC00<2><0><1><default>
nand0_ale           = port:PC01<2><0><1><default>
nand0_cle           = port:PC02<2><0><1><default>
nand0_ce1           = port:PC03<2><1><1><default>
nand0_ce0           = port:PC04<2><1><1><default>
nand0_nre           = port:PC05<2><0><1><default>
nand0_rb0           = port:PC06<2><1><1><default>
nand0_rb1           = port:PC07<2><1><1><default>
nand0_d0            = port:PC08<2><0><1><default>
nand0_d1            = port:PC09<2><0><1><default>
nand0_d2            = port:PC10<2><0><1><default>
nand0_d3            = port:PC11<2><0><1><default>
nand0_d4            = port:PC12<2><0><1><default>
nand0_d5            = port:PC13<2><0><1><default>
nand0_d6            = port:PC14<2><0><1><default>
nand0_d7            = port:PC15<2><0><1><default>
nand0_ndqs          = port:PC16<2><0><1><default>
nand0_ce2           = port:PC17<2><1><1><default>
nand0_ce3           = port:PC18<2><1><1><default>

nand0_regulator1        = "vcc-nand"
nand0_regulator2        = "none"
nand0_cache_level = 0x55aaaa55
nand0_flush_cache_num = 0x55aaaa55
nand0_capacity_level = 0x55aaaa55
nand0_id_number_ctl = 0x55aaaa55
nand0_print_level = 0x55aaaa55
nand0_p0 = 0x55aaaa55
nand0_p1 = 0x55aaaa55
nand0_p2 = 0x55aaaa55
nand0_p3 = 0x55aaaa55

;----------------------------------------------------------------------------------
;disp init configuration
;
;disp_mode             (0:screen0<screen0,fb0>)
;screenx_output_type   (0:none; 1:lcd; 3:hdmi;)
;screenx_output_mode   (used for hdmi output, 0:480i 1:576i 2:480p 3:576p 4:720p50)
;                      (5:720p60 6:1080i50 7:1080i60 8:1080p24 9:1080p50 10:1080p60)
;fbx format           (0:ARGB 1:ABGR 2:RGBA 3:BGRA 5:RGB565 8:RGB888 12:ARGB4444 16:ARGB1555 18:RGBA5551)
;fbx_width,fbx_height (framebuffer horizontal/vertical pixels, fix to output resolution while equal 0)
;----------------------------------------------------------------------------------
[disp]
disp_init_enable         = 1
disp_mode                = 0

screen0_output_type      = 3
screen0_output_mode      = 35

screen1_output_type      = 3
screen1_output_mode      = 35

fb0_format               = 0
fb0_width                = 0
fb0_height               = 0
;fb0_pixel_sequence       = 0
;fb0_scaler_mode_enable   = 0

fb1_format               = 0
fb1_width                = 0
fb1_height               = 0

;----------------------------------------------------------------------------------
;lcd0 configuration

;lcd_if:               0:hv(sync+de); 1:8080; 2:ttl; 3:lvds; 4:dsi; 5:edp
;lcd_backlight         lcd init backlight
;lcd_x:                lcd horizontal resolution
;lcd_y:                lcd vertical resolution
;lcd_width:            width of lcd in mm
;lcd_height:           height of lcd in mm
;lcd_dclk_freq:        in MHZ unit
;lcd_pwm_freq:         in HZ unit
;lcd_pwm_pol:          lcd backlight PWM polarity
;lcd_pwm_max_limit     lcd backlight PWM max limit(<=255)
;lcd_hbp:              hsync back porch
;lcd_ht:               hsync total cycle
;lcd_vbp:              vsync back porch
;lcd_vt:               vysnc total cycle
;lcd_hspw:             hsync plus width
;lcd_vspw:             vysnc plus width
;lcd_lvds_if:          0:single link;  1:dual link
;lcd_lvds_colordepth:  0:8bit; 1:6bit
;lcd_lvds_mode:        0:NS mode; 1:JEIDA mode
;lcd_frm:              0:disable; 1:enable rgb666 dither; 2:enable rgb656 dither
;lcd_hv_clk_phase      lcd hv panel lock phase, 0:0 degree; 1:90 degree; 2: 180 degree; 3: 270 degree
;lcd_hv_sync_polarity  lcd hv panel sync signals polarity
;                      0:vsync active low, hsync active low; 1:vsync active high, hsync active low
;                      2:vsync active low, hsync active high; 3:vsync active high, hsync active high
;lcd_gamma_en          lcd gamma correction enable
;lcd_bright_curve_en   lcd bright curve correction enable
;lcd_cmap_en           lcd color map function enable
;----------------------------------------------------------------------------------
[lcd0]
lcd_used            = 0
lcd_driver_name     = "S070WV20_MIPI_RGB"

lcd_bl_0_percent    = 0
lcd_bl_40_percent   = 23
lcd_bl_100_percent  = 100

lcd_backlight       = 180
lcd_if              = 4
lcd_x               = 800
lcd_y               = 480
lcd_width           = 86
lcd_height          = 154
lcd_dclk_freq       = 30
lcd_pwm_used        = 1
lcd_pwm_ch          = 16
lcd_pwm_freq        = 50000
lcd_pwm_pol         = 1
lcd_pwm_max_limit   = 255
lcd_hbp             = 88
lcd_ht              = 928
lcd_hspw            = 48
lcd_vbp             = 32
lcd_vt              = 525
lcd_vspw            = 3
lcd_lvds_if         = 0
lcd_lvds_colordepth = 0
lcd_lvds_mode       = 0
lcd_frm             = 0
lcd_hv_clk_phase    = 0
lcd_hv_sync_polarity= 0
lcd_dsi_if          = 0
lcd_dsi_lane        = 4
lcd_dsi_format      = 0
lcd_dsi_te          = 0
lcd_gamma_en        = 0
lcd_bright_curve_en = 0
lcd_cmap_en         = 0

;rst
lcd_gpio_0          = port:PD6<1><0><default><1>

;power enable
lcd_gpio_1          = port:PD7<1><0><default><1>
lcd_bl_en           = port:PD5<1><0><default><1>

lcd_power     = "vcc-dsi-33"
;lcd_power1    = "vcc-lcd"
;lcd_fix_power = "vcc-dsi-33"
lcd_pin_power = "vcc-pd"

[backlight]
backlight_used  = 0
pwm_ch      = 16
pwm_pol         = 1
pwm_freq    = 50000
dft_brightness  = 150
lth_brightness  = 50
power_name  = "vcc-pd"
bl_enable   = port:PD5<1><0><default><0>

[hdmi]
hdmi_used = 1
hdmi_power = "vcc-hdmi-33"
hdmi_hdcp_enable = 0
hdmi_cts_compatibility = 1

;----------------------------------------------------------------------------------
;pwm config
;----------------------------------------------------------------------------------
[pwm0]
pwm_used            = 0
pwm_positive        = port:PD22<2><0><default><default>

[pwm0_suspend]
pwm_positive        = port:PD22<7><0><default><default>

[spwm0]
s_pwm_used         = 1
pwm_positive        = port:PL10<2><0><default><default>

[spwm0_suspend]
pwm_positive        = port:PL10<7><0><default><default>

;-----------------------------------------------------------------
;advert_disp  -   1: can used app to change bootlogo, 0:not used
;auto_hpd     -   1:need hotplud for hdmi/tv;  0:don't hotplud for lcd
;output_type  -   0:none; 1:lcd; 2:tv; 3:hdmi; 4:vga (as default config in homlet)
;hdmi_channel -   the display channel for hdmi (as default config in homlet)
;cvbs_channel -   the display channel for cvbs (as default config in homlet)
;hdmi_mode    -   as default config for output of hdmi in homlet
;cvbs_mode    -   as default config for output of tv in homlet. 11:PAL; 14:NTSC
;hdmi_mode_check - disable/enable the function of checking hdmi mode, 0 is disable, 1 is enable
;-----------------------------------------------------------------
**[boot_disp]
**output_disp = 0
output_type = 3
output_mode = 5**   ------------ when it is set like this I see the boot logo on the side (after I modified the boot logo to be 800x480).
when I set this value to 18  or 35 or 69 I dont have any boot logo and the screen stay white.**

;--------------------------------------------------------------------------------
;csi (COMS Sensor Interface) configuration
;csi(x)_dev(x)_used: 0:disable 1:enable
;csi(x)_dev(x)_isp_used 0:not use isp 1:use isp
;csi(x)_dev(x)_fmt: 0:yuv 1:bayer raw rgb
;csi(x)_dev(x)_stby_mode: 0:not shut down power at standby 1:shut down power at standby
;csi(x)_dev(x)_vflip: flip in vertical direction 0:disable 1:enable
;csi(x)_dev(x)_hflip: flip in horizontal direction 0:disable 1:enable
;csi(x)_dev(x)_iovdd: camera module io power handle string, pmu power supply
;csi(x)_dev(x)_iovdd_vol: camera module io power voltage, pmu power supply
;csi(x)_dev(x)_avdd:    camera module analog power handle string, pmu power supply
;csi(x)_dev(x)_avdd_vol:        camera module analog power voltage, pmu power supply
;csi(x)_dev(x)_dvdd:    camera module core power handle string, pmu power supply
;csi(x)_dev(x)_dvdd_vol:        camera module core power voltage, pmu power supply
;csi(x)_dev(x)_afvdd:   camera module vcm power handle string, pmu power supply
;csi(x)_dev(x)_afvdd_vol:       camera module vcm power voltage, pmu power supply
;fill voltage in uV, e.g. iovdd = 2.8V, csix_iovdd_vol = 2800000
;fill handle string as below:
;axp22_eldo3
;axp22_dldo4
;axp22_eldo2
;fill handle string "" when not using any pmu power supply
;--------------------------------------------------------------------------------

[csi0]
csi0_used               = 1
csi0_sensor_list        = 0
csi0_pck                = port:PE00<2><default><default><default>
csi0_mck                = port:PE01<2><default><default><default>
csi0_hsync              = port:PE02<2><default><default><default>
csi0_vsync              = port:PE03<2><default><default><default>
csi0_d0                 = port:PE04<2><default><default><default>
csi0_d1                 = port:PE05<2><default><default><default>
csi0_d2                 = port:PE06<2><default><default><default>
csi0_d3                 = port:PE07<2><default><default><default>
csi0_d4                 = port:PE08<2><default><default><default>
csi0_d5                 = port:PE09<2><default><default><default>
csi0_d6                 = port:PE10<2><default><default><default>
csi0_d7                 = port:PE11<2><default><default><default>
csi0_sck                = port:PE12<2><default><default><default>
csi0_sda                = port:PE13<2><default><default><default>

[csi0/csi0_dev0]
csi0_dev0_used          = 1
csi0_dev0_mname         = "ov5640"
csi0_dev0_twi_addr      = 0x78
csi0_dev0_pos           = "rear"
csi0_dev0_isp_used      = 0
csi0_dev0_fmt           = 0
csi0_dev0_stby_mode     = 0
csi0_dev0_vflip         = 0
csi0_dev0_hflip         = 0
csi0_dev0_iovdd         = "avdd-csi"
csi0_dev0_iovdd_vol      = 2800000
csi0_dev0_avdd          = "avdd-csi"
csi0_dev0_avdd_vol      = 2800000
csi0_dev0_dvdd          = "dvdd-csi-18"
csi0_dev0_dvdd_vol      = 1500000
csi0_dev0_afvdd         = "avdd-csi"
csi0_dev0_afvdd_vol     = 2800000
csi0_dev0_power_en      =
csi0_dev0_reset         = port:PE16<1><0><1><0>
csi0_dev0_pwdn          = port:PE17<1><0><1><0>
csi0_dev0_flash_used    = 0
csi0_dev0_flash_type    = 2
csi0_dev0_flash_en      =
csi0_dev0_flash_mode    =
csi0_dev0_flvdd     = ""
csi0_dev0_flvdd_vol     =
csi0_dev0_af_pwdn       =
csi0_dev0_act_used      = 0
csi0_dev0_act_name      = "ad5820_act"
csi0_dev0_act_slave     = 0x18

[csi0/csi0_dev1]
csi0_dev1_used          = 0
csi0_dev1_mname         = "gc0328c"
csi0_dev1_twi_addr      = 0x42
csi0_dev1_pos           = "front"
csi0_dev1_isp_used      = 1
csi0_dev1_fmt           = 0
csi0_dev1_stby_mode     = 1
csi0_dev1_vflip         = 0
csi0_dev1_hflip         = 0
csi0_dev1_iovdd         = "iovdd-csi"
csi0_dev1_iovdd_vol     = 2800000
csi0_dev1_avdd          = "avdd-csi"
csi0_dev1_avdd_vol      = 2800000
csi0_dev1_dvdd          = "dvdd-csi-18"
csi0_dev1_dvdd_vol      = 1800000
csi0_dev1_afvdd         = ""
csi0_dev1_afvdd_vol     =
csi0_dev1_power_en      =
csi0_dev1_reset         =
csi0_dev1_pwdn          =
csi0_dev1_flash_used    = 0
csi0_dev1_flash_type    = 2
csi0_dev1_flash_en      =
csi0_dev1_flash_mode    =
csi0_dev1_flvdd     = "vdd-csi-led"
csi0_dev1_flvdd_vol     = 3300000
csi0_dev1_af_pwdn       =
csi0_dev1_act_used      = 0
csi0_dev1_act_name      = "ad5820_act"
csi0_dev1_act_slave     = 0x18

;--------------------------------------------------------------------------------
;tv configuration
;
;--------------------------------------------------------------------------------
[tvout_para]
tvout_used          =
tvout_channel_num   =
tv_en               =

[tvin_para]
tvin_used           =
tvin_channel_num    =

; ------------------------------------------------------------------------------|
; de-interlace configuration
;--------------------------------------------------------------------------------
[di]
di_used             = 0

;--------------------------------------------------------------------------------
;   SDMMC PINS MAPPING                                                          |
; ------------------------------------------------------------------------------|
;   Config Guide                                                                |
;   sdc_used: 1-enable card, 0-disable card                                     |
;   non-removable:if you use as main memory,you should set it,for example eMMC  |
;   bus-width: card bus width, 1-1bit, 4-4bit, 8-8bit                           |
;   sunxi-power-save-mode: if use sdio card,should not set it                   |
;   vmmc:regulator for card/emmc power                      |
;    vqmmc:regulator for card/emmc io power                 |
;    vdmmc:regulator for card detect pin pull up power              |
;   other: GPIO Mapping configuration                                           |
; ------------------------------------------------------------------------------|
;   Note:                                                                       |
;                                       |
;                                       |
;                                       |
;                                       |
;                                       |
;                                       |
;--------------------------------------------------------------------------------

[sdc0]
sdc0_used          = 1
bus-width             = 4
sdc0_d1            = port:PF00<2><1><2><default>
sdc0_d0            = port:PF01<2><1><2><default>
sdc0_clk           = port:PF02<2><1><2><default>
sdc0_cmd           = port:PF03<2><1><2><default>
sdc0_d3            = port:PF04<2><1><2><default>
sdc0_d2            = port:PF05<2><1><2><default>
cd-gpios           = port:PF06<0><1><2><default>
sunxi-power-save-mode =
sunxi-dis-signal-vol-sw =
vmmc="vcc-sdcv"
vqmmc="vcc-sdcvq33"
vdmmc="vcc-sdcvd"

[sdc1]
sdc1_used          = 1
bus-width   = 4
sdc1_clk           = port:PG00<2><1><3><default>
sdc1_cmd           = port:PG01<2><1><3><default>
sdc1_d0            = port:PG02<2><1><3><default>
sdc1_d1            = port:PG03<2><1><3><default>
sdc1_d2            = port:PG04<2><1><3><default>
sdc1_d3            = port:PG05<2><1><3><default>
;sunxi-power-save-mode =
sd-uhs-sdr50            =
sd-uhs-ddr50            =
sd-uhs-sdr104           =
cap-sdio-irq            =
keep-power-in-suspend   =
ignore-pm-notify    =
max-frequency      = 150000000

[sdc2]
sdc2_used          = 1
non-removable   =
bus-width    = 8
sdc2_ds            = port:PC01<3><1><3><default>
sdc2_clk           = port:PC05<3><1><3><default>
sdc2_cmd           = port:PC06<3><1><3><default>
sdc2_d0            = port:PC08<3><1><3><default>
sdc2_d1            = port:PC09<3><1><3><default>
sdc2_d2            = port:PC10<3><1><3><default>
sdc2_d3            = port:PC11<3><1><3><default>
sdc2_d4            = port:PC12<3><1><3><default>
sdc2_d5            = port:PC13<3><1><3><default>
sdc2_d6            = port:PC14<3><1><3><default>
sdc2_d7            = port:PC15<3><1><3><default>
sdc2_emmc_rst      = port:PC16<3><1><3><default>
cd-gpios       =
sunxi-power-save-mode =
sunxi-dis-signal-vol-sw =
;mmc-ddr-1_8v      =
;mmc-hs200-1_8v    =
;mmc-hs400-1_8v    =
max-frequency      = 100000000
sdc_tm4_sm0_freq0 = 0
sdc_tm4_sm0_freq1 = 0
sdc_tm4_sm1_freq0 = 0x00000000
sdc_tm4_sm1_freq1 = 0
sdc_tm4_sm2_freq0 = 0x00000000
sdc_tm4_sm2_freq1 = 0
sdc_tm4_sm3_freq0 = 0x05000000
sdc_tm4_sm3_freq1 = 0x00000405
sdc_tm4_sm4_freq0 = 0x00050000
sdc_tm4_sm4_freq1 = 0x00000408
vmmc="vcc-emmcv"
;vqmmc="vcc-emmcvq33"
vqmmc="vcc-emmcvq18"
vdmmc="none"

;[mmc3]
;mmc3_used          = 0
;mmc3_detmode       = 2
;mmc3_buswidth      = 4
;mmc3_clk           = port:PA10<2><1><2><default>
;mmc3_cmd           = port:PA09<2><1><2><default>
;mmc3_d0            = port:PA11<2><1><2><default>
;mmc3_d1            = port:PA12<2><1><2><default>
;mmc3_d2            = port:PA13<2><1><2><default>
;mmc3_d3            = port:PA14<2><1><2><default>
;mmc3_det           =
;mmc3_use_wp        = 0
;mmc3_wp            =
;mmc3_isio          = 0
;mmc3_regulator     = "none"

; ------------------------------------------------------------------------------|
; sim card configuration
;--------------------------------------------------------------------------------
[smc]
smc_used            =
smc_rst             =
smc_vppen           =
smc_vppp            =
smc_det             =
smc_vccen           =
smc_sck             =
smc_sda             =

;--------------------------------
;[usbc0]: usbc0 configuration.
;usb_used: usb controller enable. 0-disable, 1-enable.
;usb_port_type: usb mode. 0-device, 1-host, 2-otg.
;usb_detect_type: usb hotplug detect mode. 0-none, 1-vbus/id detect, 2-id/dpdm detect.
;usb_detect_mode: usb otg switch has two config. 0-thread scan, 1-id gpio interrupt.
;usb_id_gpio: usb id detect IO.
;usb_det_vbus_gpio: USB DET_VBUS has two config. (1)gpio pin; (2)"axp_ctrl", use axp intf.
;usb_drv_vbus_gpio: USB DRY_VBUS has two config. (1)gpio pin; (2)"axp_ctrl", use axp intf.
;--------------------------------
;--------------------------------
;---       USB0 CONFIG
;--------------------------------
[usbc0]
usbc0_used          = 1
usb_port_type       = 2
usb_detect_type     = 1
usb_id_gpio         = port:PH09<0><1><default><default>
usb_det_vbus_gpio   = "axp_ctrl"
usb_drv_vbus_gpio   = "axp_ctrl"
usb_host_init_state = 0
usb_regulator_io    = "nocare"
usb_wakeup_suspend  = 0
;---       USB Device
usb_luns            = 3
usb_serial_unique   = 1
usb_serial_number   = "20080411"
rndis_wceis         = 1

;--------------------------------
;---       USB1 CONFIG
;--------------------------------
[usbc1]
usbc1_used                     = 1
usb_drv_vbus_gpio              =
usb_host_init_state            = 1
usb_regulator_io               = "nocare"
usb_wakeup_suspend             = 0
;---  HSIC config
usb_hsic_used                  = 0
usb_hsic_regulator_io          = "vcc-hsic-12"
;---  Marvell 4G HSIC
usb_hsic_ctrl                  = 0
usb_hsic_rdy_gpio              =
;---  SMSC usb3503 HSIC HUB
usb_hsic_usb3503_flag          = 0
usb_hsic_hub_connect_gpio      =
usb_hsic_int_n_gpio            =
usb_hsic_reset_n_gpio          =

;--------------------------------
;---     序列号标志
;--------------------------------
[serial_feature]
sn_filename = "ULI/factory/snum.txt"

;--------------------------------------------------------------------------------
; G sensor configuration
; gs_twi_id    ---  TWI ID for controlling Gsensor (0: TWI0, 1: TWI1, 2: TWI2)
;--------------------------------------------------------------------------------
[gsensor]
compatible          = "allwinner,sun50i-gsensor-para"
gsensor_used        = 0
gsensor_twi_id      = 1
gsensor_twi_addr    = 0x1d
gsensor_vcc_io      = "vcc-io"
gsensor_vcc_io_val  = 3300
gsensor_int1        = port:PH05<6><1><default><default>
gsensor_int2        = port:PH06<6><1><default><default>

;--------------------------------------------------------------------------------
; G sensor automatic detection configuration
;gsensor_detect_used  --- Whether startup automatic inspection function. 1:used,0:unused
;Module name postposition 1 said detection, 0 means no detection.
;--------------------------------------------------------------------------------
[gsensor_list]
compatible                = "allwinner,sun50i-gsensor-list-para"
gsensor_list_used          = 0
lsm9ds0_acc_mag           = 0
bma250                    = 1
mma8452                   = 0
mma7660                   = 0
mma865x                   = 0
afa750                    = 0
lis3de_acc                = 0
lis3dh_acc                = 0
kxtik                     = 0
dmard10                   = 0
dmard06                   = 0
mxc622x                   = 0
fxos8700                  = 0
lsm303d                   = 0
sc7a30                    = 0

;--------------------------------------------------------------------------------
;wlan configuration
;wlan_used:         0-not use, 1- use
;wlan_busnum:       sdio/usb index
;clocks:            external low power clock input (32.768KHz)
;wlan_power_enable  gpio to enable wlan power supply
;wlan_power_num     the number of wlan power supply
;wlan_power:        input supply voltage
;wlan_io_regulator: wlan/sdio I/O voltage
;wlan_regon:        power up/down internal regulators used by wifi section
;wlan_hostwake:     wlan to wake-up host
;--------------------------------------------------------------------------------
[wlan]
wlan_used           = 1
wlan_busnum         = 1
clocks              = "losc_out"
wlan_power_enable   = 
wlan_power_num      = 1
wlan_power1         = "vcc-wifi"
wlan_power2         = 
wlan_power3         = 
wlan_io_regulator   = "vcc-wifi-io"
wlan_regon          = port:PL02<1><default><default><0>
wlan_hostwake       = port:PL03<6><default><default><0>

;--------------------------------------------------------------------------------
;bluetooth configuration
;bt_used:           0- no used, 1- used
;clocks:            external low power clock input (32.768KHz)
;bt_power:          input supply voltage
;bt_io_regulator:   bluetooth I/O voltage
;bt_rst_n:          power up/down internal regulators used by BT section
;--------------------------------------------------------------------------------
[bt]
bt_used             = 1
clocks              = "losc_out"
bt_power_num        = 1
bt_power1           = "vcc-wifi"
bt_power2           = 
bt_power3           = 
bt_io_regulator     = "vcc-wifi-io"
bt_rst_n            = port:PL04<1><default><default><0>

;--------------------------------------------------------------------------------
;bluetooth lpm configuration
;btlpm_used:        0- no used, 1- used
;uart_index:        0- uart0, 1- uart1, 2- uart2
;bt_wake:           host wake-up bluetooth device
;bt_hostwake:       bt device wake-up host
;--------------------------------------------------------------------------------
[btlpm]
btlpm_used          = 1
uart_index          = 1
bt_wake             = port:PL06<1><default><default><1>
bt_hostwake         = port:PL05<6><default><default><0>

;--------------------------------------------------------------------------------
;3G configuration
;--------------------------------------------------------------------------------
[3g_para]
3g_used                        = 0
3g_usbc_num                    = 2
3g_uart_num                    = 0
bb_vbat                        = port:PL03<1><default><default><0>
bb_host_wake                   = port:PM00<1><default><default><0>
bb_on                          = port:PM01<1><default><default><0>
bb_pwr_on                      = port:PM03<1><default><default><0>
bb_wake                        = port:PM04<1><default><default><0>
bb_rf_dis                      = port:PM05<1><default><default><0>
bb_rst                         = port:PM06<1><default><default><0>
3g_int                         =

;--------------------------------------------------------------------------------
;gyroscope
;--------------------------------------------------------------------------------
[gyroscopesensor]
compatible                ="allwinner,sun50i-gyr_sensors-para"
gyroscopesensor_used      = 0
gy_twi_id                 = 2
gy_twi_addr               = 0x6a
gy_int1                   = port:PA10<6><1><default><default>
gy_int2                   =

;--------------------------------------------------------------------------------
; Gyro automatic detection configuration
;gy_detect_used  --- Whether startup automatic inspection function. 1:used,0:unused
;Module name postposition 1 said detection, 0 means no detection.
;--------------------------------------------------------------------------------
[gy_list]
compatible            ="allwinner,sun50i-gyr_sensors-list-para"
gy_list_used          = 0
lsm9ds0_gyr          = 1
l3gd20_gyr           = 0
bmg160_gyr           = 1

;--------------------------------------------------------------------------------
;light sensor
;--------------------------------------------------------------------------------
[lightsensor]
compatible          = "allwinner,sun50i-lsensors-para"
lightsensor_used    = 0
ls_twi_id           = 2
ls_twi_addr         = 0x23
ls_int              = port:PA12<6><1><default><default>

;--------------------------------------------------------------------------------
; lsensor automatic detection configuration
;ls_detect_used  --- Whether startup automatic inspection function. 1:used,0:unused
;Module name postposition 1 said detection, 0 means no detection.
;--------------------------------------------------------------------------------
[ls_list]
compatible           = "allwinner,sun50i-lsensors-list-para"
ls_list_used         = 0
ltr_501als           = 1
jsa1212              = 0
jsa1127              = 1
stk3x1x              = 0

;--------------------------------------------------------------------------------
;compass
;--------------------------------------------------------------------------------
[compasssensor]
compatible          = "allwinner,sun50i-compass-para"
compasssensor_used  = 0
compass_twi_id      = 2
compass_twi_addr    = 0x0d
compass_int         = port:PA11<6><1><default><default>

;--------------------------------------------------------------------------------
; compass sensor automatic detection configuration
;compass_detect_used  --- Whether startup automatic inspection function. 1:used,0:unused
;Module name postposition 1 said detection, 0 means no detection.
;--------------------------------------------------------------------------------
[compass_list]
compatible              = "allwinner,sun50i-compass-list-para"
compass_list_used       = 0
lsm9ds0                 = 1
lsm303d                 = 0
;akm8963                = 1

;--------------------------------------------------------------------------------
;       NOTE :Make sure spdif_used = 0x1,spdifmach_used = 0x1,
;         if register the sound card spdif.
;--------------------------------------------------------------------------------
[spdif]
spdif_used          = 0
[sndspdif]
sndspdif_used       = 0
;----------------------------------------------------------------------------------
;       NOTE :Make sure daudio2_used = 0x1,sndhdmi_used = 0x1,
;         if register the sound card hdmi.
;---------------------------------------------------------------------------------
[daudio2]
daudio2_used        = 1
[sndhdmi]
sndhdmi_used        = 1
;--------------------------------------------------------------------------------
;allwinner,pcm_lrck_period  :16/32/64/128/256
;allwinner,pcm_lrckr_period :no use
;allwinner,slot_width_select    :16bits/20bits/24bits/32bits
;allwinner,pcm_lsb_first    :0: msb first; 1: lsb first
;allwinner,tx_data_mode     :0: 16bit linear PCM; 1: 8bit linear PCM; 2: 8bit u-law; 3: 8bit a-law
;allwinner,rx_data_mode     :0: 16bit linear PCM; 1: 8bit linear PCM; 2: 8bit u-law; 3: 8bit a-law
;allwinner,daudio_master :1: SND_SOC_DAIFMT_CBM_CFM(codec clk & FRM master)        use
;                         2: SND_SOC_DAIFMT_CBS_CFM(codec clk slave & FRM master)  not use
;                         3: SND_SOC_DAIFMT_CBM_CFS(codec clk master & frame slave) not use
;                         4: SND_SOC_DAIFMT_CBS_CFS(codec clk & FRM slave)         use
;allwinner,audio_format: 1:SND_SOC_DAIFMT_I2S(standard i2s format).            use
;              2:SND_SOC_DAIFMT_RIGHT_J(right justfied format).
;              3:SND_SOC_DAIFMT_LEFT_J(left justfied format)
;              4:SND_SOC_DAIFMT_DSP_A(pcm. MSB is available on 2nd BCLK rising edge after LRC rising edge). use
;              5:SND_SOC_DAIFMT_DSP_B(pcm. MSB is available on 1nd BCLK rising edge after LRC rising edge)
;allwinner,signal_inversion:1:SND_SOC_DAIFMT_NB_NF(normal bit clock + frame)  use
;                 2:SND_SOC_DAIFMT_NB_IF(normal BCLK + inv FRM)
;                 3:SND_SOC_DAIFMT_IB_NF(invert BCLK + nor FRM)  use
;                 4:SND_SOC_DAIFMT_IB_IF(invert BCLK + FRM)
;allwinner,frametype :0: long frame = 2 clock width;  1: short frame
;allwinner,tdm_config :0:pcm 1:i2s
;allwinner,clk_active :0:auto 1:always_on
;allwinner,daudio0_used :0:not use 1:use

;--------------------------------------------------------------------------------
;       NOTE :Make sure snddaudio0_used = 0x1,daudio1_used = 0x1,
;         if register the sound card DAUDIO1.
;--------------------------------------------------------------------------------
[snddaudio0]
snddaudio0_used = 0
;-----------------------------------------------------------------------------
[daudio0]
pcm_lrck_period =   0x60
pcm_lrckr_period =   0x01
slot_width_select =   0x18
pcm_lsb_first =   0x0
tx_data_mode =   0x0
rx_data_mode =   0x0
daudio_master =   0x04
audio_format =   0x01
signal_inversion =   0x01
frametype =   0x0
tdm_config =   0x01
clk_active = 0x0
daudio0_used = 0

;-------------------------------------------------------------------------------
;       NOTE :Make sure snddaudio1_used = 0x1,daudio0_used = 0x1,
;         if register the sound card DAUDIO0.
;--------------------------------------------------------------------------------
[snddaudio1]
snddaudio1_used = 0
;-----------------------------------------------------------------------------
[daudio1]
pcm_lrck_period =   0x20
pcm_lrckr_period =   0x01
slot_width_select =   0x10
pcm_lsb_first =   0x0
tx_data_mode =   0x0
rx_data_mode =   0x0
daudio_master =   0x04
audio_format =   0x01
signal_inversion =   0x01
frametype =   0x0
tdm_config =   0x01
clk_active = 0x1
daudio1_used = 0
;----------------------------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
;allwinner,headphonevol :headphone volume:0x0--0x3f 0db--(-62db) 1db/step
;allwinner,spkervol : speaker volume:0x0--0x1f 0db-(-43.5db) 1.5db/step
;allwinner,earpiecevol : earpiece volume:0x0--0x1f 0db-(-43.5db) 1.5db/step
;allwinner,maingain :   mainmic gain:0x0---0x7 0x0-0db 0x1:24db   3db/step
;allwinner,headsetmicgain : headphonemic gain:0x0---0x7 0x0-0db 0x1:24db   3db/step
;allwinner,adcagc_cfg : 1:use adcagc 0:no use
;allwinner,adcdrc_cfg : 1:use adcdrc 0:no use
;allwinner,adchpf_cfg : 1:use adchpf 0:no use
;allwinner,dacdrc_cfg : 1:use adcdrc 0:no use
;allwinner,dachpf_cfg : 1:use adchpf 0:no use
;allwinner,aif2config : 1:use aif2 0:no use
;allwinner,aif3config : 1:use aif3 0:no use
;allwinner,hp_detect_case :0:low 1:high
;--------------------------------------------------------------------------------
;       NOTE :Make sure sndcodec_used = 0x1,i2s_used = 0x1
;         codec_used = 0x1,if register the sound card audiocodec.
;---------------------------------------------------------------------------------
[sndcodec]
sndcodec_used    = 0x1
aif2fmt          = 0x3
aif3fmt          = 0x3
aif2master       = 0x1
linein_detect    = 
hp_detect_case   = 0x1
;------------------------------------------------------------------------------
[i2s]
i2s_used = 0x1
;-------------------------------------------------------------------------------
[codec]
codec_used = 0x1
headphonevol =   0x38
spkervol =   0x1d
earpiecevol =   0x1e
maingain =   0x4
headsetmicgain =  0x4
adcagc_cfg =   0x0
adcdrc_cfg =   0x0
adchpf_cfg =   0x1
dacdrc_cfg =   0x0
dachpf_cfg =   0x0
aif2config =  0x0
aif3config =  0x0
aif1_lrlk_div = 0x40
aif2_lrlk_div = 0x40
pa_sleep_time = 0x0a
dac_digital_vol = 0x9898
gpio-spk =

;----------------------------------------------------------------------------------
;ir --- infra remote configuration
;----------------------------------------------------------------------------------
[s_cir0]
s_cir0_used         = 1
supply          = "vcc-cir"
supply_vol      = 3300000 
ir_protocol_used    = 0
ir_power_key_code   = 116
ir_addr_code        = 0x17c612

;-------------------------------------------------------------------------------
;userspace gpio interface for android
;----------------------------------------------------------------------------------
[gpio_para]
compatible  = "allwinner,sunxi-init-gpio"
gpio_used       = 1
gpio_num        = 28
gpio_pin_1  =  port:PH3<1><default><default><0>
gpio_pin_2  =  port:PH2<1><default><default><0>
gpio_pin_3  =  port:PH6<1><default><default><0>
gpio_pin_4  =  port:PH7<1><default><default><0>
gpio_pin_5  =  port:PH10<1><default><default><0>
gpio_pin_6  =  port:PH11<1><default><default><0>
gpio_pin_7  =  port:PD2<1><default><default><0>
gpio_pin_8  =  port:PD3<1><default><default><0>
gpio_pin_9  =  port:PD1<1><default><default><0>
gpio_pin_10 =  port:PC4<1><default><default><0>
gpio_pin_11 =  port:PC7<1><default><default><0>
gpio_pin_12 =  port:PB5<1><default><default><0>
gpio_pin_13 =  port:PB4<1><default><default><0>
gpio_pin_14 =  port:PB6<1><default><default><0>
gpio_pin_15 =  port:PL12<1><default><default><0>
gpio_pin_16 =  port:PB0<1><default><default><0>
gpio_pin_17 =  port:PB1<1><default><default><0>
gpio_pin_18 =  port:PB3<1><default><default><0>
gpio_pin_19 =  port:PB2<1><default><default><0>
gpio_pin_20 =  port:PD4<1><default><default><0>
gpio_pin_21 =  port:PC0<1><default><default><0>
gpio_pin_22 =  port:PD0<1><default><default><0>
gpio_pin_23 =  port:PC2<1><default><default><0>
gpio_pin_24 =  port:PC3<1><default><default><0>
gpio_pin_25 =  port:PB7<1><default><default><0>
gpio_pin_26 =  port:PL9<1><default><default><0>
gpio_pin_27 =  port:PL7<1><default><default><0>
gpio_pin_28 =  port:PL8<1><default><default><0>

;-------------------------------------------------------------------------------------
;used                        ---0:not used,1:used
;pmu_id                      ---0:axp19x,1:axp209,2:axp22x,3:axp806,4:axp808,5:axp809,6:axp803,7:axp813
;reg                         ---pmu0 twi slave address
;pmu_vbusen_func             ---N_VBUSEN function select,0:as an output,1:as an input
;pmu_reset                   ---when power key press longer than 16s, PMU reset or not.0:not reset 1:reset
;pmu_irq_wakeup              ---press irq wakeup or not when sleep or power down.0:not wakeup 1:wakeup
;pmu_hot_shutdown            ---when PMU over temperature protect or not;0:disable 1:enable
;pmu_inshort                 ---ACIN and VBUS inshort or not by software;0:auto detect 1:inshort
;--------------------------------------------------------------------------------------------------------
[pmu0]
compatible                 = "axp803"
used                       = 1
pmu_id                     = 6
pmu_vbusen_func            = 0
pmu_reset                  = 0
pmu_irq_wakeup             = 1
pmu_hot_shutdown           = 1
pmu_inshort                = 0

;--------------------------------------------------------------------------------------------------------
;pmu_chg_ic_temp             ---intelligence charge pmu temperature. when it is 0, this function is closed.
;compatible                  ---charger0 name, support:axp803-charger
;pmu_battery_rdc             ---battery initial resistance
;pmu_battery_cap             ---battery capability,mAh
;pmu_runtime_chgcur          ---set initial charging current limite,mA, 300/450/600/750/900/1050/1200/1350/1500/1650/1800/1950/
;pmu_suspend_chgcur          ---set suspend charging current limite,mA, 300/450/600/750/900/1050/1200/1350/1500/1650/1800/1950/
;pmu_shutdown_chgcur         ---set shutdown charging current limite,mA, 300/450/600/750/900/1050/1200/1350/1500/1650/1800/1950/
;pmu_init_chgvol             ---set initial charing target voltage,mV,4100/4220/4200/4240
;pmu_ac_vol                  ---set usb-ac limited voltage level,mV,4000/4100/4200/4300/4400/4500/4600/4700,0 - not limite
;pmu_ac_cur                  ---set usb-ac limited current level,mA,500/900, 0 - not limite
;pmu_usbpc_vol               ---set usb-pc limited voltage level,mV,4000/4100/4200/4300/4400/4500/4600/4700,0 - not limite
;pmu_usbpc_cur               ---set usb-pc limited current level,mA,500/900, 0 - not limite
;pmu_battery_warning_level1  ---low power warning high level,5%-20%,1%/step
;pmu_battery_warning_level2  ---low power warning low level,0%-15%,1%/step
;pmu_chgled_func             ---CHGKED pin control, 0:controlled by pmu,1:controlled by Charger
;pmu_chgled_type             ---CHGLED Type select when pmu_chgled_func=0,0:Type A, 1:type B
;power_start                 ---when system is in charging, shutdown is power off or resart;0:restart 1:poweroff
;pmu_ocv_en                  ---charge by ocv, 1:enable, must be enabled
;pmu_cou_en                  ---charge by cou, 0:disable, 1:enable
;pmu_update_min_time         ---min time for battery capatity percentage update,second, 0/5/10/20/30/60/120/164
;pmu_init_bc_en              ---set cur by bc1.2 0:disable 1:enable
;pmu_bat_para1               ---battery indication at 3.13V
;pmu_bat_para2               ---battery indication at 3.27V
;pmu_bat_para3               ---battery indication at 3.34V
;pmu_bat_para4               ---battery indication at 3.41V
;pmu_bat_para5               ---battery indication at 3.48V
;pmu_bat_para6               ---battery indication at 3.52V
;pmu_bat_para7               ---battery indication at 3.55V
;pmu_bat_para8               ---battery indication at 3.57V
;pmu_bat_para9               ---battery indication at 3.59V
;pmu_bat_para10              ---battery indication at 3.61V
;pmu_bat_para11              ---battery indication at 3.63V
;pmu_bat_para12              ---battery indication at 3.64V
;pmu_bat_para13              ---battery indication at 3.66V
;pmu_bat_para14              ---battery indication at 3.7V
;pmu_bat_para15              ---battery indication at 3.73V
;pmu_bat_para16              ---battery indication at 3.77V
;pmu_bat_para17              ---battery indication at 3.78V
;pmu_bat_para18              ---battery indication at 3.8V
;pmu_bat_para19              ---battery indication at 3.82V
;pmu_bat_para20              ---battery indication at 3.84V
;pmu_bat_para21              ---battery indication at 3.85V
;pmu_bat_para22              ---battery indication at 3.87V
;pmu_bat_para23              ---battery indication at 3.91V
;pmu_bat_para24              ---battery indication at 3.94V
;pmu_bat_para25              ---battery indication at 3.98V
;pmu_bat_para26              ---battery indication at 4.01V
;pmu_bat_para27              ---battery indication at 4.05V
;pmu_bat_para28              ---battery indication at 4.08V
;pmu_bat_para29              ---battery indication at 4.1V
;pmu_bat_para30              ---battery indication at 4.12V
;pmu_bat_para31              ---battery indication at 4.14V
;pmu_bat_para32              ---battery indication at 4.15V
;pmu_bat_temp_enable         ---battery temp detect enable
;pmu_bat_charge_ltf          ---charge battery temp low threshold voltage
;pmu_bat_charge_htf          ---charge battery temp high threshold voltage
;pmu_bat_shutdown_ltf        ---shutdown battery temp low threshold voltage
;pmu_bat_shutdown_htf        ---shutdown battery temp high threshold voltage
;pmu_bat_temp_para1          ---battery temp -25 voltage
;pmu_bat_temp_para2          ---battery temp -15 voltage
;pmu_bat_temp_para3          ---battery temp -10 voltage
;pmu_bat_temp_para4          ---battery temp -5  voltage
;pmu_bat_temp_para5          ---battery temp  0  voltage
;pmu_bat_temp_para6          ---battery temp  5  voltage
;pmu_bat_temp_para7          ---battery temp  10 voltage
;pmu_bat_temp_para8          ---battery temp  20 voltage
;pmu_bat_temp_para9          ---battery temp  30 voltage
;pmu_bat_temp_para10         ---battery temp  40 voltage
;pmu_bat_temp_para11         ---battery temp  45 voltage
;pmu_bat_temp_para12         ---battery temp  50 voltage
;pmu_bat_temp_para13         ---battery temp  55 voltage
;pmu_bat_temp_para14         ---battery temp  60 voltage
;pmu_bat_temp_para15         ---battery temp  70 voltage
;pmu_bat_temp_para16         ---battery temp  80 voltage
;--------------------------------------------------------------------------------------------------------
[charger0]
compatible                 = "axp803-charger"
pmu_chg_ic_temp            = 0
pmu_battery_rdc            = 100
pmu_battery_cap            = 3000
pmu_runtime_chgcur         = 800
pmu_suspend_chgcur         = 1500
pmu_shutdown_chgcur        = 1500
pmu_init_chgvol            = 4200
pmu_ac_vol                 = 4000
pmu_ac_cur                 = 2500
pmu_usbpc_vol              = 4400
pmu_usbpc_cur              = 500
pmu_battery_warning_level1 = 15
pmu_battery_warning_level2 = 0
pmu_chgled_func            = 1
pmu_chgled_type            = 0
power_start                = 0
pmu_ocv_en                 = 1
pmu_cou_en                 = 1
pmu_update_min_time        = 30
pmu_init_bc_en             = 0

pmu_bat_para1              = 0
pmu_bat_para2              = 0
pmu_bat_para3              = 0
pmu_bat_para4              = 0
pmu_bat_para5              = 0
pmu_bat_para6              = 0
pmu_bat_para7              = 0
pmu_bat_para8              = 0
pmu_bat_para9              = 5
pmu_bat_para10             = 8
pmu_bat_para11             = 9
pmu_bat_para12             = 10
pmu_bat_para13             = 13
pmu_bat_para14             = 16
pmu_bat_para15             = 20
pmu_bat_para16             = 33
pmu_bat_para17             = 41
pmu_bat_para18             = 46
pmu_bat_para19             = 50
pmu_bat_para20             = 53
pmu_bat_para21             = 57
pmu_bat_para22             = 61
pmu_bat_para23             = 67
pmu_bat_para24             = 73
pmu_bat_para25             = 78
pmu_bat_para26             = 84
pmu_bat_para27             = 88
pmu_bat_para28             = 92
pmu_bat_para29             = 93
pmu_bat_para30             = 94
pmu_bat_para31             = 95
pmu_bat_para32             = 100

pmu_bat_temp_enable        = 0
pmu_bat_charge_ltf         = 2261
pmu_bat_charge_htf         = 388
pmu_bat_shutdown_ltf       = 3200
pmu_bat_shutdown_htf       = 237
pmu_bat_temp_para1         = 7466
pmu_bat_temp_para2         = 4480
pmu_bat_temp_para3         = 3518
pmu_bat_temp_para4         = 2786
pmu_bat_temp_para5         = 2223
pmu_bat_temp_para6         = 1788
pmu_bat_temp_para7         = 1448
pmu_bat_temp_para8         = 969
pmu_bat_temp_para9         = 664
pmu_bat_temp_para10        = 466
pmu_bat_temp_para11        = 393
pmu_bat_temp_para12        = 333
pmu_bat_temp_para13        = 283
pmu_bat_temp_para14        = 242
pmu_bat_temp_para15        = 179
pmu_bat_temp_para16        = 134

;--------------------------------------------------------------------------------------------------------
;compatible                  ---powerkey0 name, support:axp803-powerkey
;pmu_powkey_off_time         ---set pek off time,ms, 4000/6000/8000/10000
;pmu_powkey_off_func         ---set pek off func, 0:shutdown,1:restart
;pmu_powkey_off_en           ---set pek offlevel powerdown or not, 0:not powerdown,1:powerdown
;pmu_powkey_long_time        ---set pek pek long irq time,ms,1000/1500/2000/2500
;pmu_powkey_on_time          ---set pek on time,ms,128/1000/2000/3000
;--------------------------------------------------------------------------------------------------------
[powerkey0]
compatible                 = "axp803-powerkey"
pmu_powkey_off_time        = 6000
pmu_powkey_off_func        = 0
pmu_powkey_off_en          = 1
pmu_powkey_long_time       = 1500
pmu_powkey_on_time         = 1000

;--------------------------------------------------------------------------------------------------------
;compatible                   ---regulator0 name, support:axp803-regulator
;regulator_count              ---pmu ldo count, changed with different pmu
;regulator(1~regulator_count) ---ldo details
;--------------------------------------------------------------------------------------------------------
[regulator0]
compatible      = "axp803-regulator"
regulator_count = 23
regulator1      = "axp803_dcdc1 none vcc-nand vcc-emmc vcc-sdc vcc-usb-30 vcc-io vcc-emmcv vcc-emmcvq33 vcc-sdcvq33 vcc-sdcv vcc-sdcvd"
regulator2      = "axp803_dcdc2 none vdd-cpua"
regulator3      = "axp803_dcdc3 none"
regulator4      = "axp803_dcdc4 none"
regulator5      = "axp803_dcdc5 none vcc-dram"
regulator6      = "axp803_dcdc6 none vdd-sys"
regulator7      = "axp803_dcdc7 none"
regulator8      = "axp803_rtc none"
regulator9      = "axp803_aldo1 none vdd-csi-led iovdd-csi "
regulator10     = "axp803_aldo2 none vcc-pl"
regulator11     = "axp803_aldo3 none vcc-avcc vcc-pll"
regulator12     = "axp803_dldo1 none vcc-hdmi-33 vcc-dsi-33"
regulator13     = "axp803_dldo2 none vcc-wifi"
regulator14     = "axp803_dldo3 none avdd-csi"
regulator15     = "axp803_dldo4 none vcc-wifi-io vcc-pg"
regulator16     = "axp803_eldo1 none vcc-cpvdd vcc-pc vcc-emmcvq18"
regulator17     = "axp803_eldo2 none"
regulator18     = "axp803_eldo3 none dvdd-csi-18"
regulator19     = "axp803_fldo1 none vcc-hsic-12 vcc-ephy1"
regulator20     = "axp803_fldo2 none vdd-cpus";
regulator21     = "axp803_gpio0ldo none vcc-cir"
regulator22     = "axp803_gpio1ldo none "
regulator23     = "axp803_dc1sw none vcc-wifi-8089 vcc-gmac-33 vcc-pd vcc-ephy0"
;--------------------------------------------------------------------------------------------------------
;compatible                  ---axp_gpio0 name, support:axp803-gpio
;--------------------------------------------------------------------------------------------------------
[axp_gpio0]
compatible = "axp803-gpio"

;----------------------------------------------------------------------------------
;recovery and fastboot key
;----------------------------------------------------------------------------------
[recovery_key]
key_max         = 0xc
key_min         = 0xa
;----------------------------------------------------------------------------------
[fastboot_key]
key_max         = 0x6
key_min         = 0x4

[key_detect_en]
keyen_flag      = 1

;----------------------------------------------------------------------------------
; dvfs voltage-frequency table configuration
;
; max_freq: cpu maximum frequency, based on Hz
; min_freq: cpu minimum frequency, based on Hz
;
; lv_count: count of lv_freq/lv_volt, must be < 16
;
; lv1: core vdd is 1.30v if cpu frequency is (1104Mhz, 1152Mhz]
; lv2: core vdd is 1.26v if cpu frequency is (1008Mhz, 1104Mhz]
; lv3: core vdd is 1.20v if cpu frequency is (816Mhz,  1008Mhz]
; lv4: core vdd is 1.10v if cpu frequency is (648Mhz,   816Mhz]
; lv5: core vdd is 1.04v if cpu frequency is (480Mhz,   648Mhz]
; lv6: core vdd is 1.04v if cpu frequency is (480Mhz,   648Mhz]
; lv7: core vdd is 1.04v if cpu frequency is (480Mhz,   648Mhz]
; lv8: core vdd is 1.04v if cpu frequency is (480Mhz,   648Mhz]
;
;----------------------------------------------------------------------------------
[dvfs_table]
;extremity_freq = 1344000000
max_freq = 1152000000
min_freq = 480000000

lv_count = 8
lv1_freq = 1152000000
lv1_volt = 1300

lv2_freq = 1104000000
lv2_volt = 1260

lv3_freq = 1008000000
lv3_volt = 1200

lv4_freq = 816000000
lv4_volt = 1100

lv5_freq = 648000000
lv5_volt = 1040

lv6_freq = 0
lv6_volt = 1040

lv7_freq = 0
lv7_volt = 1040

lv8_freq = 0
lv8_volt = 1040

;----------------------------------------------------------------------------------
;s_uart0 config parameters
;s_uart0_used  --s_uart0 whether used for arisc debugging
;
;----------------------------------------------------------------------------------
[s_uart0]
s_uart0_used       = 1
s_uart0_tx         = port:PL02<2><default><default><default>
s_uart0_rx         = port:PL03<2><default><default><default>

;----------------------------------------------------------------------------------
;s_rsb0 config parameters
;s_rsb0_used  --s_rsb0 whether used for arisc
;
;----------------------------------------------------------------------------------
[s_rsb0]
s_rsb0_used        = 1
s_rsb0_sck         = port:PL00<2><1><2><default>
s_rsb0_sda         = port:PL01<2><1><2><default>

;----------------------------------------------------------------------------------
;s_jtag0 config parameters
;s_jtag0_used  --s_jtag0 whether used for arisc
;
;----------------------------------------------------------------------------------
[s_jtag0]
s_jtag0_used        = 0
s_jtag0_tms         = port:PL04<2><1><2><default>
s_jtag0_tck         = port:PL05<2><1><2><default>
s_jtag0_tdo         = port:PL06<2><1><2><default>
s_jtag0_tdi         = port:PL07<2><1><2><default>

;----------------------------------------------------------------------------------
;virtual device
;virtual device for pinctrl testing
;device have pin PA1 PA2
;----------------------------------------------------------------------------------
[Vdevice]
Vdevice_used        = 1
Vdevice_0           = port:PB01<4><1><2><default>
Vdevice_1           = port:PB02<4><1><2><default>

;----------------------------------------------------------------------------------
;GPU parameters
;dvfs_status      : dvfs status, if this is enabled, GPU DVFS will work. Actually, GPU
;                   DVFS functionality depends on some kernel features such as devfreq.
;temp_ctrl_status : temperature control status, if this is enabled, the gpu frequency
;                   will drop down if the temperature of gpu is too high.
;scene_ctrl_status: scene control status, if this is enabled, android layer can ask
;                   gpu driver to change frequency in certain scene.
;max_level        : maximum level.
;begin_level      : the corresponding frequency and voltage will be used during GPU
;                    initialization.
;lv<x>_freq       : frequency in MHz of certain level.
;lv<x>_volt       : voltage in mV of certain level, 0 means GPU power is not independent.
;----------------------------------------------------------------------------------
[gpu]
dvfs_status       = 0
temp_ctrl_status  = 1
scene_ctrl_status = 0

max_level   = 0
begin_level = 0

lv0_freq = 456
lv0_volt = 0

;----------------------------------------------------------------------------------
[secure]
dram_region_mbytes       = 64
drm_region_mbytes        = 64
drm_region_start_mbytes  = 0
;----------------------------------------------------------------------------------
shaddow501 commented 5 years ago

I dont know why it didnt bold this section but:

[boot_disp] output_disp = 0 output_type = 3 output_mode = 5 ------------ when it is set like this I see the boot logo on the side (after I modified the boot logo to be 800x480). when I set this value to 18 or 35 or 69 I dont have any boot logo and the screen stay white.

you can see the exact pictures here - http://forum.banana-pi.org/t/bpi-m64-800x480-display-support/9292/10

UPDATE:: Changing the sun50i-a64-bpi-m64-720p.dtb does not do anything.

Compiling the kernel with screen0 output mode =2 (480P) give this results only at boot, after boot again white screen. 20190703_195357

I have no idea why it works at u-boot state and when kernel start loading it fade away..

Maybe different approach? could it be a clock issue?? we did try to play with the resolution but could it be HDMI clock issue?

avafinger commented 5 years ago

Can you try this DTB with my last Image?

m64-4.4_5_inch.dtb.tar.gz