2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-01-04 20:36:34 +03:00
/*
* Copyright ( c ) 2015 MediaTek Inc .
*/
# include <linux/clk.h>
2017-03-31 14:30:31 +03:00
# include <linux/iopoll.h>
2016-01-04 20:36:34 +03:00
# include <linux/module.h>
# include <linux/of_device.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# include "mtk_drm_ddp.h"
# include "mtk_drm_ddp_comp.h"
# define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0x040
# define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN 0x044
# define DISP_REG_CONFIG_DISP_OD_MOUT_EN 0x048
# define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN 0x04c
# define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN 0x050
# define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0x084
# define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN 0x088
2018-06-20 11:19:20 +03:00
# define DISP_REG_CONFIG_DSIE_SEL_IN 0x0a4
2018-06-20 11:19:19 +03:00
# define DISP_REG_CONFIG_DSIO_SEL_IN 0x0a8
2016-01-04 20:36:34 +03:00
# define DISP_REG_CONFIG_DPI_SEL_IN 0x0ac
2018-06-20 11:19:22 +03:00
# define DISP_REG_CONFIG_DISP_RDMA2_SOUT 0x0b8
2018-06-20 11:19:15 +03:00
# define DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN 0x0c4
2018-06-20 11:19:14 +03:00
# define DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN 0x0c8
2016-01-04 20:36:34 +03:00
# define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100
2017-03-31 14:30:33 +03:00
# define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030
# define DISP_REG_CONFIG_OUT_SEL 0x04c
# define DISP_REG_CONFIG_DSI_SEL 0x050
2018-10-03 06:41:50 +03:00
# define DISP_REG_CONFIG_DPI_SEL 0x064
2017-03-31 14:30:33 +03:00
2019-08-29 17:50:30 +03:00
# define MT2701_DISP_MUTEX0_MOD0 0x2c
2019-08-29 17:50:32 +03:00
# define MT2701_DISP_MUTEX0_SOF0 0x30
2019-08-29 17:50:30 +03:00
# define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
# define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
# define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
# define DISP_REG_MUTEX_MOD(mutex_mod_reg, n) (mutex_mod_reg + 0x20 * (n))
2019-08-29 17:50:32 +03:00
# define DISP_REG_MUTEX_SOF(mutex_sof_reg, n) (mutex_sof_reg + 0x20 * (n))
2019-08-29 17:50:30 +03:00
# define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
2016-01-04 20:36:34 +03:00
2017-03-31 14:30:31 +03:00
# define INT_MUTEX BIT(1)
2018-06-20 11:19:04 +03:00
# define MT8173_MUTEX_MOD_DISP_OVL0 11
# define MT8173_MUTEX_MOD_DISP_OVL1 12
# define MT8173_MUTEX_MOD_DISP_RDMA0 13
# define MT8173_MUTEX_MOD_DISP_RDMA1 14
# define MT8173_MUTEX_MOD_DISP_RDMA2 15
# define MT8173_MUTEX_MOD_DISP_WDMA0 16
# define MT8173_MUTEX_MOD_DISP_WDMA1 17
# define MT8173_MUTEX_MOD_DISP_COLOR0 18
# define MT8173_MUTEX_MOD_DISP_COLOR1 19
# define MT8173_MUTEX_MOD_DISP_AAL 20
# define MT8173_MUTEX_MOD_DISP_GAMMA 21
# define MT8173_MUTEX_MOD_DISP_UFOE 22
# define MT8173_MUTEX_MOD_DISP_PWM0 23
# define MT8173_MUTEX_MOD_DISP_PWM1 24
# define MT8173_MUTEX_MOD_DISP_OD 25
2018-06-20 11:19:31 +03:00
# define MT2712_MUTEX_MOD_DISP_PWM2 10
# define MT2712_MUTEX_MOD_DISP_OVL0 11
# define MT2712_MUTEX_MOD_DISP_OVL1 12
# define MT2712_MUTEX_MOD_DISP_RDMA0 13
# define MT2712_MUTEX_MOD_DISP_RDMA1 14
# define MT2712_MUTEX_MOD_DISP_RDMA2 15
# define MT2712_MUTEX_MOD_DISP_WDMA0 16
# define MT2712_MUTEX_MOD_DISP_WDMA1 17
# define MT2712_MUTEX_MOD_DISP_COLOR0 18
# define MT2712_MUTEX_MOD_DISP_COLOR1 19
# define MT2712_MUTEX_MOD_DISP_AAL0 20
# define MT2712_MUTEX_MOD_DISP_UFOE 22
# define MT2712_MUTEX_MOD_DISP_PWM0 23
# define MT2712_MUTEX_MOD_DISP_PWM1 24
# define MT2712_MUTEX_MOD_DISP_OD0 25
# define MT2712_MUTEX_MOD2_DISP_AAL1 33
# define MT2712_MUTEX_MOD2_DISP_OD1 34
2018-06-20 11:19:04 +03:00
# define MT2701_MUTEX_MOD_DISP_OVL 3
# define MT2701_MUTEX_MOD_DISP_WDMA 6
# define MT2701_MUTEX_MOD_DISP_COLOR 7
# define MT2701_MUTEX_MOD_DISP_BLS 9
# define MT2701_MUTEX_MOD_DISP_RDMA0 10
# define MT2701_MUTEX_MOD_DISP_RDMA1 12
2017-03-31 14:30:39 +03:00
2016-01-04 20:36:34 +03:00
# define MUTEX_SOF_SINGLE_MODE 0
# define MUTEX_SOF_DSI0 1
# define MUTEX_SOF_DSI1 2
# define MUTEX_SOF_DPI0 3
2018-06-20 11:19:27 +03:00
# define MUTEX_SOF_DPI1 4
2018-06-20 11:19:28 +03:00
# define MUTEX_SOF_DSI2 5
2018-06-20 11:19:29 +03:00
# define MUTEX_SOF_DSI3 6
2016-01-04 20:36:34 +03:00
# define OVL0_MOUT_EN_COLOR0 0x1
# define OD_MOUT_EN_RDMA0 0x1
2018-06-20 11:19:13 +03:00
# define OD1_MOUT_EN_RDMA1 BIT(16)
2016-01-04 20:36:34 +03:00
# define UFOE_MOUT_EN_DSI0 0x1
# define COLOR0_SEL_IN_OVL0 0x1
# define OVL1_MOUT_EN_COLOR1 0x1
# define GAMMA_MOUT_EN_RDMA1 0x1
2018-06-20 11:19:15 +03:00
# define RDMA0_SOUT_DPI0 0x2
2018-08-09 05:15:36 +03:00
# define RDMA0_SOUT_DPI1 0x3
2018-08-09 05:15:37 +03:00
# define RDMA0_SOUT_DSI1 0x1
2018-06-20 11:19:16 +03:00
# define RDMA0_SOUT_DSI2 0x4
2018-06-20 11:19:17 +03:00
# define RDMA0_SOUT_DSI3 0x5
2018-06-20 11:19:14 +03:00
# define RDMA1_SOUT_DPI0 0x2
2018-06-20 11:19:18 +03:00
# define RDMA1_SOUT_DPI1 0x3
2018-06-20 11:19:19 +03:00
# define RDMA1_SOUT_DSI1 0x1
2018-06-20 11:19:20 +03:00
# define RDMA1_SOUT_DSI2 0x4
2018-06-20 11:19:21 +03:00
# define RDMA1_SOUT_DSI3 0x5
2018-06-20 11:19:22 +03:00
# define RDMA2_SOUT_DPI0 0x2
2018-06-20 11:19:23 +03:00
# define RDMA2_SOUT_DPI1 0x3
2018-06-20 11:19:24 +03:00
# define RDMA2_SOUT_DSI1 0x1
2018-06-20 11:19:25 +03:00
# define RDMA2_SOUT_DSI2 0x4
2018-06-20 11:19:26 +03:00
# define RDMA2_SOUT_DSI3 0x5
2016-01-04 20:36:34 +03:00
# define DPI0_SEL_IN_RDMA1 0x1
2018-06-20 11:19:22 +03:00
# define DPI0_SEL_IN_RDMA2 0x3
2018-06-20 11:19:18 +03:00
# define DPI1_SEL_IN_RDMA1 (0x1 << 8)
2018-06-20 11:19:23 +03:00
# define DPI1_SEL_IN_RDMA2 (0x3 << 8)
2018-08-09 05:15:38 +03:00
# define DSI0_SEL_IN_RDMA1 0x1
2018-08-09 05:15:39 +03:00
# define DSI0_SEL_IN_RDMA2 0x4
2018-06-20 11:19:19 +03:00
# define DSI1_SEL_IN_RDMA1 0x1
2018-06-20 11:19:24 +03:00
# define DSI1_SEL_IN_RDMA2 0x4
2018-06-20 11:19:20 +03:00
# define DSI2_SEL_IN_RDMA1 (0x1 << 16)
2018-06-20 11:19:25 +03:00
# define DSI2_SEL_IN_RDMA2 (0x4 << 16)
2018-06-20 11:19:21 +03:00
# define DSI3_SEL_IN_RDMA1 (0x1 << 16)
2018-06-20 11:19:26 +03:00
# define DSI3_SEL_IN_RDMA2 (0x4 << 16)
2016-01-04 20:36:34 +03:00
# define COLOR1_SEL_IN_OVL1 0x1
2017-03-31 14:30:33 +03:00
# define OVL_MOUT_EN_RDMA 0x1
# define BLS_TO_DSI_RDMA1_TO_DPI1 0x8
2018-10-03 06:41:50 +03:00
# define BLS_TO_DPI_RDMA1_TO_DSI 0x2
2017-03-31 14:30:33 +03:00
# define DSI_SEL_IN_BLS 0x0
2018-10-03 06:41:50 +03:00
# define DPI_SEL_IN_BLS 0x0
# define DSI_SEL_IN_RDMA 0x1
2017-03-31 14:30:33 +03:00
2016-01-04 20:36:34 +03:00
struct mtk_disp_mutex {
int id ;
bool claimed ;
} ;
2019-08-29 17:50:31 +03:00
enum mtk_ddp_mutex_sof_id {
DDP_MUTEX_SOF_SINGLE_MODE ,
DDP_MUTEX_SOF_DSI0 ,
DDP_MUTEX_SOF_DSI1 ,
DDP_MUTEX_SOF_DPI0 ,
DDP_MUTEX_SOF_DPI1 ,
DDP_MUTEX_SOF_DSI2 ,
DDP_MUTEX_SOF_DSI3 ,
} ;
2019-08-29 17:50:29 +03:00
struct mtk_ddp_data {
const unsigned int * mutex_mod ;
2019-08-29 17:50:31 +03:00
const unsigned int * mutex_sof ;
2019-08-29 17:50:30 +03:00
const unsigned int mutex_mod_reg ;
2019-08-29 17:50:32 +03:00
const unsigned int mutex_sof_reg ;
2019-10-09 11:37:47 +03:00
const bool no_clk ;
2019-08-29 17:50:29 +03:00
} ;
2016-01-04 20:36:34 +03:00
struct mtk_ddp {
struct device * dev ;
struct clk * clk ;
void __iomem * regs ;
struct mtk_disp_mutex mutex [ 10 ] ;
2019-08-29 17:50:29 +03:00
const struct mtk_ddp_data * data ;
2016-01-04 20:36:34 +03:00
} ;
2017-03-31 14:30:39 +03:00
static const unsigned int mt2701_mutex_mod [ DDP_COMPONENT_ID_MAX ] = {
[ DDP_COMPONENT_BLS ] = MT2701_MUTEX_MOD_DISP_BLS ,
[ DDP_COMPONENT_COLOR0 ] = MT2701_MUTEX_MOD_DISP_COLOR ,
[ DDP_COMPONENT_OVL0 ] = MT2701_MUTEX_MOD_DISP_OVL ,
[ DDP_COMPONENT_RDMA0 ] = MT2701_MUTEX_MOD_DISP_RDMA0 ,
[ DDP_COMPONENT_RDMA1 ] = MT2701_MUTEX_MOD_DISP_RDMA1 ,
[ DDP_COMPONENT_WDMA0 ] = MT2701_MUTEX_MOD_DISP_WDMA ,
} ;
2018-06-20 11:19:31 +03:00
static const unsigned int mt2712_mutex_mod [ DDP_COMPONENT_ID_MAX ] = {
[ DDP_COMPONENT_AAL0 ] = MT2712_MUTEX_MOD_DISP_AAL0 ,
[ DDP_COMPONENT_AAL1 ] = MT2712_MUTEX_MOD2_DISP_AAL1 ,
[ DDP_COMPONENT_COLOR0 ] = MT2712_MUTEX_MOD_DISP_COLOR0 ,
[ DDP_COMPONENT_COLOR1 ] = MT2712_MUTEX_MOD_DISP_COLOR1 ,
[ DDP_COMPONENT_OD0 ] = MT2712_MUTEX_MOD_DISP_OD0 ,
[ DDP_COMPONENT_OD1 ] = MT2712_MUTEX_MOD2_DISP_OD1 ,
[ DDP_COMPONENT_OVL0 ] = MT2712_MUTEX_MOD_DISP_OVL0 ,
[ DDP_COMPONENT_OVL1 ] = MT2712_MUTEX_MOD_DISP_OVL1 ,
[ DDP_COMPONENT_PWM0 ] = MT2712_MUTEX_MOD_DISP_PWM0 ,
[ DDP_COMPONENT_PWM1 ] = MT2712_MUTEX_MOD_DISP_PWM1 ,
[ DDP_COMPONENT_PWM2 ] = MT2712_MUTEX_MOD_DISP_PWM2 ,
[ DDP_COMPONENT_RDMA0 ] = MT2712_MUTEX_MOD_DISP_RDMA0 ,
[ DDP_COMPONENT_RDMA1 ] = MT2712_MUTEX_MOD_DISP_RDMA1 ,
[ DDP_COMPONENT_RDMA2 ] = MT2712_MUTEX_MOD_DISP_RDMA2 ,
[ DDP_COMPONENT_UFOE ] = MT2712_MUTEX_MOD_DISP_UFOE ,
[ DDP_COMPONENT_WDMA0 ] = MT2712_MUTEX_MOD_DISP_WDMA0 ,
[ DDP_COMPONENT_WDMA1 ] = MT2712_MUTEX_MOD_DISP_WDMA1 ,
} ;
2017-03-31 14:30:30 +03:00
static const unsigned int mt8173_mutex_mod [ DDP_COMPONENT_ID_MAX ] = {
2018-06-20 11:19:05 +03:00
[ DDP_COMPONENT_AAL0 ] = MT8173_MUTEX_MOD_DISP_AAL ,
2017-03-31 14:30:30 +03:00
[ DDP_COMPONENT_COLOR0 ] = MT8173_MUTEX_MOD_DISP_COLOR0 ,
[ DDP_COMPONENT_COLOR1 ] = MT8173_MUTEX_MOD_DISP_COLOR1 ,
[ DDP_COMPONENT_GAMMA ] = MT8173_MUTEX_MOD_DISP_GAMMA ,
2018-06-20 11:19:06 +03:00
[ DDP_COMPONENT_OD0 ] = MT8173_MUTEX_MOD_DISP_OD ,
2017-03-31 14:30:30 +03:00
[ DDP_COMPONENT_OVL0 ] = MT8173_MUTEX_MOD_DISP_OVL0 ,
[ DDP_COMPONENT_OVL1 ] = MT8173_MUTEX_MOD_DISP_OVL1 ,
[ DDP_COMPONENT_PWM0 ] = MT8173_MUTEX_MOD_DISP_PWM0 ,
[ DDP_COMPONENT_PWM1 ] = MT8173_MUTEX_MOD_DISP_PWM1 ,
[ DDP_COMPONENT_RDMA0 ] = MT8173_MUTEX_MOD_DISP_RDMA0 ,
[ DDP_COMPONENT_RDMA1 ] = MT8173_MUTEX_MOD_DISP_RDMA1 ,
[ DDP_COMPONENT_RDMA2 ] = MT8173_MUTEX_MOD_DISP_RDMA2 ,
[ DDP_COMPONENT_UFOE ] = MT8173_MUTEX_MOD_DISP_UFOE ,
[ DDP_COMPONENT_WDMA0 ] = MT8173_MUTEX_MOD_DISP_WDMA0 ,
[ DDP_COMPONENT_WDMA1 ] = MT8173_MUTEX_MOD_DISP_WDMA1 ,
2016-01-04 20:36:34 +03:00
} ;
2019-08-29 17:50:31 +03:00
static const unsigned int mt2712_mutex_sof [ DDP_MUTEX_SOF_DSI3 + 1 ] = {
[ DDP_MUTEX_SOF_SINGLE_MODE ] = MUTEX_SOF_SINGLE_MODE ,
[ DDP_MUTEX_SOF_DSI0 ] = MUTEX_SOF_DSI0 ,
[ DDP_MUTEX_SOF_DSI1 ] = MUTEX_SOF_DSI1 ,
[ DDP_MUTEX_SOF_DPI0 ] = MUTEX_SOF_DPI0 ,
[ DDP_MUTEX_SOF_DPI1 ] = MUTEX_SOF_DPI1 ,
[ DDP_MUTEX_SOF_DSI2 ] = MUTEX_SOF_DSI2 ,
[ DDP_MUTEX_SOF_DSI3 ] = MUTEX_SOF_DSI3 ,
} ;
2019-08-29 17:50:29 +03:00
static const struct mtk_ddp_data mt2701_ddp_driver_data = {
. mutex_mod = mt2701_mutex_mod ,
2019-08-29 17:50:31 +03:00
. mutex_sof = mt2712_mutex_sof ,
2019-08-29 17:50:30 +03:00
. mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0 ,
2019-08-29 17:50:32 +03:00
. mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0 ,
2019-08-29 17:50:29 +03:00
} ;
static const struct mtk_ddp_data mt2712_ddp_driver_data = {
. mutex_mod = mt2712_mutex_mod ,
2019-08-29 17:50:31 +03:00
. mutex_sof = mt2712_mutex_sof ,
2019-08-29 17:50:30 +03:00
. mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0 ,
2019-08-29 17:50:32 +03:00
. mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0 ,
2019-08-29 17:50:29 +03:00
} ;
static const struct mtk_ddp_data mt8173_ddp_driver_data = {
. mutex_mod = mt8173_mutex_mod ,
2019-08-29 17:50:31 +03:00
. mutex_sof = mt2712_mutex_sof ,
2019-08-29 17:50:30 +03:00
. mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0 ,
2019-08-29 17:50:32 +03:00
. mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0 ,
2019-08-29 17:50:29 +03:00
} ;
2016-01-04 20:36:34 +03:00
static unsigned int mtk_ddp_mout_en ( enum mtk_ddp_comp_id cur ,
enum mtk_ddp_comp_id next ,
unsigned int * addr )
{
unsigned int value ;
if ( cur = = DDP_COMPONENT_OVL0 & & next = = DDP_COMPONENT_COLOR0 ) {
* addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN ;
value = OVL0_MOUT_EN_COLOR0 ;
2017-03-31 14:30:33 +03:00
} else if ( cur = = DDP_COMPONENT_OVL0 & & next = = DDP_COMPONENT_RDMA0 ) {
* addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN ;
value = OVL_MOUT_EN_RDMA ;
2018-06-20 11:19:06 +03:00
} else if ( cur = = DDP_COMPONENT_OD0 & & next = = DDP_COMPONENT_RDMA0 ) {
2016-01-04 20:36:34 +03:00
* addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN ;
value = OD_MOUT_EN_RDMA0 ;
} else if ( cur = = DDP_COMPONENT_UFOE & & next = = DDP_COMPONENT_DSI0 ) {
* addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN ;
value = UFOE_MOUT_EN_DSI0 ;
} else if ( cur = = DDP_COMPONENT_OVL1 & & next = = DDP_COMPONENT_COLOR1 ) {
* addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN ;
value = OVL1_MOUT_EN_COLOR1 ;
} else if ( cur = = DDP_COMPONENT_GAMMA & & next = = DDP_COMPONENT_RDMA1 ) {
* addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN ;
value = GAMMA_MOUT_EN_RDMA1 ;
2018-06-20 11:19:13 +03:00
} else if ( cur = = DDP_COMPONENT_OD1 & & next = = DDP_COMPONENT_RDMA1 ) {
* addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN ;
value = OD1_MOUT_EN_RDMA1 ;
2018-06-20 11:19:15 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA0 & & next = = DDP_COMPONENT_DPI0 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN ;
value = RDMA0_SOUT_DPI0 ;
2018-08-09 05:15:36 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA0 & & next = = DDP_COMPONENT_DPI1 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN ;
value = RDMA0_SOUT_DPI1 ;
2018-08-09 05:15:37 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA0 & & next = = DDP_COMPONENT_DSI1 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN ;
value = RDMA0_SOUT_DSI1 ;
2018-06-20 11:19:16 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA0 & & next = = DDP_COMPONENT_DSI2 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN ;
value = RDMA0_SOUT_DSI2 ;
2018-06-20 11:19:17 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA0 & & next = = DDP_COMPONENT_DSI3 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN ;
value = RDMA0_SOUT_DSI3 ;
2018-06-20 11:19:19 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DSI1 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN ;
value = RDMA1_SOUT_DSI1 ;
2018-06-20 11:19:20 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DSI2 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN ;
value = RDMA1_SOUT_DSI2 ;
2018-06-20 11:19:21 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DSI3 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN ;
value = RDMA1_SOUT_DSI3 ;
2016-01-04 20:36:34 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DPI0 ) {
2018-06-20 11:19:14 +03:00
* addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN ;
value = RDMA1_SOUT_DPI0 ;
2018-06-20 11:19:18 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DPI1 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN ;
value = RDMA1_SOUT_DPI1 ;
2018-06-20 11:19:22 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DPI0 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT ;
value = RDMA2_SOUT_DPI0 ;
2018-06-20 11:19:23 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DPI1 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT ;
value = RDMA2_SOUT_DPI1 ;
2018-06-20 11:19:24 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI1 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT ;
value = RDMA2_SOUT_DSI1 ;
2018-06-20 11:19:25 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI2 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT ;
value = RDMA2_SOUT_DSI2 ;
2018-06-20 11:19:26 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI3 ) {
* addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT ;
value = RDMA2_SOUT_DSI3 ;
2016-01-04 20:36:34 +03:00
} else {
value = 0 ;
}
return value ;
}
static unsigned int mtk_ddp_sel_in ( enum mtk_ddp_comp_id cur ,
enum mtk_ddp_comp_id next ,
unsigned int * addr )
{
unsigned int value ;
if ( cur = = DDP_COMPONENT_OVL0 & & next = = DDP_COMPONENT_COLOR0 ) {
* addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN ;
value = COLOR0_SEL_IN_OVL0 ;
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DPI0 ) {
* addr = DISP_REG_CONFIG_DPI_SEL_IN ;
value = DPI0_SEL_IN_RDMA1 ;
2018-06-20 11:19:18 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DPI1 ) {
* addr = DISP_REG_CONFIG_DPI_SEL_IN ;
value = DPI1_SEL_IN_RDMA1 ;
2018-08-09 05:15:38 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DSI0 ) {
* addr = DISP_REG_CONFIG_DSIE_SEL_IN ;
value = DSI0_SEL_IN_RDMA1 ;
2018-06-20 11:19:19 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DSI1 ) {
* addr = DISP_REG_CONFIG_DSIO_SEL_IN ;
value = DSI1_SEL_IN_RDMA1 ;
2018-06-20 11:19:20 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DSI2 ) {
* addr = DISP_REG_CONFIG_DSIE_SEL_IN ;
value = DSI2_SEL_IN_RDMA1 ;
2018-06-20 11:19:21 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DSI3 ) {
* addr = DISP_REG_CONFIG_DSIO_SEL_IN ;
value = DSI3_SEL_IN_RDMA1 ;
2018-06-20 11:19:22 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DPI0 ) {
* addr = DISP_REG_CONFIG_DPI_SEL_IN ;
value = DPI0_SEL_IN_RDMA2 ;
2018-06-20 11:19:23 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DPI1 ) {
* addr = DISP_REG_CONFIG_DPI_SEL_IN ;
value = DPI1_SEL_IN_RDMA2 ;
2018-08-09 05:15:39 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI0 ) {
* addr = DISP_REG_CONFIG_DSIE_SEL_IN ;
value = DSI0_SEL_IN_RDMA2 ;
2018-06-20 11:19:24 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI1 ) {
2018-08-09 05:15:49 +03:00
* addr = DISP_REG_CONFIG_DSIO_SEL_IN ;
2018-06-20 11:19:24 +03:00
value = DSI1_SEL_IN_RDMA2 ;
2018-06-20 11:19:25 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI2 ) {
* addr = DISP_REG_CONFIG_DSIE_SEL_IN ;
value = DSI2_SEL_IN_RDMA2 ;
2018-06-20 11:19:26 +03:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI3 ) {
* addr = DISP_REG_CONFIG_DSIE_SEL_IN ;
value = DSI3_SEL_IN_RDMA2 ;
2016-01-04 20:36:34 +03:00
} else if ( cur = = DDP_COMPONENT_OVL1 & & next = = DDP_COMPONENT_COLOR1 ) {
* addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN ;
value = COLOR1_SEL_IN_OVL1 ;
2017-03-31 14:30:33 +03:00
} else if ( cur = = DDP_COMPONENT_BLS & & next = = DDP_COMPONENT_DSI0 ) {
* addr = DISP_REG_CONFIG_DSI_SEL ;
value = DSI_SEL_IN_BLS ;
2016-01-04 20:36:34 +03:00
} else {
value = 0 ;
}
return value ;
}
2017-03-31 14:30:33 +03:00
static void mtk_ddp_sout_sel ( void __iomem * config_regs ,
enum mtk_ddp_comp_id cur ,
enum mtk_ddp_comp_id next )
{
2018-10-03 06:41:50 +03:00
if ( cur = = DDP_COMPONENT_BLS & & next = = DDP_COMPONENT_DSI0 ) {
2017-03-31 14:30:33 +03:00
writel_relaxed ( BLS_TO_DSI_RDMA1_TO_DPI1 ,
config_regs + DISP_REG_CONFIG_OUT_SEL ) ;
2018-10-03 06:41:50 +03:00
} else if ( cur = = DDP_COMPONENT_BLS & & next = = DDP_COMPONENT_DPI0 ) {
writel_relaxed ( BLS_TO_DPI_RDMA1_TO_DSI ,
config_regs + DISP_REG_CONFIG_OUT_SEL ) ;
writel_relaxed ( DSI_SEL_IN_RDMA ,
config_regs + DISP_REG_CONFIG_DSI_SEL ) ;
writel_relaxed ( DPI_SEL_IN_BLS ,
config_regs + DISP_REG_CONFIG_DPI_SEL ) ;
}
2017-03-31 14:30:33 +03:00
}
2016-01-04 20:36:34 +03:00
void mtk_ddp_add_comp_to_path ( void __iomem * config_regs ,
enum mtk_ddp_comp_id cur ,
enum mtk_ddp_comp_id next )
{
unsigned int addr , value , reg ;
value = mtk_ddp_mout_en ( cur , next , & addr ) ;
if ( value ) {
reg = readl_relaxed ( config_regs + addr ) | value ;
writel_relaxed ( reg , config_regs + addr ) ;
}
2017-03-31 14:30:33 +03:00
mtk_ddp_sout_sel ( config_regs , cur , next ) ;
2016-01-04 20:36:34 +03:00
value = mtk_ddp_sel_in ( cur , next , & addr ) ;
if ( value ) {
reg = readl_relaxed ( config_regs + addr ) | value ;
writel_relaxed ( reg , config_regs + addr ) ;
}
}
void mtk_ddp_remove_comp_from_path ( void __iomem * config_regs ,
enum mtk_ddp_comp_id cur ,
enum mtk_ddp_comp_id next )
{
unsigned int addr , value , reg ;
value = mtk_ddp_mout_en ( cur , next , & addr ) ;
if ( value ) {
reg = readl_relaxed ( config_regs + addr ) & ~ value ;
writel_relaxed ( reg , config_regs + addr ) ;
}
value = mtk_ddp_sel_in ( cur , next , & addr ) ;
if ( value ) {
reg = readl_relaxed ( config_regs + addr ) & ~ value ;
writel_relaxed ( reg , config_regs + addr ) ;
}
}
struct mtk_disp_mutex * mtk_disp_mutex_get ( struct device * dev , unsigned int id )
{
struct mtk_ddp * ddp = dev_get_drvdata ( dev ) ;
if ( id > = 10 )
return ERR_PTR ( - EINVAL ) ;
if ( ddp - > mutex [ id ] . claimed )
return ERR_PTR ( - EBUSY ) ;
ddp - > mutex [ id ] . claimed = true ;
return & ddp - > mutex [ id ] ;
}
void mtk_disp_mutex_put ( struct mtk_disp_mutex * mutex )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
WARN_ON ( & ddp - > mutex [ mutex - > id ] ! = mutex ) ;
mutex - > claimed = false ;
}
int mtk_disp_mutex_prepare ( struct mtk_disp_mutex * mutex )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
return clk_prepare_enable ( ddp - > clk ) ;
}
void mtk_disp_mutex_unprepare ( struct mtk_disp_mutex * mutex )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
clk_disable_unprepare ( ddp - > clk ) ;
}
void mtk_disp_mutex_add_comp ( struct mtk_disp_mutex * mutex ,
enum mtk_ddp_comp_id id )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
unsigned int reg ;
2019-08-29 17:50:31 +03:00
unsigned int sof_id ;
2018-06-20 11:19:04 +03:00
unsigned int offset ;
2016-01-04 20:36:34 +03:00
WARN_ON ( & ddp - > mutex [ mutex - > id ] ! = mutex ) ;
switch ( id ) {
case DDP_COMPONENT_DSI0 :
2019-08-29 17:50:31 +03:00
sof_id = DDP_MUTEX_SOF_DSI0 ;
2016-01-04 20:36:34 +03:00
break ;
case DDP_COMPONENT_DSI1 :
2019-08-29 17:50:31 +03:00
sof_id = DDP_MUTEX_SOF_DSI0 ;
2016-01-04 20:36:34 +03:00
break ;
2018-06-20 11:19:28 +03:00
case DDP_COMPONENT_DSI2 :
2019-08-29 17:50:31 +03:00
sof_id = DDP_MUTEX_SOF_DSI2 ;
2018-06-20 11:19:28 +03:00
break ;
2018-06-20 11:19:29 +03:00
case DDP_COMPONENT_DSI3 :
2019-08-29 17:50:31 +03:00
sof_id = DDP_MUTEX_SOF_DSI3 ;
2018-06-20 11:19:29 +03:00
break ;
2016-01-04 20:36:34 +03:00
case DDP_COMPONENT_DPI0 :
2019-08-29 17:50:31 +03:00
sof_id = DDP_MUTEX_SOF_DPI0 ;
2016-01-04 20:36:34 +03:00
break ;
2018-06-20 11:19:27 +03:00
case DDP_COMPONENT_DPI1 :
2019-08-29 17:50:31 +03:00
sof_id = DDP_MUTEX_SOF_DPI1 ;
2018-06-20 11:19:27 +03:00
break ;
2016-01-04 20:36:34 +03:00
default :
2019-08-29 17:50:29 +03:00
if ( ddp - > data - > mutex_mod [ id ] < 32 ) {
2019-08-29 17:50:30 +03:00
offset = DISP_REG_MUTEX_MOD ( ddp - > data - > mutex_mod_reg ,
mutex - > id ) ;
2018-06-20 11:19:04 +03:00
reg = readl_relaxed ( ddp - > regs + offset ) ;
2019-08-29 17:50:29 +03:00
reg | = 1 < < ddp - > data - > mutex_mod [ id ] ;
2018-06-20 11:19:04 +03:00
writel_relaxed ( reg , ddp - > regs + offset ) ;
} else {
offset = DISP_REG_MUTEX_MOD2 ( mutex - > id ) ;
reg = readl_relaxed ( ddp - > regs + offset ) ;
2019-08-29 17:50:29 +03:00
reg | = 1 < < ( ddp - > data - > mutex_mod [ id ] - 32 ) ;
2018-06-20 11:19:04 +03:00
writel_relaxed ( reg , ddp - > regs + offset ) ;
}
2016-01-04 20:36:34 +03:00
return ;
}
2019-08-29 17:50:31 +03:00
writel_relaxed ( ddp - > data - > mutex_sof [ sof_id ] ,
2019-08-29 17:50:32 +03:00
ddp - > regs +
DISP_REG_MUTEX_SOF ( ddp - > data - > mutex_sof_reg , mutex - > id ) ) ;
2016-01-04 20:36:34 +03:00
}
void mtk_disp_mutex_remove_comp ( struct mtk_disp_mutex * mutex ,
enum mtk_ddp_comp_id id )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
unsigned int reg ;
2018-06-20 11:19:04 +03:00
unsigned int offset ;
2016-01-04 20:36:34 +03:00
WARN_ON ( & ddp - > mutex [ mutex - > id ] ! = mutex ) ;
switch ( id ) {
case DDP_COMPONENT_DSI0 :
case DDP_COMPONENT_DSI1 :
2018-06-20 11:19:28 +03:00
case DDP_COMPONENT_DSI2 :
2018-06-20 11:19:29 +03:00
case DDP_COMPONENT_DSI3 :
2016-01-04 20:36:34 +03:00
case DDP_COMPONENT_DPI0 :
2018-06-20 11:19:27 +03:00
case DDP_COMPONENT_DPI1 :
2016-01-04 20:36:34 +03:00
writel_relaxed ( MUTEX_SOF_SINGLE_MODE ,
2019-08-29 17:50:31 +03:00
ddp - > regs +
2019-08-29 17:50:32 +03:00
DISP_REG_MUTEX_SOF ( ddp - > data - > mutex_sof_reg ,
mutex - > id ) ) ;
2016-01-04 20:36:34 +03:00
break ;
default :
2019-08-29 17:50:29 +03:00
if ( ddp - > data - > mutex_mod [ id ] < 32 ) {
2019-08-29 17:50:30 +03:00
offset = DISP_REG_MUTEX_MOD ( ddp - > data - > mutex_mod_reg ,
mutex - > id ) ;
2018-06-20 11:19:04 +03:00
reg = readl_relaxed ( ddp - > regs + offset ) ;
2019-08-29 17:50:29 +03:00
reg & = ~ ( 1 < < ddp - > data - > mutex_mod [ id ] ) ;
2018-06-20 11:19:04 +03:00
writel_relaxed ( reg , ddp - > regs + offset ) ;
} else {
offset = DISP_REG_MUTEX_MOD2 ( mutex - > id ) ;
reg = readl_relaxed ( ddp - > regs + offset ) ;
2019-08-29 17:50:29 +03:00
reg & = ~ ( 1 < < ( ddp - > data - > mutex_mod [ id ] - 32 ) ) ;
2018-06-20 11:19:04 +03:00
writel_relaxed ( reg , ddp - > regs + offset ) ;
}
2016-01-04 20:36:34 +03:00
break ;
}
}
void mtk_disp_mutex_enable ( struct mtk_disp_mutex * mutex )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
WARN_ON ( & ddp - > mutex [ mutex - > id ] ! = mutex ) ;
writel ( 1 , ddp - > regs + DISP_REG_MUTEX_EN ( mutex - > id ) ) ;
}
void mtk_disp_mutex_disable ( struct mtk_disp_mutex * mutex )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
WARN_ON ( & ddp - > mutex [ mutex - > id ] ! = mutex ) ;
writel ( 0 , ddp - > regs + DISP_REG_MUTEX_EN ( mutex - > id ) ) ;
}
2017-03-31 14:30:31 +03:00
void mtk_disp_mutex_acquire ( struct mtk_disp_mutex * mutex )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
u32 tmp ;
writel ( 1 , ddp - > regs + DISP_REG_MUTEX_EN ( mutex - > id ) ) ;
writel ( 1 , ddp - > regs + DISP_REG_MUTEX ( mutex - > id ) ) ;
if ( readl_poll_timeout_atomic ( ddp - > regs + DISP_REG_MUTEX ( mutex - > id ) ,
tmp , tmp & INT_MUTEX , 1 , 10000 ) )
pr_err ( " could not acquire mutex %d \n " , mutex - > id ) ;
}
void mtk_disp_mutex_release ( struct mtk_disp_mutex * mutex )
{
struct mtk_ddp * ddp = container_of ( mutex , struct mtk_ddp ,
mutex [ mutex - > id ] ) ;
writel ( 0 , ddp - > regs + DISP_REG_MUTEX ( mutex - > id ) ) ;
}
2016-01-04 20:36:34 +03:00
static int mtk_ddp_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct mtk_ddp * ddp ;
struct resource * regs ;
int i ;
ddp = devm_kzalloc ( dev , sizeof ( * ddp ) , GFP_KERNEL ) ;
if ( ! ddp )
return - ENOMEM ;
for ( i = 0 ; i < 10 ; i + + )
ddp - > mutex [ i ] . id = i ;
2019-10-09 11:37:47 +03:00
ddp - > data = of_device_get_match_data ( dev ) ;
if ( ! ddp - > data - > no_clk ) {
ddp - > clk = devm_clk_get ( dev , NULL ) ;
if ( IS_ERR ( ddp - > clk ) ) {
dev_err ( dev , " Failed to get clock \n " ) ;
return PTR_ERR ( ddp - > clk ) ;
}
2016-01-04 20:36:34 +03:00
}
regs = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
ddp - > regs = devm_ioremap_resource ( dev , regs ) ;
if ( IS_ERR ( ddp - > regs ) ) {
dev_err ( dev , " Failed to map mutex registers \n " ) ;
return PTR_ERR ( ddp - > regs ) ;
}
platform_set_drvdata ( pdev , ddp ) ;
return 0 ;
}
static int mtk_ddp_remove ( struct platform_device * pdev )
{
return 0 ;
}
static const struct of_device_id ddp_driver_dt_match [ ] = {
2019-08-29 17:50:29 +03:00
{ . compatible = " mediatek,mt2701-disp-mutex " ,
. data = & mt2701_ddp_driver_data } ,
{ . compatible = " mediatek,mt2712-disp-mutex " ,
. data = & mt2712_ddp_driver_data } ,
{ . compatible = " mediatek,mt8173-disp-mutex " ,
. data = & mt8173_ddp_driver_data } ,
2016-01-04 20:36:34 +03:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , ddp_driver_dt_match ) ;
struct platform_driver mtk_ddp_driver = {
. probe = mtk_ddp_probe ,
. remove = mtk_ddp_remove ,
. driver = {
. name = " mediatek-ddp " ,
. owner = THIS_MODULE ,
. of_match_table = ddp_driver_dt_match ,
} ,
} ;