Ejemplo n.º 1
0
zx_status_t Osd::Init(zx_device_t* parent) {
    if (initialized_) {
        return ZX_OK;
    }

    zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev_);
    if (status != ZX_OK) {
        return status;
    }

    // Map vpu mmio used by the OSD object
    mmio_buffer_t mmio;
    status = pdev_map_mmio_buffer(&pdev_, MMIO_VPU, ZX_CACHE_POLICY_UNCACHED_DEVICE,
                                  &mmio);
    if (status != ZX_OK) {
        DISP_ERROR("osd: Could not map VPU mmio\n");
        return status;
    }

    vpu_mmio_ = ddk::MmioBuffer(mmio);

    // Get BTI from parent
    status = pdev_get_bti(&pdev_, 0, bti_.reset_and_get_address());
    if (status != ZX_OK) {
        DISP_ERROR("Could not get BTI handle\n");
        return status;
    }

    //Map RDMA Done Interrupt
    status = pdev_map_interrupt(&pdev_, IRQ_RDMA, rdma_irq_.reset_and_get_address());
    if (status != ZX_OK) {
        DISP_ERROR("Could not map RDMA interrupt\n");
        return status;
    }

    auto start_thread = [](void* arg) {return static_cast<Osd*>(arg)->RdmaThread(); };
    status = thrd_create_with_name(&rdma_thread_, start_thread, this, "rdma_thread");
    if (status != ZX_OK) {
        DISP_ERROR("Could not create rdma_thread\n");
        return status;
    }

    // Setup RDMA
    status = SetupRdma();
    if (status != ZX_OK) {
        DISP_ERROR("Could not setup RDMA\n");
        return status;
    }

    // OSD object is ready to be used.
    initialized_ = true;
    return ZX_OK;
}
Ejemplo n.º 2
0
zx_status_t Osd::SetupRdma() {
    zx_status_t status = ZX_OK;
    DISP_INFO("Setting up RDMA\n");

    // since we are flushing the caches, make sure the tables are at least cache_line apart
    ZX_DEBUG_ASSERT(kChannelBaseOffset > zx_system_get_dcache_line_size());

    // Allocate one page for RDMA Table
    status = zx_vmo_create_contiguous(bti_.get(), ZX_PAGE_SIZE, 0,
                                                  rdma_vmo_.reset_and_get_address());
    if (status != ZX_OK) {
        DISP_ERROR("Could not create RDMA VMO (%d)\n", status);
        return status;
    }

    status = zx_bti_pin(bti_.get(), ZX_BTI_PERM_READ | ZX_BTI_PERM_WRITE, rdma_vmo_.get(),
                        0, ZX_PAGE_SIZE, &rdma_phys_, 1, &rdma_pmt_);
    if (status != ZX_OK) {
        DISP_ERROR("Could not pin RDMA VMO (%d)\n", status);
        return status;
    }

    status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                         0, rdma_vmo_.get(), 0, ZX_PAGE_SIZE,
                         reinterpret_cast<zx_vaddr_t*>(&rdma_vbuf_));
    if (status != ZX_OK) {
        DISP_ERROR("Could not map vmar (%d)\n", status);
        return status;
    }

    // Initialize each rdma channel container
    for (int i = 0; i < kMaxRdmaChannels; i++) {
        ZX_DEBUG_ASSERT((i * kChannelBaseOffset) < ZX_PAGE_SIZE);
        rdma_chnl_container_[i].phys_offset = rdma_phys_ + (i * kChannelBaseOffset);
        rdma_chnl_container_[i].virt_offset = rdma_vbuf_ + (i * kChannelBaseOffset);
        rdma_chnl_container_[i].active = false;
    }

    // Setup RDMA_CTRL:
    // Default: no reset, no clock gating, burst size 4x16B for read and write
    // DDR Read/Write request urgent
    uint32_t regVal = RDMA_CTRL_READ_URGENT | RDMA_CTRL_WRITE_URGENT;
    vpu_mmio_->Write32(regVal, VPU_RDMA_CTRL);

    ResetRdmaTable();

    return status;
}
Ejemplo n.º 3
0
HI_S32 DISP_UA_Init(HI_DRV_DISP_VERSION_S *pstVersion)
{
    HI_S32 nRet;

    if (!pstVersion)
    {
        DISP_ERROR("FUNC(%s) Error! Invalid input parameters!\n", __FUNCTION__);
        return HI_FAILURE;
    }

    if (g_bUAInitFlag)
    {
        DISP_INFO("FUNC(%s) inited!\n", __FUNCTION__);
        return HI_SUCCESS;
    }

    DISP_MEMSET(&g_stUAFuntion, 0, sizeof(g_stUAFuntion));

    if (   (pstVersion->u32VersionPartH == DISP_CV200_ES_VERSION_H)
        && (pstVersion->u32VersionPartL == DISP_CV200_ES_VERSION_L)
        )
    {
        // 准备工作,包括资源申请
        nRet = ALG_VZmeVdpComnInit(&g_stVZMEInstance);
        if (nRet)
        {
            DISP_ERROR("ALG_VZmeVdpComnInit failed!\n");
            return HI_FAILURE;
        }

        // 函数指针赋值
        g_stUAFuntion.pfCalcCscCoef  = DISP_ALG_CscCoefSet;

        g_stUAFuntion.pfVZmeVdpHQSet = UA_VZmeVdpHQSet;
        g_stUAFuntion.pfVZmeVdpSQSet = UA_VZmeVdpSQSet;
        g_stUAFuntion.pfVZmeVdpSQSetSeperateAddr = UA_VZmeVdpSQSetSeparateAddr;
    }
    else
    {
        DISP_ERROR("FUNC(%s) Error! Invalid display version!", __FUNCTION__);
        return HI_FAILURE;
    }
    

    g_bUAInitFlag = HI_TRUE;

    return HI_SUCCESS;
}
Ejemplo n.º 4
0
HI_S32 DispBuf_GetFullNodeNumber(DISP_BUF_S *pstBuffer, HI_U32 *pu32Num)
{
    HI_U32 num;
    HI_U32 r, w;

    DBC_CHECK_NULL_RETURN(pstBuffer);
    DBC_CHECK_NULL_RETURN(pu32Num);
    
    r = pstBuffer->u32FullReaddPos;
    w = pstBuffer->u32FullWritePos;
    if (w >= r)
    {
        num = w - r;
    }
    else
    {
        num = w + pstBuffer->u32Number- r;
    }

    if (num <= pstBuffer->u32Number)
    {
        *pu32Num = num;
    }
    else
    {
        DISP_ERROR("DispBuf_GetFullNodeNumber invalid!\n");
        *pu32Num = 0;
    }

    return HI_SUCCESS;
}
Ejemplo n.º 5
0
void Osd::FlushRdmaTable(uint32_t channel) {
    zx_status_t status = zx_cache_flush(rdma_chnl_container_[channel].virt_offset,
                                        sizeof(RdmaTable),
                                        ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE);
    if (status != ZX_OK) {
        DISP_ERROR("Could not clean cache %d\n", status);
        return;
    }
}
Ejemplo n.º 6
0
HI_S32 DispBuf_Create(DISP_BUF_S *pstBuffer, HI_U32 number)
{
    DISP_BUF_NODE_S *pstNewNode;
    HI_U32 u;

    if (!number || (number > DISP_BUF_NODE_MAX_NUMBER))
    {
        DISP_ERROR("DispBuf_Create buffer number is invalid %d\n", number);
        return HI_FAILURE;
    }

    DISP_MEMSET(pstBuffer, 0, sizeof(DISP_BUF_S));

    pstBuffer->u32BufID = (s_u32BufIDCount++) & 0xffffUL;
    pstBuffer->u32Number = number;

    for(u=0; u<pstBuffer->u32Number; u++)
    {
        pstNewNode = (DISP_BUF_NODE_S *)DISP_MALLOC(sizeof(DISP_BUF_NODE_S));
        if (!pstNewNode)
        {
            DISP_ERROR("DispBuf_Create malloc node memory!\n");
            goto __ERR_RELEASE__;
        }

        pstBuffer->pstBufArray[u] = pstNewNode;
    }

    DispBuf_Reset(pstBuffer);
    return HI_SUCCESS;

__ERR_RELEASE__:
    for(; u>0; u--)
    {
        DISP_FREE(pstBuffer->pstBufArray[u-1]);
    }

    return HI_FAILURE;
}
Ejemplo n.º 7
0
HI_S32 DISP_DA_Init(HI_DRV_DISP_VERSION_S *pstVersion)
{
    //HI_S32 nRet;

    if (!pstVersion)
    {
        DISP_ERROR("FUNC(%s) Error! Invalid input parameters!\n", __FUNCTION__);
        return HI_FAILURE;
    }

    if (g_bDAInitFlag)
    {
        DISP_INFO("FUNC(%s) inited!\n", __FUNCTION__);
        return HI_SUCCESS;
    }

    DISP_MEMSET(&g_stDAFuntion, 0, sizeof(g_stDAFuntion));

    if (   (pstVersion->u32VersionPartH == DISP_CV200_ES_VERSION_H)
        && (pstVersion->u32VersionPartL == DISP_CV200_ES_VERSION_L)
        )
    {

        // º¯ÊýÖ¸Õ븳ֵ
        g_stDAFuntion.PFCscRgb2Yuv   = DISP_ALG_CscRgb2Yuv;
        g_stDAFuntion.pfCalcCscCoef  = DISP_ALG_CscCoefSet;

    }
    else
    {
        DISP_ERROR("FUNC(%s) Error! Invalid display version!", __FUNCTION__);
        return HI_FAILURE;
    }
    

    g_bDAInitFlag = HI_TRUE;

    return HI_SUCCESS;
}
Ejemplo n.º 8
0
zx_status_t get_vic(const display_mode_t* disp_timing, struct hdmi_param* p)
{
    // Monitor has its own preferred timings. Use that
    p->timings.interlace_mode =     disp_timing->flags & MODE_FLAG_INTERLACED;
    p->timings.pfreq =              (disp_timing->pixel_clock_10khz * 10); // KHz
    //TODO: pixel repetition is 0 for most progressive. We don't support interlaced
    p->timings.pixel_repeat =       0;
    p->timings.hactive =            disp_timing->h_addressable;
    p->timings.hblank =             disp_timing->h_blanking;
    p->timings.hfront =             disp_timing->h_front_porch;
    p->timings.hsync =              disp_timing->h_sync_pulse;
    p->timings.htotal =             (p->timings.hactive) + (p->timings.hblank);
    p->timings.hback =              (p->timings.hblank) - (p->timings.hfront + p->timings.hsync);
    p->timings.hpol =               disp_timing->flags & MODE_FLAG_HSYNC_POSITIVE;

    p->timings.vactive =            disp_timing->v_addressable;
    p->timings.vblank0 =            disp_timing->v_blanking;
    p->timings.vfront =             disp_timing->v_front_porch;
    p->timings.vsync =              disp_timing->v_sync_pulse;
    p->timings.vtotal =             (p->timings.vactive) + (p->timings.vblank0);
    p->timings.vback =              (p->timings.vblank0) - (p->timings.vfront + p->timings.vsync);
    p->timings.vpol =               disp_timing->flags & MODE_FLAG_VSYNC_POSITIVE;

    //FIXE: VENC Repeat is undocumented. It seems to be only needed for the following
    // resolutions: 1280x720p60, 1280x720p50, 720x480p60, 720x480i60, 720x576p50, 720x576i50
    // For now, we will simply not support this feature.
    p->timings.venc_pixel_repeat = 0;
    // Let's make sure we support what we've got so far
    if (p->timings.interlace_mode) {
        return ZX_ERR_NOT_SUPPORTED;
    }

    if (p->timings.vactive == 2160) {
        DISP_INFO("4K Monitor Detected.\n");

        if (p->timings.pfreq == 533250) {
            // FIXME: 4K with reduced blanking (533.25MHz) does not work
            DISP_INFO("4K @ 30Hz\n");
            p->timings.interlace_mode =     0;
            p->timings.pfreq =              (297000); // KHz
            p->timings.pixel_repeat =       0;
            p->timings.hactive =            3840;
            p->timings.hblank =             560;
            p->timings.hfront =             176;
            p->timings.hsync =              88;
            p->timings.htotal =             (p->timings.hactive) + (p->timings.hblank);
            p->timings.hback =              (p->timings.hblank) -
                                               (p->timings.hfront + p->timings.hsync);
            p->timings.hpol =               1;
            p->timings.vactive =            2160;
            p->timings.vblank0 =            90;
            p->timings.vfront =             8;
            p->timings.vsync =              10;
            p->timings.vtotal =             (p->timings.vactive) + (p->timings.vblank0);
            p->timings.vback =              (p->timings.vblank0) -
                                               (p->timings.vfront + p->timings.vsync);
            p->timings.vpol =               1;
        }
    }

    if (p->timings.pfreq > 500000) {
        p->is4K = true;
    } else {
        p->is4K = false;
    }

    if (p->timings.hactive * 3 == p->timings.vactive * 4) {
        p->aspect_ratio = HDMI_ASPECT_RATIO_4x3;
    } else if (p->timings.hactive * 9 == p->timings.vactive * 16) {
        p->aspect_ratio = HDMI_ASPECT_RATIO_16x9;
    } else {
        p->aspect_ratio = HDMI_ASPECT_RATIO_NONE;
    }

    p->colorimetry = HDMI_COLORIMETRY_ITU601;

    if (p->timings.pfreq > 500000) {
        p->phy_mode = 1;
    } else if (p->timings.pfreq > 200000) {
        p->phy_mode = 2;
    } else if (p->timings.pfreq > 100000) {
        p->phy_mode = 3;
    } else {
        p->phy_mode = 4;
    }

    //TODO: We probably need a more sophisticated method for calculating
    // clocks. This will do for now.
    p->pll_p_24b.viu_channel =          1;
    p->pll_p_24b.viu_type =             VIU_ENCP;
    p->pll_p_24b.vid_pll_div =          VID_PLL_DIV_5;
    p->pll_p_24b.vid_clk_div =          2;
    p->pll_p_24b.hdmi_tx_pixel_div =    1;
    p->pll_p_24b.encp_div =             1;
    p->pll_p_24b.od1 =                  1;
    p->pll_p_24b.od2 =                  1;
    p->pll_p_24b.od3 =                  1;

    p->pll_p_24b.hpll_clk_out = (p->timings.pfreq * 10);
    while (p->pll_p_24b.hpll_clk_out < 2900000) {
        if (p->pll_p_24b.od1 < 4) {
            p->pll_p_24b.od1 *= 2;
            p->pll_p_24b.hpll_clk_out *= 2;
        } else if (p->pll_p_24b.od2 < 4) {
            p->pll_p_24b.od2 *= 2;
            p->pll_p_24b.hpll_clk_out *= 2;
        } else if (p->pll_p_24b.od3 < 4) {
            p->pll_p_24b.od3 *= 2;
            p->pll_p_24b.hpll_clk_out *= 2;
        } else {
            return ZX_ERR_OUT_OF_RANGE;
        }
    }
    if(p->pll_p_24b.hpll_clk_out > 6000000) {
        DISP_ERROR("Something went wrong in clock calculation (pll_out = %d)\n",
            p->pll_p_24b.hpll_clk_out);
        return ZX_ERR_OUT_OF_RANGE;
    }

    return ZX_OK;
}