⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c-mfc.c

📁 s3c6400 video code,you play video smooth with it,it is hardware codec
💻 C
📖 第 1 页 / 共 2 页
字号:
				MFC_Mutex_Release();
				return -EFAULT;
			}

			// FRAM_BUF address is calculated differently for Encoder and Decoder.
			switch (pMfcInst->codec_mode) {
			case MP4_DEC:
			case AVC_DEC:
			case VC1_DEC:
			case H263_DEC:
				// Decoder case
				args.get_buf_addr.out_buf_size	= (pMfcInst->width * pMfcInst->height * 3) >> 1;
				tmp	= (unsigned int)args.get_buf_addr.in_usr_data + ( ((unsigned int) pMfcInst->pFramBuf)	\
					+ (pMfcInst->idx) * (args.get_buf_addr.out_buf_size) - (unsigned int)GetDataBufVirAddr() );
#if (MFC_ROTATE_ENABLE == 1)
				if ( (pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->PostRotMode & 0x0010) ) {
					tmp	= (unsigned int)args.get_buf_addr.in_usr_data + ( ((unsigned int) pMfcInst->pFramBuf)	\
					+ (pMfcInst->frambufCnt) * (args.get_buf_addr.out_buf_size) - (unsigned int)GetDataBufVirAddr() );	
				}
#endif
				args.get_buf_addr.out_buf_addr = tmp;
				break;

			case MP4_ENC:
			case AVC_ENC:
			case H263_ENC:
				// Encoder case
				tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1;
				args.get_buf_addr.out_buf_addr = args.get_buf_addr.in_usr_data + (pMfcInst->idx * tmp) + (int)(pMfcInst->pFramBuf - GetDataBufVirAddr());
				break;
			}

			args.get_buf_addr.ret_code	= MFCINST_RET_OK;
			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));

			MFC_Mutex_Release();
			break;
			
		case IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR:
			MFC_Mutex_Lock();

			Copy_From_User(&args.get_buf_addr, (MFC_GET_BUF_ADDR_ARG *)arg, sizeof(MFC_GET_BUF_ADDR_ARG));

			args.get_buf_addr.out_buf_size	= (pMfcInst->width * pMfcInst->height * 3) >> 1;
			tmp	= (unsigned int)S3C6400_BASEADDR_MFC_DATA_BUF + ( ((unsigned int) pMfcInst->pFramBuf)	\
				+ (pMfcInst->idx) * (args.get_buf_addr.out_buf_size) - (unsigned int)GetDataBufVirAddr() );
			args.get_buf_addr.out_buf_addr = tmp;
			args.get_buf_addr.ret_code = MFCINST_RET_OK;

			Copy_To_User((MFC_GET_BUF_ADDR_ARG *)arg, &args.get_buf_addr, sizeof(MFC_GET_BUF_ADDR_ARG));

			MFC_Mutex_Release();
			break;

		case IOCTL_MFC_GET_CONFIG:
			MFC_Mutex_Lock();

			Copy_From_User(&args, (MFC_ARGS *)arg, sizeof(MFC_ARGS));

			ret = MFC_GetConfigParams(pMfcInst, &args);

			Copy_To_User((MFC_ARGS *)arg, &args, sizeof(MFC_ARGS));

			MFC_Mutex_Release();
			break;

		case IOCTL_MFC_SET_CONFIG:
			MFC_Mutex_Lock();

			Copy_From_User(&args, (MFC_ARGS *)arg, sizeof(MFC_ARGS));

			ret = MFC_SetConfigParams(pMfcInst, &args);

			Copy_To_User((MFC_ARGS *)arg, &args, sizeof(MFC_ARGS));
			
			MFC_Mutex_Release();
			break;

		case IOCTL_MFC_SET_H263_MULTIPLE_SLICE:
			MFC_Mutex_Lock();

			pMfcInst->multiple_slice = 1;

			MFC_Mutex_Release();
			break;
	
		default:
			MFC_Mutex_Lock();
			LOG_MSG(LOG_TRACE, "s3c_mfc_ioctl", "Requested ioctl command is not defined. (ioctl cmd=0x%X)\n", cmd);
			MFC_Mutex_Release();
			return -EINVAL;
	}

	switch(ret) {
	case MFCINST_RET_OK:
		return TRUE;
	default:
		return -1;
	}
	return -1;
}

int s3c_mfc_mmap(struct file *filp, struct vm_area_struct *vma)
{
	unsigned long size	= vma->vm_end - vma->vm_start;
	unsigned long maxSize;
	unsigned long pageFrameNo;

	pageFrameNo = __phys_to_pfn(S3C6400_BASEADDR_MFC_DATA_BUF);

	maxSize = MFC_DATA_BUF_SIZE + PAGE_SIZE - (MFC_DATA_BUF_SIZE % PAGE_SIZE);

	if(size > maxSize) {
		return -EINVAL;
	}

	vma->vm_flags |= VM_RESERVED | VM_IO;

	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

	if( remap_pfn_range(vma, vma->vm_start, pageFrameNo, size,	\
				vma->vm_page_prot) ) {
		LOG_MSG(LOG_TRACE, "mfc_mmap", "remap error");
		return -EAGAIN;
	}

	return 0;
}


static struct file_operations s3c_mfc_fops = {
			owner:		THIS_MODULE,
			open:		s3c_mfc_open,
			release:	s3c_mfc_release,
			ioctl:		s3c_mfc_ioctl,
			read:		s3c_mfc_read,
			write:		s3c_mfc_write,
			mmap:		s3c_mfc_mmap,
};


static struct miscdevice s3c_mfc_miscdev = {
			minor:		252, 		
			name:		"s3c-mfc",
			fops:		&s3c_mfc_fops
};


static int s3c_mfc_probe(struct platform_device *pdev)
{
	struct resource *res;
	int 			size;
	int				ret;
	unsigned int	mfc_clk;
	
	// mfc clock enable 
	mfc_hclk	= clk_get(NULL, "hclk_mfc");
	if (!mfc_hclk) {
		printk(KERN_ERR "failed to get mfc hclk source\n");
		return -ENOENT;
	}
	clk_enable(mfc_hclk);

	mfc_sclk	= clk_get(NULL, "sclk_mfc");
	if (!mfc_sclk) {
		printk(KERN_ERR "failed to get mfc sclk source\n");
		return -ENOENT;
	}
	clk_enable(mfc_sclk);

	mfc_pclk	= clk_get(NULL, "pclk_mfc");
	if (!mfc_pclk) {
		printk(KERN_ERR "failed to get mfc pclk source\n");
		return -ENOENT;
	}
	clk_enable(mfc_pclk);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		printk(KERN_INFO "failed to get memory region resouce\n");
		return -ENOENT;
	}

	size = (res->end-res->start)+1;
	mfc_mem = request_mem_region(res->start, size, pdev->name);
	if (mfc_mem == NULL) {
		printk(KERN_INFO "failed to get memory region\n");
		return -ENOENT;
	}

	mfc_base = ioremap(res->start, size);
	if (mfc_base == 0) {
		printk(KERN_INFO "failed to ioremap() region\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		printk(KERN_INFO "failed to get irq resource\n");
		return -ENOENT;
	}

	
	ret = request_irq(res->start, s3c_mfc_irq, 0, pdev->name, pdev);
	if (ret != 0) {
		printk(KERN_INFO "failed to install irq (%d)\n", ret);
		return ret;
	}
	
	if (MFC_Mutex_Create() == FALSE)
		return -ENOMEM;


	// mfc clock set 133 Mhz
	mfc_clk = readl(S3C_CLK_DIV0);
	mfc_clk |= (1<<28);
	__raw_writel(mfc_clk, S3C_CLK_DIV0);

	//////////////////////////////////
	//	2. MFC Memory Setup			//
	//////////////////////////////////
	if (MFC_MemorySetup() == FALSE)
		return -ENOMEM;
	
	//////////////////////////////////////
	//	3. MFC Hardware Initialization	//
	//////////////////////////////////////
	if (MFC_HW_Init() == FALSE)
		return -ENODEV;

	ret = misc_register(&s3c_mfc_miscdev);

	clk_disable(mfc_hclk);
	clk_disable(mfc_sclk);
	clk_disable(mfc_pclk);

	return 0;
}

static int s3c_mfc_remove(struct platform_device *dev)
{
	if (mfc_mem != NULL) {
		release_resource(mfc_mem);
		kfree(mfc_mem);
		mfc_mem = NULL;
	}

	free_irq(IRQ_MFC, dev);
	
	misc_deregister(&s3c_mfc_miscdev);
	return 0;
}

static int s3c_mfc_suspend(struct platform_device *dev, pm_message_t state)
{

#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,21)

	MFCInstCtx *mfcinst_ctx;
	int         inst_no;
	int			is_mfc_on = 0;
	int			i, index = 0;
	unsigned int	dwMfcBase;


	MFC_Mutex_Lock();

	
	is_mfc_on = 0;

	// 1. Power Off state
	// Invalidate all the MFC Instances
	for (inst_no = 0; inst_no < MFC_NUM_INSTANCES_MAX; inst_no++) {
		mfcinst_ctx = MFCInst_GetCtx(inst_no);
		if (mfcinst_ctx) {
			is_mfc_on = 1;

			// On Power Down, the MFC instance is invalidated.
			// Then the MFC operations (DEC_EXE, ENC_EXE, etc.) will not be performed
			// until it is validated by entering Power up state transition
			MFCInst_PowerOffState(mfcinst_ctx);
			printk(KERN_INFO "MFC_Suspend %d-th instance is invalidated\n", inst_no);
		}
	}

	// 2. Command MFC sleep and save MFC SFR
	if (is_mfc_on) {
		dwMfcBase = (unsigned int)GetMfcSfrVirAddr();

		for(i=SAVE_START_ADDR; i <= SAVE_END_ADDR; i+=4)
		{
			mfc_save[index] = (unsigned int)MFC_READ_REG(dwMfcBase + i);
			index++;	
		}

		MFC_Sleep();
	}


	// 3. Disable MFC clock
	clk_disable(mfc_hclk);
	clk_disable(mfc_sclk);
	clk_disable(mfc_pclk);
	
/*
	// 4. MFC Power Off(Domain V)
	mfc_pwr = readl(S3C_NORMAL_CFG);
	mfc_pwr &= ~(1<<9);
	printk("mfc_pwr : 0x%X\n", mfc_pwr);
	__raw_writel(mfc_pwr, S3C_NORMAL_CFG);
*/

	MFC_Mutex_Release();

#endif

	return 0;
}

static int s3c_mfc_resume(struct platform_device *pdev)
{

#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,21)

	unsigned int	mfc_pwr, dwMfcBase;
	int 			i, index = 0;
	MFCInstCtx 		*mfcinst_ctx;
	int         	inst_no;
	unsigned int	domain_v_ready;
	int				is_mfc_on = 0;
	
	
	MFC_Mutex_Lock();
	
	clk_enable(mfc_hclk);
	clk_enable(mfc_sclk);
	clk_enable(mfc_pclk);


	// 1. MFC Power On(Domain V)
	mfc_pwr = readl(S3C_NORMAL_CFG);
	mfc_pwr |= (1<<9);
	__raw_writel(mfc_pwr, S3C_NORMAL_CFG);


	// 2. Check MFC power on
	do {
		domain_v_ready = readl(S3C_BLK_PWR_STAT);
		printk("domain v ready : 0x%X\n", domain_v_ready);
		msleep(1);
	}while(!(domain_v_ready & (1<<1)));


	// 3. Firmware download
	MfcFirmwareIntoCodeDownReg();


	// 4. Power On state
	// Validate all the MFC Instances
	for (inst_no = 0; inst_no < MFC_NUM_INSTANCES_MAX; inst_no++) {
		mfcinst_ctx = MFCInst_GetCtx(inst_no);
		if (mfcinst_ctx) {
			is_mfc_on = 1;

			// When MFC Power On, the MFC instance is validated.
			// Then the MFC operations (DEC_EXE, ENC_EXE, etc.) will be performed again
			MFCInst_PowerOnState(mfcinst_ctx);
			printk(KERN_INFO "MFC_Resume %d-th instance is validated\n", inst_no);
		}
	}


	if (is_mfc_on) {
		// 5. Restore MFC SFR
		dwMfcBase = (unsigned int)GetMfcSfrVirAddr();
		for( i=SAVE_START_ADDR; i<= SAVE_END_ADDR; i+=4 )
		{
			MFC_WRITE_REG( ( dwMfcBase + i ), mfc_save[index] );
			index++;
		}

		// 6. Command MFC wakeup
		MFC_Wakeup();
	}

	MFC_Mutex_Release();

#endif

	return 0;
}

static struct platform_driver s3c_mfc_driver = {
	.probe		= s3c_mfc_probe,
	.remove		= s3c_mfc_remove,
	.shutdown	= NULL,
	.suspend	= s3c_mfc_suspend,
	.resume		= s3c_mfc_resume,
	.driver		= {
	.owner		= THIS_MODULE,
	.name		= "s3c-mfc",
	},
};


static char banner[] __initdata = KERN_INFO "S3C6400 MFC Driver, (c) 2007 Samsung Electronics\n";

static int __init s3c_mfc_init(void)
{

	printk(banner);

#ifdef CONFIG_S3C6400_PDFW
	pd_register_dev(&mfc_pmdev, "domain_v");
	printk(KERN_INFO "pdfw: mfc devid = %d\n", mfc_pmdev.devid);
#endif

	if(platform_driver_register(&s3c_mfc_driver)!=0)
  	{
   		printk("platform device register Failed \n");
   		return -1;
  	}

	printk("S3C6400 MFC driver module init OK.\n");
	return 0;
}

static void __exit s3c_mfc_exit(void)
{
	MFC_Mutex_Delete();

#ifdef CONFIG_S3C6400_PDFW
	pd_unregister_dev(&mfc_pmdev);
#endif

	platform_driver_unregister(&s3c_mfc_driver);
	printk("S3C6400 MFC driver module exit\n");	
}


module_init(s3c_mfc_init);
module_exit(s3c_mfc_exit);

MODULE_AUTHOR("Jiun, Yu");
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -