/* * make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ static int fsl_check_usbclk(void) { unsigned long freq; usb_ahb_clk = clk_get(NULL, "usb_ahb_clk"); if (clk_enable(usb_ahb_clk)) { if (cpu_is_mx6()) return 0; /* there is no ahb clock at mx6 */ printk(KERN_ERR "clk_enable(usb_ahb_clk) failed\n"); return -EINVAL; } clk_put(usb_ahb_clk); usb_clk = clk_get(NULL, "usb_clk"); if (clk_enable(usb_clk)) { if (cpu_is_mx6()) return 0; /* there is usb_clk at mx6 */ printk(KERN_ERR "clk_enable(usb_clk) failed\n"); return -EINVAL; } freq = clk_get_rate(usb_clk); clk_put(usb_clk); if ((freq < 59999000) || (freq > 60001000)) { printk(KERN_ERR "USB_CLK=%lu, should be 60MHz\n", freq); return -1; } return 0; }
static int imx6_mmu_init(void) { void __iomem *l2x0_base = IOMEM(0x00a02000); u32 val; if (!cpu_is_mx6()) return 0; /* Configure the L2 PREFETCH and POWER registers */ val = readl(l2x0_base + L310_PREFETCH_CTRL); val |= 0x70800000; /* * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2 * But according to ARM PL310 errata: 752271 * ID: 752271: Double linefill feature can cause data corruption * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 * Workaround: The only workaround to this erratum is to disable the * double linefill feature. This is the default behavior. */ if (cpu_is_mx6q()) val &= ~(1 << 30 | 1 << 23); writel(val, l2x0_base + L310_PREFETCH_CTRL); l2x0_init(l2x0_base, 0x0, ~0UL); return 0; }
static enum filetype imx_bbu_expected_filetype(void) { if (cpu_is_mx8mq() || cpu_is_mx7() || cpu_is_mx6() || cpu_is_vf610() || cpu_is_mx53()) return filetype_imx_image_v2; return filetype_imx_image_v1; }
static int set_cpu_freq(int op) { int ret = 0; if (cpu_is_mx6()) ret = mx6_set_cpu_freq(op); else ret = mx5_set_cpu_freq(op); cpufreq_trig_needed = 1; old_op = op; return ret; }
static u32 esdhc_readl_le(struct sdhci_host *host, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = pltfm_host->priv; /* fake CARD_PRESENT flag on mx25/35 */ u32 val = readl(host->ioaddr + reg); /* * mx6q: SDHCI_PRESENT_STATE bit 16, CINST is not functional on SD3. * So move the section up, and check GPIO for card presence again in * the following block. */ if (reg == SDHCI_PRESENT_STATE && cpu_is_mx6()) { u32 fsl_prss = readl(host->ioaddr + SDHCI_PRESENT_STATE); /* save the least 20 bits */ val |= fsl_prss & 0x000FFFFF; /* move dat[0-3] line signal bits */ val |= (fsl_prss & 0x0F000000) >> 4; /* move cmd line signal bits */ val |= (fsl_prss & 0x00800000) << 1; }
/*! * This is the probe routine for the DVFS driver. * * @param pdev The platform device structure * * @return The function returns 0 on success */ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev) { int err = 0; struct resource *res; printk(KERN_INFO "mxc_dvfs_core_probe\n"); dvfs_dev = &pdev->dev; dvfs_data = pdev->dev.platform_data; INIT_DELAYED_WORK(&dvfs_core_handler, dvfs_core_work_handler); pll1_sw_clk = clk_get(NULL, "pll1_sw_clk"); if (IS_ERR(pll1_sw_clk)) { printk(KERN_INFO "%s: failed to get pll1_sw_clk\n", __func__); return PTR_ERR(pll1_sw_clk); } cpu_clk = clk_get(NULL, dvfs_data->clk1_id); if (IS_ERR(cpu_clk)) { printk(KERN_ERR "%s: failed to get cpu clock\n", __func__); return PTR_ERR(cpu_clk); } if (!cpu_is_mx6()) { dvfs_clk = clk_get(NULL, dvfs_data->clk2_id); if (IS_ERR(dvfs_clk)) { printk(KERN_ERR "%s: failed to get dvfs clock\n", __func__); return PTR_ERR(dvfs_clk); } } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { err = -ENODEV; goto err1; } dvfs_data->membase = ioremap(res->start, res->end - res->start + 1); /* * Request the DVFS interrupt */ dvfs_data->irq = platform_get_irq(pdev, 0); if (dvfs_data->irq < 0) { err = dvfs_data->irq; goto err2; } /* request the DVFS interrupt */ err = request_irq(dvfs_data->irq, dvfs_irq, IRQF_SHARED, "dvfs", dvfs_dev); if (err) { printk(KERN_ERR "DVFS: Unable to attach to DVFS interrupt,err = %d", err); goto err2; } dvfs_core_setpoint = get_dvfs_core_op(&dvfs_core_op); if (dvfs_core_setpoint == NULL) { printk(KERN_ERR "No dvfs_core working point table defined\n"); goto err3; } clk_enable(dvfs_clk); err = init_dvfs_controller(); if (err) { printk(KERN_ERR "DVFS: Unable to initialize DVFS"); return err; } clk_disable(dvfs_clk); err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr); if (err) { printk(KERN_ERR "DVFS: Unable to register sysdev entry for DVFS"); goto err3; } err = sysfs_create_file(&dvfs_dev->kobj, &dev_attr_show_regs.attr); if (err) { printk(KERN_ERR "DVFS: Unable to register sysdev entry for DVFS"); goto err3; } /* Set the current working point. */ cpu_op_tbl = get_cpu_op(&cpu_op_nr); old_op = 0; curr_op = 0; dvfs_core_resume = 0; cpufreq_trig_needed = 0; return err; err3: free_irq(dvfs_data->irq, dvfs_dev); err2: iounmap(dvfs_data->membase); err1: dev_err(&pdev->dev, "Failed to probe DVFS CORE\n"); return err; }
static int start_dvfs(void) { u32 reg, cpu_rate; unsigned long flags; if (dvfs_core_is_active) return 0; spin_lock_irqsave(&mxc_dvfs_core_lock, flags); clk_enable(dvfs_clk); /* get current working point */ cpu_rate = clk_get_rate(cpu_clk); curr_op = cpu_op_nr - 1; do { if (cpu_rate <= cpu_op_tbl[curr_op].cpu_rate) break; } while (--curr_op >= 0); old_op = curr_op; dvfs_load_config(curr_op); if (curr_op == 0) maxf = 1; else maxf = 0; if (curr_op == (cpu_op_nr - 1)) minf = 1; else minf = 0; /* config reg GPC_CNTR */ reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset); reg &= ~MXC_GPCCNTR_GPCIRQM; /* GPCIRQ=1, select ARM IRQ */ reg |= MXC_GPCCNTR_GPCIRQ_ARM; /* ADU=1, select ARM domain */ if (!cpu_is_mx6()) reg |= MXC_GPCCNTR_ADU; __raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset); /* Set PREDIV bits */ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR); reg = (reg & ~(dvfs_data->prediv_mask)); reg |= (dvfs_data->prediv_val) << (dvfs_data->prediv_offset); __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR); /* Enable DVFS interrupt */ reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR); /* FSVAIM=0 */ reg = (reg & ~MXC_DVFSCNTR_FSVAIM); /* Set MAXF, MINF */ reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK)); reg |= 1 << MXC_DVFSCNTR_MAXF_OFFSET; /* Select ARM domain */ reg |= MXC_DVFSCNTR_DVFIS; /* Enable DVFS frequency adjustment interrupt */ reg = (reg & ~MXC_DVFSCNTR_FSVAIM); /* Set load tracking buffer register source */ reg = (reg & ~MXC_DVFSCNTR_LTBRSR_MASK); reg |= DVFS_LTBRSR; /* Set DIV3CK */ reg = (reg & ~(dvfs_data->div3ck_mask)); reg |= (dvfs_data->div3ck_val) << (dvfs_data->div3ck_offset); __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR); /* Enable DVFS */ if (cpu_is_mx6()) { unsigned long cpu_wfi = 0; int num_cpus = num_possible_cpus(); reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_EMAC); /* Need to enable DVFS tracking for each core that is active */ do { if (cpu_active(num_cpus)) set_bit(num_cpus, &cpu_wfi); } while (num_cpus--); reg |= cpu_wfi << 9; __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_EMAC); } else { reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR); reg |= MXC_DVFSCNTR_DVFEN; __raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR); } dvfs_core_is_active = 1; spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags); printk(KERN_DEBUG "DVFS is started\n"); return 0; }
int usbotg_init(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; struct fsl_xcvr_ops *xops; pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata); xops = fsl_usb_get_xcvr(pdata->transceiver); if (!xops) { printk(KERN_ERR "DR transceiver ops missing\n"); return -EINVAL; } pdata->xcvr_ops = xops; pdata->xcvr_type = xops->xcvr_type; pdata->pdev = pdev; if (fsl_check_usbclk() != 0) return -EINVAL; if (!mxc_otg_used) { if (cpu_is_mx50()) /* Turn on AHB CLK for OTG*/ USB_CLKONOFF_CTRL &= ~OTG_AHBCLK_OFF; pr_debug("%s: grab pins\n", __func__); if (pdata->gpio_usb_active && pdata->gpio_usb_active()) return -EINVAL; if (xops->init) xops->init(xops); if (!(cpu_is_mx6())) { UOG_PORTSC1 = UOG_PORTSC1 & ~PORTSC_PHCD; if (xops->xcvr_type == PORTSC_PTS_SERIAL) { if (pdata->operating_mode == FSL_USB2_DR_HOST) { otg_set_serial_host(); /* need reset */ UOG_USBCMD |= UCMD_RESET; msleep(100); } else if (pdata->operating_mode == FSL_USB2_DR_DEVICE) otg_set_serial_peripheral(); otg_set_serial_xcvr(); } else if (xops->xcvr_type == PORTSC_PTS_ULPI) { otg_set_ulpi_xcvr(); } else if (xops->xcvr_type == PORTSC_PTS_UTMI) { otg_set_utmi_xcvr(); } } else { #ifdef CONFIG_ARCH_MX6 if (machine_is_mx6q_arm2()) USB_OTG_CTRL &= ~UCTRL_OVER_CUR_POL; else if (machine_is_mx6q_sabrelite()) USB_OTG_CTRL |= UCTRL_OVER_CUR_POL; USB_OTG_CTRL |= UCTRL_OVER_CUR_DIS; #endif } } if (usb_register_remote_wakeup(pdev)) pr_debug("DR is not a wakeup source.\n"); mxc_otg_used++; pr_debug("%s: success\n", __func__); return 0; }
int fsl_usb_host_init(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; struct fsl_xcvr_ops *xops; pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata); xops = fsl_usb_get_xcvr(pdata->transceiver); if (!xops) { printk(KERN_ERR "%s transceiver ops missing\n", pdata->name); return -EINVAL; } pdata->xcvr_ops = xops; pdata->xcvr_type = xops->xcvr_type; pdata->pdev = pdev; if (fsl_check_usbclk() != 0) return -EINVAL; pr_debug("%s: grab pins\n", __func__); if (pdata->gpio_usb_active && pdata->gpio_usb_active()) return -EINVAL; if (cpu_is_mx50()) /* Turn on AHB CLK for H1*/ USB_CLKONOFF_CTRL &= ~H1_AHBCLK_OFF; /* enable board power supply for xcvr */ if (pdata->xcvr_pwr) { if (pdata->xcvr_pwr->regu1) regulator_enable(pdata->xcvr_pwr->regu1); if (pdata->xcvr_pwr->regu2) regulator_enable(pdata->xcvr_pwr->regu2); } if (xops->init) xops->init(xops); if (usb_register_remote_wakeup(pdev)) pr_debug("%s port is not a wakeup source.\n", pdata->name); if (!(cpu_is_mx6())) { if (xops->xcvr_type == PORTSC_PTS_SERIAL) { if (cpu_is_mx35()) { usbh2_set_serial_xcvr(); /* Close the internal 60Mhz */ USBCTRL &= ~UCTRL_XCSH2; } else if (cpu_is_mx25()) usbh2_set_serial_xcvr(); else usbh1_set_serial_xcvr(); } else if (xops->xcvr_type == PORTSC_PTS_ULPI) { if (!strcmp("Host 1", pdata->name)) usbh1_set_ulpi_xcvr(); if (!strcmp("Host 2", pdata->name)) usbh2_set_ulpi_xcvr(); } else if (xops->xcvr_type == PORTSC_PTS_UTMI) { usbh1_set_utmi_xcvr(); } } else { #ifdef CONFIG_ARCH_MX6 if (!strcmp("Host 1", pdata->name)) { if (machine_is_mx6q_arm2()) USB_H1_CTRL &= ~UCTRL_OVER_CUR_POL; else if (machine_is_mx6q_sabrelite()) USB_H1_CTRL |= UCTRL_OVER_CUR_POL; USB_H1_CTRL |= UCTRL_OVER_CUR_DIS; if (machine_is_cm_fx6()) USB_H1_CTRL |= UCTRL_PWR_POL; } #endif } pr_debug("%s: %s success\n", __func__, pdata->name); return 0; }
int32_t encoder_open(struct encode *enc) { EncHandle handle = { 0 }; EncOpenParam encop = { 0 }; RetCode ret; /* Fill up parameters for encoding */ encop.bitstreamBuffer = enc->phy_bsbuf_addr; encop.bitstreamBufferSize = STREAM_BUF_SIZE; encop.bitstreamFormat = enc->codecctrl->format; encop.mapType = enc->codecctrl->mapType; encop.linear2TiledEnable = enc->linear2TiledEnable; /* width and height in command line means source image size */ if (enc->codecctrl->width && enc->codecctrl->height) { enc->src_picwidth = enc->codecctrl->width; enc->src_picheight = enc->codecctrl->height; } /* enc_width and enc_height in command line means encoder output size */ if (enc->codecctrl->enc_width && enc->codecctrl->enc_height) { enc->enc_picwidth = enc->codecctrl->enc_width; enc->enc_picheight = enc->codecctrl->enc_height; } else { enc->enc_picwidth = enc->src_picwidth; enc->enc_picheight = enc->src_picheight; } /* If rotation angle is 90 or 270, pic width and height are swapped */ if (enc->codecctrl->rot_angle == 90 || enc->codecctrl->rot_angle == 270) { encop.picWidth = enc->enc_picheight; encop.picHeight = enc->enc_picwidth; } else { encop.picWidth = enc->enc_picwidth; encop.picHeight = enc->enc_picheight; } /*Note: Frame rate cannot be less than 15fps per H.263 spec */ encop.frameRateInfo = frameRateInfo = 30; encop.bitRate = enc->codecctrl->bitrate; encop.gopSize = enc->codecctrl->gop; encop.slicemode.sliceMode = 0; /* 0: 1 slice per picture; 1: Multiple slices per picture */ encop.slicemode.sliceSizeMode = 0; /* 0: silceSize defined by bits; 1: sliceSize defined by MB number */ encop.slicemode.sliceSize = 4000; /* Size of a slice in bits or MB numbers */ encop.initialDelay = 0; encop.vbvBufferSize = 0; /* 0 = ignore 8 */ encop.intraRefresh = 0; encop.sliceReport = 0; encop.mbReport = 0; encop.mbQpReport = 0; encop.rcIntraQp = -1; encop.userQpMax = 0; encop.userQpMin = 0; encop.userQpMinEnable = 0; encop.userQpMaxEnable = 0; encop.IntraCostWeight = 0; encop.MEUseZeroPmv = 0; /* (3: 16x16, 2:32x16, 1:64x32, 0:128x64, H.263(Short Header : always 3) */ encop.MESearchRange = 3; encop.userGamma = (uint32_t) (0.75 * 32768); /* (0*32768 <= gamma <= 1*32768) */ encop.RcIntervalMode = 1; /* 0:normal, 1:frame_level, 2:slice_level, 3: user defined Mb_level */ encop.MbInterval = 0; encop.avcIntra16x16OnlyModeEnable = 0; encop.ringBufferEnable = enc->ringBufferEnable = 0; encop.dynamicAllocEnable = 0; encop.chromaInterleave = enc->codecctrl->chromaInterleave; if (enc->codecctrl->format == STD_MPEG4) { encop.EncStdParam.mp4Param.mp4_dataPartitionEnable = 0; enc->mp4_dataPartitionEnable = encop.EncStdParam.mp4Param.mp4_dataPartitionEnable; encop.EncStdParam.mp4Param.mp4_reversibleVlcEnable = 0; encop.EncStdParam.mp4Param.mp4_intraDcVlcThr = 0; encop.EncStdParam.mp4Param.mp4_hecEnable = 0; encop.EncStdParam.mp4Param.mp4_verid = 2; } else if (enc->codecctrl->format == STD_H263) { encop.EncStdParam.h263Param.h263_annexIEnable = 0; encop.EncStdParam.h263Param.h263_annexJEnable = 1; encop.EncStdParam.h263Param.h263_annexKEnable = 0; encop.EncStdParam.h263Param.h263_annexTEnable = 0; } else if (enc->codecctrl->format == STD_AVC) { encop.EncStdParam.avcParam.avc_constrainedIntraPredFlag = 0; encop.EncStdParam.avcParam.avc_disableDeblk = 1; encop.EncStdParam.avcParam.avc_deblkFilterOffsetAlpha = 6; encop.EncStdParam.avcParam.avc_deblkFilterOffsetBeta = 0; encop.EncStdParam.avcParam.avc_chromaQpOffset = 10; encop.EncStdParam.avcParam.avc_audEnable = 0; if (cpu_is_mx6()) { encop.EncStdParam.avcParam.interview_en = 0; encop.EncStdParam.avcParam.paraset_refresh_en = enc->mvc_paraset_refresh_en = 0; encop.EncStdParam.avcParam.prefix_nal_en = 0; encop.EncStdParam.avcParam.mvc_extension = enc->codecctrl->mp4_h264Class; enc->mvc_extension = enc->codecctrl->mp4_h264Class; encop.EncStdParam.avcParam.avc_frameCroppingFlag = 0; encop.EncStdParam.avcParam.avc_frameCropLeft = 0; encop.EncStdParam.avcParam.avc_frameCropRight = 0; encop.EncStdParam.avcParam.avc_frameCropTop = 0; encop.EncStdParam.avcParam.avc_frameCropBottom = 0; if (enc->codecctrl->rot_angle != 90 && enc->codecctrl->rot_angle != 270 && enc->enc_picheight == 1080) { /* * In case of AVC encoder, when we want to use * unaligned display width frameCroppingFlag * parameters should be adjusted to displayable * rectangle */ encop.EncStdParam.avcParam.avc_frameCroppingFlag = 1; encop.EncStdParam.avcParam.avc_frameCropBottom = 8; } } else { encop.EncStdParam.avcParam.avc_fmoEnable = 0; encop.EncStdParam.avcParam.avc_fmoType = 0; encop.EncStdParam.avcParam.avc_fmoSliceNum = 1; encop.EncStdParam.avcParam.avc_fmoSliceSaveBufSize = 32; /* FMO_SLICE_SAVE_BUF_SIZE */ } } ret = VPU_EncOpen(&handle, &encop); if (ret != RETCODE_SUCCESS) { err_msg("Encoder open failed %d\n", ret); return -1; } enc->handle = handle; return 0; }
int32_t encoder_allocate_framebuffer(struct encode *enc) { EncHandle handle = enc->handle; int32_t i, enc_stride, src_stride, src_fbid; int32_t totalfb, minfbcount, srcfbcount, extrafbcount; RetCode ret; FrameBuffer *fb; PhysicalAddress subSampBaseA = 0, subSampBaseB = 0; struct frame_buf **pfbpool; EncExtBufInfo extbufinfo = { 0 }; int32_t enc_fbwidth, enc_fbheight, src_fbwidth, src_fbheight; minfbcount = enc->minFrameBufferCount; srcfbcount = 1; enc_fbwidth = (enc->enc_picwidth + 15) & ~15; enc_fbheight = (enc->enc_picheight + 15) & ~15; src_fbwidth = (enc->src_picwidth + 15) & ~15; src_fbheight = (enc->src_picheight + 15) & ~15; if (cpu_is_mx6()) { if (enc->codecctrl->format == STD_AVC && enc->mvc_extension) /* MVC */ extrafbcount = 2 + 2; /* Subsamp [2] + Subsamp MVC [2] */ else if (enc->codecctrl->format == STD_MJPG) extrafbcount = 0; else extrafbcount = 2; /* Subsamp buffer [2] */ } else extrafbcount = 0; enc->totalfb = totalfb = minfbcount + extrafbcount + srcfbcount; /* last framebuffer is used as src frame in the test */ enc->src_fbid = src_fbid = totalfb - 1; fb = enc->fb = calloc(totalfb, sizeof(FrameBuffer)); if (fb == NULL) { err_msg("Failed to allocate enc->fb\n"); return -1; } pfbpool = enc->pfbpool = calloc(totalfb, sizeof(struct frame_buf *)); if (pfbpool == NULL) { err_msg("Failed to allocate enc->pfbpool\n"); free(fb); return -1; } if (enc->codecctrl->mapType == LINEAR_FRAME_MAP) { /* All buffers are linear */ for (i = 0; i < minfbcount + extrafbcount; i++) { pfbpool[i] = framebuf_alloc(enc->codecctrl->format, enc->mjpg_fmt, enc_fbwidth, enc_fbheight, 0); if (pfbpool[i] == NULL) { goto err1; } } } else { /* Encoded buffers are tiled */ for (i = 0; i < minfbcount; i++) { pfbpool[i] = tiled_framebuf_alloc(enc->codecctrl->format, enc->mjpg_fmt, enc_fbwidth, enc_fbheight, 0, enc->codecctrl->mapType); if (pfbpool[i] == NULL) goto err1; } /* sub frames are linear */ for (i = minfbcount; i < minfbcount + extrafbcount; i++) { pfbpool[i] = framebuf_alloc(enc->codecctrl->format, enc->mjpg_fmt, enc_fbwidth, enc_fbheight, 0); if (pfbpool[i] == NULL) goto err1; } } for (i = 0; i < minfbcount + extrafbcount; i++) { fb[i].myIndex = i; fb[i].bufY = pfbpool[i]->addrY; fb[i].bufCb = pfbpool[i]->addrCb; fb[i].bufCr = pfbpool[i]->addrCr; fb[i].strideY = pfbpool[i]->strideY; fb[i].strideC = pfbpool[i]->strideC; } if (cpu_is_mx6() && (enc->codecctrl->format != STD_MJPG)) { subSampBaseA = fb[minfbcount].bufY; subSampBaseB = fb[minfbcount + 1].bufY; if (enc->codecctrl->format == STD_AVC && enc->mvc_extension) { /* MVC */ extbufinfo.subSampBaseAMvc = fb[minfbcount + 2].bufY; extbufinfo.subSampBaseBMvc = fb[minfbcount + 3].bufY; } } /* Must be a multiple of 16 */ if (enc->codecctrl->rot_angle == 90 || enc->codecctrl->rot_angle == 270) enc_stride = (enc->enc_picheight + 15) & ~15; else enc_stride = (enc->enc_picwidth + 15) & ~15; src_stride = (enc->src_picwidth + 15) & ~15; extbufinfo.scratchBuf = enc->scratchBuf; ret = VPU_EncRegisterFrameBuffer(handle, fb, minfbcount, enc_stride, src_stride, subSampBaseA, subSampBaseB, &extbufinfo); if (ret != RETCODE_SUCCESS) { err_msg("Register frame buffer failed\n"); goto err1; } { /* Allocate a single frame buffer for source frame */ pfbpool[src_fbid] = framebuf_alloc(enc->codecctrl->format, enc->mjpg_fmt, src_fbwidth, src_fbheight, 0); if (pfbpool[src_fbid] == NULL) { err_msg("failed to allocate single framebuf\n"); goto err1; } fb[src_fbid].myIndex = enc->src_fbid; fb[src_fbid].bufY = pfbpool[src_fbid]->addrY; fb[src_fbid].bufCb = pfbpool[src_fbid]->addrCb; fb[src_fbid].bufCr = pfbpool[src_fbid]->addrCr; fb[src_fbid].strideY = pfbpool[src_fbid]->strideY; fb[src_fbid].strideC = pfbpool[src_fbid]->strideC; } return 0; err1: for (i = 0; i < totalfb; i++) { framebuf_free(pfbpool[i]); } free(fb); free(pfbpool); return -1; }