⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drvdll.c

📁 mstar 776 开发的车载dvd
💻 C
字号:
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2007 MStar Semiconductor, Inc.
// All rights reserved.
//
// Unless otherwise stipulated in writing, any and all information contained
// herein regardless in any format shall remain the sole proprietary of
// MStar Semiconductor Inc. and be kept in strict confidence
// (¨MStar Confidential Information〃) by the recipient.
// Any unauthorized act including without limitation unauthorized disclosure,
// copying, use, reproduction, sale, distribution, modification, disassembling,
// reverse engineering and compiling of the contents of MStar Confidential
// Information is unlawful and strictly prohibited. MStar hereby reserves the
// rights to any and all damages, losses, costs and expenses resulting therefrom.
//
////////////////////////////////////////////////////////////////////////////////

#include <intrins.h>

#include "Datatype.h"
#include "R8051XC.h"
#include "hwreg.h"

#define REG_DLL_CTRL        (DLL_REG_BASE + 0x00)

#define DLL_CTRL_ENABLE     (1 << 0)
#define DLL_CTRL_SOFT_RST   (1 << 1)

#define REG_DLL_DET1T       (DLL_REG_BASE + 0x02)   // detect 1T

#define DET1T_SETDLY        0x07
#define DET1T_GO            (1 << 4)
#define DET1T_RDY           (1 << 5)

#define REG_DLL_PD          (DLL_REG_BASE + 0x03)   // detect phase

#define PD_SELMUX           0x1F
#define PD_GO               (1 << 6)
#define PD_RDY              (1 << 7)

#define REG_DLL_DLY_OE      (DLL_REG_BASE + 0x04)
#define REG_DLL_DLY32_OE    (DLL_REG_BASE + 0x06)

#define REG_DLL_DET1T_STAT  (DLL_REG_BASE + 0x0A)
#define REG_DLL_PD_STAT     (DLL_REG_BASE + 0x0E)

static U8 code u8OE[] = { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };

static void MDrv_DLL_SetDly32OE(U8 u8SelectMux)
{
    // assume DLL_DLY32_OE is 0xFFFFFFFF

    if (u8SelectMux < 8)
    {
        XBYTE[REG_DLL_DLY32_OE + 3] = 0;
        XBYTE[REG_DLL_DLY32_OE + 2] = 0;
        XBYTE[REG_DLL_DLY32_OE + 1] = 0;
        XBYTE[REG_DLL_DLY32_OE + 0] = u8OE[u8SelectMux];
    }
    else if (u8SelectMux < 16)
    {
        XBYTE[REG_DLL_DLY32_OE + 3] = 0;
        XBYTE[REG_DLL_DLY32_OE + 2] = 0;
        XBYTE[REG_DLL_DLY32_OE + 1] = u8OE[u8SelectMux & 0x07];
    }
    else if (u8SelectMux < 24)
    {
        XBYTE[REG_DLL_DLY32_OE + 3] = 0;
        XBYTE[REG_DLL_DLY32_OE + 2] = u8OE[u8SelectMux & 0x07];
    }
    else
    {
        XBYTE[REG_DLL_DLY32_OE + 3] = u8OE[u8SelectMux & 0x07];
    }
}

void MDrv_DLL_Init(void)
{
    U8 n;
    U8 i;
    U8 j;

    // reset DLL
    XBYTE[REG_DLL_CTRL] = DLL_CTRL_SOFT_RST;
    XBYTE[REG_DLL_CTRL] = DLL_CTRL_ENABLE;

    // detect 1T
    for (n = 0; n < 32; n++)
    {
        i = n & 3;
        if (!i)
        {
            XBYTE[REG_DLL_DET1T] = DET1T_GO | (n >> 2);

            while (!(XBYTE[REG_DLL_DET1T] & DET1T_RDY))
             /* forever */;

            j = 0;
        }

        // find "0..0 1..1 0..0"  pattern in 32-bit DLL_DET1T_STAT

        i = XBYTE[REG_DLL_DET1T_STAT + 3 - i];    // little endian
        for (B = 0x80; B > 0; B >>= 1)
        {
            UD = i & B;        /* bit mask */
            switch (j)
            {
            case 0:
            case 1:
                if (UD)
                    j = 0;
                else
                    j++;
                break;
            case 2:
                if (UD)
                    j++;
                break;
            case 3:
                if (UD)
                    j++;
                else
                    j = 0;
                break;
            case 4:
                if (!UD)
                    j++;
                break;
            case 5:
                if (UD)
                    j = 0;
                else
                    goto detect_1T_done;
                break;
            }
        }
    }

detect_1T_done:

    if (n < 32)
    {
        // detect phase
        for (n = 0; n < 32; n++)
        {
            XBYTE[REG_DLL_PD] = PD_GO | n;

            while (!(XBYTE[REG_DLL_PD] & PD_RDY))
                /* forever */;

            i = XBYTE[REG_DLL_PD_STAT];
            j = XBYTE[REG_DLL_PD_STAT];

            // okay cases: 5'b10000 5'b11000 5'b11100 5'b11110
            if ( (i == 0x10 || i == 0x18 || i == 0x1C || i == 0x1E) &&
                 (j == 0x10 || j == 0x18 || j == 0x1C || j == 0x1E) )
                 break;
        }
    }

    if (n == 32)
    {
        // detect 1T or phase fail
        XBYTE[REG_DLL_CTRL] = 0;
    }
    else
    {
        // set DLL_DLY_OE & DLL_DLY32_OE for power saving
        XBYTE[REG_DLL_DLY_OE + 0] = u8OE[XBYTE[REG_DLL_DET1T] & 0x07];
        XBYTE[REG_DLL_DLY_OE + 1] = 0;

        MDrv_DLL_SetDly32OE(n);
    }
}

// Fine tune DLL phase while MIU is idle
void MDrv_DLL_Monitor(void)
{
    U8 u8PDStat1;
    U8 u8PDStat2;
    U8 u8SelectMux;

    XBYTE[REG_DLL_DLY32_OE + 3] = 0xFF;
    XBYTE[REG_DLL_DLY32_OE + 2] = 0xFF;
    XBYTE[REG_DLL_DLY32_OE + 1] = 0xFF;
    XBYTE[REG_DLL_DLY32_OE + 0] = 0xFF;
    XBYTE[REG_DLL_DLY_OE + 1] = 0xFF;

    u8SelectMux = XBYTE[REG_DLL_PD] & 0x1F;

    while (1)
    {
        XBYTE[REG_DLL_PD] = PD_GO | u8SelectMux;

        while (!(XBYTE[REG_DLL_PD] & PD_RDY))
            /* forever */;

        u8PDStat1 = XBYTE[REG_DLL_PD_STAT];
        u8PDStat2 = XBYTE[REG_DLL_PD_STAT];

        if (((u8PDStat1 == 0x0) || (u8PDStat1 == 0x1))
         && ((u8PDStat2 == 0x0) || (u8PDStat2 == 0x1)))
        {
            u8SelectMux = (u8SelectMux + 1) & 0x1F;
        }
        else if (((u8PDStat1 == 0x1F) || (u8PDStat1 == 0x0F))
              && ((u8PDStat2 == 0x1F) || (u8PDStat2 == 0x0F)))
        {
            u8SelectMux = (u8SelectMux - 1) & 0x1F;
        }
        else
        {
            XBYTE[REG_DLL_DLY_OE + 1] = 0;
            MDrv_DLL_SetDly32OE(u8SelectMux);
            break;
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -