2020-03-20 16:12:54 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* Hantro VPU codec driver
*
* Copyright ( C ) 2019 Pengutronix , Philipp Zabel < kernel @ pengutronix . de >
*/
# include <linux/clk.h>
# include <linux/delay.h>
# include "hantro.h"
2021-06-03 14:50:04 +03:00
# include "hantro_jpeg.h"
# include "hantro_g1_regs.h"
# include "hantro_g2_regs.h"
2020-03-20 16:12:54 +03:00
# define CTRL_SOFT_RESET 0x00
# define RESET_G1 BIT(1)
# define RESET_G2 BIT(0)
# define CTRL_CLOCK_ENABLE 0x04
# define CLOCK_G1 BIT(1)
# define CLOCK_G2 BIT(0)
# define CTRL_G1_DEC_FUSE 0x08
# define CTRL_G1_PP_FUSE 0x0c
# define CTRL_G2_DEC_FUSE 0x10
static void imx8m_soft_reset ( struct hantro_dev * vpu , u32 reset_bits )
{
u32 val ;
/* Assert */
val = readl ( vpu - > ctrl_base + CTRL_SOFT_RESET ) ;
val & = ~ reset_bits ;
writel ( val , vpu - > ctrl_base + CTRL_SOFT_RESET ) ;
udelay ( 2 ) ;
/* Release */
val = readl ( vpu - > ctrl_base + CTRL_SOFT_RESET ) ;
val | = reset_bits ;
writel ( val , vpu - > ctrl_base + CTRL_SOFT_RESET ) ;
}
static void imx8m_clk_enable ( struct hantro_dev * vpu , u32 clock_bits )
{
u32 val ;
val = readl ( vpu - > ctrl_base + CTRL_CLOCK_ENABLE ) ;
val | = clock_bits ;
writel ( val , vpu - > ctrl_base + CTRL_CLOCK_ENABLE ) ;
}
static int imx8mq_runtime_resume ( struct hantro_dev * vpu )
{
int ret ;
ret = clk_bulk_prepare_enable ( vpu - > variant - > num_clocks , vpu - > clocks ) ;
if ( ret ) {
dev_err ( vpu - > dev , " Failed to enable clocks \n " ) ;
return ret ;
}
imx8m_soft_reset ( vpu , RESET_G1 | RESET_G2 ) ;
imx8m_clk_enable ( vpu , CLOCK_G1 | CLOCK_G2 ) ;
/* Set values of the fuse registers */
writel ( 0xffffffff , vpu - > ctrl_base + CTRL_G1_DEC_FUSE ) ;
writel ( 0xffffffff , vpu - > ctrl_base + CTRL_G1_PP_FUSE ) ;
writel ( 0xffffffff , vpu - > ctrl_base + CTRL_G2_DEC_FUSE ) ;
clk_bulk_disable_unprepare ( vpu - > variant - > num_clocks , vpu - > clocks ) ;
return 0 ;
}
/*
* Supported formats .
*/
static const struct hantro_fmt imx8m_vpu_postproc_fmts [ ] = {
{
. fourcc = V4L2_PIX_FMT_YUYV ,
. codec_mode = HANTRO_MODE_NONE ,
2021-11-16 17:38:33 +03:00
. postprocessed = true ,
2022-05-18 11:53:49 +03:00
. frmsize = {
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = MB_DIM ,
} ,
2020-03-20 16:12:54 +03:00
} ,
} ;
static const struct hantro_fmt imx8m_vpu_dec_fmts [ ] = {
{
. fourcc = V4L2_PIX_FMT_NV12 ,
. codec_mode = HANTRO_MODE_NONE ,
2022-05-18 11:53:49 +03:00
. frmsize = {
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = MB_DIM ,
} ,
2020-03-20 16:12:54 +03:00
} ,
{
. fourcc = V4L2_PIX_FMT_MPEG2_SLICE ,
. codec_mode = HANTRO_MODE_MPEG2_DEC ,
. max_depth = 2 ,
. frmsize = {
2022-05-18 11:53:49 +03:00
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_FHD_WIDTH ,
2020-03-20 16:12:54 +03:00
. step_width = MB_DIM ,
2022-05-18 11:53:49 +03:00
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_FHD_HEIGHT ,
2020-03-20 16:12:54 +03:00
. step_height = MB_DIM ,
} ,
} ,
{
. fourcc = V4L2_PIX_FMT_VP8_FRAME ,
. codec_mode = HANTRO_MODE_VP8_DEC ,
. max_depth = 2 ,
. frmsize = {
2022-05-18 11:53:49 +03:00
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
2021-04-01 17:43:29 +03:00
. step_width = MB_DIM ,
2022-05-18 11:53:49 +03:00
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
2021-04-01 17:43:29 +03:00
. step_height = MB_DIM ,
2020-03-20 16:12:54 +03:00
} ,
} ,
{
. fourcc = V4L2_PIX_FMT_H264_SLICE ,
. codec_mode = HANTRO_MODE_H264_DEC ,
. max_depth = 2 ,
. frmsize = {
2022-05-18 11:53:49 +03:00
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
2020-03-20 16:12:54 +03:00
. step_width = MB_DIM ,
2022-05-18 11:53:49 +03:00
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
2020-03-20 16:12:54 +03:00
. step_height = MB_DIM ,
} ,
} ,
} ;
2021-11-16 17:38:42 +03:00
static const struct hantro_fmt imx8m_vpu_g2_postproc_fmts [ ] = {
{
. fourcc = V4L2_PIX_FMT_NV12 ,
. codec_mode = HANTRO_MODE_NONE ,
2023-02-20 13:48:48 +03:00
. match_depth = true ,
2021-11-16 17:38:42 +03:00
. postprocessed = true ,
2022-05-18 11:53:49 +03:00
. frmsize = {
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = MB_DIM ,
} ,
2021-11-16 17:38:42 +03:00
} ,
2022-08-29 19:21:58 +03:00
{
. fourcc = V4L2_PIX_FMT_P010 ,
. codec_mode = HANTRO_MODE_NONE ,
2023-02-20 13:48:48 +03:00
. match_depth = true ,
2022-08-29 19:21:58 +03:00
. postprocessed = true ,
. frmsize = {
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = MB_DIM ,
} ,
} ,
2021-11-16 17:38:42 +03:00
} ;
2021-06-03 14:50:04 +03:00
static const struct hantro_fmt imx8m_vpu_g2_dec_fmts [ ] = {
{
2021-11-16 17:38:34 +03:00
. fourcc = V4L2_PIX_FMT_NV12_4L4 ,
2021-06-03 14:50:04 +03:00
. codec_mode = HANTRO_MODE_NONE ,
2022-08-29 19:21:58 +03:00
. match_depth = true ,
. frmsize = {
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = TILE_MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = TILE_MB_DIM ,
} ,
} ,
{
. fourcc = V4L2_PIX_FMT_P010_4L4 ,
. codec_mode = HANTRO_MODE_NONE ,
. match_depth = true ,
2022-05-18 11:53:49 +03:00
. frmsize = {
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = TILE_MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = TILE_MB_DIM ,
} ,
2021-06-03 14:50:04 +03:00
} ,
{
. fourcc = V4L2_PIX_FMT_HEVC_SLICE ,
. codec_mode = HANTRO_MODE_HEVC_DEC ,
. max_depth = 2 ,
. frmsize = {
2022-05-18 11:53:49 +03:00
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = TILE_MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = TILE_MB_DIM ,
2021-06-03 14:50:04 +03:00
} ,
} ,
2021-11-16 17:38:40 +03:00
{
. fourcc = V4L2_PIX_FMT_VP9_FRAME ,
. codec_mode = HANTRO_MODE_VP9_DEC ,
. max_depth = 2 ,
. frmsize = {
2022-05-18 11:53:49 +03:00
. min_width = FMT_MIN_WIDTH ,
. max_width = FMT_UHD_WIDTH ,
. step_width = TILE_MB_DIM ,
. min_height = FMT_MIN_HEIGHT ,
. max_height = FMT_UHD_HEIGHT ,
. step_height = TILE_MB_DIM ,
2021-11-16 17:38:40 +03:00
} ,
} ,
2021-06-03 14:50:04 +03:00
} ;
static irqreturn_t imx8m_vpu_g1_irq ( int irq , void * dev_id )
{
struct hantro_dev * vpu = dev_id ;
enum vb2_buffer_state state ;
u32 status ;
status = vdpu_read ( vpu , G1_REG_INTERRUPT ) ;
state = ( status & G1_REG_INTERRUPT_DEC_RDY_INT ) ?
VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR ;
vdpu_write ( vpu , 0 , G1_REG_INTERRUPT ) ;
vdpu_write ( vpu , G1_REG_CONFIG_DEC_CLK_GATE_E , G1_REG_CONFIG ) ;
hantro_irq_done ( vpu , state ) ;
return IRQ_HANDLED ;
}
2020-03-20 16:12:54 +03:00
static int imx8mq_vpu_hw_init ( struct hantro_dev * vpu )
{
vpu - > ctrl_base = vpu - > reg_bases [ vpu - > variant - > num_regs - 1 ] ;
return 0 ;
}
static void imx8m_vpu_g1_reset ( struct hantro_ctx * ctx )
{
struct hantro_dev * vpu = ctx - > dev ;
imx8m_soft_reset ( vpu , RESET_G1 ) ;
}
/*
* Supported codec ops .
*/
static const struct hantro_codec_ops imx8mq_vpu_codec_ops [ ] = {
[ HANTRO_MODE_MPEG2_DEC ] = {
. run = hantro_g1_mpeg2_dec_run ,
. reset = imx8m_vpu_g1_reset ,
. init = hantro_mpeg2_dec_init ,
. exit = hantro_mpeg2_dec_exit ,
} ,
[ HANTRO_MODE_VP8_DEC ] = {
. run = hantro_g1_vp8_dec_run ,
. reset = imx8m_vpu_g1_reset ,
. init = hantro_vp8_dec_init ,
. exit = hantro_vp8_dec_exit ,
} ,
[ HANTRO_MODE_H264_DEC ] = {
. run = hantro_g1_h264_dec_run ,
. reset = imx8m_vpu_g1_reset ,
. init = hantro_h264_dec_init ,
. exit = hantro_h264_dec_exit ,
} ,
} ;
2022-01-25 20:11:23 +03:00
static const struct hantro_codec_ops imx8mq_vpu_g1_codec_ops [ ] = {
[ HANTRO_MODE_MPEG2_DEC ] = {
. run = hantro_g1_mpeg2_dec_run ,
. init = hantro_mpeg2_dec_init ,
. exit = hantro_mpeg2_dec_exit ,
} ,
[ HANTRO_MODE_VP8_DEC ] = {
. run = hantro_g1_vp8_dec_run ,
. init = hantro_vp8_dec_init ,
. exit = hantro_vp8_dec_exit ,
} ,
[ HANTRO_MODE_H264_DEC ] = {
. run = hantro_g1_h264_dec_run ,
. init = hantro_h264_dec_init ,
. exit = hantro_h264_dec_exit ,
} ,
} ;
2021-06-03 14:50:04 +03:00
static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops [ ] = {
[ HANTRO_MODE_HEVC_DEC ] = {
. run = hantro_g2_hevc_dec_run ,
. init = hantro_hevc_dec_init ,
. exit = hantro_hevc_dec_exit ,
} ,
2021-11-16 17:38:40 +03:00
[ HANTRO_MODE_VP9_DEC ] = {
. run = hantro_g2_vp9_dec_run ,
. done = hantro_g2_vp9_dec_done ,
. init = hantro_vp9_dec_init ,
. exit = hantro_vp9_dec_exit ,
} ,
2021-06-03 14:50:04 +03:00
} ;
2020-03-20 16:12:54 +03:00
/*
* VPU variants .
*/
static const struct hantro_irq imx8mq_irqs [ ] = {
2021-06-03 14:50:04 +03:00
{ " g1 " , imx8m_vpu_g1_irq } ,
} ;
static const struct hantro_irq imx8mq_g2_irqs [ ] = {
2021-11-29 21:26:30 +03:00
{ " g2 " , hantro_g2_irq } ,
2020-03-20 16:12:54 +03:00
} ;
static const char * const imx8mq_clk_names [ ] = { " g1 " , " g2 " , " bus " } ;
static const char * const imx8mq_reg_names [ ] = { " g1 " , " g2 " , " ctrl " } ;
2022-01-25 20:11:23 +03:00
static const char * const imx8mq_g1_clk_names [ ] = { " g1 " } ;
static const char * const imx8mq_g2_clk_names [ ] = { " g2 " } ;
2020-03-20 16:12:54 +03:00
const struct hantro_variant imx8mq_vpu_variant = {
. dec_fmts = imx8m_vpu_dec_fmts ,
. num_dec_fmts = ARRAY_SIZE ( imx8m_vpu_dec_fmts ) ,
. postproc_fmts = imx8m_vpu_postproc_fmts ,
. num_postproc_fmts = ARRAY_SIZE ( imx8m_vpu_postproc_fmts ) ,
2021-11-16 17:38:32 +03:00
. postproc_ops = & hantro_g1_postproc_ops ,
2020-03-20 16:12:54 +03:00
. codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER ,
. codec_ops = imx8mq_vpu_codec_ops ,
. init = imx8mq_vpu_hw_init ,
. runtime_resume = imx8mq_runtime_resume ,
. irqs = imx8mq_irqs ,
. num_irqs = ARRAY_SIZE ( imx8mq_irqs ) ,
. clk_names = imx8mq_clk_names ,
. num_clocks = ARRAY_SIZE ( imx8mq_clk_names ) ,
. reg_names = imx8mq_reg_names ,
. num_regs = ARRAY_SIZE ( imx8mq_reg_names )
} ;
2021-06-03 14:50:04 +03:00
2022-01-25 20:11:23 +03:00
const struct hantro_variant imx8mq_vpu_g1_variant = {
. dec_fmts = imx8m_vpu_dec_fmts ,
. num_dec_fmts = ARRAY_SIZE ( imx8m_vpu_dec_fmts ) ,
. postproc_fmts = imx8m_vpu_postproc_fmts ,
. num_postproc_fmts = ARRAY_SIZE ( imx8m_vpu_postproc_fmts ) ,
. postproc_ops = & hantro_g1_postproc_ops ,
. codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER ,
. codec_ops = imx8mq_vpu_g1_codec_ops ,
. irqs = imx8mq_irqs ,
. num_irqs = ARRAY_SIZE ( imx8mq_irqs ) ,
. clk_names = imx8mq_g1_clk_names ,
. num_clocks = ARRAY_SIZE ( imx8mq_g1_clk_names ) ,
} ;
2021-06-03 14:50:04 +03:00
const struct hantro_variant imx8mq_vpu_g2_variant = {
. dec_offset = 0x0 ,
. dec_fmts = imx8m_vpu_g2_dec_fmts ,
. num_dec_fmts = ARRAY_SIZE ( imx8m_vpu_g2_dec_fmts ) ,
2021-11-16 17:38:42 +03:00
. postproc_fmts = imx8m_vpu_g2_postproc_fmts ,
. num_postproc_fmts = ARRAY_SIZE ( imx8m_vpu_g2_postproc_fmts ) ,
. postproc_ops = & hantro_g2_postproc_ops ,
2021-11-16 17:38:40 +03:00
. codec = HANTRO_HEVC_DECODER | HANTRO_VP9_DECODER ,
2021-06-03 14:50:04 +03:00
. codec_ops = imx8mq_vpu_g2_codec_ops ,
. irqs = imx8mq_g2_irqs ,
. num_irqs = ARRAY_SIZE ( imx8mq_g2_irqs ) ,
2022-01-25 20:11:23 +03:00
. clk_names = imx8mq_g2_clk_names ,
. num_clocks = ARRAY_SIZE ( imx8mq_g2_clk_names ) ,
2021-06-03 14:50:04 +03:00
} ;
2022-01-25 20:11:27 +03:00
const struct hantro_variant imx8mm_vpu_g1_variant = {
. dec_fmts = imx8m_vpu_dec_fmts ,
. num_dec_fmts = ARRAY_SIZE ( imx8m_vpu_dec_fmts ) ,
. codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER |
HANTRO_H264_DECODER ,
. codec_ops = imx8mq_vpu_g1_codec_ops ,
. irqs = imx8mq_irqs ,
. num_irqs = ARRAY_SIZE ( imx8mq_irqs ) ,
. clk_names = imx8mq_g1_clk_names ,
. num_clocks = ARRAY_SIZE ( imx8mq_g1_clk_names ) ,
} ;