/****************************************************************************** * Resize_config ******************************************************************************/ Int Resize_config(Resize_Handle hResize, Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf) { #ifdef CONFIG_DM365_IPIPE BufferGfx_Dimensions srcDim, dstDim; UInt hDif; UInt vDif; struct rsz_channel_config rsz_chan_config; struct rsz_single_shot_config rsz_ss_config; /* Make sure our input parameters are valid */ if (!hResize) { Dmai_err0("Resize_Handle parameter must not be NULL\n"); return Dmai_EINVAL; } if (!hSrcBuf) { Dmai_err0("Source buffer parameter must not be NULL\n"); return Dmai_EINVAL; } if (!hDstBuf) { Dmai_err0("Destination buffer parameter must not be NULL\n"); return Dmai_EINVAL; } /* Buffer needs to be graphics buffers */ if (Buffer_getType(hSrcBuf) != Buffer_Type_GRAPHICS || Buffer_getType(hDstBuf) != Buffer_Type_GRAPHICS) { Dmai_err0("Src and dst buffers need to be graphics buffers\n"); return Dmai_EINVAL; } BufferGfx_getDimensions(hSrcBuf, &srcDim); BufferGfx_getDimensions(hDstBuf, &dstDim); if (dstDim.width <= 0) { Dmai_err0("Destination buffer width must be greater than zero\n"); return Dmai_EINVAL; } if (dstDim.height <= 0) { Dmai_err0("Destination buffer height must be greater than zero\n"); return Dmai_EINVAL; } if ((srcDim.lineLength & 0x1F) != 0) { Dmai_err0("Source buffer pitch must be a multiple of 32 bytes\n"); return Dmai_EINVAL; } if ((dstDim.lineLength & 0x1F) != 0) { Dmai_err0("Destination buffer pitch must be a multiple of 32 bytes\n"); return Dmai_EINVAL; } /* Check for valid buffer scaling */ hDif = srcDim.width * 256 / dstDim.width; vDif = srcDim.height * 256 / dstDim.height; if (hDif < 32) { Dmai_err0("Horizontal up-scaling must not exceed 8x\n"); return Dmai_EINVAL; } if (hDif > 4096) { Dmai_err0("Horizontal down-scaling must not exceed 1/16x\n"); return Dmai_EINVAL; } if (vDif < 32) { Dmai_err0("Vertical up-scaling must not exceed 8x\n"); return Dmai_EINVAL; } if (vDif > 4096) { Dmai_err0("Vertical down-scaling must not exceed 1/16x\n"); return Dmai_EINVAL; } /* Set the driver default parameters and retrieve what was set */ Dmai_clear(rsz_ss_config); rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT; rsz_chan_config.chain = 0; rsz_chan_config.len = 0; rsz_chan_config.config = NULL; /* to set defaults in driver */ if (ioctl(hResize->fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) { Dmai_err0("Error in setting default configuration for single shot mode\n"); goto cleanup; } /* default configuration setting in Resizer successfull */ Dmai_clear(rsz_ss_config); rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT; rsz_chan_config.chain = 0; rsz_chan_config.len = sizeof(struct rsz_single_shot_config); rsz_chan_config.config = &rsz_ss_config; if (ioctl(hResize->fd, RSZ_G_CONFIG, &rsz_chan_config) < 0) { Dmai_err0("Error in getting resizer channel configuration from driver\n"); goto cleanup; } /* input params are set at the resizer */ rsz_ss_config.input.image_width = srcDim.width; rsz_ss_config.input.image_height = srcDim.height; rsz_ss_config.input.ppln = rsz_ss_config.input.image_width + 8; rsz_ss_config.input.lpfr = rsz_ss_config.input.image_height + 10; rsz_ss_config.input.pix_fmt = pixFormatConversion(BufferGfx_getColorSpace(hSrcBuf)); rsz_ss_config.output1.pix_fmt = pixFormatConversion(BufferGfx_getColorSpace(hDstBuf)); rsz_ss_config.output1.enable = 1; rsz_ss_config.output1.width = dstDim.width; rsz_ss_config.output1.height = dstDim.height; rsz_ss_config.output2.enable = 0; rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT; rsz_chan_config.chain = 0; rsz_chan_config.len = sizeof(struct rsz_single_shot_config); if (ioctl(hResize->fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) { Dmai_err0("Error in setting default configuration for single shot mode\n"); goto cleanup; } rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT; rsz_chan_config.chain = 0; rsz_chan_config.len = sizeof(struct rsz_single_shot_config); /* read again and verify */ if (ioctl(hResize->fd, RSZ_G_CONFIG, &rsz_chan_config) < 0) { Dmai_err0("Error in getting configuration from driver\n"); goto cleanup; } return Dmai_EOK; cleanup: close(hResize->fd); hResize->fd = 0; return Dmai_EFAIL; #else Dmai_err0("not implemented\n"); return Dmai_ENOTIMPL; #endif }
/****************************************************************************** * Framecopy_accel_execute ******************************************************************************/ Int Framecopy_accel_config(Framecopy_Handle hFc, Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf) { #ifdef CONFIG_VDCE vdce_params_t params; BufferGfx_Dimensions srcDim; BufferGfx_Dimensions dstDim; Int width, height; /* Buffer needs to be graphics buffers */ if (Buffer_getType(hSrcBuf) != Buffer_Type_GRAPHICS || Buffer_getType(hDstBuf) != Buffer_Type_GRAPHICS) { Dmai_err0("Src and dst buffers need to be graphics buffers\n"); return Dmai_EINVAL; } /* Sanity check buffer color space */ if (BufferGfx_getColorSpace(hSrcBuf) != BufferGfx_getColorSpace(hDstBuf)) { Dmai_err0("Src and dst buffers need to have same colorspace\n"); return Dmai_EINVAL; } BufferGfx_getDimensions(hSrcBuf, &srcDim); BufferGfx_getDimensions(hDstBuf, &dstDim); /* Source and destination width must be even */ if (dstDim.width % 2 || srcDim.width % 2) { Dmai_err2("Output (%d) and input width (%d) must be even\n", dstDim.width, srcDim.width); return Dmai_EINVAL; } /* Pitches must be a multiple of 8 */ if (dstDim.lineLength % 8 || srcDim.lineLength % 8) { Dmai_err2("Dst (%ld) and src (%ld) pitch must be a multiple of 8\n", dstDim.lineLength, srcDim.lineLength); return Dmai_EINVAL; } /* Select the smallest resolution */ width = srcDim.width < dstDim.width ? srcDim.width : dstDim.width; height = srcDim.height < dstDim.height ? srcDim.height : dstDim.height; Dmai_dbg2("Configuring resizer to copy image resolution %dx%d\n", width, height); params.vdce_mode = VDCE_OPERATION_RESIZING; if (ioctl(hFc->fd, VDCE_GET_DEFAULT, ¶ms) < 0) { Dmai_err0("default params failed error.\n"); return Dmai_EFAIL; } switch (BufferGfx_getColorSpace(hSrcBuf)) { case ColorSpace_YUV422PSEMI: params.vdce_mode_params.rsz_params.rsz_mode = VDCE_MODE_422; /* Speed up the conversion, note that this value hangs the resizer * for 420P color format */ params.common_params.prcs_unit_value = 256; break; case ColorSpace_YUV420PSEMI: params.vdce_mode_params.rsz_params.rsz_mode = VDCE_MODE_420; break; default: Dmai_err0("Colorspace format not supported\n"); return Dmai_ENOTIMPL; } params.common_params.src_hsz_luminance = width; params.common_params.src_vsz_luminance = height; params.common_params.dst_hsz_luminance = width; params.common_params.dst_vsz_luminance = height; params.common_params.src_processing_mode = VDCE_PROGRESSIVE; params.common_params.src_mode = VDCE_FRAME_MODE; params.common_params.res_mode = VDCE_FRAME_MODE; /* call ioctl to set parameters */ if (ioctl(hFc->fd, VDCE_SET_PARAMS, ¶ms) < 0) { Dmai_err0("VDCE_SET_PARAMS failed \n"); return Dmai_EFAIL; } return Dmai_EOK; #else Dmai_err0("not implemented\n"); return Dmai_ENOTIMPL; #endif }
/****************************************************************************** * Display_v4l2_create ******************************************************************************/ Display_Handle Display_v4l2_create(BufTab_Handle hBufTab, Display_Attrs *attrs) { struct v4l2_format fmt; enum v4l2_buf_type type; Display_Handle hDisplay; Int32 width, height, bytesperline; assert(attrs); /* delayStreamon not supported for this platform */ if (attrs->delayStreamon == TRUE) { Dmai_err0("Support for delayed VIDIOC_STREAMON not implemented\n"); return NULL; } /* Allocate space for state object */ hDisplay = calloc(1, sizeof(Display_Object)); if (hDisplay == NULL) { Dmai_err0("Failed to allocate space for Display Object\n"); return NULL; } hDisplay->userAlloc = TRUE; /* Open video capture device */ hDisplay->fd = open(attrs->displayDevice, O_RDWR, 0); if (hDisplay->fd == -1) { Dmai_err2("Cannot open %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } /* Determine the video image dimensions */ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (ioctl(hDisplay->fd, VIDIOC_G_FMT, &fmt) == -1) { Dmai_err0("Failed to determine video display format\n"); cleanup(hDisplay); return NULL; } Dmai_dbg3("Found video output size %dx%d pitch %d\n", fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline); /* If video standard is set to auto then use current height and width */ if (attrs->videoStd == VideoStd_AUTO) { width = fmt.fmt.pix.width; height = fmt.fmt.pix.height; bytesperline = fmt.fmt.pix.bytesperline; } else if (attrs->videoStd == -1) { width = attrs->width; height = attrs->height; bytesperline = width; } else { VideoStd_getResolution(attrs->videoStd, &width, &height); bytesperline = width; } fmt.fmt.pix.width = width; fmt.fmt.pix.height = height; fmt.fmt.pix.bytesperline = bytesperline; fmt.fmt.pix.sizeimage = bytesperline * height * 2; /* If colorspace is passed then use this colorspace */ switch (attrs->colorSpace) { case ColorSpace_YUV422PSEMI: fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV16; break; default: Dmai_err0("Output colorspace is not supported\n"); cleanup(hDisplay); return NULL; break; } Dmai_dbg3("Setting video output size %dx%d pitch %d\n", fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline); if (ioctl(hDisplay->fd, VIDIOC_S_FMT, &fmt) == -1) { Dmai_err0("Failed to set video display format\n"); cleanup(hDisplay); return NULL; } Dmai_dbg3("Current video output size %dx%d pitch %d\n", fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline); /* Should the device driver allocate the display buffers? */ if (hBufTab == NULL) { hDisplay->userAlloc = FALSE; if (_Dmai_v4l2DriverAlloc(hDisplay->fd, attrs->numBufs, V4L2_BUF_TYPE_VIDEO_OUTPUT, &hDisplay->bufDescs, &hBufTab, 0, attrs->colorSpace) < 0) { Dmai_err1("Failed to allocate display driver buffers on %s\n", attrs->displayDevice); cleanup(hDisplay); return NULL; } } else { Dmai_err0("User supplied buffers not supported\n"); cleanup(hDisplay); return NULL; } /* Start the video streaming */ type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (ioctl(hDisplay->fd, VIDIOC_STREAMON, &type) == -1) { Dmai_err2("VIDIOC_STREAMON failed on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } hDisplay->started = TRUE; hDisplay->hBufTab = hBufTab; hDisplay->displayStd = Display_Std_V4L2; return hDisplay; }
/****************************************************************************** * Sdec_create ******************************************************************************/ Sdec_Handle Sdec_create(Engine_Handle hEngine, Char *codecName, SPHDEC_Params *params, SPHDEC_DynamicParams *dynParams) { Sdec_Handle hSd; SPHDEC_Handle hDecode; SPHDEC_Status decStatus; XDAS_Int32 status; if (hEngine == NULL || codecName == NULL || params == NULL || dynParams == NULL) { Dmai_err0("Cannot pass null for engine, codec name, params or " "dynamic params\n"); return NULL; } /* Allocate space for the object */ hSd = (Sdec_Handle)calloc(1, sizeof(Sdec_Object)); if (hSd == NULL) { Dmai_err0("Failed to allocate space for Sdec Object\n"); return NULL; } /* Create speech decoder */ hDecode = SPHDEC_create(hEngine, codecName, params); if (hDecode == NULL) { Dmai_err0("Failed to create speech decoder\n"); cleanup(hSd); return NULL; } Dmai_dbg1("Speech decoder instance of %s created\n", codecName); /* Set dynamic parameters */ decStatus.size = sizeof(SPHDEC_Status); status = SPHDEC_control(hDecode, XDM_SETPARAMS, dynParams, &decStatus); if (status != SPHDEC_EOK) { Dmai_err1("XDM_SETPARAMS failed, status=%d\n", status); SPHDEC_delete(hDecode); cleanup(hSd); return NULL; } /* Get buffer information from video decoder */ status = SPHDEC_control(hDecode, XDM_GETBUFINFO, dynParams, &decStatus); if (status != SPHDEC_EOK) { Dmai_err0("XDM_GETBUFINFO control failed\n"); SPHDEC_delete(hDecode); cleanup(hSd); return NULL; } Dmai_dbg2("Speech decoder requires buffer sizes in %u and out %u\n", (Uns) decStatus.bufInfo.minInBufSize[0], (Uns) decStatus.bufInfo.minInBufSize[1]); memcpy(hSd->minInBufSize, decStatus.bufInfo.minInBufSize, sizeof(hSd->minInBufSize)); hSd->minNumInBufs = decStatus.bufInfo.minNumInBufs; memcpy(hSd->minOutBufSize, decStatus.bufInfo.minOutBufSize, sizeof(hSd->minOutBufSize)); hSd->minNumOutBufs = decStatus.bufInfo.minNumOutBufs; hSd->hDecode = hDecode; return hSd; }
/****************************************************************************** * Framecopy_accel_execute ******************************************************************************/ Int Framecopy_accel_execute(Framecopy_Handle hFc, Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf) { #ifdef CONFIG_VDCE vdce_address_start_t params; BufferGfx_Dimensions srcDim; BufferGfx_Dimensions dstDim; UInt32 srcOffset, dstOffset; assert(hFc); assert(hSrcBuf); assert(hDstBuf); /* VDCE addresses must be a multiple of 8 */ assert((((UInt32) Buffer_getUserPtr(hDstBuf)) & 0x7) == 0); assert((((UInt32) Buffer_getUserPtr(hSrcBuf)) & 0x7) == 0); /* Buffer sizes / 4 must be a multiple of 8 */ assert(((Buffer_getSize(hSrcBuf) / 4) & 0x7) == 0); assert(((Buffer_getSize(hDstBuf) / 4) & 0x7) == 0); BufferGfx_getDimensions(hSrcBuf, &srcDim); BufferGfx_getDimensions(hDstBuf, &dstDim); assert(srcDim.x >= 0); assert(srcDim.y >= 0); assert(dstDim.x >= 0); assert(dstDim.y >= 0); assert((srcDim.x & 0x7) == 0); assert((dstDim.x & 0x7) == 0); srcOffset = srcDim.y * srcDim.lineLength + srcDim.x; dstOffset = dstDim.y * dstDim.lineLength + dstDim.x; params.buffers[VDCE_BUF_IN].index = -1; params.buffers[VDCE_BUF_IN].buf_type = VDCE_BUF_IN; params.buffers[VDCE_BUF_IN].virt_ptr = ((Int32) Buffer_getUserPtr(hSrcBuf)+ srcOffset); params.buffers[VDCE_BUF_IN].size = Buffer_getSize(hSrcBuf); params.buffers[VDCE_BUF_OUT].index = -1; params.buffers[VDCE_BUF_OUT].buf_type = VDCE_BUF_OUT; params.buffers[VDCE_BUF_OUT].virt_ptr = ((Int32) Buffer_getUserPtr(hDstBuf)+ dstOffset); params.buffers[VDCE_BUF_OUT].size = Buffer_getSize(hDstBuf); params.src_horz_pitch = srcDim.lineLength; params.res_horz_pitch = dstDim.lineLength; if (ioctl(hFc->fd, VDCE_START, ¶ms) < 0) { Dmai_err0("Failed VDCE_START\n"); return Dmai_EFAIL; } if (BufferGfx_getColorSpace(hDstBuf) == ColorSpace_YUV420PSEMI) { Buffer_setNumBytesUsed(hDstBuf, dstDim.width * dstDim.height * 3 / 2); } else { Buffer_setNumBytesUsed(hDstBuf, dstDim.width * dstDim.height * 2); } return Dmai_EOK; #else Dmai_err0("not implemented\n"); return Dmai_ENOTIMPL; #endif }
/****************************************************************************** * _Dmai_v4l2DriverAlloc ******************************************************************************/ Int _Dmai_v4l2DriverAlloc(Int fd, Int numBufs, enum v4l2_buf_type type, struct _VideoBufDesc **bufDescsPtr, BufTab_Handle *hBufTabPtr, Int topOffset, ColorSpace_Type colorSpace) { BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; struct v4l2_requestbuffers req; struct v4l2_format fmt; _VideoBufDesc *bufDesc; Buffer_Handle hBuf; Int bufIdx; Int8 *virtPtr; Dmai_clear(fmt); fmt.type = type; if (ioctl(fd, VIDIOC_G_FMT, &fmt) == -1) { Dmai_err1("VIDIOC_G_FMT failed (%s)\n", strerror(errno)); return Dmai_EFAIL; } Dmai_clear(req); req.count = numBufs; req.type = type; req.memory = V4L2_MEMORY_MMAP; /* Allocate buffers in the capture device driver */ if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { Dmai_err1("VIDIOC_REQBUFS failed (%s)\n", strerror(errno)); return Dmai_ENOMEM; } if (req.count < numBufs || !req.count) { Dmai_err0("Insufficient device driver buffer memory\n"); return Dmai_ENOMEM; } /* Allocate space for buffer descriptors */ *bufDescsPtr = calloc(numBufs, sizeof(_VideoBufDesc)); if (*bufDescsPtr == NULL) { Dmai_err0("Failed to allocate space for buffer descriptors\n"); return Dmai_ENOMEM; } gfxAttrs.dim.width = fmt.fmt.pix.width; gfxAttrs.dim.height = fmt.fmt.pix.height; gfxAttrs.dim.lineLength = fmt.fmt.pix.bytesperline; gfxAttrs.colorSpace = colorSpace; gfxAttrs.bAttrs.reference = TRUE; *hBufTabPtr = BufTab_create(numBufs, fmt.fmt.pix.sizeimage, BufferGfx_getBufferAttrs(&gfxAttrs)); if (*hBufTabPtr == NULL) { return Dmai_ENOMEM; } for (bufIdx = 0; bufIdx < numBufs; bufIdx++) { bufDesc = &(*bufDescsPtr)[bufIdx]; /* Ask for information about the driver buffer */ Dmai_clear(bufDesc->v4l2buf); bufDesc->v4l2buf.type = type; bufDesc->v4l2buf.memory = V4L2_MEMORY_MMAP; bufDesc->v4l2buf.index = bufIdx; if (ioctl(fd, VIDIOC_QUERYBUF, &bufDesc->v4l2buf) == -1) { Dmai_err1("Failed VIDIOC_QUERYBUF (%s)\n", strerror(errno)); return Dmai_EFAIL; } /* Map the driver buffer to user space */ virtPtr = mmap(NULL, bufDesc->v4l2buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bufDesc->v4l2buf.m.offset) + topOffset; if (virtPtr == MAP_FAILED) { Dmai_err1("Failed to mmap buffer (%s)\n", strerror(errno)); return Dmai_EFAIL; } /* Initialize the Buffer with driver buffer information */ hBuf = BufTab_getBuf(*hBufTabPtr, bufIdx); Buffer_setNumBytesUsed(hBuf, fmt.fmt.pix.bytesperline * fmt.fmt.pix.height); Buffer_setUseMask(hBuf, gfxAttrs.bAttrs.useMask); Buffer_setUserPtr(hBuf, virtPtr); /* Initialize buffer to black */ _Dmai_blackFill(hBuf); Dmai_dbg3("Driver buffer %d mapped to %#x has physical address " "%#lx\n", bufIdx, (Int) virtPtr, Buffer_getPhysicalPtr(hBuf)); bufDesc->hBuf = hBuf; /* Queue buffer in device driver */ if (ioctl(fd, VIDIOC_QBUF, &bufDesc->v4l2buf) == -1) { Dmai_err1("VIODIOC_QBUF failed (%s)\n", strerror(errno)); return Dmai_EFAIL; } } return Dmai_EOK; }
/****************************************************************************** * Sound_alsa_create ******************************************************************************/ Sound_Handle Sound_alsa_create(Sound_Attrs *attrs) { Sound_Handle hSound; Int status; snd_output_t *log; assert(attrs); hSound = calloc(1, sizeof(Sound_Object)); if (hSound == NULL) { Dmai_err0("Failed to allocate space for Sound Object\n"); return NULL; } hSound->soundStd = attrs->soundStd; hSound->sampleRate = attrs->sampleRate; hSound->channels = attrs->channels; hSound->bufSize = attrs->bufSize; if (attrs->mode == Sound_Mode_INPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { status = snd_pcm_open(&hSound->rcIn, AUDIO_DEVICE, SND_PCM_STREAM_CAPTURE, 0); if (status < 0) { Dmai_err2("Failed to open ALSA sound device for input %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } /* Allocate a PCM SW and HW Param structure */ status = snd_pcm_hw_params_malloc(&hSound->hwParamsIn); if (status < 0) { Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } status = snd_pcm_sw_params_malloc(&hSound->swParamsIn); if (status < 0) { Dmai_err2("Failed to alloc software param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } if (initHwParams(hSound->rcIn,hSound->hwParamsIn,attrs,hSound) < 0) { Sound_alsa_delete(hSound); return NULL; } if (initSwParams(hSound->rcIn,hSound->swParamsIn,hSound,1) < 0) { Sound_alsa_delete(hSound); return NULL; } } if (attrs->mode == Sound_Mode_OUTPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { status = snd_pcm_open(&hSound->rcOut, AUDIO_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); if (status < 0) { Dmai_err2("Failed to open ALSA sound device for output %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } /* Allocate a PCM SW and HW Param structure */ status = snd_pcm_hw_params_malloc(&hSound->hwParamsOut); if (status < 0) { Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } status = snd_pcm_sw_params_malloc(&hSound->swParamsOut); if (status < 0) { Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } if (initHwParams(hSound->rcOut,hSound->hwParamsOut,attrs,hSound) < 0) { Sound_alsa_delete(hSound); return NULL; } if (initSwParams(hSound->rcOut,hSound->swParamsOut,hSound,0) < 0) { Sound_alsa_delete(hSound); return NULL; } if (setMixerVolume (attrs) <0) { Sound_alsa_delete (hSound); return NULL; } } #if 0 if (attrs->mode != Sound_Mode_OUTPUT) { if (attrs->soundInput == Sound_Input_MIC) { if(setMixerControl(RIGHT_LINE_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Line1R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_LINE_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Line1L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(RIGHT_MIC_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Mic3R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_MIC_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Mic3L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } } else if (attrs->soundInput == Sound_Input_LINE) { if(setMixerControl(RIGHT_LINE_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Line1R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_LINE_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Line1L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(RIGHT_MIC_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Mic3R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_MIC_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Mic3L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } } } snd_output_close(log); #endif return hSound; }
/****************************************************************************** * _Dmai_v4l2UserAlloc ******************************************************************************/ Int _Dmai_v4l2UserAlloc(Int fd, Int numBufs, enum v4l2_buf_type type, struct _VideoBufDesc **bufDescsPtr, BufTab_Handle hBufTab, Int topOffset, ColorSpace_Type colorSpace, Int queueBuffers) { struct v4l2_requestbuffers req; struct v4l2_format fmt; _VideoBufDesc *bufDesc; Buffer_Handle hBuf; Int bufIdx; Dmai_clear(fmt); fmt.type = type; /* * Tell the driver that we will use user allocated buffers, but don't * allocate any buffers in the driver (just the internal descriptors). */ Dmai_clear(req); req.type = type; req.count = numBufs; req.memory = V4L2_MEMORY_USERPTR; if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { Dmai_err0("Could not allocate video display buffers\n"); return Dmai_ENOMEM; } /* The driver may return less buffers than requested */ if (req.count < numBufs || !req.count) { Dmai_err0("Insufficient device driver buffer memory\n"); return Dmai_ENOMEM; } /* Allocate space for buffer descriptors */ *bufDescsPtr = calloc(numBufs, sizeof(_VideoBufDesc)); if (*bufDescsPtr == NULL) { Dmai_err0("Failed to allocate space for buffer descriptors\n"); return Dmai_ENOMEM; } for (bufIdx = 0; bufIdx < numBufs; bufIdx++) { bufDesc = &(*bufDescsPtr)[bufIdx]; hBuf = BufTab_getBuf(hBufTab, bufIdx); if (hBuf == NULL) { Dmai_err0("Failed to get buffer from BufTab for display\n"); return Dmai_ENOMEM; } if (Buffer_getType(hBuf) != Buffer_Type_GRAPHICS) { Dmai_err0("Buffer supplied to Display not a Graphics buffer\n"); return Dmai_EINVAL; } Dmai_clear(bufDesc->v4l2buf); bufDesc->v4l2buf.index = bufIdx; bufDesc->v4l2buf.type = type; bufDesc->v4l2buf.memory = V4L2_MEMORY_USERPTR; bufDesc->v4l2buf.m.userptr = (UInt32) Buffer_getUserPtr(hBuf); bufDesc->v4l2buf.length = Buffer_getSize(hBuf); bufDesc->hBuf = hBuf; bufDesc->used = (queueBuffers == FALSE) ? TRUE : FALSE; /* If queueBuffers is TRUE, initialize the buffers to black and queue * them into the driver. */ if (queueBuffers == TRUE) { Buffer_setNumBytesUsed(hBuf, Buffer_getSize(hBuf)); _Dmai_blackFill(hBuf); /* Queue buffer in device driver */ if (ioctl(fd, VIDIOC_QBUF, &bufDesc->v4l2buf) == -1) { Dmai_err1("VIODIC_QBUF failed (%s)\n", strerror(errno)); return Dmai_EFAIL; } } } return Dmai_EOK; }
/****************************************************************************** * Framecopy_resizer_accel_config ******************************************************************************/ Int Framecopy_resizer_accel_config(Framecopy_Handle hFc, Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf) { #if defined(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) struct v4l2_requestbuffers reqbuf; Int rszRate; BufferGfx_Dimensions srcDim, dstDim; struct rsz_params params = { 0, /* in_hsize (set at run time) */ 0, /* in_vsize (set at run time) */ 0, /* in_pitch (set at run time) */ RSZ_INTYPE_YCBCR422_16BIT, /* inptyp */ 0, /* vert_starting_pixel */ 0, /* horz_starting_pixel */ 0, /* cbilin */ RSZ_PIX_FMT_UYVY, /* pix_fmt */ 0, /* out_hsize (set at run time) */ 0, /* out_vsize (set at run time) */ 0, /* out_pitch (set at run time) */ 0, /* hstph */ 0, /* vstph */ { /* hfilt_coeffs */ 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0 }, { /* vfilt_coeffs */ 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0 }, { /* yenh_params */ 0, /* type */ 0, /* gain */ 0, /* slop */ 0 /* core */ } }; /* Pointers must be a multiple of 4096 bytes */ assert((Buffer_getPhysicalPtr(hDstBuf) & 0xFFF) == 0); assert((Buffer_getPhysicalPtr(hSrcBuf) & 0xFFF) == 0); BufferGfx_getDimensions(hSrcBuf, &srcDim); BufferGfx_getDimensions(hDstBuf, &dstDim); Dmai_dbg2("Configuring resizer to copy image of resolution %dx%d\n", srcDim.width, srcDim.height); /* Source and destination pitch must be 32 bytes aligned */ if (srcDim.lineLength % 32 || dstDim.lineLength % 32) { Dmai_err2("Src (%ld) and dst (%ld) must be aligned on 32 bytes\n", srcDim.lineLength, dstDim.lineLength); return Dmai_EINVAL; } /* Set up the copy job */ params.in_hsize = srcDim.width; params.in_vsize = srcDim.height; params.in_pitch = srcDim.lineLength; params.out_hsize = dstDim.width; params.out_vsize = dstDim.height; params.out_pitch = dstDim.lineLength; params.cbilin = 0; params.pix_fmt = RSZ_PIX_FMT_UYVY; params.vert_starting_pixel = 0; params.horz_starting_pixel = 0; params.inptyp = RSZ_INTYPE_YCBCR422_16BIT; params.hstph = 0; params.vstph = 0; params.yenh_params.type = 0; params.yenh_params.gain = 0; params.yenh_params.slop = 0; params.yenh_params.core = 0; hFc->inSize = srcDim.lineLength * params.in_vsize; hFc->outSize = dstDim.lineLength * params.out_vsize; if (ioctl(hFc->fd, RSZ_S_PARAM, ¶ms) == -1) { Dmai_err0("Framecopy setting parameters failed.\n"); return Dmai_EFAIL; } rszRate = 0x0; if (ioctl(hFc->fd, RSZ_S_EXP, &rszRate) == -1) { Dmai_err0("Framecopy setting read cycle failed.\n"); return Dmai_EFAIL; } reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_USERPTR; reqbuf.count = 2; if (ioctl(hFc->fd, RSZ_REQBUF, &reqbuf) == -1) { Dmai_err0("Request buffer failed.\n"); return Dmai_EFAIL; } return Dmai_EOK; #else Dmai_err0("not implemented\n"); return Dmai_ENOTIMPL; #endif /* end CONFIG_VIDEO_OMAP34XX_ISP_RESIZER */ }
/****************************************************************************** * Capture_detectVideoStd ******************************************************************************/ Int Capture_detectVideoStd(Capture_Handle hCapture, VideoStd_Type *videoStdPtr, Capture_Attrs *attrs) { v4l2_std_id id; struct v4l2_input input; Int index; Int fd; struct v4l2_standard std; assert(videoStdPtr); assert(attrs); if (attrs->videoStd < 0 || attrs->videoStd > VideoStd_COUNT) { Dmai_err1("Invalid capture standard given (%d)\n", attrs->videoStd); return Dmai_EINVAL; } if (hCapture) { fd = hCapture->fd; } else { fd = open(attrs->captureDevice, O_RDWR, 0); if (fd == -1) { Dmai_err2("Cannot open %s (%s)\n", attrs->captureDevice, strerror(errno)); return Dmai_EFAIL; } } /* Display available video input */ Dmai_dbg0("Available video input:\n"); for (index=0;; index++) { input.index = index; if (ioctl(fd, VIDIOC_ENUMINPUT, &input) < 0) { if (errno == EINVAL || errno == ENOTTY) break; } Dmai_dbg1(" name=%s\n", input.name); } /* Set video input */ switch (attrs->videoInput) { case Capture_Input_SVIDEO: Dmai_dbg0("Setting video input to SVIDEO\n"); index = 1; break; case Capture_Input_COMPOSITE: Dmai_dbg0("Setting video input to COMPOSITE\n"); index = 0; break; default: Dmai_err0("Unknown video input\n"); return Dmai_EFAIL; break; } if (ioctl(fd, VIDIOC_S_INPUT, &index) < 0) { Dmai_err0("Failed VIDIOC_S_INPUT\n"); return Dmai_EFAIL; } /* Display available video standards */ Dmai_dbg0("Available video standard:\n"); for (index=0;; index++) { std.frameperiod.numerator = 1; std.frameperiod.denominator = 0; std.index = index; if (ioctl(fd, VIDIOC_ENUMSTD, &std) < 0) { if (errno == EINVAL || errno == ENOTTY) break; } Dmai_dbg3(" name=%s, fps=%d/%d\n", std.name, std.frameperiod.denominator, std.frameperiod.numerator); } /* Get current video standard */ if (ioctl(fd, VIDIOC_G_STD, &id) < 0) { Dmai_err0("Failed VIDIOC_G_STD\n"); return Dmai_EFAIL; } if (!hCapture) { close(fd); } if (id & V4L2_STD_NTSC) { *videoStdPtr = VideoStd_D1_NTSC; Dmai_dbg0("Found NTSC std input\n"); } else if (id & V4L2_STD_PAL) { *videoStdPtr = VideoStd_D1_PAL; Dmai_dbg0("Found PAL std input\n"); } else if (id & V4L2_STD_525_60) { *videoStdPtr = VideoStd_480P; Dmai_dbg0("Found 525_60 std input\n"); } else if (id & V4L2_STD_625_50) { *videoStdPtr = VideoStd_576P; Dmai_dbg0("Found 625_50 std input\n"); } else { Dmai_err1("Unknown video standard on capture device %s\n", attrs->captureDevice); return Dmai_EFAIL; } return Dmai_EOK; }
/****************************************************************************** * Capture_create ******************************************************************************/ Capture_Handle Capture_create(BufTab_Handle hBufTab, Capture_Attrs *attrs) { struct v4l2_capability cap; struct v4l2_cropcap cropCap; struct v4l2_crop crop; struct v4l2_format fmt; enum v4l2_buf_type type; Capture_Handle hCapture; VideoStd_Type videoStd; Int32 width, height; Int32 pixelformat; assert(attrs); memset(&fmt, 0x00, sizeof(struct v4l2_format)); /* Allocate space for state object */ hCapture = calloc(1, sizeof(Capture_Object)); if (hCapture == NULL) { Dmai_err0("Failed to allocate space for Capture Object\n"); return NULL; } /* User allocated buffers by default */ hCapture->userAlloc = TRUE; /* Open video capture device */ hCapture->fd = open(attrs->captureDevice, O_RDWR, 0); if (hCapture->fd == -1) { Dmai_err2("Cannot open %s (%s)\n", attrs->captureDevice, strerror(errno)); cleanup(hCapture); return NULL; } /* See if an input is connected, and if so which standard */ if (Capture_detectVideoStd(hCapture, &videoStd, attrs) < 0) { cleanup(hCapture); return NULL; } hCapture->videoStd = videoStd; if (VideoStd_getResolution(videoStd, &width, &height) < 0) { cleanup(hCapture); Dmai_err0("Failed to get resolution of capture video standard\n"); return NULL; } /* Query for capture device capabilities */ if (ioctl(hCapture->fd, VIDIOC_QUERYCAP, &cap) == -1) { cleanup(hCapture); if (errno == EINVAL) { Dmai_err1("%s is no V4L2 device\n", attrs->captureDevice); cleanup(hCapture); return NULL; } Dmai_err2("Failed VIDIOC_QUERYCAP on %s (%s)\n", attrs->captureDevice, strerror(errno)); cleanup(hCapture); return NULL; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { Dmai_err1("%s is not a video capture device\n", attrs->captureDevice); cleanup(hCapture); return NULL; } if (!(cap.capabilities & V4L2_CAP_STREAMING)) { Dmai_err1("%s does not support streaming i/o\n", attrs->captureDevice); cleanup(hCapture); return NULL; } /* Query for video input cropping capability */ cropCap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(hCapture->fd, VIDIOC_CROPCAP, &cropCap) == -1) { Dmai_err2("VIDIOC_CROPCAP failed on %s (%s)\n", attrs->captureDevice, strerror(errno)); cleanup(hCapture); return NULL; } Dmai_dbg4("Cropping window boundry left=%d, top=%d, width=%d, height=%d\n", cropCap.bounds.left, cropCap.bounds.top, cropCap.bounds.width, cropCap.bounds.height); Dmai_dbg4("Default cropping rect left=%d, top=%d, width=%d, height=%d\n", cropCap.defrect.left, cropCap.defrect.top, cropCap.defrect.width, cropCap.defrect.height); if (attrs->cropWidth > 0 && attrs->cropHeight > 0) { if (attrs->cropX & 0x1) { Dmai_err1("Crop width (%ld) needs to be even\n", attrs->cropX); cleanup(hCapture); return NULL; } crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c.left = attrs->cropX; crop.c.top = attrs->cropY; crop.c.width = attrs->cropWidth; crop.c.height = hCapture->topOffset ? attrs->cropHeight + 4 + 2 : attrs->cropHeight; Dmai_dbg4("Setting capture cropping at %dx%d size %dx%d\n", crop.c.left, crop.c.top, crop.c.width, crop.c.height); /* Crop the image depending on requested image size */ if (ioctl(hCapture->fd, VIDIOC_S_CROP, &crop) == -1) { Dmai_err2("VIDIOC_S_CROP failed on %s (%s)\n", attrs->captureDevice, strerror(errno)); cleanup(hCapture); return NULL; } width = crop.c.width; height = crop.c.height; } /* Query for video input format */ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(hCapture->fd, VIDIOC_G_FMT, &fmt) == -1) { Dmai_err2("Failed VIDIOC_G_FMT on %s (%s)\n", attrs->captureDevice, strerror(errno)); cleanup(hCapture); return NULL; } fmt.fmt.pix.width = width; fmt.fmt.pix.height = height; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; switch(attrs->colorSpace) { case ColorSpace_UYVY: fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; pixelformat = fmt.fmt.pix.pixelformat; break; default: Dmai_err0("Dmai capture module does not support this colorSpace\n"); cleanup(hCapture); return NULL; } if (ioctl(hCapture->fd, VIDIOC_S_FMT, &fmt) == -1) { Dmai_err2("Failed VIDIOC_S_FMT on %s (%s)\n", attrs->captureDevice, strerror(errno)); cleanup(hCapture); return NULL; } if ((fmt.fmt.pix.width != width) || (fmt.fmt.pix.height != height)) { Dmai_err4("Failed to set resolution %d x %d (%d x %d)\n", width, height, fmt.fmt.pix.width, fmt.fmt.pix.height); cleanup(hCapture); return NULL; } if (pixelformat != fmt.fmt.pix.pixelformat) { Dmai_err0("Failed to set pixelformat\n"); cleanup(hCapture); return NULL; } Dmai_dbg3("Video input connected size %dx%d pitch %d\n", fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.bytesperline); if (hBufTab == NULL) { hCapture->userAlloc = FALSE; /* The driver allocates the buffers */ if (_Dmai_v4l2DriverAlloc(hCapture->fd, attrs->numBufs, V4L2_BUF_TYPE_VIDEO_CAPTURE, &hCapture->bufDescs, &hBufTab, hCapture->topOffset, attrs->colorSpace) < 0) { Dmai_err1("Failed to allocate capture driver buffers on %s\n", attrs->captureDevice); cleanup(hCapture); return NULL; } } else { /* Make the driver use the user supplied buffers */ if (_Dmai_v4l2UserAlloc(hCapture->fd, attrs->numBufs, V4L2_BUF_TYPE_VIDEO_CAPTURE, &hCapture->bufDescs, hBufTab, 0, attrs->colorSpace) < 0) { Dmai_err1("Failed to intialize capture driver buffers on %s\n", attrs->captureDevice); cleanup(hCapture); return NULL; } } hCapture->hBufTab = hBufTab; /* Start the video streaming */ type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(hCapture->fd, VIDIOC_STREAMON, &type) == -1) { Dmai_err2("VIDIOC_STREAMON failed on %s (%s)\n", attrs->captureDevice, strerror(errno)); cleanup(hCapture); return NULL; } hCapture->started = TRUE; return hCapture; }
/****************************************************************************** * Display_fbdev_create ******************************************************************************/ Display_Handle Display_fbdev_create(BufTab_Handle hBufTab, Display_Attrs *attrs) { BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT; struct fb_var_screeninfo varInfo; struct fb_fix_screeninfo fixInfo; Int displaySize; Int bufIdx; Int8 *virtPtr; Int32 physPtr; Int32 height, width; Display_Handle hDisplay; Buffer_Handle hBuf; if (attrs == NULL) { Dmai_err0("Must supply valid attrs\n"); return NULL; } if (hBufTab != NULL) { Dmai_err0("FBdev display does not accept user allocated buffers\n"); return NULL; } hDisplay = calloc(1, sizeof(Display_Object)); if (hDisplay == NULL) { Dmai_err0("Failed to allocate space for Display Object\n"); return NULL; } /* Setup sysfs variable */ /* Set up the sysfs variables before opening the display device */ if (_SysFs_setup(attrs) < 0) { cleanup(hDisplay); return NULL; } /* Open video display device */ hDisplay->fd = open(attrs->displayDevice, O_RDWR); if (hDisplay->fd == -1) { Dmai_err2("Failed to open fb device %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } /* Get fixed screen info */ if (ioctl(hDisplay->fd, FBIOGET_FSCREENINFO, &fixInfo) == -1) { Dmai_err2("Failed FBIOGET_FSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } /* Get virtual screen info */ if (ioctl(hDisplay->fd, FBIOGET_VSCREENINFO, &varInfo) == -1) { Dmai_err2("Failed FBIOGET_VSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } Dmai_dbg5("Found width=%d height=%d, yres_virtual=%d,xres_virtual=%d," " line_length=%d\n", varInfo.xres, varInfo.yres, varInfo.yres_virtual,varInfo.xres_virtual, fixInfo.line_length); /* Save current virtual screen info. */ memcpy(&hDisplay->origVarInfo, &varInfo, sizeof(struct fb_var_screeninfo)); /* If video standard is set to auto then use current height and width */ if (attrs->videoStd == VideoStd_AUTO) { width = varInfo.xres; height = varInfo.yres; } else { VideoStd_getResolution(attrs->videoStd, &width, &height); } if (attrs->width > 0) { if (attrs->width > varInfo.xres) width = varInfo.xres; else width = attrs->width; } if (attrs->height > 0) { if (attrs->height > varInfo.yres) height = varInfo.yres; else height = attrs->height; } varInfo.xoffset = 0; varInfo.yoffset = 0; varInfo.xres = width; varInfo.yres = height; varInfo.xres_virtual = width; varInfo.yres_virtual = varInfo.yres * attrs->numBufs; /* Set video display format */ Dmai_dbg4("Setting width=%d height=%d, yres_virtual=%d," " xres_virtual=%d\n", varInfo.xres, varInfo.yres, varInfo.yres_virtual, varInfo.xres_virtual); if (ioctl(hDisplay->fd, FBIOPUT_VSCREENINFO, &varInfo) == -1) { Dmai_err2("Failed FBIOPUT_VSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } if (ioctl(hDisplay->fd, FBIOGET_FSCREENINFO, &fixInfo) == -1) { Dmai_err2("Failed FBIOGET_FSCREENINFO on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } Dmai_dbg5("New width=%d, height=%d, yres_virtual=%d,xres_virtual=%d, " "line_length=%d\n", varInfo.xres, varInfo.yres, varInfo.yres_virtual, varInfo.xres_virtual, fixInfo.line_length); gfxAttrs.dim.width = varInfo.xres; gfxAttrs.colorSpace = attrs->colorSpace; gfxAttrs.dim.height = varInfo.yres; gfxAttrs.dim.lineLength = fixInfo.line_length; gfxAttrs.bAttrs.reference = TRUE; displaySize = fixInfo.line_length * varInfo.yres; hBufTab = BufTab_create(attrs->numBufs, displaySize, BufferGfx_getBufferAttrs(&gfxAttrs)); if (hBufTab == NULL) { Dmai_err0("Failed to allocate BufTab for display buffers\n"); cleanup(hDisplay); return NULL; } hBuf = BufTab_getBuf(hBufTab, 0); Buffer_setNumBytesUsed(hBuf, varInfo.xres * varInfo.yres * varInfo.bits_per_pixel / 8); virtPtr = (Int8 *) mmap (NULL, displaySize * attrs->numBufs, PROT_READ | PROT_WRITE, MAP_SHARED, hDisplay->fd, 0); if (virtPtr == MAP_FAILED) { Dmai_err2("Failed mmap on %s (%s)\n", attrs->displayDevice, strerror(errno)); cleanup(hDisplay); return NULL; } if (Buffer_setUserPtr(hBuf, virtPtr) < 0) { cleanup(hDisplay); return NULL; } _Dmai_blackFill(hBuf); Dmai_dbg3("Display buffer %d mapped to %#lx has physical address %#lx\n", 0, (Int32) virtPtr, physPtr); for (bufIdx=1; bufIdx < attrs->numBufs; bufIdx++) { hBuf = BufTab_getBuf(hBufTab, bufIdx); Buffer_setNumBytesUsed(hBuf, varInfo.xres * varInfo.yres * varInfo.bits_per_pixel / 8); virtPtr = virtPtr + displaySize; Buffer_setUserPtr(hBuf, virtPtr); _Dmai_blackFill(hBuf); Dmai_dbg3("Display buffer %d mapped to %#lx, physical address %#lx\n", bufIdx, (unsigned long) virtPtr, physPtr); } hDisplay->hBufTab = hBufTab; hDisplay->displayIdx = 0; hDisplay->workingIdx = attrs->numBufs > 1 ? 1 : 0; hDisplay->displayStd = Display_Std_FBDEV; if (setDisplayBuffer(hDisplay, hDisplay->displayIdx) < 0) { cleanup(hDisplay); return NULL; } if (ioctl(hDisplay->fd, FBIOBLANK, 0)) { Dmai_err1("Error enabling %s\n", attrs->displayDevice); cleanup(hDisplay); return NULL; } return hDisplay; }