www.pudn.com > camera.rar > camera.cpp


// 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
// 
// 
// Use of this sample source code is subject to the terms of the Microsoft 
// license agreement under which you licensed this sample source code. If 
// you did not accept the terms of the license agreement, you are not 
// authorized to use this sample source code. For the terms of the license, 
// please see the license agreement between you and Microsoft or, if applicable, 
// see the LICENSE.RTF on your install media or the root of your tools installation. 
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES. 
// 
// 
// (C) Copyright 2006 Marvell International Ltd. 
// All Rights Reserved 
// 
 
#include  
#include  
#include "Cs.h" 
#include "Csmedia.h" 
 
#include "CameraPDDProps.h" 
#include "dstruct.h" 
#include "dbgsettings.h" 
#include  
#include "CameraDriver.h" 
#include "PinDriver.h" 
 
#include "camerapdd.h" 
#include "pdd_private.h" 
 
TCHAR *dev_name = L"CAM1"; 
 
void CCameraPdd::init_ipm_client() 
{ 
    //set up IPM 
    //TCHAR szTemp[MAX_PATH]; 
    IPM_STATUS_T status; 
    is_ipm_enabled = FALSE; 
    ipm_block_ref_count = 0; 
    // IPM Registration: 
    status = IPM_Register(dev_name, &(ipm_client_id) ,3000); 
    if ( status==IPM_STATUS_SUCCESS) 
    { 
        DWORD dwProcState;         
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Registration Completed, client id is %d\r\n",dev_name, ipm_client_id)); 
        dwProcState = IPM_PROCESSOR_D0_RDY | IPM_PROCESSOR_RING_OSC_RDY  | IPM_PROCESSOR_D2_RDY| IPM_PROCESSOR_D1_RDY; // Initial 
 
        // Notify IPM          
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Initial Notify IPM Ready For Processor state. dwProcState=%x \r\n", dev_name, dwProcState)); 
        if (IPM_NotifyReadyForProcState(ipm_client_id, dwProcState ,3000) != IPM_STATUS_SUCCESS)         
            DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Notify IPM Ready For Processor state for driver FAILED\r\n", dev_name)); 
        is_ipm_enabled = TRUE; 
    } 
    else if(status == IPM_STATUS_IPM_DISABLED)         
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] NOIPM \r\n", dev_name)); 
    else         
        DEBUGMSG(ZONE_IOCTL,(L"CAM: [%s] Registration Failed, IPM Error %d\r\n", dev_name, status)); 
} 
 
void CCameraPdd::set_ipm_block(BOOL is_on) 
{ 
    if (!is_ipm_enabled) 
        return; 
 
    if (is_on) 
    { 
        ipm_block_ref_count++; 
        if (ipm_block_ref_count > 1) 
            return; 
    } 
    else 
    { 
        if (ipm_block_ref_count) 
        { 
            ipm_block_ref_count--; 
            if (ipm_block_ref_count) 
                return; 
        } else 
            return; 
    } 
     
    DEBUGMSG(ZONE_IOCTL,(L"CAM: set_ipm_block %d, ref count %d!\r\n", is_on, ipm_block_ref_count)); 
     
    DWORD dwProcState; 
    dwProcState = IPM_PROCESSOR_D0_RDY 
                | IPM_PROCESSOR_RING_OSC_RDY   
                | IPM_PROCESSOR_D2_RDY 
                | IPM_PROCESSOR_D1_RDY; // Initial 
 
    if (ipm_block_ref_count) 
        dwProcState = IPM_PROCESSOR_D0_RDY; 
 
    IPM_STATUS_T status; 
    status = IPM_NotifyReadyForProcState(ipm_client_id, dwProcState, 1000); 
         
    if (status != IPM_STATUS_SUCCESS)         
        DEBUGMSG( ZONE_IOCTL, ( _T("CAM: camera IPM_NotifyReadyForProcState failed!\r\n")) ); 
    if (ipm_block_ref_count) 
        status = IPM_SetFreqChangeBlock(ipm_client_id, 1000); 
    else 
        status = IPM_ReleaseFreqChangeBlock(ipm_client_id, 1000); 
 
    if (status != IPM_STATUS_SUCCESS) 
        DEBUGMSG( ZONE_IOCTL, ( _T("CAM: camera IPM_SetFreqChangeBlock failed!\r\n")) ); 
         
} 
 
void CCameraPdd::power_on() 
{ 
    qci_clock_enable(1); 
    qci_set_interface(sensor->get_qci_interface()); 
    sensor->set_power_mode(1); 
    Sleep(1); 
} 
 
bool CCameraPdd::detect_sensor() 
{ 
    set_ipm_block(1); 
    power_on(); 
 
    qci_enable(); 
    Sleep(150); 
    bool detected = sensor->detect(); 
    if (detected) 
        sensor->stop_capture(); 
    is_sensor_on = 1; 
 
    set_ipm_block(0); 
    return detected; 
} 
 
void CCameraPdd::power_off() 
{ 
    qci_stop_capture(); 
    sensor->set_power_mode(0); 
    qci_clock_enable(0); 
    is_sensor_on = 0; 
} 
  
void CCameraPdd::set_capture_format(int sensor_format, 
                                    FrameSize sensor_size, 
                                    format_t* qci_format) 
{ 
    qci_master_timing_t timing; 
 
    timing.width = qci_format->width - 1; 
    timing.height = qci_format->height - 1; 
    if (qci_format->format != sensor_format) 
        timing.height++; 
    timing.timing = sensor->get_timing(); 
    sensor->set_frame_format(sensor_format, sensor_size); 
    qci_set_master_timing(&timing); 
    qci_set_image_format(sensor_format, qci_format->format); 
    qci_set_frame_format(qci_format); 
} 
 
void CCameraPdd::start_capture(ULONG mode) 
{ 
     
    set_ipm_block(1); 
    PCS_VIDEOINFOHEADER video_info; 
 
    video_info = &m_pCurrentFormat[mode].VideoInfoHeader; 
    UINT32 width        = video_info->bmiHeader.biWidth; 
    UINT32 height       = video_info->bmiHeader.biHeight; 
 
    qci_image_proc_cfg_t qci_cfg; 
    qci_image_proc_cfg_t* qci_cfg_ptr = 0; 
 
    float *coe; 
 
    if (!is_sensor_on) 
        detect_sensor(); 
 
    camera_cfg = sensor->get_camera_cfg(video_info, mode); 
 
    set_capture_format(camera_cfg->sensor_format, 
                       camera_cfg->sensor_size, 
                       &camera_cfg->qci_format); 
 
    // coefficent for color conversion.  
    if (camera_cfg->color_cfg) 
    { 
        coe = camera_cfg->color_cfg->color_correct_coe; 
        qci_cfg.coe.k00 = QCI_COE_CONVERT(0.299 * coe[0] + 0.587 * coe[3] + 0.114 * coe[6]); 
        qci_cfg.coe.k01 = QCI_COE_CONVERT(0.299 * coe[1] + 0.587 * coe[4] + 0.114 * coe[7]); 
        qci_cfg.coe.k02 = QCI_COE_CONVERT(0.299 * coe[2] + 0.587 * coe[5] + 0.114 * coe[8]); 
 
        qci_cfg.coe.k10 = QCI_COE_CONVERT(-0.16874 * coe[0] -0.33126 * coe[3] + 0.5 * coe[6]); 
        qci_cfg.coe.k11 = QCI_COE_CONVERT(-0.16874 * coe[1] -0.33126 * coe[4] + 0.5 * coe[7]); 
        qci_cfg.coe.k12 = QCI_COE_CONVERT(-0.16874 * coe[2] -0.33126 * coe[5] + 0.5 * coe[8]); 
 
        qci_cfg.coe.k20 = QCI_COE_CONVERT(0.5 * coe[0] -0.41869 * coe[3] - 0.08131 * coe[6]); 
        qci_cfg.coe.k21 = QCI_COE_CONVERT(0.5 * coe[1] -0.41869 * coe[4] - 0.08131 * coe[7]); 
        qci_cfg.coe.k22 = QCI_COE_CONVERT(0.5 * coe[2] -0.41869 * coe[5] - 0.08131 * coe[8]); 
 
        qci_cfg.scale = 0; 
        qci_cfg.black_level = camera_cfg->color_cfg->black_level; 
        qci_cfg.lut = camera_cfg->color_cfg->gama; 
        qci_cfg_ptr = &qci_cfg; 
    } 
 
    // CMU will not be enabled when input is raw data 
    if (camera_cfg->qci_format.format != PXA_CAMERA_IMAGE_FORMAT_RAW10) 
        qci_set_image_proc_cfg(qci_cfg_ptr); 
 
#define DEFAULT_STILL_SKIPS 2 
    qci_start_capture(mode == STILL? DEFAULT_STILL_SKIPS : 0); 
    sensor->start_capture(); 
} 
 
void CCameraPdd::stop_capture() 
{ 
    sensor->stop_capture(); 
    qci_stop_capture(); 
    set_ipm_block(0); 
} 
 
const UINT32 color_proc_max_width = 1280; 
const UINT32 color_proc_max_height = 1024; 
 
void fill_plane(PUCHAR dest, plane_t* plane, UINT32 size) 
{ 
    DEBUGMSG(ZONE_IOCTL,(L"CAM: DestAddr:0x%08x, BufAddr:0x%08x, size:%d\r\n", dest, plane->buf.buf, size)); 
    memcpy(dest, plane->buf.buf, plane->buf.size); 
} 
 
void fill_plane_cb_cr(PUCHAR dest, PUCHAR src,  
                      UINT32 width, UINT32 height) 
{ 
     
    for (UINT32 i = 0; i < height; i++) 
    { 
        memcpy(dest, src, width); 
        dest += width; 
        src += width << 1; 
    } 
} 
 
void fill_buffer_yv12(PUCHAR* dest_plane, frame_t* frame) 
{ 
    format_t *format = &frame->list->format; 
    UINT32 y_size = format->width * format->height; 
     
    fill_plane(dest_plane[0], &frame->plane[0], y_size); 
     
    DEBUGMSG(ZONE_IOCTL,(L"CAM: DestAddr:0x%08x, BufAddr:0x%08x, cbcr...", dest_plane[2], frame->plane[1].buf.buf));     
    fill_plane_cb_cr(dest_plane[2], (PUCHAR)frame->plane[1].buf.buf,  
        format->width >> 1, format->height >> 1); 
     
    DEBUGMSG(ZONE_IOCTL,(L"CAM: DestAddr:0x%08x, BufAddr:0x%08x, cbcr...", dest_plane[1], frame->plane[2].buf.buf));     
    fill_plane_cb_cr(dest_plane[1], (PUCHAR)frame->plane[2].buf.buf,  
        format->width >> 1, format->height >> 1); 
} 
 
#define CROP_RGGB 
void convert_rggb10_rgb565(UINT16 *dst, UINT16 *src,  
              UINT32 dst_width, UINT32 dst_height, 
              UINT32 src_width, UINT32 src_height) 
{ 
    UINT32 src_x0_pos = 0; 
    UINT32 src_pos = 0; 
 
    UINT32 line_step = src_height / dst_height / 2; 
    line_step *= 2; 
    UINT32 col_step = src_width / dst_width / 2; 
    col_step *= 2; 
    UINT32 src_size = src_width * src_height; 
 
#ifdef CROP_RGGB 
    line_step = 2; 
    col_step = 2; 
#endif 
 
    UINT32 line, col; 
 
    for (line = 0; line < dst_height && (src_x0_pos + src_width) < src_size; line++) 
    { 
        for (col = 0; col < dst_width && (src_pos + 1 - src_x0_pos) < src_width; col++) 
        { 
            UINT16 r = src[src_pos]; 
            UINT16 g = (src[src_pos + 1] + src[src_pos + src_width]) >> 1; 
            UINT16 b = src[src_pos + src_width + 1]; 
 
            dst[line * dst_width + col] = ((r >> 5) << 11) | ((g >> 4) << 5) | (b >> 5); 
            src_pos += col_step; 
        } 
        src_x0_pos += src_width * line_step; 
        src_pos = src_x0_pos; 
    } 
} 
 
 
#ifndef _CALLBACK 
#define _CALLBACK __STDCALL 
#endif 
 
void* _CALLBACK ippiMalloc(int size) 
{ 
    return malloc(size); 
} 
 
void _CALLBACK ippiFree(void* pSrcBuf) 
{ 
    free(pSrcBuf); 
}