2011-06-21 10:51:26 -03:00
/*
2012-08-14 17:31:16 -03:00
* linux / drivers / media / platform / s5p - mfc / s5p_mfc_ctrl . c
2011-06-21 10:51:26 -03:00
*
* Copyright ( c ) 2010 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com/
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <linux/delay.h>
# include <linux/err.h>
# include <linux/firmware.h>
# include <linux/jiffies.h>
# include <linux/sched.h>
2012-10-03 22:19:08 -03:00
# include "s5p_mfc_cmd.h"
2011-06-21 10:51:26 -03:00
# include "s5p_mfc_common.h"
# include "s5p_mfc_debug.h"
# include "s5p_mfc_intr.h"
2012-10-03 22:19:08 -03:00
# include "s5p_mfc_opr.h"
2011-06-21 10:51:26 -03:00
# include "s5p_mfc_pm.h"
2014-08-26 10:58:23 -03:00
# include "s5p_mfc_ctrl.h"
2011-06-21 10:51:26 -03:00
2013-01-03 11:02:07 -03:00
/* Allocate memory for firmware */
int s5p_mfc_alloc_firmware ( struct s5p_mfc_dev * dev )
{
void * bank2_virt ;
dma_addr_t bank2_dma_addr ;
2017-02-08 08:23:31 -02:00
unsigned int align_size = 1 < < MFC_BASE_ALIGN_ORDER ;
2013-01-03 11:02:07 -03:00
dev - > fw_size = dev - > variant - > buf_size - > fw ;
if ( dev - > fw_virt_addr ) {
mfc_err ( " Attempting to allocate firmware when it seems that it is already loaded \n " ) ;
return - ENOMEM ;
}
2017-02-08 08:23:31 -02:00
dev - > fw_virt_addr = dma_alloc_coherent ( dev - > mem_dev [ BANK1_CTX ] ,
2017-02-08 06:53:48 -02:00
dev - > fw_size , & dev - > dma_base [ BANK1_CTX ] ,
GFP_KERNEL ) ;
2014-06-27 06:28:31 -03:00
if ( ! dev - > fw_virt_addr ) {
2013-01-03 11:02:07 -03:00
mfc_err ( " Allocating bitprocessor buffer failed \n " ) ;
return - ENOMEM ;
}
if ( HAS_PORTNUM ( dev ) & & IS_TWOPORT ( dev ) ) {
2017-02-08 08:23:31 -02:00
bank2_virt = dma_alloc_coherent ( dev - > mem_dev [ BANK2_CTX ] ,
align_size , & bank2_dma_addr , GFP_KERNEL ) ;
2013-01-03 11:02:07 -03:00
2014-06-27 06:28:31 -03:00
if ( ! bank2_virt ) {
2013-01-03 11:02:07 -03:00
mfc_err ( " Allocating bank2 base failed \n " ) ;
2017-02-08 08:23:31 -02:00
dma_free_coherent ( dev - > mem_dev [ BANK1_CTX ] , dev - > fw_size ,
2017-02-08 06:53:48 -02:00
dev - > fw_virt_addr ,
dev - > dma_base [ BANK1_CTX ] ) ;
2013-01-03 11:02:07 -03:00
dev - > fw_virt_addr = NULL ;
return - ENOMEM ;
}
/* Valid buffers passed to MFC encoder with LAST_FRAME command
* should not have address of bank2 - MFC will treat it as a null frame .
* To avoid such situation we set bank2 address below the pool address .
*/
2017-02-08 06:53:48 -02:00
dev - > dma_base [ BANK2_CTX ] = bank2_dma_addr - align_size ;
2013-01-03 11:02:07 -03:00
2017-02-08 08:23:31 -02:00
dma_free_coherent ( dev - > mem_dev [ BANK2_CTX ] , align_size ,
bank2_virt , bank2_dma_addr ) ;
2013-01-03 11:02:07 -03:00
} else {
/* In this case bank2 can point to the same address as bank1.
2013-10-20 21:34:01 -03:00
* Firmware will always occupy the beginning of this area so it is
2013-01-03 11:02:07 -03:00
* impossible having a video frame buffer with zero address . */
2017-02-08 06:53:48 -02:00
dev - > dma_base [ BANK2_CTX ] = dev - > dma_base [ BANK1_CTX ] ;
2013-01-03 11:02:07 -03:00
}
return 0 ;
}
2011-06-21 10:51:26 -03:00
2013-01-03 11:02:07 -03:00
/* Load firmware */
int s5p_mfc_load_firmware ( struct s5p_mfc_dev * dev )
2011-06-21 10:51:26 -03:00
{
struct firmware * fw_blob ;
2014-05-21 06:29:30 -03:00
int i , err = - EINVAL ;
2011-06-21 10:51:26 -03:00
/* Firmare has to be present as a separate file or compiled
* into kernel . */
mfc_debug_enter ( ) ;
2012-10-03 22:19:11 -03:00
2014-05-21 06:29:30 -03:00
for ( i = MFC_FW_MAX_VERSIONS - 1 ; i > = 0 ; i - - ) {
if ( ! dev - > variant - > fw_name [ i ] )
continue ;
err = request_firmware ( ( const struct firmware * * ) & fw_blob ,
dev - > variant - > fw_name [ i ] , dev - > v4l2_dev . dev ) ;
if ( ! err ) {
dev - > fw_ver = ( enum s5p_mfc_fw_ver ) i ;
break ;
}
}
2011-06-21 10:51:26 -03:00
if ( err ! = 0 ) {
mfc_err ( " Firmware is not present in the /lib/firmware directory nor compiled in kernel \n " ) ;
return - EINVAL ;
}
if ( fw_blob - > size > dev - > fw_size ) {
mfc_err ( " MFC firmware is too big to be loaded \n " ) ;
release_firmware ( fw_blob ) ;
return - ENOMEM ;
}
2013-01-11 11:29:32 -03:00
if ( ! dev - > fw_virt_addr ) {
2013-01-03 11:02:07 -03:00
mfc_err ( " MFC firmware is not allocated \n " ) ;
2011-06-21 10:51:26 -03:00
release_firmware ( fw_blob ) ;
return - EINVAL ;
}
2013-01-03 11:02:07 -03:00
memcpy ( dev - > fw_virt_addr , fw_blob - > data , fw_blob - > size ) ;
2011-06-21 10:51:26 -03:00
wmb ( ) ;
release_firmware ( fw_blob ) ;
mfc_debug_leave ( ) ;
return 0 ;
}
/* Release firmware memory */
int s5p_mfc_release_firmware ( struct s5p_mfc_dev * dev )
{
/* Before calling this function one has to make sure
* that MFC is no longer processing */
2013-01-03 11:02:07 -03:00
if ( ! dev - > fw_virt_addr )
2011-06-21 10:51:26 -03:00
return - EINVAL ;
2017-02-08 08:23:31 -02:00
dma_free_coherent ( dev - > mem_dev [ BANK1_CTX ] , dev - > fw_size ,
2017-02-08 06:53:48 -02:00
dev - > fw_virt_addr , dev - > dma_base [ BANK1_CTX ] ) ;
2013-01-03 11:02:07 -03:00
dev - > fw_virt_addr = NULL ;
2011-06-21 10:51:26 -03:00
return 0 ;
}
2014-10-28 15:48:50 -02:00
static int s5p_mfc_bus_reset ( struct s5p_mfc_dev * dev )
2014-10-21 08:07:00 -03:00
{
unsigned int status ;
unsigned long timeout ;
/* Reset */
mfc_write ( dev , 0x1 , S5P_FIMV_MFC_BUS_RESET_CTRL ) ;
timeout = jiffies + msecs_to_jiffies ( MFC_BW_TIMEOUT ) ;
/* Check bus status */
do {
if ( time_after ( jiffies , timeout ) ) {
mfc_err ( " Timeout while resetting MFC. \n " ) ;
return - EIO ;
}
status = mfc_read ( dev , S5P_FIMV_MFC_BUS_RESET_CTRL ) ;
} while ( ( status & 0x2 ) = = 0 ) ;
return 0 ;
}
2011-06-21 10:51:26 -03:00
/* Reset the device */
int s5p_mfc_reset ( struct s5p_mfc_dev * dev )
{
unsigned int mc_status ;
unsigned long timeout ;
2012-10-03 22:19:11 -03:00
int i ;
2011-06-21 10:51:26 -03:00
mfc_debug_enter ( ) ;
2013-07-09 01:24:36 -03:00
if ( IS_MFCV6_PLUS ( dev ) ) {
2012-10-03 22:19:11 -03:00
/* Zero Initialization of MFC registers */
mfc_write ( dev , 0 , S5P_FIMV_RISC2HOST_CMD_V6 ) ;
mfc_write ( dev , 0 , S5P_FIMV_HOST2RISC_CMD_V6 ) ;
mfc_write ( dev , 0 , S5P_FIMV_FW_VERSION_V6 ) ;
for ( i = 0 ; i < S5P_FIMV_REG_CLEAR_COUNT_V6 ; i + + )
mfc_write ( dev , 0 , S5P_FIMV_REG_CLEAR_BEGIN_V6 + ( i * 4 ) ) ;
2014-10-21 08:07:00 -03:00
/* check bus reset control before reset */
if ( dev - > risc_on )
if ( s5p_mfc_bus_reset ( dev ) )
return - EIO ;
2014-10-21 08:06:59 -03:00
/* Reset
* set RISC_ON to 0 during power_on & wake_up .
* V6 needs RISC_ON set to 0 during reset also .
*/
2014-10-21 08:07:00 -03:00
if ( ( ! dev - > risc_on ) | | ( ! IS_MFCV7_PLUS ( dev ) ) )
2014-10-21 08:06:59 -03:00
mfc_write ( dev , 0 , S5P_FIMV_RISC_ON_V6 ) ;
2012-10-03 22:19:11 -03:00
mfc_write ( dev , 0x1FFF , S5P_FIMV_MFC_RESET_V6 ) ;
mfc_write ( dev , 0 , S5P_FIMV_MFC_RESET_V6 ) ;
} else {
/* Stop procedure */
/* reset RISC */
mfc_write ( dev , 0x3f6 , S5P_FIMV_SW_RESET ) ;
/* All reset except for MC */
mfc_write ( dev , 0x3e2 , S5P_FIMV_SW_RESET ) ;
mdelay ( 10 ) ;
2011-06-21 10:51:26 -03:00
2012-10-03 22:19:11 -03:00
timeout = jiffies + msecs_to_jiffies ( MFC_BW_TIMEOUT ) ;
/* Check MC status */
do {
if ( time_after ( jiffies , timeout ) ) {
mfc_err ( " Timeout while resetting MFC \n " ) ;
return - EIO ;
}
mc_status = mfc_read ( dev , S5P_FIMV_MC_STATUS ) ;
} while ( mc_status & 0x3 ) ;
mfc_write ( dev , 0x0 , S5P_FIMV_SW_RESET ) ;
mfc_write ( dev , 0x3fe , S5P_FIMV_SW_RESET ) ;
}
2011-06-21 10:51:26 -03:00
mfc_debug_leave ( ) ;
return 0 ;
}
static inline void s5p_mfc_init_memctrl ( struct s5p_mfc_dev * dev )
{
2013-07-09 01:24:36 -03:00
if ( IS_MFCV6_PLUS ( dev ) ) {
2017-02-08 06:53:48 -02:00
mfc_write ( dev , dev - > dma_base [ BANK1_CTX ] ,
S5P_FIMV_RISC_BASE_ADDRESS_V6 ) ;
mfc_debug ( 2 , " Base Address : %pad \n " ,
& dev - > dma_base [ BANK1_CTX ] ) ;
2012-10-03 22:19:11 -03:00
} else {
2017-02-08 06:53:48 -02:00
mfc_write ( dev , dev - > dma_base [ BANK1_CTX ] ,
S5P_FIMV_MC_DRAMBASE_ADR_A ) ;
mfc_write ( dev , dev - > dma_base [ BANK2_CTX ] ,
S5P_FIMV_MC_DRAMBASE_ADR_B ) ;
2014-09-24 19:07:36 -03:00
mfc_debug ( 2 , " Bank1: %pad, Bank2: %pad \n " ,
2017-02-08 06:53:48 -02:00
& dev - > dma_base [ BANK1_CTX ] , & dev - > dma_base [ BANK2_CTX ] ) ;
2012-10-03 22:19:11 -03:00
}
2011-06-21 10:51:26 -03:00
}
static inline void s5p_mfc_clear_cmds ( struct s5p_mfc_dev * dev )
{
2013-07-09 01:24:36 -03:00
if ( IS_MFCV6_PLUS ( dev ) ) {
2012-10-03 22:19:11 -03:00
/* Zero initialization should be done before RESET.
* Nothing to do here . */
} else {
mfc_write ( dev , 0xffffffff , S5P_FIMV_SI_CH0_INST_ID ) ;
mfc_write ( dev , 0xffffffff , S5P_FIMV_SI_CH1_INST_ID ) ;
mfc_write ( dev , 0 , S5P_FIMV_RISC2HOST_CMD ) ;
mfc_write ( dev , 0 , S5P_FIMV_HOST2RISC_CMD ) ;
}
2011-06-21 10:51:26 -03:00
}
/* Initialize hardware */
int s5p_mfc_init_hw ( struct s5p_mfc_dev * dev )
{
unsigned int ver ;
int ret ;
mfc_debug_enter ( ) ;
2013-01-03 11:02:07 -03:00
if ( ! dev - > fw_virt_addr ) {
mfc_err ( " Firmware memory is not allocated. \n " ) ;
2011-06-21 10:51:26 -03:00
return - EINVAL ;
2013-01-03 11:02:07 -03:00
}
2011-06-21 10:51:26 -03:00
/* 0. MFC reset */
mfc_debug ( 2 , " MFC reset.. \n " ) ;
s5p_mfc_clock_on ( ) ;
2014-10-21 08:06:59 -03:00
dev - > risc_on = 0 ;
2011-06-21 10:51:26 -03:00
ret = s5p_mfc_reset ( dev ) ;
if ( ret ) {
mfc_err ( " Failed to reset MFC - timeout \n " ) ;
return ret ;
}
mfc_debug ( 2 , " Done MFC reset.. \n " ) ;
/* 1. Set DRAM base Addr */
s5p_mfc_init_memctrl ( dev ) ;
/* 2. Initialize registers of channel I/F */
s5p_mfc_clear_cmds ( dev ) ;
/* 3. Release reset signal to the RISC */
s5p_mfc_clean_dev_int_flags ( dev ) ;
2014-10-21 08:06:59 -03:00
if ( IS_MFCV6_PLUS ( dev ) ) {
dev - > risc_on = 1 ;
2012-10-03 22:19:11 -03:00
mfc_write ( dev , 0x1 , S5P_FIMV_RISC_ON_V6 ) ;
2014-10-21 08:06:59 -03:00
}
2012-10-03 22:19:11 -03:00
else
mfc_write ( dev , 0x3ff , S5P_FIMV_SW_RESET ) ;
2011-06-21 10:51:26 -03:00
mfc_debug ( 2 , " Will now wait for completion of firmware transfer \n " ) ;
2012-10-03 22:19:08 -03:00
if ( s5p_mfc_wait_for_done_dev ( dev , S5P_MFC_R2H_CMD_FW_STATUS_RET ) ) {
2011-06-21 10:51:26 -03:00
mfc_err ( " Failed to load firmware \n " ) ;
s5p_mfc_reset ( dev ) ;
s5p_mfc_clock_off ( ) ;
return - EIO ;
}
s5p_mfc_clean_dev_int_flags ( dev ) ;
/* 4. Initialize firmware */
2012-10-03 22:19:08 -03:00
ret = s5p_mfc_hw_call ( dev - > mfc_cmds , sys_init_cmd , dev ) ;
2011-06-21 10:51:26 -03:00
if ( ret ) {
mfc_err ( " Failed to send command to MFC - timeout \n " ) ;
s5p_mfc_reset ( dev ) ;
s5p_mfc_clock_off ( ) ;
return ret ;
}
2014-08-13 23:11:47 -03:00
mfc_debug ( 2 , " Ok, now will wait for completion of hardware init \n " ) ;
2012-10-03 22:19:08 -03:00
if ( s5p_mfc_wait_for_done_dev ( dev , S5P_MFC_R2H_CMD_SYS_INIT_RET ) ) {
2014-08-13 23:11:47 -03:00
mfc_err ( " Failed to init hardware \n " ) ;
2011-06-21 10:51:26 -03:00
s5p_mfc_reset ( dev ) ;
s5p_mfc_clock_off ( ) ;
return - EIO ;
}
dev - > int_cond = 0 ;
if ( dev - > int_err ! = 0 | | dev - > int_type ! =
2012-10-03 22:19:08 -03:00
S5P_MFC_R2H_CMD_SYS_INIT_RET ) {
2011-06-21 10:51:26 -03:00
/* Failure. */
mfc_err ( " Failed to init firmware - error: %d int: %d \n " ,
dev - > int_err , dev - > int_type ) ;
s5p_mfc_reset ( dev ) ;
s5p_mfc_clock_off ( ) ;
return - EIO ;
}
2013-07-09 01:24:36 -03:00
if ( IS_MFCV6_PLUS ( dev ) )
2012-10-03 22:19:11 -03:00
ver = mfc_read ( dev , S5P_FIMV_FW_VERSION_V6 ) ;
else
ver = mfc_read ( dev , S5P_FIMV_FW_VERSION ) ;
2011-06-21 10:51:26 -03:00
mfc_debug ( 2 , " MFC F/W version : %02xyy, %02xmm, %02xdd \n " ,
( ver > > 16 ) & 0xFF , ( ver > > 8 ) & 0xFF , ver & 0xFF ) ;
s5p_mfc_clock_off ( ) ;
mfc_debug_leave ( ) ;
return 0 ;
}
2012-10-03 22:19:08 -03:00
/* Deinitialize hardware */
void s5p_mfc_deinit_hw ( struct s5p_mfc_dev * dev )
{
s5p_mfc_clock_on ( ) ;
s5p_mfc_reset ( dev ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , release_dev_context_buffer , dev ) ;
2012-10-03 22:19:08 -03:00
s5p_mfc_clock_off ( ) ;
}
2011-06-21 10:51:26 -03:00
int s5p_mfc_sleep ( struct s5p_mfc_dev * dev )
{
int ret ;
mfc_debug_enter ( ) ;
s5p_mfc_clock_on ( ) ;
s5p_mfc_clean_dev_int_flags ( dev ) ;
2012-10-03 22:19:08 -03:00
ret = s5p_mfc_hw_call ( dev - > mfc_cmds , sleep_cmd , dev ) ;
2011-06-21 10:51:26 -03:00
if ( ret ) {
mfc_err ( " Failed to send command to MFC - timeout \n " ) ;
return ret ;
}
2012-10-03 22:19:08 -03:00
if ( s5p_mfc_wait_for_done_dev ( dev , S5P_MFC_R2H_CMD_SLEEP_RET ) ) {
2011-06-21 10:51:26 -03:00
mfc_err ( " Failed to sleep \n " ) ;
return - EIO ;
}
s5p_mfc_clock_off ( ) ;
dev - > int_cond = 0 ;
if ( dev - > int_err ! = 0 | | dev - > int_type ! =
2012-10-03 22:19:08 -03:00
S5P_MFC_R2H_CMD_SLEEP_RET ) {
2011-06-21 10:51:26 -03:00
/* Failure. */
mfc_err ( " Failed to sleep - error: %d int: %d \n " , dev - > int_err ,
dev - > int_type ) ;
return - EIO ;
}
mfc_debug_leave ( ) ;
return ret ;
}
2014-10-21 08:07:02 -03:00
static int s5p_mfc_v8_wait_wakeup ( struct s5p_mfc_dev * dev )
{
int ret ;
/* Release reset signal to the RISC */
dev - > risc_on = 1 ;
mfc_write ( dev , 0x1 , S5P_FIMV_RISC_ON_V6 ) ;
if ( s5p_mfc_wait_for_done_dev ( dev , S5P_MFC_R2H_CMD_FW_STATUS_RET ) ) {
mfc_err ( " Failed to reset MFCV8 \n " ) ;
return - EIO ;
}
mfc_debug ( 2 , " Write command to wakeup MFCV8 \n " ) ;
ret = s5p_mfc_hw_call ( dev - > mfc_cmds , wakeup_cmd , dev ) ;
if ( ret ) {
mfc_err ( " Failed to send command to MFCV8 - timeout \n " ) ;
return ret ;
}
if ( s5p_mfc_wait_for_done_dev ( dev , S5P_MFC_R2H_CMD_WAKEUP_RET ) ) {
mfc_err ( " Failed to wakeup MFC \n " ) ;
return - EIO ;
}
return ret ;
}
static int s5p_mfc_wait_wakeup ( struct s5p_mfc_dev * dev )
{
int ret ;
/* Send MFC wakeup command */
ret = s5p_mfc_hw_call ( dev - > mfc_cmds , wakeup_cmd , dev ) ;
if ( ret ) {
mfc_err ( " Failed to send command to MFC - timeout \n " ) ;
return ret ;
}
/* Release reset signal to the RISC */
if ( IS_MFCV6_PLUS ( dev ) ) {
dev - > risc_on = 1 ;
mfc_write ( dev , 0x1 , S5P_FIMV_RISC_ON_V6 ) ;
} else {
mfc_write ( dev , 0x3ff , S5P_FIMV_SW_RESET ) ;
}
if ( s5p_mfc_wait_for_done_dev ( dev , S5P_MFC_R2H_CMD_WAKEUP_RET ) ) {
mfc_err ( " Failed to wakeup MFC \n " ) ;
return - EIO ;
}
return ret ;
}
2011-06-21 10:51:26 -03:00
int s5p_mfc_wakeup ( struct s5p_mfc_dev * dev )
{
int ret ;
mfc_debug_enter ( ) ;
/* 0. MFC reset */
mfc_debug ( 2 , " MFC reset.. \n " ) ;
s5p_mfc_clock_on ( ) ;
2014-10-21 08:06:59 -03:00
dev - > risc_on = 0 ;
2011-06-21 10:51:26 -03:00
ret = s5p_mfc_reset ( dev ) ;
if ( ret ) {
mfc_err ( " Failed to reset MFC - timeout \n " ) ;
2014-10-21 08:07:02 -03:00
s5p_mfc_clock_off ( ) ;
2011-06-21 10:51:26 -03:00
return ret ;
}
mfc_debug ( 2 , " Done MFC reset.. \n " ) ;
/* 1. Set DRAM base Addr */
s5p_mfc_init_memctrl ( dev ) ;
/* 2. Initialize registers of channel I/F */
s5p_mfc_clear_cmds ( dev ) ;
s5p_mfc_clean_dev_int_flags ( dev ) ;
2014-10-21 08:07:02 -03:00
/* 3. Send MFC wakeup command and wait for completion*/
if ( IS_MFCV8 ( dev ) )
ret = s5p_mfc_v8_wait_wakeup ( dev ) ;
2012-10-03 22:19:11 -03:00
else
2014-10-21 08:07:02 -03:00
ret = s5p_mfc_wait_wakeup ( dev ) ;
2011-06-21 10:51:26 -03:00
s5p_mfc_clock_off ( ) ;
2014-10-21 08:07:02 -03:00
if ( ret )
return ret ;
2011-06-21 10:51:26 -03:00
dev - > int_cond = 0 ;
if ( dev - > int_err ! = 0 | | dev - > int_type ! =
2012-10-03 22:19:08 -03:00
S5P_MFC_R2H_CMD_WAKEUP_RET ) {
2011-06-21 10:51:26 -03:00
/* Failure. */
mfc_err ( " Failed to wakeup - error: %d int: %d \n " , dev - > int_err ,
dev - > int_type ) ;
return - EIO ;
}
mfc_debug_leave ( ) ;
return 0 ;
}
2014-05-19 09:32:59 -03:00
int s5p_mfc_open_mfc_inst ( struct s5p_mfc_dev * dev , struct s5p_mfc_ctx * ctx )
{
int ret = 0 ;
ret = s5p_mfc_hw_call ( dev - > mfc_ops , alloc_instance_buffer , ctx ) ;
if ( ret ) {
mfc_err ( " Failed allocating instance buffer \n " ) ;
goto err ;
}
if ( ctx - > type = = MFCINST_DECODER ) {
ret = s5p_mfc_hw_call ( dev - > mfc_ops ,
alloc_dec_temp_buffers , ctx ) ;
if ( ret ) {
mfc_err ( " Failed allocating temporary buffers \n " ) ;
goto err_free_inst_buf ;
}
}
set_work_bit_irqsave ( ctx ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , try_run , dev ) ;
2014-05-19 09:32:59 -03:00
if ( s5p_mfc_wait_for_done_ctx ( ctx ,
S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET , 0 ) ) {
/* Error or timeout */
mfc_err ( " Error getting instance from hardware \n " ) ;
ret = - EIO ;
goto err_free_desc_buf ;
}
mfc_debug ( 2 , " Got instance number: %d \n " , ctx - > inst_no ) ;
return ret ;
err_free_desc_buf :
if ( ctx - > type = = MFCINST_DECODER )
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , release_dec_desc_buffer , ctx ) ;
2014-05-19 09:32:59 -03:00
err_free_inst_buf :
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , release_instance_buffer , ctx ) ;
2014-05-19 09:32:59 -03:00
err :
return ret ;
}
void s5p_mfc_close_mfc_inst ( struct s5p_mfc_dev * dev , struct s5p_mfc_ctx * ctx )
{
ctx - > state = MFCINST_RETURN_INST ;
set_work_bit_irqsave ( ctx ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , try_run , dev ) ;
2014-05-19 09:32:59 -03:00
/* Wait until instance is returned or timeout occurred */
if ( s5p_mfc_wait_for_done_ctx ( ctx ,
S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET , 0 ) )
mfc_err ( " Err returning instance \n " ) ;
/* Free resources */
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , release_codec_buffers , ctx ) ;
s5p_mfc_hw_call ( dev - > mfc_ops , release_instance_buffer , ctx ) ;
2014-05-19 09:32:59 -03:00
if ( ctx - > type = = MFCINST_DECODER )
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , release_dec_desc_buffer , ctx ) ;
2014-05-19 09:32:59 -03:00
2014-05-19 09:33:00 -03:00
ctx - > inst_no = MFC_NO_INSTANCE_SET ;
2014-05-19 09:32:59 -03:00
ctx - > state = MFCINST_FREE ;
}