2024-04-28 06:49:01 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2020 MediaTek Inc.
|
|
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/mm_types.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <generated/autoconf.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/cdev.h>
|
|
|
|
#include <linux/kdev_t.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/ioport.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/wait.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/param.h>
|
|
|
|
#include <linux/uaccess.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
#ifdef CONFIG_MTK_PSEUDO_M4U
|
|
|
|
#include <mach/mt_iommu.h>
|
|
|
|
#include "mach/pseudo_m4u.h"
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* #include <linux/xlog.h> */
|
|
|
|
|
|
|
|
#include <linux/io.h>
|
|
|
|
/* ============================================================ */
|
|
|
|
|
|
|
|
/* #include <linux/uaccess.h> */
|
|
|
|
/* #include <linux/module.h> */
|
|
|
|
/* #include <linux/fs.h> */
|
|
|
|
/* #include <linux/platform_device.h> */
|
|
|
|
/* #include <linux/cdev.h> */
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
/* #include <asm/io.h> */
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/wait.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/suspend.h>
|
|
|
|
/* #include <linux/earlysuspend.h> */
|
|
|
|
/* #include <linux/mm.h> */
|
|
|
|
#include <linux/vmalloc.h>
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
/* #include <linux/slab.h> */
|
|
|
|
/* #include <linux/gfp.h> */
|
|
|
|
/* #include <linux/aee.h> */
|
|
|
|
#include <linux/timer.h>
|
|
|
|
/* #include <linux/disp_assert_layer.h> */
|
|
|
|
/* #include <linux/xlog.h> */
|
|
|
|
/* #include <linux/fs.h> */
|
|
|
|
|
|
|
|
/* Arch dependent files */
|
|
|
|
/* #include <asm/mach/map.h> */
|
|
|
|
/* #include <mach/mt6577_pll.h> */
|
|
|
|
/* #include <mach/mt_irq.h> */
|
|
|
|
/* #include <mach/irqs.h> */
|
|
|
|
|
|
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
|
|
#include <mach/mt_clkmgr.h>
|
|
|
|
#endif /* defined(CONFIG_MTK_LEGACY) */
|
|
|
|
|
|
|
|
/* #include <asm/tcm.h> */
|
|
|
|
#include <asm/cacheflush.h>
|
|
|
|
/* #include <asm/system.h> */
|
|
|
|
/* #include <linux/mm.h> */
|
|
|
|
#include <linux/pagemap.h>
|
|
|
|
|
|
|
|
#ifndef FPGA_VERSION
|
|
|
|
/* #include <mach/mt_boot.h> */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MTK_JPEG_CMDQ_SUPPORT
|
|
|
|
#include <cmdq_core.h>
|
|
|
|
#include <cmdq_record.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef JPEG_DEV
|
|
|
|
#include <linux/proc_fs.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_OF
|
|
|
|
/* device tree */
|
|
|
|
#include <linux/of.h>
|
|
|
|
#include <linux/of_irq.h>
|
|
|
|
#include <linux/of_address.h>
|
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/of_device.h>
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
#include <linux/pm_runtime.h>
|
|
|
|
#include <linux/clk.h>
|
|
|
|
#include "mtk_smi.h"
|
|
|
|
#endif
|
|
|
|
/* ========================================================== */
|
|
|
|
|
|
|
|
#include "jpeg_drv.h"
|
|
|
|
#include "jpeg_drv_common.h"
|
|
|
|
|
|
|
|
#ifdef MTK_JPEG_CMDQ_SUPPORT
|
|
|
|
#include "jpeg_cmdq.h"
|
|
|
|
#endif
|
|
|
|
/* #define USE_SYSRAM */
|
|
|
|
|
|
|
|
#define JPEG_DEVNAME "mtk_jpeg"
|
|
|
|
#define JDEC_DEVNAME "mtk_jdec"
|
|
|
|
|
|
|
|
#define TABLE_SIZE 4096
|
|
|
|
|
|
|
|
#define JPEG_DEC_PROCESS 0x1
|
|
|
|
#define JPEG_ENC_PROCESS 0x2
|
|
|
|
|
|
|
|
/* #define FPGA_VERSION */
|
|
|
|
#include "jpeg_drv_reg.h"
|
|
|
|
|
|
|
|
#include "smi_public.h"
|
|
|
|
|
|
|
|
/* Support QoS */
|
|
|
|
#include <linux/soc/mediatek/mtk-pm-qos.h>
|
|
|
|
|
|
|
|
#if ENABLE_MMQOS || defined(JPEG_HYBRID_DEC_DRIVER)
|
|
|
|
#include "smi_port.h"
|
|
|
|
#include "mmdvfs_pmqos.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <ion_drv.h>
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* */
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#ifdef JPEG_DEV
|
|
|
|
/* device and driver */
|
|
|
|
static dev_t jenc_devno;
|
|
|
|
static struct cdev *jenc_cdev;
|
|
|
|
static struct class *jenc_class;
|
|
|
|
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
static dev_t jdec_devno;
|
|
|
|
static struct cdev *jdec_cdev;
|
|
|
|
static struct class *jdec_class;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct JpegDeviceStruct gJpegqDev;
|
|
|
|
#ifdef CONFIG_OF
|
|
|
|
static struct JpegDeviceStruct *gJpegqDevs;
|
|
|
|
static int nrJpegDevs;
|
|
|
|
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
static const struct of_device_id venc_jpg_of_ids[] = {
|
|
|
|
{.compatible = "mediatek,venc_jpg",},
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
static const struct of_device_id jdec_hybrid_of_ids[] = {
|
|
|
|
{.compatible = "mediatek,jpgdec",},
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
static const struct of_device_id jdec_of_ids[] = {
|
|
|
|
{.compatible = "mediatek,jpgdec",},
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef CONFIG_MTK_CLKMGR
|
|
|
|
static struct JpegClk gJpegClk;
|
|
|
|
#endif
|
|
|
|
/* decoder */
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
static wait_queue_head_t dec_wait_queue;
|
|
|
|
static spinlock_t jpeg_dec_lock;
|
|
|
|
static int dec_status;
|
|
|
|
static int dec_ready;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* hybrid decoder */
|
|
|
|
int jpg_dbg_level;
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
static wait_queue_head_t hybrid_dec_wait_queue[HW_CORE_NUMBER];
|
|
|
|
static DEFINE_MUTEX(jpeg_hybrid_dec_lock);
|
|
|
|
|
|
|
|
static bool dec_hwlocked[HW_CORE_NUMBER] = {false, false, false};
|
|
|
|
|
|
|
|
module_param(jpg_dbg_level, int, 0644);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
struct platform_device *pjdec_dev;
|
|
|
|
struct platform_device *pjenc_dev;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* encoder */
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
static wait_queue_head_t enc_wait_queue;
|
|
|
|
static spinlock_t jpeg_enc_lock;
|
|
|
|
static int enc_status;
|
|
|
|
static int enc_ready;
|
|
|
|
#endif
|
|
|
|
static DEFINE_MUTEX(jpeg_enc_power_lock);
|
|
|
|
static DEFINE_MUTEX(DriverOpenCountLock);
|
|
|
|
static int Driver_Open_Count;
|
|
|
|
|
|
|
|
#if ENABLE_MMQOS
|
|
|
|
static struct plist_head jpegenc_rlist;
|
|
|
|
static struct mm_qos_request jpeg_y_rdma;
|
|
|
|
static struct mm_qos_request jpeg_c_rdma;
|
|
|
|
static struct mm_qos_request jpeg_qtbl;
|
|
|
|
static struct mm_qos_request jpeg_bsdma;
|
|
|
|
static unsigned int cshot_spec_dts;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Support QoS */
|
|
|
|
struct mtk_pm_qos_request jpgenc_qos_request;
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
static struct mtk_pm_qos_request jpgdec_qos_request;
|
|
|
|
static u64 g_freq_steps[MAX_FREQ_STEP]; //index 0 is max
|
|
|
|
static u32 freq_step_size;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct ion_client *g_jpeg_ion_client;
|
|
|
|
|
|
|
|
|
|
|
|
/* ========================================== */
|
|
|
|
/* CMDQ */
|
|
|
|
|
|
|
|
/* static cmdqRecStruct jpegCMDQ_handle; */
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
/* static cmdqRecHandle jpegCMDQ_handle; */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* JPEG Common Function */
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#ifdef FPGA_VERSION
|
|
|
|
|
|
|
|
|
|
|
|
void jpeg_drv_dec_power_on(void)
|
|
|
|
{
|
|
|
|
JPEG_MSG("JPEG Decoder Power On\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_dec_power_off(void)
|
|
|
|
{
|
|
|
|
JPEG_MSG("JPEG Decoder Power Off\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_enc_power_on(void)
|
|
|
|
{
|
|
|
|
#ifdef FPGA_VERSION
|
|
|
|
IMG_REG_WRITE((0), JPEG_EARLY_MM_BASE);
|
|
|
|
JPEG_MSG("JPEG Encoder RESET_MM_BASE!!\n");
|
|
|
|
#endif
|
|
|
|
JPEG_MSG("JPEG Encoder Power On\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_enc_power_off(void)
|
|
|
|
{
|
|
|
|
JPEG_MSG("JPEG Encoder Power Off\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
void jpeg_drv_enc_prepare_bw_request(void)
|
|
|
|
{
|
|
|
|
#if ENABLE_MMQOS
|
|
|
|
plist_head_init(&jpegenc_rlist);
|
|
|
|
mm_qos_add_request(&jpegenc_rlist, &jpeg_y_rdma, SMI_JPGENC_Y_RDMA);
|
|
|
|
mm_qos_add_request(&jpegenc_rlist, &jpeg_c_rdma, SMI_JPGENC_C_RDMA);
|
|
|
|
mm_qos_add_request(&jpegenc_rlist, &jpeg_qtbl, SMI_JPGENC_Q_TABLE);
|
|
|
|
mm_qos_add_request(&jpegenc_rlist, &jpeg_bsdma, SMI_JPGENC_BSDMA);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpegenc_drv_enc_update_bw_request(struct JPEG_ENC_DRV_IN cfgEnc)
|
|
|
|
{
|
|
|
|
#if ENABLE_MMQOS
|
|
|
|
/* No spec, considering [picture size] x [target fps] */
|
|
|
|
unsigned int cshot_spec = 0xffffffff;
|
|
|
|
/* limiting FPS, Upper Bound FPS = 20 */
|
|
|
|
unsigned int target_fps = 20;
|
|
|
|
|
|
|
|
/* Support QoS */
|
|
|
|
unsigned int emi_bw = 0;
|
|
|
|
unsigned int picSize = 0;
|
|
|
|
unsigned int limitedFPS = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/* Support QoS */
|
|
|
|
picSize = (cfgEnc.encWidth * cfgEnc.encHeight) / 1000000;
|
|
|
|
/* BW = encode width x height x bpp x 1.6 */
|
|
|
|
/* Assume compress ratio is 0.6 */
|
|
|
|
|
|
|
|
cshot_spec = cshot_spec_dts;
|
|
|
|
|
|
|
|
if ((picSize * target_fps) < cshot_spec) {
|
|
|
|
emi_bw = picSize * target_fps;
|
|
|
|
} else {
|
|
|
|
limitedFPS = cshot_spec / picSize;
|
|
|
|
emi_bw = (limitedFPS + 1) * picSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* QoS requires Occupied BW */
|
|
|
|
/* Data BW x 1.33 */
|
|
|
|
emi_bw = emi_bw * 4/3;
|
|
|
|
|
|
|
|
JPEG_MSG("Width %d Height %d emi_bw %d cshot_spec %d\n",
|
|
|
|
cfgEnc.encWidth, cfgEnc.encHeight, emi_bw, cshot_spec);
|
|
|
|
|
|
|
|
mm_qos_set_request(&jpeg_y_rdma, emi_bw, 0, BW_COMP_NONE);
|
|
|
|
|
|
|
|
if (cfgEnc.encFormat == 0x0 || cfgEnc.encFormat == 0x1)
|
|
|
|
mm_qos_set_request(&jpeg_c_rdma, emi_bw, 0, BW_COMP_NONE);
|
|
|
|
else
|
|
|
|
mm_qos_set_request(&jpeg_c_rdma, emi_bw * 1/2, 0, BW_COMP_NONE);
|
|
|
|
|
|
|
|
|
|
|
|
mm_qos_set_request(&jpeg_qtbl, 10, 0, BW_COMP_NONE);
|
|
|
|
mm_qos_set_request(&jpeg_bsdma, emi_bw, 0, BW_COMP_NONE);
|
|
|
|
mm_qos_update_all_request(&jpegenc_rlist);
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void jpegenc_drv_enc_remove_bw_request(void)
|
|
|
|
{
|
|
|
|
#if ENABLE_MMQOS
|
|
|
|
mm_qos_remove_all_request(&jpegenc_rlist);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static irqreturn_t jpeg_drv_enc_isr(int irq, void *dev_id)
|
|
|
|
{
|
|
|
|
/* JPEG_MSG("JPEG Encoder Interrupt\n"); */
|
|
|
|
if (enc_status == 0) {
|
|
|
|
JPEG_ERR("interrupt without power on");
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (irq == gJpegqDev.encIrqId) {
|
|
|
|
if (jpeg_isr_enc_lisr() == 0)
|
|
|
|
wake_up_interruptible(&enc_wait_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
|
|
|
|
static int jpeg_drv_hybrid_dec_suspend_notifier(
|
|
|
|
struct notifier_block *nb,
|
|
|
|
unsigned long action, void *data)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int wait_cnt = 0;
|
|
|
|
|
|
|
|
JPEG_LOG(0, "%s, action:%ld\n", __func__, action);
|
|
|
|
switch (action) {
|
|
|
|
case PM_SUSPEND_PREPARE:
|
|
|
|
gJpegqDev.is_suspending = 1;
|
|
|
|
for (i = 0 ; i < HW_CORE_NUMBER; i++) {
|
|
|
|
JPEG_LOG(0, "jpeg dec sn wait core %d\n", i);
|
|
|
|
while (dec_hwlocked[i]) {
|
|
|
|
JPEG_LOG(1, "jpeg dec sn core %d locked. wait...\n", i);
|
|
|
|
usleep_range(10000, 20000);
|
|
|
|
wait_cnt++;
|
|
|
|
if (wait_cnt > 5) {
|
|
|
|
JPEG_LOG(0, "jpeg dec sn wait core %d fail\n", i);
|
|
|
|
return NOTIFY_DONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NOTIFY_OK;
|
|
|
|
case PM_POST_SUSPEND:
|
|
|
|
gJpegqDev.is_suspending = 0;
|
|
|
|
return NOTIFY_OK;
|
|
|
|
default:
|
|
|
|
return NOTIFY_DONE;
|
|
|
|
}
|
|
|
|
return NOTIFY_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static irqreturn_t jpeg_drv_hybrid_dec_isr(int irq, void *dev_id)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
JPEG_LOG(1, "JPEG Hybrid Decoder Interrupt %d\n", irq);
|
|
|
|
for (i = 0 ; i < HW_CORE_NUMBER; i++) {
|
|
|
|
if (irq == gJpegqDev.hybriddecIrqId[i]) {
|
|
|
|
if (!dec_hwlocked[i]) {
|
|
|
|
JPEG_LOG(0, "JPEG isr from unlocked HW %d",
|
|
|
|
i);
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
ret = jpeg_isr_hybrid_dec_lisr(i);
|
|
|
|
if (ret == 0)
|
|
|
|
wake_up_interruptible(
|
|
|
|
&(hybrid_dec_wait_queue[i]));
|
|
|
|
JPEG_LOG(1, "JPEG Hybrid Dec clear Interrupt %d ret %d\n"
|
|
|
|
, irq, ret);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_hybrid_dec_prepare_dvfs(void)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!freq_step_size) {
|
|
|
|
mtk_pm_qos_add_request(&jpgdec_qos_request, PM_QOS_VENC_FREQ,
|
|
|
|
PM_QOS_DEFAULT_VALUE);
|
|
|
|
ret = mmdvfs_qos_get_freq_steps(PM_QOS_VENC_FREQ, g_freq_steps,
|
|
|
|
&freq_step_size);
|
|
|
|
if (ret < 0)
|
|
|
|
JPEG_LOG(0, "Failed to get venc freq steps (%d)\n", ret);
|
|
|
|
|
|
|
|
for (i = 0 ; i < freq_step_size ; i++)
|
|
|
|
JPEG_LOG(1, "freq %d %lx", i, g_freq_steps[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_hybrid_dec_unprepare_dvfs(void)
|
|
|
|
{
|
|
|
|
mtk_pm_qos_update_request(&jpgdec_qos_request, 0);
|
|
|
|
mtk_pm_qos_remove_request(&jpgdec_qos_request);
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_hybrid_dec_start_dvfs(void)
|
|
|
|
{
|
|
|
|
if (g_freq_steps[0] != 0) {
|
|
|
|
JPEG_LOG(1, "highest freq 0x%x", g_freq_steps[0]);
|
|
|
|
mtk_pm_qos_update_request(&jpgdec_qos_request, g_freq_steps[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_hybrid_dec_end_dvfs(void)
|
|
|
|
{
|
|
|
|
mtk_pm_qos_update_request(&jpgdec_qos_request, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_hybrid_dec_power_on(int id)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
#ifdef CONFIG_MTK_PSEUDO_M4U
|
|
|
|
int i, larb_port_num, larb_id;
|
|
|
|
struct M4U_PORT_STRUCT port;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (id <= 1) {
|
|
|
|
if (!dec_hwlocked[(id+1)%2]) {
|
|
|
|
smi_bus_prepare_enable(SMI_LARB7, "JPEG0");
|
|
|
|
ret = clk_prepare_enable(gJpegClk.clk_venc_jpgDec);
|
|
|
|
if (ret)
|
|
|
|
JPEG_LOG(0, "clk MT_CG_VENC_JPGDEC failed %d",
|
|
|
|
ret);
|
|
|
|
ret = clk_prepare_enable(gJpegClk.clk_venc_jpgDec_c1);
|
|
|
|
if (ret)
|
|
|
|
JPEG_LOG(0, "clk MT_CG_VENC_JPGDEC_C1 failed %d",
|
|
|
|
ret);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
smi_bus_prepare_enable(SMI_LARB8, "JPEG1");
|
|
|
|
ret = clk_prepare_enable(gJpegClk.clk_venc_c1_jpgDec);
|
|
|
|
if (ret)
|
|
|
|
JPEG_LOG(0, "clk enable MT_CG_VENC_C1_JPGDEC failed %d",
|
|
|
|
ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
jpeg_drv_hybrid_dec_start_dvfs();
|
|
|
|
|
|
|
|
#ifdef CONFIG_MTK_PSEUDO_M4U
|
|
|
|
if (id <= 1) {
|
|
|
|
larb_port_num = SMI_LARB7_PORT_NUM;
|
|
|
|
larb_id = 7;
|
|
|
|
} else {
|
|
|
|
larb_port_num = SMI_LARB8_PORT_NUM;
|
|
|
|
larb_id = 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
//enable 34bits port configs & sram settings
|
|
|
|
for (i = 0; i < larb_port_num; i++) {
|
|
|
|
if (i == 11 || i == 12 ||
|
|
|
|
(i >= 23 && i <= 26)) {
|
|
|
|
port.ePortID = MTK_M4U_ID(larb_id, i);
|
|
|
|
port.Direction = 0;
|
|
|
|
port.Distance = 1;
|
|
|
|
port.domain = 0;
|
|
|
|
port.Security = 0;
|
|
|
|
port.Virtuality = 1;
|
|
|
|
m4u_config_port(&port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
JPEG_LOG(1, "JPEG Hybrid Decoder Power On %d\n", id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_hybrid_dec_power_off(int id)
|
|
|
|
{
|
|
|
|
jpeg_drv_hybrid_dec_end_dvfs();
|
|
|
|
if (id <= 1) {
|
|
|
|
if (!dec_hwlocked[(id+1)%2]) {
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgDec);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgDec_c1);
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB7, "JPEG0");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_c1_jpgDec);
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB8, "JPEG1");
|
|
|
|
}
|
|
|
|
JPEG_LOG(1, "JPEG Hybrid Decoder Power Off %d\n", id);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
static irqreturn_t jpeg_drv_dec_isr(int irq, void *dev_id)
|
|
|
|
{
|
|
|
|
/* JPEG_MSG("JPEG Decoder Interrupt\n"); */
|
|
|
|
|
|
|
|
if (irq == gJpegqDev.decIrqId) {
|
|
|
|
/* mt65xx_irq_mask(MT6575_JPEG_CODEC_IRQ_ID); */
|
|
|
|
|
|
|
|
if (jpeg_isr_dec_lisr() == 0)
|
|
|
|
wake_up_interruptible(&dec_wait_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_dec_power_on(void)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
|
|
enable_clock(MT_CG_DISP0_SMI_COMMON, "JPEG");
|
|
|
|
enable_clock(MT_CG_VENC_LARB, "JPEG");
|
|
|
|
enable_clock(MT_CG_VENC_JPGDEC, "JPEG");
|
|
|
|
#else
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
mtk_smi_larb_clock_on(3, true);
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_jpgDec))
|
|
|
|
JPEG_ERR("enable clk_venc_jpgDec fail!");
|
|
|
|
#else
|
|
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
|
|
|
smi_bus_prepare_enable(SMI_LARB7_REG_INDX, "JPEG", true);
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_jpgDec))
|
|
|
|
JPEG_ERR("enable clk_venc_jpgDec fail!");
|
|
|
|
#else
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_scp_sys_mm0))
|
|
|
|
JPEG_ERR("enable clk_scp_sys_mm0 fail!");
|
|
|
|
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_smi_common))
|
|
|
|
JPEG_ERR("enable clk_smi_common fail!");
|
|
|
|
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_scp_sys_ven))
|
|
|
|
JPEG_ERR("enable clk_scp_sys_ven fail!");
|
|
|
|
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_jpgDec))
|
|
|
|
JPEG_ERR("enable clk_venc_jpgDec fail!");
|
|
|
|
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_larb))
|
|
|
|
JPEG_ERR("enable clk_venc_larb fail!");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_dec_power_off(void)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
|
|
disable_clock(MT_CG_VENC_JPGDEC, "JPEG");
|
|
|
|
disable_clock(MT_CG_VENC_LARB, "JPEG");
|
|
|
|
disable_clock(MT_CG_DISP0_SMI_COMMON, "JPEG");
|
|
|
|
#else
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgDec);
|
|
|
|
mtk_smi_larb_clock_off(3, true);
|
|
|
|
#else
|
|
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgDec);
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB7_REG_INDX, "JPEG", true);
|
|
|
|
#else
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_larb);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgDec);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_scp_sys_ven);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_smi_common);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_scp_sys_mm0);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
void jpeg_drv_enc_power_on(void)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
|
|
/* REG_JPEG_MM_REG_MASK = 0; */
|
|
|
|
enable_clock(MT_CG_DISP0_SMI_COMMON, "JPEG");
|
|
|
|
#ifdef CONFIG_ARCH_MT6735M
|
|
|
|
enable_clock(MT_CG_IMAGE_JPGENC, "JPEG");
|
|
|
|
#else
|
|
|
|
enable_clock(MT_CG_VENC_LARB, "JPEG");
|
|
|
|
enable_clock(MT_CG_VENC_JPGENC, "JPEG");
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
mtk_smi_larb_clock_on(3, true);
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_jpgEnc))
|
|
|
|
JPEG_ERR("enable clk_venc_jpgEnc fail!");
|
|
|
|
#else
|
|
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
|
|
|
#if defined(PLATFORM_MT6779)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB3, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6785)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB3, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6768)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB4, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6767)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB4, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6765)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB1, "JPEG");
|
|
|
|
#elif defined(PLATFORM_MT6761)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB1, "JPEG");
|
|
|
|
#elif defined(PLATFORM_MT6739)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB1, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6771)
|
|
|
|
|
|
|
|
smi_bus_prepare_enable(SMI_LARB4, "JPEG");
|
|
|
|
|
|
|
|
#endif
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_jpgEnc))
|
|
|
|
JPEG_ERR("enable clk_venc_jpgDec fail!");
|
|
|
|
#else
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_scp_sys_mm0))
|
|
|
|
JPEG_ERR("enable clk_scp_sys_mm0 fail!");
|
|
|
|
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_smi_common))
|
|
|
|
JPEG_ERR("enable clk_smi_common fail!");
|
|
|
|
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_scp_sys_ven))
|
|
|
|
JPEG_ERR("enable clk_scp_sys_ven clk fail!");
|
|
|
|
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_jpgEnc))
|
|
|
|
JPEG_ERR("enable clk_venc_jpgEnc fail!");
|
|
|
|
|
|
|
|
#ifndef CONFIG_ARCH_MT6735M
|
|
|
|
if (clk_prepare_enable(gJpegClk.clk_venc_larb))
|
|
|
|
JPEG_ERR("enable clk_venc_larb fail!");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
enable_irq(gJpegqDev.encIrqId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void jpeg_drv_enc_power_off(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
disable_irq(gJpegqDev.encIrqId);
|
|
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
|
|
#ifdef CONFIG_ARCH_MT6735M
|
|
|
|
disable_clock(MT_CG_IMAGE_JPGENC, "JPEG");
|
|
|
|
#else
|
|
|
|
disable_clock(MT_CG_VENC_JPGENC, "JPEG");
|
|
|
|
disable_clock(MT_CG_VENC_LARB, "JPEG");
|
|
|
|
#endif
|
|
|
|
disable_clock(MT_CG_DISP0_SMI_COMMON, "JPEG");
|
|
|
|
#else
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgEnc);
|
|
|
|
mtk_smi_larb_clock_off(3, true);
|
|
|
|
#else
|
|
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgEnc);
|
|
|
|
#if defined(PLATFORM_MT6779)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB3, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6785)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB3, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6768)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB4, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6767)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB4, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6765)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB1, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6761)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB1, "JPEG");
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6739)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB1, "JPEG");
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(PLATFORM_MT6771)
|
|
|
|
|
|
|
|
smi_bus_disable_unprepare(SMI_LARB4, "JPEG");
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
#ifndef CONFIG_ARCH_MT6735M
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_larb);
|
|
|
|
#endif
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_venc_jpgEnc);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_scp_sys_ven);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_smi_common);
|
|
|
|
clk_disable_unprepare(gJpegClk.clk_scp_sys_mm0);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
static int jpeg_drv_hybrid_dec_lock(int *hwid)
|
|
|
|
{
|
|
|
|
int retValue = 0;
|
|
|
|
int id = 0;
|
|
|
|
|
|
|
|
if (gJpegqDev.is_suspending) {
|
|
|
|
JPEG_LOG(0, "jpeg dec is suspending");
|
|
|
|
*hwid = -1;
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_lock(&jpeg_hybrid_dec_lock);
|
|
|
|
for (id = 0; id < HW_CORE_NUMBER; id++) {
|
|
|
|
if (dec_hwlocked[id]) {
|
|
|
|
JPEG_LOG(1, "jpeg dec HW core %d is busy", id);
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
*hwid = id;
|
|
|
|
dec_hwlocked[id] = true;
|
|
|
|
JPEG_LOG(1, "jpeg dec get %d HW core", id);
|
|
|
|
_jpeg_hybrid_dec_int_status[id] = 0;
|
|
|
|
jpeg_drv_hybrid_dec_power_on(id);
|
|
|
|
enable_irq(gJpegqDev.hybriddecIrqId[id]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
|
|
|
if (id == HW_CORE_NUMBER) {
|
|
|
|
JPEG_LOG(1, "jpeg dec HW core all busy");
|
|
|
|
*hwid = -1;
|
|
|
|
retValue = -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jpeg_drv_hybrid_dec_unlock(int hwid)
|
|
|
|
{
|
|
|
|
mutex_lock(&jpeg_hybrid_dec_lock);
|
|
|
|
if (!dec_hwlocked[hwid]) {
|
|
|
|
JPEG_LOG(0, "try to unlock a free core %d", hwid);
|
|
|
|
} else {
|
|
|
|
dec_hwlocked[hwid] = false;
|
|
|
|
JPEG_LOG(1, "jpeg dec HW core %d is unlocked", hwid);
|
|
|
|
jpeg_drv_hybrid_dec_power_off(hwid);
|
|
|
|
disable_irq(gJpegqDev.hybriddecIrqId[hwid]);
|
2024-04-28 06:51:13 -07:00
|
|
|
gJpegqDev.is_dec_started[hwid] = false;
|
2024-04-28 06:49:01 -07:00
|
|
|
}
|
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_drv_hybrid_dec_suspend(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
JPEG_LOG(0, "%s\n", __func__);
|
|
|
|
for (i = 0 ; i < HW_CORE_NUMBER; i++) {
|
|
|
|
JPEG_LOG(0, "jpeg dec suspend core %d\n", i);
|
|
|
|
if (dec_hwlocked[i]) {
|
|
|
|
JPEG_LOG(0, "suspend unlock core %d\n", i);
|
|
|
|
jpeg_drv_hybrid_dec_unlock(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_drv_hybrid_dec_get_status(int hwid)
|
|
|
|
{
|
|
|
|
int p_n_s;
|
|
|
|
|
|
|
|
p_n_s = -1;
|
|
|
|
mutex_lock(&jpeg_hybrid_dec_lock);
|
|
|
|
if (!dec_hwlocked[hwid]) {
|
|
|
|
JPEG_LOG(1, "hw %d unlocked, return -1 status", hwid);
|
|
|
|
} else {
|
|
|
|
JPEG_LOG(1, "get p_n_s @ hw %d", hwid);
|
|
|
|
jpeg_drv_hybrid_dec_get_p_n_s(hwid, &p_n_s);
|
|
|
|
}
|
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
|
|
|
|
|
|
|
return p_n_s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
static int jpeg_drv_dec_init(void)
|
|
|
|
{
|
|
|
|
int retValue;
|
|
|
|
|
|
|
|
spin_lock(&jpeg_dec_lock);
|
|
|
|
if (dec_status != 0) {
|
|
|
|
JPEG_WRN("%s HW is busy\n", __func__);
|
|
|
|
retValue = -EBUSY;
|
|
|
|
} else {
|
|
|
|
dec_status = 1;
|
|
|
|
dec_ready = 0;
|
|
|
|
retValue = 0;
|
|
|
|
}
|
|
|
|
spin_unlock(&jpeg_dec_lock);
|
|
|
|
|
|
|
|
if (retValue == 0) {
|
|
|
|
jpeg_drv_dec_power_on();
|
|
|
|
jpeg_drv_dec_verify_state_and_reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
return retValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jpeg_drv_dec_deinit(void)
|
|
|
|
{
|
|
|
|
if (dec_status != 0) {
|
|
|
|
|
|
|
|
spin_lock(&jpeg_dec_lock);
|
|
|
|
dec_status = 0;
|
|
|
|
dec_ready = 0;
|
|
|
|
spin_unlock(&jpeg_dec_lock);
|
|
|
|
|
|
|
|
jpeg_drv_dec_reset();
|
|
|
|
|
|
|
|
jpeg_drv_dec_power_off();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
static int jpeg_drv_enc_init(void)
|
|
|
|
{
|
|
|
|
int retValue;
|
|
|
|
|
|
|
|
spin_lock(&jpeg_enc_lock);
|
|
|
|
if (enc_status != 0) {
|
|
|
|
JPEG_WRN("%s HW is busy\n", __func__);
|
|
|
|
retValue = -EBUSY;
|
|
|
|
} else {
|
|
|
|
enc_status = 1;
|
|
|
|
enc_ready = 0;
|
|
|
|
retValue = 0;
|
|
|
|
}
|
|
|
|
spin_unlock(&jpeg_enc_lock);
|
|
|
|
|
|
|
|
mutex_lock(&jpeg_enc_power_lock);
|
|
|
|
if (retValue == 0) {
|
|
|
|
jpeg_drv_enc_power_on();
|
|
|
|
jpeg_drv_enc_verify_state_and_reset();
|
|
|
|
}
|
|
|
|
mutex_unlock(&jpeg_enc_power_lock);
|
|
|
|
|
|
|
|
return retValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jpeg_drv_enc_deinit(void)
|
|
|
|
{
|
|
|
|
if (enc_status != 0) {
|
|
|
|
spin_lock(&jpeg_enc_lock);
|
|
|
|
enc_status = 0;
|
|
|
|
enc_ready = 0;
|
|
|
|
spin_unlock(&jpeg_enc_lock);
|
|
|
|
|
|
|
|
mutex_lock(&jpeg_enc_power_lock);
|
|
|
|
jpeg_drv_enc_reset();
|
|
|
|
jpeg_drv_enc_power_off();
|
|
|
|
mutex_unlock(&jpeg_enc_power_lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* JPEG REG DUMP FUNCTION */
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
void jpeg_reg_dump(void)
|
|
|
|
{
|
|
|
|
unsigned int reg_value = 0;
|
|
|
|
unsigned int index = 0;
|
|
|
|
|
|
|
|
JPEG_WRN("JPEG REG:\n ********************\n");
|
|
|
|
for (index = 0; index < 0x168; index += 4) {
|
|
|
|
/* reg_value = ioread32(JPEG_DEC_BASE + index); */
|
|
|
|
reg_value = IMG_REG_READ(JPEG_DEC_BASE + index);
|
|
|
|
JPEG_WRN("+0x%x 0x%x\n", index, reg_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* JPEG DECODER IOCTRL FUNCTION */
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
static int jpeg_dec_ioctl(unsigned int cmd, unsigned long arg,
|
|
|
|
struct file *file)
|
|
|
|
{
|
|
|
|
unsigned int *pStatus;
|
|
|
|
unsigned int decResult;
|
|
|
|
unsigned int index = 0;
|
|
|
|
long timeout_jiff;
|
|
|
|
JPEG_DEC_DRV_IN dec_params;
|
|
|
|
JPEG_DEC_CONFIG_ROW dec_row_params;
|
|
|
|
/* JPEG_DEC_CONFIG_CMDQ cfg_cmdq_params; */
|
|
|
|
|
|
|
|
unsigned int irq_st = 0;
|
|
|
|
/* unsigned int timeout = 0x1FFFFF; */
|
|
|
|
|
|
|
|
JPEG_DEC_DRV_OUT outParams;
|
|
|
|
|
|
|
|
pStatus = (unsigned int *)file->private_data;
|
|
|
|
|
|
|
|
if (pStatus == NULL) {
|
|
|
|
JPEG_MSG
|
|
|
|
("[JPGDRV]Dec: Private data is null in flush operation\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
switch (cmd) {
|
|
|
|
/* initial and reset JPEG encoder */
|
|
|
|
case JPEG_DEC_IOCTL_INIT: /* OT:OK */
|
|
|
|
/*JPEG_MSG("[JPEGDRV][IOCTL] JPEG Decoder Init!!\n");*/
|
|
|
|
if (jpeg_drv_dec_init() == 0)
|
|
|
|
*pStatus = JPEG_DEC_PROCESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_RESET: /* OT:OK */
|
|
|
|
JPEG_MSG("[JPEGDRV][IOCTL] JPEG Decoder Reset!!\n");
|
|
|
|
jpeg_drv_dec_reset();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_CONFIG:
|
|
|
|
if (*pStatus != JPEG_DEC_PROCESS) {
|
|
|
|
JPEG_MSG
|
|
|
|
("[JPGDRV]This process can not access decoder\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (dec_status == 0) {
|
|
|
|
JPEG_MSG("[JPEGDRV]JPEG Decoder is unlocked!!");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (copy_from_user(&dec_params,
|
|
|
|
(void *)arg,
|
|
|
|
sizeof(JPEG_DEC_DRV_IN))) {
|
|
|
|
JPEG_MSG("[JPGDRV]JPEG Dec:Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
/* _jpeg_dec_dump_reg_en = dec_params.regDecDumpEn; */
|
|
|
|
if (dec_params.decodeMode == JPEG_DEC_MODE_MCU_ROW)
|
|
|
|
_jpeg_dec_mode = 1;
|
|
|
|
else
|
|
|
|
_jpeg_dec_mode = 0;
|
|
|
|
|
|
|
|
if (jpeg_drv_dec_set_config_data(&dec_params) == 0)
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
spin_lock(&jpeg_dec_lock);
|
|
|
|
dec_ready = 1;
|
|
|
|
spin_unlock(&jpeg_dec_lock);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_FLUSH_CMDQ:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_RESUME:
|
|
|
|
if (*pStatus != JPEG_DEC_PROCESS) {
|
|
|
|
JPEG_MSG
|
|
|
|
("[JPGDRV]This process can not access decoder\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (dec_status == 0 || dec_ready == 0) {
|
|
|
|
JPEG_MSG("[JPEGDRV]JPEG Decoder is unlocked!!");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (copy_from_user(&dec_row_params,
|
|
|
|
(void *)arg,
|
|
|
|
sizeof(JPEG_DEC_CONFIG_ROW))) {
|
|
|
|
JPEG_MSG("[JPGDRV]JPEG Dec:Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
JPEG_MSG("[JPGDRV]JPEG Decoder Resume, [%d] %x %x %x !!\n",
|
|
|
|
dec_row_params.pauseMCU - 1, dec_row_params.decRowBuf[0],
|
|
|
|
dec_row_params.decRowBuf[1], dec_row_params.decRowBuf[2]);
|
|
|
|
|
|
|
|
if (!jpeg_drv_dec_set_dst_bank0(dec_row_params.decRowBuf[0],
|
|
|
|
dec_row_params.decRowBuf[1],
|
|
|
|
dec_row_params.decRowBuf[2])) {
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
index = dec_row_params.pauseMCU - 1;
|
|
|
|
if (!jpeg_drv_dec_set_pause_mcu_idx(index))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
|
|
|
|
/* lock CPU to ensure irq is enabled after trigger HW */
|
|
|
|
spin_lock(&jpeg_dec_lock);
|
|
|
|
jpeg_drv_dec_resume(BIT_INQST_MASK_PAUSE);
|
|
|
|
spin_unlock(&jpeg_dec_lock);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_START: /* OT:OK */
|
|
|
|
if (*pStatus != JPEG_DEC_PROCESS) {
|
|
|
|
JPEG_WRN("This process can not access decoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (dec_status == 0 || dec_ready == 0) {
|
|
|
|
JPEG_WRN("Dec status is available,it can't HAPPEN");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
/*JPEG_MSG("[JPEGDRV][IOCTL] JPEG Decoder Start!!\n");*/
|
|
|
|
|
|
|
|
jpeg_drv_dec_start();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_WAIT:
|
|
|
|
if (*pStatus != JPEG_DEC_PROCESS) {
|
|
|
|
JPEG_WRN("This process can not access decoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (dec_status == 0 || dec_ready == 0) {
|
|
|
|
JPEG_WRN("Dec status is available,it can't HAPPEN ??");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (copy_from_user(&outParams,
|
|
|
|
(void *)arg,
|
|
|
|
sizeof(JPEG_DEC_DRV_OUT))) {
|
|
|
|
JPEG_WRN("JPEG Decoder : Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set timeout */
|
|
|
|
timeout_jiff = outParams.timeout * HZ / 1000;
|
|
|
|
#ifdef FPGA_VERSION
|
|
|
|
JPEG_MSG("[JPEGDRV]Polling JPEG Status");
|
|
|
|
|
|
|
|
do {
|
|
|
|
_jpeg_dec_int_status =
|
|
|
|
IMG_REG_READ(REG_ADDR_JPGDEC_STATUS);
|
|
|
|
} while (_jpeg_dec_int_status == 0);
|
|
|
|
#else
|
|
|
|
if (jpeg_isr_dec_lisr() < 0) {
|
|
|
|
long ret = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* JPEG_MSG("wait JPEG irq\n"); */
|
|
|
|
ret = wait_event_interruptible_timeout(
|
|
|
|
dec_wait_queue,
|
|
|
|
_jpeg_dec_int_status,
|
|
|
|
timeout_jiff);
|
|
|
|
if (ret == 0)
|
|
|
|
JPEG_MSG("[JPGDRV]Dec isr timeout\n");
|
|
|
|
} while (ret < 0);
|
|
|
|
} else
|
|
|
|
JPEG_MSG("[JPGDRV] JPG Dec IRQ Wait Already Done!!\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
decResult = jpeg_drv_dec_get_result();
|
|
|
|
|
|
|
|
if (decResult >= 2) {
|
|
|
|
JPEG_MSG("[JPEGDRV]Dec Result : %d, status %x!\n",
|
|
|
|
decResult,
|
|
|
|
_jpeg_dec_int_status);
|
|
|
|
|
|
|
|
jpeg_drv_dec_dump_key_reg();
|
|
|
|
|
|
|
|
#ifndef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
|
|
|
/* need to dump smi for the case that no irq coming from HW */
|
|
|
|
if (decResult == 5)
|
|
|
|
smi_debug_bus_hang_detect(0, "JPEG");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
jpeg_drv_dec_warm_reset();
|
|
|
|
}
|
|
|
|
irq_st = _jpeg_dec_int_status;
|
|
|
|
decResult = decResult | (irq_st << 8);
|
|
|
|
_jpeg_dec_int_status = 0;
|
|
|
|
if (copy_to_user(outParams.result,
|
|
|
|
&decResult,
|
|
|
|
sizeof(unsigned int))) {
|
|
|
|
JPEG_WRN("JPEG Dec: Copy to user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_BREAK:
|
|
|
|
if (jpeg_drv_dec_break() < 0)
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_DUMP_REG:
|
|
|
|
JPEG_MSG("[JPEGDRV][IOCTL] JPEG Decoder DUMP REGISTER !!\n");
|
|
|
|
jpeg_drv_dec_dump_reg();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_DEINIT:
|
|
|
|
/*JPEG_MSG("[JPEGDRV][IOCTL] JPEG Decoder Deinit !!\n");*/
|
|
|
|
/* copy input parameters */
|
|
|
|
if (*pStatus != JPEG_DEC_PROCESS) {
|
|
|
|
JPEG_ERR("This process can not access encoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dec_status == 0) {
|
|
|
|
JPEG_ERR("Enc status is available,can't HAPPEN");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
jpeg_drv_dec_deinit();
|
|
|
|
*pStatus = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
JPEG_ERR("JPEG DEC IOCTL NO THIS COMMAND\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* JPEG_DEC_DRIVER */
|
|
|
|
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
static int jpeg_enc_ioctl(unsigned int cmd, unsigned long arg,
|
|
|
|
struct file *file)
|
|
|
|
{
|
|
|
|
int retValue;
|
|
|
|
/* unsigned int decResult; */
|
|
|
|
|
|
|
|
long timeout_jiff;
|
|
|
|
unsigned int file_size, enc_result_code;
|
|
|
|
|
|
|
|
/* unsigned int _jpeg_enc_int_status; */
|
|
|
|
unsigned int jpeg_enc_wait_timeout = 0;
|
|
|
|
unsigned int cycle_count;
|
|
|
|
unsigned int ret;
|
|
|
|
/* No spec, considering [picture size] x [target fps] */
|
|
|
|
unsigned int cshot_spec = 0xffffffff;
|
|
|
|
/* limiting FPS, Upper Bound FPS = 20 */
|
|
|
|
unsigned int target_fps = 20;
|
|
|
|
|
|
|
|
unsigned int *pStatus;
|
|
|
|
|
|
|
|
/* Support QoS */
|
|
|
|
unsigned int emi_bw = 0;
|
|
|
|
unsigned int picSize = 0;
|
|
|
|
unsigned int picCost = 0;
|
|
|
|
|
|
|
|
/* JpegDrvEncParam cfgEnc; */
|
|
|
|
struct JPEG_ENC_DRV_IN cfgEnc;
|
|
|
|
|
|
|
|
struct JPEG_ENC_DRV_OUT enc_result;
|
|
|
|
|
|
|
|
pStatus = (unsigned int *)file->private_data;
|
|
|
|
|
|
|
|
if (pStatus == NULL) {
|
|
|
|
JPEG_WRN("Private data null in flush,can't HAPPEN ??\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case JPEG_ENC_IOCTL_RW_REG:
|
|
|
|
/* jpeg_drv_enc_rw_reg(); */
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* initial and reset JPEG encoder */
|
|
|
|
case JPEG_ENC_IOCTL_INIT:
|
|
|
|
/*JPEG_MSG("[JPEGDRV][IOCTL] JPEG Encoder Init!!\n");*/
|
|
|
|
|
|
|
|
retValue = jpeg_drv_enc_init();
|
|
|
|
|
|
|
|
if (retValue == 0)
|
|
|
|
*pStatus = JPEG_ENC_PROCESS;
|
|
|
|
|
|
|
|
return retValue;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_ENC_IOCTL_WARM_RESET:
|
|
|
|
if (*pStatus != JPEG_ENC_PROCESS) {
|
|
|
|
JPEG_WRN("Permission Denied!");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (enc_status == 0) {
|
|
|
|
JPEG_WRN("Encoder status is available");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
JPEG_MSG("[JPEGDRV][IOCTL] JPEG Encoder Warm Reset\n");
|
|
|
|
enc_result_code = jpeg_drv_enc_warm_reset();
|
|
|
|
if (enc_result_code == 0)
|
|
|
|
return -EFAULT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* configure the register */
|
|
|
|
case JPEG_ENC_IOCTL_CONFIG:
|
|
|
|
if (*pStatus != JPEG_ENC_PROCESS) {
|
|
|
|
JPEG_WRN("This process can not access encoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enc_status == 0) {
|
|
|
|
JPEG_WRN("Enc status is available,can't HAPPEN");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy input parameters */
|
|
|
|
if (copy_from_user(&cfgEnc, (void *)arg,
|
|
|
|
sizeof(struct JPEG_ENC_DRV_IN))) {
|
|
|
|
JPEG_MSG("[JPGDRV]Encoder : Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 0. reset */
|
|
|
|
jpeg_drv_enc_reset();
|
|
|
|
|
|
|
|
/* 1. set src config */
|
|
|
|
/* memset(&src_cfg, 0, sizeof(JpegDrvEncSrcCfg)); */
|
|
|
|
|
|
|
|
/* src_cfg.luma_addr = cfgEnc.srcBufferAddr; */
|
|
|
|
/* if (cfgEnc.encFormat == NV12 || cfgEnc.encFormat == NV21) */
|
|
|
|
/* { */
|
|
|
|
/* unsigned int srcChromaAddr = cfgEnc.srcChromaAddr; */
|
|
|
|
/* srcChromaAddr = TO_CEIL(srcChromaAddr, 128); */
|
|
|
|
/* //((srcChromaAddr+127)&~127); */
|
|
|
|
/* src_cfg.chroma_addr = srcChromaAddr; */
|
|
|
|
/* } */
|
|
|
|
/* */
|
|
|
|
/* src_cfg.width = cfgEnc.encWidth; */
|
|
|
|
/* src_cfg.height = cfgEnc.encHeight; */
|
|
|
|
/* src_cfg.yuv_format = cfgEnc.encFormat; */
|
|
|
|
|
|
|
|
/* Support QoS */
|
|
|
|
picSize = (cfgEnc.encWidth * cfgEnc.encHeight) / 1000000;
|
|
|
|
/* BW = encode width x height x bpp x 1.6 */
|
|
|
|
/* Assume compress ratio is 0.6 */
|
|
|
|
if (cfgEnc.encFormat == 0x0 || cfgEnc.encFormat == 0x1)
|
|
|
|
picCost = ((picSize * 2) * 8/5) + 1;
|
|
|
|
else
|
|
|
|
picCost = ((picSize * 3/2) * 8/5) + 1;
|
|
|
|
|
|
|
|
#ifdef QOS_MT6765_SUPPORT
|
|
|
|
/* on mt6765, 16MP = 14.5 FPS */
|
|
|
|
cshot_spec = 232;
|
|
|
|
#endif
|
|
|
|
#ifdef QOS_MT6761_SUPPORT
|
|
|
|
/* on mt6761, lpddr4: 26MP = 5 FPS , lpddr3: 26MP = 1 FPS*/
|
|
|
|
cshot_spec = 26;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ((picCost * target_fps) < cshot_spec) {
|
|
|
|
emi_bw = picCost * target_fps;
|
|
|
|
} else {
|
|
|
|
emi_bw = cshot_spec / picCost;
|
|
|
|
emi_bw = (emi_bw + 1) * picCost;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* QoS requires Occupied BW */
|
|
|
|
/* Data BW x 1.33 */
|
|
|
|
emi_bw = emi_bw * 4/3;
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLE_MMQOS
|
|
|
|
jpegenc_drv_enc_update_bw_request(cfgEnc);
|
|
|
|
#else
|
|
|
|
/* update BW request before trigger HW */
|
|
|
|
mtk_pm_qos_update_request(&jpgenc_qos_request, emi_bw);
|
|
|
|
#endif
|
|
|
|
/* 1. set src config */
|
|
|
|
JPEG_MSG("[JPEGDRV]SRC_IMG:%x %x, DU:%x, fmt:%x\n",
|
|
|
|
cfgEnc.encWidth, cfgEnc.encHeight,
|
|
|
|
cfgEnc.totalEncDU, cfgEnc.encFormat);
|
|
|
|
|
|
|
|
JPEG_MSG("[JPEGDRV]picSize:%d, BW:%d\n", picSize, emi_bw);
|
|
|
|
|
|
|
|
ret =
|
|
|
|
jpeg_drv_enc_set_src_image(cfgEnc.encWidth,
|
|
|
|
cfgEnc.encHeight,
|
|
|
|
cfgEnc.encFormat,
|
|
|
|
cfgEnc.totalEncDU);
|
|
|
|
if (ret == 0) {
|
|
|
|
JPEG_MSG("[JPGDRV]Enc set srouce image failed\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 2. set src buffer info */
|
|
|
|
JPEG_MSG("[JPEGDRV]SRC_BUF: addr %x, %x, stride %x, %x fd %d %d!!\n",
|
|
|
|
cfgEnc.srcBufferAddr,
|
|
|
|
cfgEnc.srcChromaAddr,
|
|
|
|
cfgEnc.imgStride,
|
|
|
|
cfgEnc.memStride,
|
|
|
|
cfgEnc.srcFd,
|
|
|
|
cfgEnc.srcFd2);
|
|
|
|
|
|
|
|
ret =
|
|
|
|
jpeg_drv_enc_set_src_buf(g_jpeg_ion_client,
|
|
|
|
cfgEnc.encFormat,
|
|
|
|
cfgEnc.imgStride,
|
|
|
|
cfgEnc.memStride,
|
|
|
|
cfgEnc.memHeight,
|
|
|
|
cfgEnc.srcFd,
|
|
|
|
cfgEnc.srcFd2);
|
|
|
|
if (ret == 0) {
|
|
|
|
JPEG_MSG("[JPGDRV]Enc set srouce buffer failed\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if (0 == jpeg_drv_enc_src_cfg(src_cfg)) */
|
|
|
|
/* { */
|
|
|
|
/* JPEG_MSG("JPEG Encoder src cfg failed\n"); */
|
|
|
|
/* return -EFAULT; */
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
/* 3. set dst buffer info */
|
|
|
|
JPEG_MSG("[JPGDRV]DST_BUF: addr:%x, size:%x, ofs:%x, mask:%x Fd 0x%x\n",
|
|
|
|
cfgEnc.dstBufferAddr,
|
|
|
|
cfgEnc.dstBufferSize,
|
|
|
|
cfgEnc.dstBufAddrOffset,
|
|
|
|
cfgEnc.dstBufAddrOffsetMask,
|
|
|
|
cfgEnc.dstFd);
|
|
|
|
|
|
|
|
|
|
|
|
ret =
|
|
|
|
jpeg_drv_enc_set_dst_buff(g_jpeg_ion_client,
|
|
|
|
cfgEnc.dstFd,
|
|
|
|
cfgEnc.dstBufferSize,
|
|
|
|
cfgEnc.dstBufAddrOffset,
|
|
|
|
cfgEnc.dstBufAddrOffsetMask);
|
|
|
|
if (ret == 0) {
|
|
|
|
JPEG_MSG("[JPGDRV]Enc set dst buffer failed\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 4 .set ctrl config */
|
|
|
|
JPEG_MSG("[JPEGDRV]ENC_CFG: exif:%d, q:%d, DRI:%d !!\n",
|
|
|
|
cfgEnc.enableEXIF,
|
|
|
|
cfgEnc.encQuality,
|
|
|
|
cfgEnc.restartInterval);
|
|
|
|
|
|
|
|
jpeg_drv_enc_ctrl_cfg(cfgEnc.enableEXIF,
|
|
|
|
cfgEnc.encQuality,
|
|
|
|
cfgEnc.restartInterval);
|
|
|
|
|
|
|
|
spin_lock(&jpeg_enc_lock);
|
|
|
|
enc_ready = 1;
|
|
|
|
spin_unlock(&jpeg_enc_lock);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_ENC_IOCTL_START:
|
|
|
|
/*JPEG_MSG("[JPEGDRV][IOCTL] JPEG Encoder Start!!\n");*/
|
|
|
|
if (*pStatus != JPEG_ENC_PROCESS) {
|
|
|
|
JPEG_WRN("This process can not access encoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enc_status == 0 || enc_ready == 0) {
|
|
|
|
JPEG_WRN("Enc status is unavailable,can't HAPPEN");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
jpeg_drv_enc_start();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_ENC_IOCTL_WAIT:
|
|
|
|
/*JPEG_MSG("[JPEGDRV][IOCTL] JPEG Encoder Wait!!\n");*/
|
|
|
|
if (*pStatus != JPEG_ENC_PROCESS) {
|
|
|
|
JPEG_WRN("This process can not access encoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enc_status == 0 || enc_ready == 0) {
|
|
|
|
JPEG_WRN("Enc status is unavailable, can't HAPPEN");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (copy_from_user(&enc_result,
|
|
|
|
(void *)arg,
|
|
|
|
sizeof(struct JPEG_ENC_DRV_OUT))) {
|
|
|
|
JPEG_WRN("JPEG Encoder : Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: ENC_DONE in REG_JPEG_ENC_INTERRUPT_STATUS*/
|
|
|
|
/*need to set to 0 after read. */
|
|
|
|
jpeg_enc_wait_timeout = 0xFFFFFF;
|
|
|
|
|
|
|
|
#ifdef FPGA_VERSION
|
|
|
|
do {
|
|
|
|
_jpeg_enc_int_status = IMG_REG_READ(
|
|
|
|
REG_ADDR_JPEG_ENC_INTERRUPT_STATUS);
|
|
|
|
jpeg_enc_wait_timeout--;
|
|
|
|
} while (_jpeg_enc_int_status == 0 &&
|
|
|
|
jpeg_enc_wait_timeout > 0);
|
|
|
|
|
|
|
|
if (jpeg_enc_wait_timeout == 0)
|
|
|
|
JPEG_MSG("JPEG Encoder timeout\n");
|
|
|
|
|
|
|
|
ret = jpeg_drv_enc_get_result(&file_size);
|
|
|
|
|
|
|
|
JPEG_MSG("Result : %d, Size : %u, address : 0x%x\n",
|
|
|
|
ret,
|
|
|
|
file_size,
|
|
|
|
ioread32(JPEG_ENC_BASE + 0x120));
|
|
|
|
|
|
|
|
if (_jpeg_enc_int_status != 1)
|
|
|
|
jpeg_drv_enc_dump_reg();
|
|
|
|
#else
|
|
|
|
/* set timeout */
|
|
|
|
timeout_jiff = enc_result.timeout * HZ / 1000;
|
|
|
|
JPEG_MSG("[JPEGDRV]JPEG Encoder Time Jiffies : %ld\n",
|
|
|
|
timeout_jiff);
|
|
|
|
|
|
|
|
if (jpeg_isr_enc_lisr() < 0) {
|
|
|
|
do {
|
|
|
|
ret = wait_event_interruptible_timeout(
|
|
|
|
enc_wait_queue,
|
|
|
|
_jpeg_enc_int_status,
|
|
|
|
timeout_jiff);
|
|
|
|
if (ret > 0)
|
|
|
|
JPEG_MSG("[JPGDRV]Enc Wait done\n");
|
|
|
|
else if (ret == 0)
|
|
|
|
JPEG_MSG("[JPGDRV]Enc Wait timeout\n");
|
|
|
|
} while (0);
|
|
|
|
} else
|
|
|
|
JPEG_MSG("[JPGDRV]Enc already done !!\n");
|
|
|
|
|
|
|
|
/* Support QoS: remove BW request after HW done */
|
|
|
|
mtk_pm_qos_update_request(&jpgenc_qos_request, 0);
|
|
|
|
|
|
|
|
ret = jpeg_drv_enc_get_result(&file_size);
|
|
|
|
|
|
|
|
JPEG_MSG("[JPEGDRV]Result : %d, Size : %u!!\n", ret, file_size);
|
|
|
|
if (ret != 0) {
|
|
|
|
jpeg_drv_enc_dump_reg();
|
|
|
|
|
|
|
|
#ifndef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
#ifdef CONFIG_MTK_SMI_EXT
|
|
|
|
/* need to dump smi for the case that no irq coming from HW */
|
|
|
|
if (ret == 3)
|
|
|
|
smi_debug_bus_hang_detect(0, "JPEG");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
jpeg_drv_enc_warm_reset();
|
|
|
|
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
cycle_count = jpeg_drv_enc_get_cycle_count();
|
|
|
|
|
|
|
|
if (copy_to_user(enc_result.fileSize,
|
|
|
|
&file_size,
|
|
|
|
sizeof(unsigned int))) {
|
|
|
|
JPEG_MSG("[JPGDRV]Enc:Copy to user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (copy_to_user(enc_result.result,
|
|
|
|
&ret,
|
|
|
|
sizeof(unsigned int))) {
|
|
|
|
JPEG_MSG("[JPGDRV]Enc:Copy to user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (copy_to_user(enc_result.cycleCount,
|
|
|
|
&cycle_count,
|
|
|
|
sizeof(unsigned int))) {
|
|
|
|
JPEG_MSG("[JPGDRV]Enc:Copy to user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_ENC_IOCTL_DEINIT:
|
|
|
|
/*JPEG_MSG("[JPEGDRV][IOCTL] JPEG Encoder Deinit!!\n");*/
|
|
|
|
/* copy input parameters */
|
|
|
|
if (*pStatus != JPEG_ENC_PROCESS) {
|
|
|
|
JPEG_WRN("This process can not access encoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enc_status == 0) {
|
|
|
|
JPEG_WRN("Enc status is available,can't HAPPEN");
|
|
|
|
*pStatus = 0;
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
jpeg_drv_enc_deinit();
|
|
|
|
*pStatus = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case JPEG_ENC_IOCTL_DUMP_REG:
|
|
|
|
jpeg_drv_enc_dump_reg();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
JPEG_MSG("[JPEGDRV]JPEG ENC IOCTL NO THIS COMMAND\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
static int jpeg_hybrid_dec_ioctl(unsigned int cmd, unsigned long arg,
|
|
|
|
struct file *file)
|
|
|
|
{
|
|
|
|
unsigned int *pStatus;
|
|
|
|
int hwid;
|
|
|
|
int index_buf_fd;
|
|
|
|
long timeout_jiff;
|
|
|
|
int progress_n_status;
|
|
|
|
|
|
|
|
struct JPEG_DEC_DRV_HYBRID_TASK taskParams;
|
|
|
|
struct JPEG_DEC_DRV_HYBRID_P_N_S pnsParmas;
|
|
|
|
|
|
|
|
pStatus = (unsigned int *)file->private_data;
|
|
|
|
|
|
|
|
if (pStatus == NULL) {
|
|
|
|
JPEG_LOG
|
|
|
|
(0, "Private data is null\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
switch (cmd) {
|
|
|
|
case JPEG_DEC_IOCTL_HYBRID_START:
|
|
|
|
JPEG_LOG(1, "JPEG DEC IOCTL HYBRID START\n");
|
|
|
|
if (copy_from_user(
|
|
|
|
&taskParams, (void *)arg,
|
|
|
|
sizeof(struct JPEG_DEC_DRV_HYBRID_TASK))) {
|
|
|
|
JPEG_LOG(0, "Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (taskParams.timeout != 3000) // JPEG oal magic number
|
|
|
|
return -EFAULT;
|
|
|
|
if (jpeg_drv_hybrid_dec_lock(&hwid) == 0) {
|
|
|
|
*pStatus = JPEG_DEC_PROCESS;
|
|
|
|
} else {
|
|
|
|
JPEG_LOG(0, "jpeg_drv_hybrid_dec_lock failed (hw busy)\n");
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
2024-04-28 06:51:13 -07:00
|
|
|
mutex_lock(&jpeg_hybrid_dec_lock);
|
2024-04-28 06:49:01 -07:00
|
|
|
if (jpeg_drv_hybrid_dec_start(taskParams.data, hwid, &index_buf_fd) == 0) {
|
|
|
|
JPEG_LOG(1, "jpeg_drv_hybrid_dec_start success %u index buffer fd:%d\n",
|
|
|
|
hwid, index_buf_fd);
|
|
|
|
if (copy_to_user(
|
|
|
|
taskParams.hwid, &hwid, sizeof(int))) {
|
|
|
|
JPEG_LOG(0, "Copy to user error\n");
|
2024-04-28 06:51:13 -07:00
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
2024-04-28 06:49:01 -07:00
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (copy_to_user(
|
|
|
|
taskParams.index_buf_fd, &index_buf_fd, sizeof(int))) {
|
|
|
|
JPEG_LOG(0, "Copy to user error\n");
|
2024-04-28 06:51:13 -07:00
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
2024-04-28 06:49:01 -07:00
|
|
|
return -EFAULT;
|
|
|
|
}
|
2024-04-28 06:51:13 -07:00
|
|
|
gJpegqDev.is_dec_started[hwid] = true;
|
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
2024-04-28 06:49:01 -07:00
|
|
|
} else {
|
|
|
|
JPEG_LOG(0, "jpeg_drv_dec_hybrid_start failed\n");
|
2024-04-28 06:51:13 -07:00
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
2024-04-28 06:49:01 -07:00
|
|
|
jpeg_drv_hybrid_dec_unlock(hwid);
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case JPEG_DEC_IOCTL_HYBRID_WAIT:
|
|
|
|
JPEG_LOG(1, "JPEG DEC IOCTL HYBRID WAIT\n");
|
|
|
|
|
|
|
|
if (*pStatus != JPEG_DEC_PROCESS) {
|
|
|
|
JPEG_LOG(0,
|
|
|
|
"Permission Denied! This process cannot access decoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copy_from_user(
|
|
|
|
&pnsParmas, (void *)arg,
|
|
|
|
sizeof(struct JPEG_DEC_DRV_HYBRID_P_N_S))) {
|
|
|
|
JPEG_LOG(0, "Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set timeout */
|
|
|
|
timeout_jiff = msecs_to_jiffies(3000);
|
|
|
|
JPEG_LOG(1, "JPEG Hybrid Decoder Wait Resume Time: %ld\n",
|
|
|
|
timeout_jiff);
|
|
|
|
hwid = pnsParmas.hwid;
|
2024-04-28 06:51:13 -07:00
|
|
|
if (hwid < 0 || hwid >= HW_CORE_NUMBER) {
|
2024-04-28 06:49:01 -07:00
|
|
|
JPEG_LOG(0, "get hybrid dec id failed\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
2024-04-28 06:51:13 -07:00
|
|
|
mutex_lock(&jpeg_hybrid_dec_lock);
|
|
|
|
if (!gJpegqDev.is_dec_started[hwid]) {
|
|
|
|
JPEG_LOG(0, "Wait before decode get started");
|
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
mutex_unlock(&jpeg_hybrid_dec_lock);
|
2024-04-28 06:49:01 -07:00
|
|
|
#ifdef FPGA_VERSION
|
|
|
|
JPEG_LOG(1, "Polling JPEG Hybrid Dec Status hwpa: 0x%x\n",
|
|
|
|
hwpa);
|
|
|
|
|
|
|
|
do {
|
|
|
|
_jpeg_hybrid_dec_int_status[hwid] =
|
|
|
|
IMG_REG_READ(REG_JPGDEC_HYBRID_INT_STATUS(hwid));
|
|
|
|
JPEG_LOG(1, "Hybrid Polling status %d\n",
|
|
|
|
_jpeg_hybrid_dec_int_status[hwid]);
|
|
|
|
} while (_jpeg_hybrid_dec_int_status[hwid] == 0);
|
|
|
|
|
|
|
|
#else
|
|
|
|
if (jpeg_isr_hybrid_dec_lisr(hwid) < 0) {
|
|
|
|
long ret = 0;
|
|
|
|
int waitfailcnt = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = wait_event_interruptible_timeout(
|
|
|
|
hybrid_dec_wait_queue[hwid],
|
|
|
|
_jpeg_hybrid_dec_int_status[hwid],
|
|
|
|
timeout_jiff);
|
|
|
|
if (ret == 0)
|
|
|
|
JPEG_LOG(0,
|
|
|
|
"JPEG Hybrid Dec Wait timeout!\n");
|
|
|
|
if (ret < 0) {
|
|
|
|
waitfailcnt++;
|
|
|
|
JPEG_LOG(0,
|
|
|
|
"JPEG Hybrid Dec Wait Error %d",
|
|
|
|
waitfailcnt);
|
|
|
|
}
|
|
|
|
} while (ret < 0 && waitfailcnt < 5);
|
|
|
|
} else
|
|
|
|
JPEG_LOG(1, "JPEG Hybrid Dec IRQ Wait Already Done!\n");
|
|
|
|
_jpeg_hybrid_dec_int_status[hwid] = 0;
|
|
|
|
#endif
|
|
|
|
progress_n_status = jpeg_drv_hybrid_dec_get_status(hwid);
|
|
|
|
JPEG_LOG(1, "jpeg_drv_hybrid_dec_get_status %d\n", progress_n_status);
|
|
|
|
|
|
|
|
if (copy_to_user(
|
|
|
|
pnsParmas.progress_n_status, &progress_n_status, sizeof(int))) {
|
|
|
|
JPEG_LOG(0, "Copy to user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMG_REG_WRITE(0x0, REG_JPGDEC_HYBRID_090(hwid));
|
|
|
|
IMG_REG_WRITE(0x00000010, REG_JPGDEC_HYBRID_090(hwid));
|
|
|
|
|
|
|
|
jpeg_drv_hybrid_dec_unlock(hwid);
|
|
|
|
break;
|
|
|
|
case JPEG_DEC_IOCTL_HYBRID_GET_PROGRESS_STATUS:
|
|
|
|
JPEG_LOG(1, "JPEG DEC IOCTL HYBRID GET PROGRESS N STATUS\n");
|
|
|
|
|
|
|
|
if (*pStatus != JPEG_DEC_PROCESS) {
|
|
|
|
JPEG_LOG(0,
|
|
|
|
"Permission Denied! This process cannot access decoder");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copy_from_user(
|
|
|
|
&pnsParmas, (void *)arg,
|
|
|
|
sizeof(struct JPEG_DEC_DRV_HYBRID_P_N_S))) {
|
|
|
|
JPEG_LOG(0, "JPEG Decoder : Copy from user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
hwid = pnsParmas.hwid;
|
2024-04-28 06:51:13 -07:00
|
|
|
if (hwid < 0 || hwid >= HW_CORE_NUMBER) {
|
|
|
|
JPEG_LOG(0, "get P_N_S hwid invalid");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
2024-04-28 06:49:01 -07:00
|
|
|
progress_n_status = jpeg_drv_hybrid_dec_get_status(hwid);
|
|
|
|
|
|
|
|
if (copy_to_user(
|
|
|
|
pnsParmas.progress_n_status, &progress_n_status, sizeof(int))) {
|
|
|
|
JPEG_LOG(0, "JPEG Decoder: Copy to user error\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
JPEG_LOG(0, "JPEG DEC IOCTL NO THIS COMMAND\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* JPEG_HYBRID_DEC_DRIVER */
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/* */
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
static int compat_get_jpeg_hybrid_task_data(
|
|
|
|
struct compat_JPEG_DEC_DRV_HYBRID_TASK __user *data32,
|
|
|
|
struct JPEG_DEC_DRV_HYBRID_TASK __user *data)
|
|
|
|
{
|
|
|
|
compat_long_t timeout;
|
|
|
|
compat_uptr_t hwid;
|
|
|
|
compat_uptr_t index_buf_fd;
|
|
|
|
int err, i;
|
|
|
|
unsigned int temp;
|
|
|
|
|
|
|
|
err = get_user(timeout, &data32->timeout);
|
|
|
|
err |= put_user(timeout, &data->timeout);
|
|
|
|
err |= get_user(hwid, &data32->hwid);
|
|
|
|
err |= put_user(compat_ptr(hwid), &data->hwid);
|
|
|
|
err |= get_user(index_buf_fd, &data32->index_buf_fd);
|
|
|
|
err |= put_user(compat_ptr(index_buf_fd), &data->index_buf_fd);
|
|
|
|
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
|
|
err |= get_user(temp, &data32->data[i]);
|
|
|
|
err |= put_user(temp, &data->data[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_get_jpeg_hybrid_pns_data(
|
|
|
|
struct compat_JPEG_DEC_DRV_HYBRID_P_N_S __user *data32,
|
|
|
|
struct JPEG_DEC_DRV_HYBRID_P_N_S __user *data)
|
|
|
|
{
|
|
|
|
int hwid;
|
|
|
|
compat_uptr_t progress_n_status;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(hwid, &data32->hwid);
|
|
|
|
err |= put_user(hwid, &data->hwid);
|
|
|
|
err |= get_user(progress_n_status, &data32->progress_n_status);
|
|
|
|
err |= put_user(compat_ptr(progress_n_status), &data->progress_n_status);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_get_jpeg_dec_ioctl_wait_data(
|
|
|
|
struct compat_JPEG_DEC_DRV_OUT __user *data32,
|
|
|
|
struct JPEG_DEC_DRV_OUT __user *data)
|
|
|
|
{
|
|
|
|
compat_long_t timeout;
|
|
|
|
compat_uptr_t result;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(timeout, &data32->timeout);
|
|
|
|
err |= put_user(timeout, &data->timeout);
|
|
|
|
err |= get_user(result, &data32->result);
|
|
|
|
err |= put_user(compat_ptr(result), &data->result);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_put_jpeg_dec_ioctl_wait_data(
|
|
|
|
struct compat_JPEG_DEC_DRV_OUT __user *data32,
|
|
|
|
struct JPEG_DEC_DRV_OUT __user *data)
|
|
|
|
{
|
|
|
|
compat_long_t timeout;
|
|
|
|
/* compat_uptr_t result; */
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(timeout, &data->timeout);
|
|
|
|
err |= put_user(timeout, &data32->timeout);
|
|
|
|
/* err |= get_user(result, &data->result); */
|
|
|
|
/* err |= put_user(result, &data32->result); */
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_get_jpeg_dec_ioctl_chksum_data(
|
|
|
|
struct compat_JpegDrvDecResult __user *data32,
|
|
|
|
struct JpegDrvDecResult __user *data)
|
|
|
|
{
|
|
|
|
compat_uptr_t pChksum;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(pChksum, &data32->pChksum);
|
|
|
|
err |= put_user(compat_ptr(pChksum), &data->pChksum);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_put_jpeg_dec_ioctl_chksum_data(
|
|
|
|
struct compat_JpegDrvDecResult __user *data32,
|
|
|
|
struct JpegDrvDecResult __user *data)
|
|
|
|
{
|
|
|
|
/* compat_uptr_t pChksum; */
|
|
|
|
/* int err; */
|
|
|
|
|
|
|
|
/* err = get_user(pChksum, &data->pChksum); */
|
|
|
|
/* err |= put_user(pChksum, &data32->pChksum); */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_get_jpeg_enc_ioctl_wait_data(
|
|
|
|
struct compat_JPEG_ENC_DRV_OUT __user *data32,
|
|
|
|
struct JPEG_ENC_DRV_OUT __user *data)
|
|
|
|
{
|
|
|
|
compat_long_t timeout;
|
|
|
|
compat_uptr_t fileSize;
|
|
|
|
compat_uptr_t result;
|
|
|
|
compat_uptr_t cycleCount;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(timeout, &data32->timeout);
|
|
|
|
err |= put_user(timeout, &data->timeout);
|
|
|
|
err |= get_user(fileSize, &data32->fileSize);
|
|
|
|
err |= put_user(compat_ptr(fileSize), &data->fileSize);
|
|
|
|
err |= get_user(result, &data32->result);
|
|
|
|
err |= put_user(compat_ptr(result), &data->result);
|
|
|
|
err |= get_user(cycleCount, &data32->cycleCount);
|
|
|
|
err |= put_user(compat_ptr(cycleCount), &data->cycleCount);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compat_put_jpeg_enc_ioctl_wait_data(
|
|
|
|
struct compat_JPEG_ENC_DRV_OUT __user *data32,
|
|
|
|
struct JPEG_ENC_DRV_OUT __user *data)
|
|
|
|
{
|
|
|
|
compat_long_t timeout;
|
|
|
|
/* compat_uptr_t fileSize; */
|
|
|
|
/* compat_uptr_t result; */
|
|
|
|
/* compat_uptr_t cycleCount; */
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = get_user(timeout, &data->timeout);
|
|
|
|
err |= put_user(timeout, &data32->timeout);
|
|
|
|
/* err |= get_user(fileSize, &data->fileSize); */
|
|
|
|
/* err |= put_user(fileSize, &data32->fileSize); */
|
|
|
|
/* err |= get_user(result, &data->result); */
|
|
|
|
/* err |= put_user(result, &data32->result); */
|
|
|
|
/* err |= get_user(cycleCount, &data->cycleCount); */
|
|
|
|
/* err |= put_user(cycleCount, &data32->cycleCount); */
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static long compat_jpeg_ioctl(
|
|
|
|
struct file *filp,
|
|
|
|
unsigned int cmd,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
long ret;
|
|
|
|
|
|
|
|
if (!filp->f_op || !filp->f_op->unlocked_ioctl)
|
|
|
|
return -ENOTTY;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case COMPAT_JPEG_DEC_IOCTL_WAIT:
|
|
|
|
{
|
|
|
|
struct compat_JPEG_DEC_DRV_OUT __user *data32;
|
|
|
|
struct JPEG_DEC_DRV_OUT __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
err = compat_get_jpeg_dec_ioctl_wait_data(data32, data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
ret =
|
|
|
|
filp->f_op->unlocked_ioctl(filp, JPEG_DEC_IOCTL_WAIT,
|
|
|
|
(unsigned long)data);
|
|
|
|
err = compat_put_jpeg_dec_ioctl_wait_data(data32, data);
|
|
|
|
return ret ? ret : err;
|
|
|
|
} case COMPAT_JPEG_DEC_IOCTL_CHKSUM: {
|
|
|
|
struct compat_JpegDrvDecResult __user *data32;
|
|
|
|
struct JpegDrvDecResult __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
err = compat_get_jpeg_dec_ioctl_chksum_data(
|
|
|
|
data32,
|
|
|
|
data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
ret =
|
|
|
|
filp->f_op->unlocked_ioctl(filp,
|
|
|
|
JPEG_DEC_IOCTL_CHKSUM,
|
|
|
|
(unsigned long)data);
|
|
|
|
err = compat_put_jpeg_dec_ioctl_chksum_data(
|
|
|
|
data32,
|
|
|
|
data);
|
|
|
|
return ret ? ret : err;
|
|
|
|
}
|
|
|
|
case COMPAT_JPEG_ENC_IOCTL_WAIT:
|
|
|
|
{
|
|
|
|
struct compat_JPEG_ENC_DRV_OUT __user *data32;
|
|
|
|
struct JPEG_ENC_DRV_OUT __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
err = compat_get_jpeg_enc_ioctl_wait_data(data32, data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
ret =
|
|
|
|
filp->f_op->unlocked_ioctl(
|
|
|
|
filp,
|
|
|
|
JPEG_ENC_IOCTL_WAIT,
|
|
|
|
(unsigned long)data);
|
|
|
|
err = compat_put_jpeg_enc_ioctl_wait_data(data32, data);
|
|
|
|
return ret ? ret : err;
|
|
|
|
}
|
|
|
|
case JPEG_DEC_IOCTL_INIT:
|
|
|
|
case JPEG_DEC_IOCTL_START:
|
|
|
|
case JPEG_DEC_IOCTL_DEINIT:
|
|
|
|
case JPEG_DEC_IOCTL_DUMP_REG:
|
|
|
|
case JPEG_ENC_IOCTL_INIT:
|
|
|
|
case JPEG_ENC_IOCTL_DEINIT:
|
|
|
|
case JPEG_ENC_IOCTL_START:
|
|
|
|
return filp->f_op->unlocked_ioctl(filp, cmd, arg);
|
|
|
|
|
|
|
|
case JPEG_DEC_IOCTL_CONFIG:
|
|
|
|
case JPEG_DEC_IOCTL_RESUME:
|
|
|
|
case JPEG_DEC_IOCTL_FLUSH_CMDQ:
|
|
|
|
case JPEG_ENC_IOCTL_CONFIG:
|
|
|
|
return filp->f_op->unlocked_ioctl(
|
|
|
|
filp, cmd,
|
|
|
|
(unsigned long)compat_ptr(arg));
|
|
|
|
case COMPAT_JPEG_DEC_IOCTL_HYBRID_START:
|
|
|
|
{
|
|
|
|
struct compat_JPEG_DEC_DRV_HYBRID_TASK __user *data32;
|
|
|
|
struct JPEG_DEC_DRV_HYBRID_TASK __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
JPEG_LOG(1, "COMPAT_JPEG_DEC_IOCTL_HYBRID_START\n");
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return -EFAULT;
|
|
|
|
err = compat_get_jpeg_hybrid_task_data(data32, data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
ret =
|
|
|
|
filp->f_op->unlocked_ioctl(filp, JPEG_DEC_IOCTL_HYBRID_START,
|
|
|
|
(unsigned long)data);
|
|
|
|
return ret ? ret : err;
|
|
|
|
}
|
|
|
|
case COMPAT_JPEG_DEC_IOCTL_HYBRID_WAIT:
|
|
|
|
{
|
|
|
|
struct compat_JPEG_DEC_DRV_HYBRID_P_N_S __user *data32;
|
|
|
|
struct JPEG_DEC_DRV_HYBRID_P_N_S __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
JPEG_MSG("COMPAT_JPEG_DEC_IOCTL_HYBRID_WAIT\n");
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return -EFAULT;
|
|
|
|
err = compat_get_jpeg_hybrid_pns_data(data32, data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
ret =
|
|
|
|
filp->f_op->unlocked_ioctl(
|
|
|
|
filp, JPEG_DEC_IOCTL_HYBRID_WAIT,
|
|
|
|
(unsigned long)data);
|
|
|
|
return ret ? ret : err;
|
|
|
|
}
|
|
|
|
case COMPAT_JPEG_DEC_IOCTL_HYBRID_GET_PROGRESS_STATUS:
|
|
|
|
{
|
|
|
|
struct compat_JPEG_DEC_DRV_HYBRID_P_N_S __user *data32;
|
|
|
|
struct JPEG_DEC_DRV_HYBRID_P_N_S __user *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
JPEG_MSG("COMPAT_JPEG_DEC_IOCTL_HYBRID_GET_PROGRESS_STATUS\n");
|
|
|
|
data32 = compat_ptr(arg);
|
|
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
|
|
if (data == NULL)
|
|
|
|
return -EFAULT;
|
|
|
|
err = compat_get_jpeg_hybrid_pns_data(data32, data);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
ret =
|
|
|
|
filp->f_op->unlocked_ioctl(filp, JPEG_DEC_IOCTL_HYBRID_GET_PROGRESS_STATUS,
|
|
|
|
(unsigned long)data);
|
|
|
|
return ret ? ret : err;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return -ENOIOCTLCMD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static long jpeg_unlocked_ioctl(
|
|
|
|
struct file *file,
|
|
|
|
unsigned int cmd,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
case JPEG_DEC_IOCTL_INIT:
|
|
|
|
case JPEG_DEC_IOCTL_CONFIG:
|
|
|
|
case JPEG_DEC_IOCTL_START:
|
|
|
|
case JPEG_DEC_IOCTL_RESUME:
|
|
|
|
case JPEG_DEC_IOCTL_WAIT:
|
|
|
|
case JPEG_DEC_IOCTL_DEINIT:
|
|
|
|
case JPEG_DEC_IOCTL_DUMP_REG:
|
|
|
|
case JPEG_DEC_IOCTL_FLUSH_CMDQ:
|
|
|
|
return jpeg_dec_ioctl(cmd, arg, file);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
case JPEG_DEC_IOCTL_HYBRID_START:
|
|
|
|
case JPEG_DEC_IOCTL_HYBRID_WAIT:
|
|
|
|
case JPEG_DEC_IOCTL_HYBRID_GET_PROGRESS_STATUS:
|
|
|
|
return jpeg_hybrid_dec_ioctl(cmd, arg, file);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
case JPEG_ENC_IOCTL_INIT:
|
|
|
|
case JPEG_ENC_IOCTL_CONFIG:
|
|
|
|
case JPEG_ENC_IOCTL_WAIT:
|
|
|
|
case JPEG_ENC_IOCTL_DEINIT:
|
|
|
|
case JPEG_ENC_IOCTL_START:
|
|
|
|
return jpeg_enc_ioctl(cmd, arg, file);
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
unsigned int *pStatus;
|
|
|
|
|
|
|
|
mutex_lock(&DriverOpenCountLock);
|
|
|
|
Driver_Open_Count++;
|
|
|
|
mutex_unlock(&DriverOpenCountLock);
|
|
|
|
|
|
|
|
/* Allocate and initialize private data */
|
|
|
|
file->private_data = kmalloc(sizeof(unsigned int), GFP_ATOMIC);
|
|
|
|
|
|
|
|
if (file->private_data == NULL) {
|
|
|
|
JPEG_WRN("Not enough entry for JPEG open operation\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
pStatus = (unsigned int *)file->private_data;
|
|
|
|
*pStatus = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t jpeg_read(
|
|
|
|
struct file *file,
|
|
|
|
char __user *data,
|
|
|
|
size_t len, loff_t *ppos)
|
|
|
|
{
|
|
|
|
JPEG_MSG("jpeg driver read\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_release(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
mutex_lock(&DriverOpenCountLock);
|
|
|
|
Driver_Open_Count--;
|
|
|
|
if (Driver_Open_Count == 0) {
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
if (enc_status != 0) {
|
|
|
|
JPEG_WRN("Enable error handle for enc");
|
|
|
|
jpeg_drv_enc_deinit();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
if (dec_status != 0) {
|
|
|
|
JPEG_WRN("Enable error handle for dec");
|
|
|
|
jpeg_drv_dec_deinit();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
mutex_unlock(&DriverOpenCountLock);
|
|
|
|
|
|
|
|
|
|
|
|
if (file->private_data != NULL) {
|
|
|
|
kfree(file->private_data);
|
|
|
|
file->private_data = NULL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_flush(struct file *a_pstFile, fl_owner_t a_id)
|
|
|
|
{
|
|
|
|
unsigned int *pStatus;
|
|
|
|
|
|
|
|
pStatus = (unsigned int *)a_pstFile->private_data;
|
|
|
|
|
|
|
|
if (pStatus == NULL) {
|
|
|
|
JPEG_WRN("Private data null in flush, can't HAPPEN\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
if (*pStatus == JPEG_ENC_PROCESS) {
|
|
|
|
if (enc_status != 0) {
|
|
|
|
JPEG_WRN("Enable error handle for enc");
|
|
|
|
jpeg_drv_enc_deinit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
else if (*pStatus == JPEG_DEC_PROCESS) {
|
|
|
|
if (dec_status != 0) {
|
|
|
|
JPEG_WRN("Enable error handle for dec");
|
|
|
|
jpeg_drv_dec_deinit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Kernel interface */
|
|
|
|
static struct file_operations const jpeg_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
/* .ioctl = jpeg_ioctl, */
|
|
|
|
.unlocked_ioctl = jpeg_unlocked_ioctl,
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
.compat_ioctl = compat_jpeg_ioctl,
|
|
|
|
#endif
|
|
|
|
.open = jpeg_open,
|
|
|
|
.release = jpeg_release,
|
|
|
|
.flush = jpeg_flush,
|
|
|
|
.read = jpeg_read,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const long jpeg_dev_get_encoder_base_VA(void)
|
|
|
|
{
|
|
|
|
return gJpegqDev.encRegBaseVA;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const long jpeg_dev_get_decoder_base_VA(void)
|
|
|
|
{
|
|
|
|
return gJpegqDev.decRegBaseVA;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
const long jpeg_dev_get_hybrid_decoder_base_VA(int id)
|
|
|
|
{
|
|
|
|
return gJpegqDev.hybriddecRegBaseVA[id];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int jpeg_probe(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_OF
|
|
|
|
int new_count;
|
|
|
|
struct JpegDeviceStruct *jpegDev;
|
|
|
|
struct device_node *node = NULL;
|
|
|
|
void *tmpPtr;
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
int i;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
new_count = nrJpegDevs + 1;
|
|
|
|
tmpPtr = krealloc(gJpegqDevs,
|
|
|
|
sizeof(struct JpegDeviceStruct) * new_count,
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!tmpPtr) {
|
|
|
|
JPEG_ERR("Unable to allocate JpegDeviceStruct\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
gJpegqDevs = (struct JpegDeviceStruct *)tmpPtr;
|
|
|
|
|
|
|
|
jpegDev = &(gJpegqDevs[nrJpegDevs]);
|
|
|
|
jpegDev->pDev = &pdev->dev;
|
|
|
|
memset(&gJpegqDev, 0x0, sizeof(struct JpegDeviceStruct));
|
|
|
|
|
|
|
|
node = pdev->dev.of_node;
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
jpegDev->encRegBaseVA = (unsigned long)of_iomap(node, 0);
|
|
|
|
jpegDev->encIrqId = irq_of_parse_and_map(node, 0);
|
|
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
|
|
#else
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
pjenc_dev = pdev;
|
|
|
|
#else
|
|
|
|
#ifndef CONFIG_MTK_SMI_EXT
|
|
|
|
/* venc-mtcmos lead to disp */
|
|
|
|
/* power scpsys SCP_SYS_DISP */
|
|
|
|
gJpegClk.clk_scp_sys_mm0 =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_SCP_SYS_MM0");
|
|
|
|
if (IS_ERR(gJpegClk.clk_scp_sys_mm0))
|
|
|
|
JPEG_ERR("get MT_CG_SCP_SYS_MM0 err");
|
|
|
|
/* venc-mtcmos lead to venc */
|
|
|
|
/* power scpsys SCP_SYS_VEN */
|
|
|
|
gJpegClk.clk_scp_sys_ven =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_SCP_SYS_VEN");
|
|
|
|
if (IS_ERR(gJpegClk.clk_scp_sys_ven))
|
|
|
|
JPEG_ERR("get MT_CG_SCP_SYS_VEN err");
|
|
|
|
|
|
|
|
gJpegClk.clk_smi_common =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_SMI_COMMON");
|
|
|
|
if (IS_ERR(gJpegClk.clk_smi_common))
|
|
|
|
JPEG_ERR("get MT_CG_SMI_COMMON err");
|
|
|
|
gJpegClk.clk_venc_larb =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_VENC_LARB");
|
|
|
|
if (IS_ERR(gJpegClk.clk_venc_larb))
|
|
|
|
JPEG_ERR("get MT_CG_VENC_LARB err");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
gJpegClk.clk_venc_jpgEnc =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_VENC_JPGENC");
|
|
|
|
if (IS_ERR(gJpegClk.clk_venc_jpgEnc))
|
|
|
|
JPEG_ERR("get MT_CG_VENC_JPGENC clk error!");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
node = of_find_compatible_node(NULL, NULL, "mediatek,jpgdec");
|
|
|
|
for (i = 0; i < HW_CORE_NUMBER; i++) {
|
|
|
|
jpegDev->hybriddecRegBaseVA[i] =
|
|
|
|
(unsigned long)of_iomap(node, i);
|
|
|
|
jpegDev->hybriddecIrqId[i] = irq_of_parse_and_map(node, i);
|
|
|
|
JPEG_ERR("Jpeg Hybrid Dec Probe %d base va 0x%x irqid %d",
|
|
|
|
i, jpegDev->hybriddecRegBaseVA[i],
|
|
|
|
jpegDev->hybriddecIrqId[i]);
|
|
|
|
}
|
|
|
|
jpeg_drv_hybrid_dec_prepare_dvfs();
|
|
|
|
JPEG_MSG("get JPGDEC clk!");
|
|
|
|
gJpegClk.clk_venc_jpgDec =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_VENC_JPGDEC");
|
|
|
|
if (IS_ERR(gJpegClk.clk_venc_jpgDec))
|
|
|
|
JPEG_ERR("get MT_CG_VENC_JPGDEC clk error!");
|
|
|
|
gJpegClk.clk_venc_jpgDec_c1 =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_VENC_JPGDEC_C1");
|
|
|
|
if (IS_ERR(gJpegClk.clk_venc_jpgDec_c1))
|
|
|
|
JPEG_ERR("get MT_CG_VENC_JPGDEC_C1 clk error!");
|
|
|
|
gJpegClk.clk_venc_c1_jpgDec =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_VENC_C1_JPGDEC");
|
|
|
|
if (IS_ERR(gJpegClk.clk_venc_c1_jpgDec))
|
|
|
|
JPEG_ERR("get MT_CG_VENC_C1_JPGDEC clk error!");
|
|
|
|
JPEG_MSG("get JPGDEC clk done!");
|
|
|
|
jpegDev->pm_notifier.notifier_call = jpeg_drv_hybrid_dec_suspend_notifier;
|
|
|
|
register_pm_notifier(&jpegDev->pm_notifier);
|
|
|
|
jpegDev->is_suspending = 0;
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
jpegDev->decRegBaseVA = (unsigned long)of_iomap(node, 1);
|
|
|
|
jpegDev->decIrqId = irq_of_parse_and_map(node, 1);
|
|
|
|
#ifdef CONFIG_MTK_CLKMGR
|
|
|
|
#else
|
|
|
|
gJpegClk.clk_venc_jpgDec =
|
|
|
|
of_clk_get_by_name(node, "MT_CG_VENC_JPGDEC");
|
|
|
|
if (IS_ERR(gJpegClk.clk_venc_jpgDec))
|
|
|
|
JPEG_ERR("get MT_CG_VENC_JPGDEC err");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
#if ENABLE_MMQOS
|
|
|
|
if (of_property_read_u32(node, "cshot-spec", &cshot_spec_dts)) {
|
|
|
|
JPEG_ERR("cshot spec read failed\n");
|
|
|
|
JPEG_ERR("init cshot spec as 0xFFFFFFFF\n");
|
|
|
|
cshot_spec_dts = 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
gJpegqDev = *jpegDev;
|
|
|
|
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
/* Support QoS */
|
|
|
|
mtk_pm_qos_add_request(&jpgenc_qos_request,
|
|
|
|
MTK_PM_QOS_MEMORY_BANDWIDTH,
|
|
|
|
MTK_PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#else
|
|
|
|
gJpegqDev.encRegBaseVA = (0L | 0xF7003000);
|
|
|
|
gJpegqDev.decRegBaseVA = (0L | 0xF7004000);
|
|
|
|
gJpegqDev.encIrqId = JPGENC_IRQ_BIT_ID;
|
|
|
|
gJpegqDev.decIrqId = JPGDEC_IRQ_BIT_ID;
|
|
|
|
|
|
|
|
gJpegqDev.pDev = &pdev->dev;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
{
|
|
|
|
#ifdef JPEG_DEV
|
|
|
|
int ret;
|
|
|
|
struct class_device *class_dev = NULL;
|
|
|
|
|
|
|
|
JPEG_MSG("-------------jpeg driver probe-------\n");
|
|
|
|
ret = alloc_chrdev_region(&jenc_devno, 0, 1, JPEG_DEVNAME);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
JPEG_ERR("Can't Get Major number for JPEG Device\n");
|
|
|
|
else
|
|
|
|
JPEG_MSG("Get JPEG Device Major number (%d)\n", jenc_devno);
|
|
|
|
|
|
|
|
jenc_cdev = cdev_alloc();
|
|
|
|
jenc_cdev->owner = THIS_MODULE;
|
|
|
|
jenc_cdev->ops = &jpeg_fops;
|
|
|
|
|
|
|
|
ret = cdev_add(jenc_cdev, jenc_devno, 1);
|
|
|
|
|
|
|
|
jenc_class = class_create(THIS_MODULE, JPEG_DEVNAME);
|
|
|
|
class_dev =
|
|
|
|
(struct class_device *)device_create(jenc_class,
|
|
|
|
NULL, jenc_devno, NULL, JPEG_DEVNAME);
|
|
|
|
#else
|
|
|
|
proc_create("mtk_jpeg", 0x644, NULL, &jpeg_fops);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
spin_lock_init(&jpeg_enc_lock);
|
|
|
|
|
|
|
|
/* initial codec, register codec ISR */
|
|
|
|
enc_status = 0;
|
|
|
|
_jpeg_enc_int_status = 0;
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
spin_lock_init(&jpeg_dec_lock);
|
|
|
|
|
|
|
|
dec_status = 0;
|
|
|
|
_jpeg_dec_int_status = 0;
|
|
|
|
_jpeg_dec_mode = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef FPGA_VERSION
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
init_waitqueue_head(&dec_wait_queue);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
init_waitqueue_head(&enc_wait_queue);
|
|
|
|
|
|
|
|
/* mt6575_irq_unmask(MT6575_JPEG_CODEC_IRQ_ID); */
|
|
|
|
JPEG_MSG("request JPEG Encoder IRQ\n");
|
|
|
|
if (request_irq(gJpegqDev.encIrqId,
|
|
|
|
jpeg_drv_enc_isr, IRQF_TRIGGER_LOW,
|
|
|
|
"jpeg_enc_driver", NULL))
|
|
|
|
JPEG_ERR("JPEG ENC Driver request irq failed\n");
|
|
|
|
disable_irq(gJpegqDev.encIrqId);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
enable_irq(gJpegqDev.decIrqId);
|
|
|
|
JPEG_MSG("request JPEG Decoder IRQ\n");
|
|
|
|
if (request_irq(gJpegqDev.decIrqId,
|
|
|
|
jpeg_drv_dec_isr, IRQF_TRIGGER_FALLING,
|
|
|
|
"jpeg_dec_driver", NULL))
|
|
|
|
JPEG_ERR("JPEG DEC Driver request irq failed\n");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
|
|
|
|
memset(_jpeg_hybrid_dec_int_status, 0, HW_CORE_NUMBER);
|
|
|
|
for (i = 0; i < HW_CORE_NUMBER; i++) {
|
|
|
|
JPEG_MSG("Request irq %d\n", gJpegqDev.hybriddecIrqId[i]);
|
|
|
|
init_waitqueue_head(&(hybrid_dec_wait_queue[i]));
|
|
|
|
if (request_irq(gJpegqDev.hybriddecIrqId[i],
|
|
|
|
jpeg_drv_hybrid_dec_isr, IRQF_TRIGGER_HIGH,
|
|
|
|
"jpeg_dec_driver", NULL))
|
|
|
|
JPEG_ERR("JPEG Hybrid DEC requestirq %d failed\n", i);
|
|
|
|
disable_irq(gJpegqDev.hybriddecIrqId[i]);
|
|
|
|
}
|
|
|
|
jpg_ion_create("JPEG");
|
|
|
|
#endif
|
|
|
|
JPEG_MSG("JPEG Probe Done\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_remove(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
int i;
|
|
|
|
#endif
|
|
|
|
JPEG_MSG("JPEG Codec remove\n");
|
|
|
|
/* unregister_chrdev(JPEGDEC_MAJOR, JPEGDEC_DEVNAME); */
|
|
|
|
#ifndef FPGA_VERSION
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
free_irq(gJpegqDev.encIrqId, NULL);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
free_irq(gJpegqDev.decIrqId, NULL);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
for (i = 0; i < HW_CORE_NUMBER; i++)
|
|
|
|
free_irq(gJpegqDev.hybriddecIrqId[i], NULL);
|
|
|
|
jpeg_drv_hybrid_dec_unprepare_dvfs();
|
|
|
|
jpg_ion_destroy();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
/* Support QoS */
|
|
|
|
mtk_pm_qos_remove_request(&jpgenc_qos_request);
|
|
|
|
#endif
|
|
|
|
JPEG_MSG("Done\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void jpeg_shutdown(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
JPEG_MSG("JPEG Codec shutdown\n");
|
|
|
|
/* Nothing yet */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PM suspend */
|
|
|
|
static int jpeg_suspend(struct platform_device *pdev, pm_message_t mesg)
|
|
|
|
{
|
|
|
|
#ifdef JPEG_DEC_DRIVER
|
|
|
|
if (dec_status != 0)
|
|
|
|
jpeg_drv_dec_deinit();
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = jpeg_drv_hybrid_dec_suspend();
|
|
|
|
if (ret != 0)
|
|
|
|
return ret;
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
if (enc_status != 0)
|
|
|
|
jpeg_drv_enc_deinit();
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PM resume */
|
|
|
|
static int jpeg_resume(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int jpeg_pm_suspend(struct device *pDevice)
|
|
|
|
{
|
|
|
|
struct platform_device *pdev = to_platform_device(pDevice);
|
|
|
|
|
|
|
|
WARN_ON(pdev == NULL);
|
|
|
|
|
|
|
|
return jpeg_suspend(pdev, PMSG_SUSPEND);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_pm_resume(struct device *pDevice)
|
|
|
|
{
|
|
|
|
struct platform_device *pdev = to_platform_device(pDevice);
|
|
|
|
|
|
|
|
WARN_ON(pdev == NULL);
|
|
|
|
|
|
|
|
return jpeg_resume(pdev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jpeg_pm_restore_noirq(struct device *pDevice)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct dev_pm_ops const jpeg_pm_ops = {
|
|
|
|
.suspend = jpeg_pm_suspend,
|
|
|
|
.resume = jpeg_pm_resume,
|
|
|
|
.freeze = NULL,
|
|
|
|
.thaw = NULL,
|
|
|
|
.poweroff = NULL,
|
|
|
|
.restore = NULL,
|
|
|
|
.restore_noirq = jpeg_pm_restore_noirq,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct platform_driver jpeg_driver = {
|
|
|
|
.probe = jpeg_probe,
|
|
|
|
.remove = jpeg_remove,
|
|
|
|
.shutdown = jpeg_shutdown,
|
|
|
|
.suspend = jpeg_suspend,
|
|
|
|
.resume = jpeg_resume,
|
|
|
|
.driver = {
|
|
|
|
.name = JPEG_DEVNAME,
|
|
|
|
.pm = &jpeg_pm_ops,
|
|
|
|
#ifdef CONFIG_OF
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
.of_match_table = venc_jpg_of_ids,
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_HYBRID_DEC_DRIVER
|
|
|
|
.of_match_table = jdec_hybrid_of_ids,
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void jpeg_device_release(struct device *dev)
|
|
|
|
{
|
|
|
|
/* Nothing to release? */
|
|
|
|
}
|
|
|
|
|
|
|
|
static u64 jpegdec_dmamask = ~(u32) 0;
|
|
|
|
|
|
|
|
static struct platform_device jpeg_device = {
|
|
|
|
.name = JPEG_DEVNAME,
|
|
|
|
.id = 0,
|
|
|
|
.dev = {
|
|
|
|
.release = jpeg_device_release,
|
|
|
|
.dma_mask = &jpegdec_dmamask,
|
|
|
|
.coherent_dma_mask = 0xffffffff,
|
|
|
|
},
|
|
|
|
.num_resources = 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int __init jpeg_init(void)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
JPEG_MSG("JPEG Codec initialize\n");
|
|
|
|
|
|
|
|
|
|
|
|
JPEG_MSG("Register the JPEG Codec driver\n");
|
|
|
|
if (platform_driver_register(&jpeg_driver)) {
|
|
|
|
JPEG_ERR("failed to register jpeg codec driver\n");
|
|
|
|
platform_device_unregister(&jpeg_device);
|
|
|
|
ret = -ENODEV;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MTK_JPEG_CMDQ_SUPPORT
|
|
|
|
cmdqCoreRegisterCB(CMDQ_GROUP_JPEG,
|
|
|
|
cmdqJpegClockOn,
|
|
|
|
cmdqJpegDumpInfo,
|
|
|
|
cmdqJpegResetEng,
|
|
|
|
cmdqJpegClockOff);
|
|
|
|
#endif
|
|
|
|
Driver_Open_Count = 0;
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
jpeg_drv_enc_prepare_bw_request();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!g_jpeg_ion_client && g_ion_device) {
|
|
|
|
JPEG_MSG("create ion client\n");
|
|
|
|
g_jpeg_ion_client = ion_client_create(g_ion_device, "jpegenc");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit jpeg_exit(void)
|
|
|
|
{
|
|
|
|
JPEG_MSG("%s +\n", __func__);
|
|
|
|
#ifdef JPEG_DEV
|
|
|
|
cdev_del(jenc_cdev);
|
|
|
|
unregister_chrdev_region(jenc_devno, 1);
|
|
|
|
device_destroy(jenc_class, jenc_devno);
|
|
|
|
class_destroy(jenc_class);
|
|
|
|
#else
|
|
|
|
remove_proc_entry("mtk_jpeg", NULL);
|
|
|
|
#endif
|
|
|
|
#ifdef MTK_JPEG_CMDQ_SUPPORT
|
|
|
|
cmdqCoreRegisterCB(CMDQ_GROUP_JPEG, NULL, NULL, NULL, NULL);
|
|
|
|
#endif
|
|
|
|
/* JPEG_MSG("Unregistering driver\n"); */
|
|
|
|
platform_driver_unregister(&jpeg_driver);
|
|
|
|
platform_device_unregister(&jpeg_device);
|
|
|
|
#ifdef JPEG_PM_DOMAIN_ENABLE
|
|
|
|
#ifdef JPEG_DEV
|
|
|
|
/* cdev_del(jdec_cdev); */
|
|
|
|
/* unregister_chrdev_region(jdec_devno, 1); */
|
|
|
|
/* device_destroy(jdec_class, jdec_devno); */
|
|
|
|
/* class_destroy(jdec_class);*/
|
|
|
|
#else
|
|
|
|
remove_proc_entry("mtk_jenc", NULL);
|
|
|
|
#endif
|
|
|
|
/*platform_driver_unregister(&jdec_driver);*/
|
|
|
|
platform_device_unregister(pjenc_dev);
|
|
|
|
JPEG_MSG("%s jdec remove\n", __func__);
|
|
|
|
#endif
|
|
|
|
#ifdef JPEG_ENC_DRIVER
|
|
|
|
jpegenc_drv_enc_remove_bw_request();
|
|
|
|
#endif
|
|
|
|
if (g_jpeg_ion_client)
|
|
|
|
ion_client_destroy(g_jpeg_ion_client);
|
|
|
|
g_jpeg_ion_client = NULL;
|
|
|
|
JPEG_MSG("%s -\n", __func__);
|
|
|
|
}
|
|
|
|
module_init(jpeg_init);
|
|
|
|
module_exit(jpeg_exit);
|
|
|
|
MODULE_AUTHOR("Hao-Ting Huang <otis.huang@mediatek.com>");
|
|
|
|
MODULE_DESCRIPTION("MT6582 JPEG Codec Driver");
|
|
|
|
MODULE_LICENSE("GPL");
|