예제 #1
0
dma_addr_t ispmmu_kmap(u32 pa, int size)
{
	void *da;

	da = (void *)iommu_kmap(isp_iommu, 0, pa, size, IOMMU_FLAG);
	if (IS_ERR(da))
		return PTR_ERR(da);

	return (dma_addr_t)da;
}
예제 #2
0
파일: ispdss.c 프로젝트: kapoloclubs/diana
/** ispdss_begin - Function to be called by DSS when resizing of the input
  * image buffer is needed
  * @slot: buffer index where the input image is stored
  * @output_buffer_index: output buffer index where output of resizer will
  * be stored
  * @out_off: The line size in bytes for output buffer. as most probably
  * this will be VRFB with YUV422 data, it should come 0x2000 as input
  * @out_phy_add: physical address of the start of output memory area for this
  * @in_phy_add: physical address of the start of input memory area for this
  * @in_off:: The line size in bytes for output buffer.
  * ispdss_begin()  takes the input buffer index and output buffer index
  * to start the process of resizing. after resizing is complete,
  * the callback function will be called with the argument.
  * Indexes of the input and output buffers are used so that it is faster
  * and easier to configure the input and output address for the ISP resizer.
  * As per the current implementation, DSS uses six VRFB contexts for rotation.
  * for both input and output buffers index and physical address has been taken
  * as argument. if this buffer is not already mapped to ISP address space we
  * use physical address to map it, otherwise only the index is used.
  **/
int ispdss_begin(struct isp_node *pipe, u32 input_buffer_index,
		 int output_buffer_index, u32 out_off, u32 out_phy_add,
		 u32 in_phy_add, u32 in_off)
{
	unsigned int output_size;
	struct isp_device *isp = dev_get_drvdata(dev_ctx.isp);
	struct isp_res_device *isp_res = &isp->isp_res;
//LGE_CHANGE_S [[email protected]]  2011_04_22, for improve ISP to get 30fps (OMAPS00236923)
	u32 speed_val = 0;
//LGE_CHANGE_E [[email protected]]  2011_04_22, for improve ISP to get 30fps (OMAPS00236923)	

//LGE_CHANGE_S [[email protected]] 2011_07_19 Froyo_to_GB
	struct device *dev = to_device(isp_res);
//LGE_CHANGE_E [[email protected]] 2011_07_19 Froyo_to_GB

	if (output_buffer_index >= dev_ctx.num_video_buffers) {
		dev_err(dev_ctx.isp,
		"ouput buffer index is out of range %d", output_buffer_index);
		return -EINVAL;
	}

	if (dev_ctx.config_state != STATE_CONFIGURED) {
		dev_err(dev_ctx.isp, "State not configured \n");
		return -EINVAL;
	}

	dev_ctx.tmp_buf_size = PAGE_ALIGN(pipe->out.image.bytesperline *
					  pipe->out.image.height);
	ispdss_tmp_buf_alloc(dev_ctx.tmp_buf_size);

	pipe->in.path = RSZ_MEM_YUV;
	if (ispresizer_s_pipeline(isp_res, pipe) != 0)
		return -EINVAL;

	/* If this output buffer has not been mapped till now then map it */
	if (!dev_ctx.out_buf_virt_addr[output_buffer_index]) {
		output_size = pipe->out.image.height * out_off;
		dev_ctx.out_buf_virt_addr[output_buffer_index] =
			iommu_kmap(isp->iommu, 0, out_phy_add, output_size,
				   IOMMU_FLAG);
		if (IS_ERR_VALUE(
			dev_ctx.out_buf_virt_addr[output_buffer_index])) {
			dev_err(dev_ctx.isp, "Mapping of output buffer failed"
						"for index \n");
			return -ENOMEM;
		}
	}

	if (!dev_ctx.in_buf_virt_addr[input_buffer_index]) {
		dev_ctx.in_buf_virt_addr[input_buffer_index] =
			iommu_kmap(isp->iommu, 0, in_phy_add, in_off,
				   IOMMU_FLAG);
		if (IS_ERR_VALUE(
			dev_ctx.in_buf_virt_addr[input_buffer_index])) {
			dev_err(dev_ctx.isp, "Mapping of input buffer failed"
						"for index \n");
			return -ENOMEM;
		}
	}

	if (ispresizer_set_inaddr(isp_res,
				  dev_ctx.in_buf_virt_addr[input_buffer_index],
				  pipe) != 0)
		return -EINVAL;

	if (ispresizer_set_out_offset(isp_res, out_off) != 0)
		return -EINVAL;

	if (ispresizer_set_outaddr(isp_res,
		(u32)dev_ctx.out_buf_virt_addr[output_buffer_index]) != 0)
		return -EINVAL;

	/* Set ISP callback for the resizing complete even */
	if (isp_set_callback(dev_ctx.isp, CBK_RESZ_DONE, ispdss_isr,
			     (void *) NULL, (void *)NULL)) {
		dev_err(dev_ctx.isp, "No callback for RSZR\n");
		return -1;
	}

	/* All settings are done.Enable the resizer */
	init_completion(&dev_ctx.compl_isr);

//LGE_CHANGE_S [[email protected]]  2011_04_22, for improve ISP to get 30fps (OMAPS00236923)
//	isp_start(dev_ctx.isp);
	/* Only for 720p case*/
	if (use_isp_resizer_decoder){
		/*decoder */
		speed_val = 0;

	}else{
		/* encoder */
		speed_val = 8;

	}
//LGE_CHANGE_S [[email protected]] 2011_07_19 Froyo_to_GB
	
	isp_reg_and_or(dev, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
		       ~ISPSBL_SDR_REQ_RSZ_EXP_MASK,
				speed_val << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT);

	isp_start(dev_ctx.isp);
//LGE_CHANGE_E [[email protected]] 2011_07_19 Froyo_to_GB
	ispresizer_enable(isp_res, 1);

	/* Wait for resizing complete event */
	if (wait_for_completion_interruptible_timeout(
				&dev_ctx.compl_isr, msecs_to_jiffies(500)) == 0)
		dev_crit(dev_ctx.isp, "\nTimeout exit from "
			 "wait_for_completion\n");

	/* Unset the ISP callback function */
	isp_unset_callback(dev_ctx.isp, CBK_RESZ_DONE);

	return 0;
}
예제 #3
0
/*
 *  ======== bridge_brd_start ========
 *  purpose:
 *      Initializes DSP MMU and Starts DSP.
 *
 *  Preconditions:
 *  a) DSP domain is 'ACTIVE'.
 *  b) DSP_RST1 is asserted.
 *  b) DSP_RST2 is released.
 */
static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
				   u32 dsp_addr)
{
	int status = 0;
	struct bridge_dev_context *dev_context = dev_ctxt;
	struct iommu *mmu = NULL;
	struct shm_segs *sm_sg;
	int l4_i = 0, tlb_i = 0;
	u32 sg0_da = 0, sg1_da = 0;
	struct bridge_ioctl_extproc *tlb = dev_context->atlb_entry;
	u32 dw_sync_addr = 0;
	u32 ul_shm_base;	/* Gpp Phys SM base addr(byte) */
	u32 ul_shm_base_virt;	/* Dsp Virt SM base addr */
	u32 ul_tlb_base_virt;	/* Base of MMU TLB entry */
	/* Offset of shm_base_virt from tlb_base_virt */
	u32 ul_shm_offset_virt;
	struct cfg_hostres *resources = NULL;
	u32 temp;
	u32 ul_dsp_clk_rate;
	u32 ul_dsp_clk_addr;
	u32 ul_bios_gp_timer;
	u32 clk_cmd;
	struct io_mgr *hio_mgr;
	u32 ul_load_monitor_timer;
	struct omap_dsp_platform_data *pdata =
		omap_dspbridge_dev->dev.platform_data;

	/* The device context contains all the mmu setup info from when the
	 * last dsp base image was loaded. The first entry is always
	 * SHMMEM base. */
	/* Get SHM_BEG - convert to byte address */
	(void)dev_get_symbol(dev_context->hdev_obj, SHMBASENAME,
			     &ul_shm_base_virt);
	ul_shm_base_virt *= DSPWORDSIZE;
	DBC_ASSERT(ul_shm_base_virt != 0);
	/* DSP Virtual address */
	ul_tlb_base_virt = dev_context->sh_s.seg0_da;
	DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt);
	ul_shm_offset_virt =
	    ul_shm_base_virt - (ul_tlb_base_virt * DSPWORDSIZE);
	/* Kernel logical address */
	ul_shm_base = dev_context->sh_s.seg0_va + ul_shm_offset_virt;

	DBC_ASSERT(ul_shm_base != 0);
	/* 2nd wd is used as sync field */
	dw_sync_addr = ul_shm_base + SHMSYNCOFFSET;
	/* Write a signature into the shm base + offset; this will
	 * get cleared when the DSP program starts. */
	if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) {
		pr_err("%s: Illegal SM base\n", __func__);
		status = -EPERM;
	} else
		__raw_writel(0xffffffff, dw_sync_addr);

	if (!status) {
		resources = dev_context->resources;
		if (!resources)
			status = -EPERM;

		/* Assert RST1 i.e only the RST only for DSP megacell */
		if (!status) {
			(*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,
					OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD,
					OMAP2_RM_RSTCTRL);
			/* Mask address with 1K for compatibility */
			__raw_writel(dsp_addr & OMAP3_IVA2_BOOTADDR_MASK,
					OMAP343X_CTRL_REGADDR(
					OMAP343X_CONTROL_IVA2_BOOTADDR));
			/*
			 * Set bootmode to self loop if dsp_debug flag is true
			 */
			__raw_writel((dsp_debug) ? OMAP3_IVA2_BOOTMOD_IDLE : 0,
					OMAP343X_CTRL_REGADDR(
					OMAP343X_CONTROL_IVA2_BOOTMOD));
		}
	}

	if (!status) {
		(*pdata->dsp_prm_rmw_bits)(OMAP3430_RST2_IVA2_MASK, 0,
					OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
		mmu = dev_context->dsp_mmu;
		if (mmu)
			dsp_mmu_exit(mmu);
		mmu = dsp_mmu_init();
		if (IS_ERR(mmu)) {
			dev_err(bridge, "dsp_mmu_init failed!\n");
			dev_context->dsp_mmu = NULL;
			status = (int)mmu;
		}
	}
	if (!status) {
		dev_context->dsp_mmu = mmu;
		sm_sg = &dev_context->sh_s;
		sg0_da = iommu_kmap(mmu, sm_sg->seg0_da, sm_sg->seg0_pa,
			sm_sg->seg0_size, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32);
		if (IS_ERR_VALUE(sg0_da)) {
			status = (int)sg0_da;
			sg0_da = 0;
		}
	}
	if (!status) {
		sg1_da = iommu_kmap(mmu, sm_sg->seg1_da, sm_sg->seg1_pa,
			sm_sg->seg1_size, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32);
		if (IS_ERR_VALUE(sg1_da)) {
			status = (int)sg1_da;
			sg1_da = 0;
		}
	}
	if (!status) {
		u32 da;
		for (tlb_i = 0; tlb_i < BRDIOCTL_NUMOFMMUTLB; tlb_i++) {
			if (!tlb[tlb_i].ul_gpp_pa)
				continue;

			dev_dbg(bridge, "IOMMU %d GppPa: 0x%x DspVa 0x%x Size"
				" 0x%x\n", tlb_i, tlb[tlb_i].ul_gpp_pa,
				tlb[tlb_i].ul_dsp_va, tlb[tlb_i].ul_size);

			da = iommu_kmap(mmu, tlb[tlb_i].ul_dsp_va,
				tlb[tlb_i].ul_gpp_pa, PAGE_SIZE,
				IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32);
			if (IS_ERR_VALUE(da)) {
				status = (int)da;
				break;
			}
		}
	}
	if (!status) {
		u32 da;
		l4_i = 0;
		while (l4_peripheral_table[l4_i].phys_addr) {
			da = iommu_kmap(mmu, l4_peripheral_table[l4_i].
				dsp_virt_addr, l4_peripheral_table[l4_i].
				phys_addr, PAGE_SIZE,
				IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_32);
			if (IS_ERR_VALUE(da)) {
				status = (int)da;
				break;
			}
			l4_i++;
		}
	}

	/* Lock the above TLB entries and get the BIOS and load monitor timer
	 * information */
	if (!status) {
		/* Enable the BIOS clock */
		(void)dev_get_symbol(dev_context->hdev_obj,
				     BRIDGEINIT_BIOSGPTIMER, &ul_bios_gp_timer);
		(void)dev_get_symbol(dev_context->hdev_obj,
				     BRIDGEINIT_LOADMON_GPTIMER,
				     &ul_load_monitor_timer);

		if (ul_load_monitor_timer != 0xFFFF) {
			clk_cmd = (BPWR_ENABLE_CLOCK << MBX_PM_CLK_CMDSHIFT) |
			    ul_load_monitor_timer;
			dsp_peripheral_clk_ctrl(dev_context, &clk_cmd);
		} else {
			dev_dbg(bridge, "Not able to get the symbol for Load "
				"Monitor Timer\n");
		}

		if (ul_bios_gp_timer != 0xFFFF) {
			clk_cmd = (BPWR_ENABLE_CLOCK << MBX_PM_CLK_CMDSHIFT) |
			    ul_bios_gp_timer;
			dsp_peripheral_clk_ctrl(dev_context, &clk_cmd);
		} else {
			dev_dbg(bridge,
				"Not able to get the symbol for BIOS Timer\n");
		}

		/* Set the DSP clock rate */
		(void)dev_get_symbol(dev_context->hdev_obj,
				     "_BRIDGEINIT_DSP_FREQ", &ul_dsp_clk_addr);
		/*Set Autoidle Mode for IVA2 PLL */
		(*pdata->dsp_cm_write)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
				OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL);

		if ((unsigned int *)ul_dsp_clk_addr != NULL) {
			/* Get the clock rate */
			ul_dsp_clk_rate = dsp_clk_get_iva2_rate();
			dev_dbg(bridge, "%s: DSP clock rate (KHZ): 0x%x \n",
				__func__, ul_dsp_clk_rate);
			(void)bridge_brd_write(dev_context,
					       (u8 *) &ul_dsp_clk_rate,
					       ul_dsp_clk_addr, sizeof(u32), 0);
		}
		/*
		 * Enable Mailbox events and also drain any pending
		 * stale messages.
		 */
		dev_context->mbox = omap_mbox_get("dsp");
		if (IS_ERR(dev_context->mbox)) {
			dev_context->mbox = NULL;
			pr_err("%s: Failed to get dsp mailbox handle\n",
								__func__);
			status = -EPERM;
		}

	}
	if (!status) {
		dev_context->mbox->rxq->callback = (int (*)(void *))io_mbox_msg;

/*PM_IVA2GRPSEL_PER = 0xC0;*/
		temp = readl(resources->dw_per_pm_base + 0xA8);
		temp = (temp & 0xFFFFFF30) | 0xC0;
		writel(temp, resources->dw_per_pm_base + 0xA8);

/*PM_MPUGRPSEL_PER &= 0xFFFFFF3F; */
		temp = readl(resources->dw_per_pm_base + 0xA4);
		temp = (temp & 0xFFFFFF3F);
		writel(temp, resources->dw_per_pm_base + 0xA4);
/*CM_SLEEPDEP_PER |= 0x04; */
		temp = readl(resources->dw_per_base + 0x44);
		temp = (temp & 0xFFFFFFFB) | 0x04;
		writel(temp, resources->dw_per_base + 0x44);

/*CM_CLKSTCTRL_IVA2 = 0x00000003 -To Allow automatic transitions */
		(*pdata->dsp_cm_write)(OMAP34XX_CLKSTCTRL_ENABLE_AUTO,
					OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);

		/* Let DSP go */
		dev_dbg(bridge, "%s Unreset\n", __func__);
		/* release the RST1, DSP starts executing now .. */
		(*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0,
					OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);

		dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr);
		dev_dbg(bridge, "DSP c_int00 Address =  0x%x\n", dsp_addr);
		if (dsp_debug)
			while (__raw_readw(dw_sync_addr))
				;;

		/* Wait for DSP to clear word in shared memory */
		/* Read the Location */
		if (!wait_for_start(dev_context, dw_sync_addr))
			status = -ETIMEDOUT;

		/* Start wdt */
		dsp_wdt_sm_set((void *)ul_shm_base);
		dsp_wdt_enable(true);

		status = dev_get_io_mgr(dev_context->hdev_obj, &hio_mgr);
		if (hio_mgr) {
			io_sh_msetting(hio_mgr, SHM_OPPINFO, NULL);
			/* Write the synchronization bit to indicate the
			 * completion of OPP table update to DSP
			 */
			__raw_writel(0XCAFECAFE, dw_sync_addr);

			/* update board state */
			dev_context->dw_brd_state = BRD_RUNNING;
			return 0;
		} else {
			dev_context->dw_brd_state = BRD_UNKNOWN;
		}
	}

	while (tlb_i--) {
		if (!tlb[tlb_i].ul_gpp_pa)
			continue;
		iommu_kunmap(mmu, tlb[tlb_i].ul_gpp_va);
	}
	while (l4_i--)
		iommu_kunmap(mmu, l4_peripheral_table[l4_i].dsp_virt_addr);
	if (sg0_da)
		iommu_kunmap(mmu, sg0_da);
	if (sg1_da)
		iommu_kunmap(mmu, sg1_da);
	return status;
}