2016-01-04 18:36:34 +01:00
/*
* Copyright ( c ) 2015 MediaTek Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# include <linux/clk.h>
2017-03-31 19:30:31 +08:00
# include <linux/iopoll.h>
2016-01-04 18:36:34 +01: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 16:19:20 +08:00
# define DISP_REG_CONFIG_DSIE_SEL_IN 0x0a4
2018-06-20 16:19:19 +08:00
# define DISP_REG_CONFIG_DSIO_SEL_IN 0x0a8
2016-01-04 18:36:34 +01:00
# define DISP_REG_CONFIG_DPI_SEL_IN 0x0ac
2018-06-20 16:19:22 +08:00
# define DISP_REG_CONFIG_DISP_RDMA2_SOUT 0x0b8
2018-06-20 16:19:15 +08:00
# define DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN 0x0c4
2018-06-20 16:19:14 +08:00
# define DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN 0x0c8
2016-01-04 18:36:34 +01:00
# define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100
2017-03-31 19:30:33 +08:00
# define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030
# define DISP_REG_CONFIG_OUT_SEL 0x04c
# define DISP_REG_CONFIG_DSI_SEL 0x050
2016-01-04 18:36:34 +01:00
# define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
2017-03-31 19:30:31 +08:00
# define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
2016-01-04 18:36:34 +01:00
# define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
# define DISP_REG_MUTEX_MOD(n) (0x2c + 0x20 * (n))
# define DISP_REG_MUTEX_SOF(n) (0x30 + 0x20 * (n))
2018-06-20 16:19:04 +08:00
# define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
2016-01-04 18:36:34 +01:00
2017-03-31 19:30:31 +08:00
# define INT_MUTEX BIT(1)
2018-06-20 16:19:04 +08: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 16:19:31 +08: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 16:19:04 +08: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 19:30:39 +08:00
2016-01-04 18:36:34 +01: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 16:19:27 +08:00
# define MUTEX_SOF_DPI1 4
2018-06-20 16:19:28 +08:00
# define MUTEX_SOF_DSI2 5
2018-06-20 16:19:29 +08:00
# define MUTEX_SOF_DSI3 6
2016-01-04 18:36:34 +01:00
# define OVL0_MOUT_EN_COLOR0 0x1
# define OD_MOUT_EN_RDMA0 0x1
2018-06-20 16:19:13 +08:00
# define OD1_MOUT_EN_RDMA1 BIT(16)
2016-01-04 18:36:34 +01: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 16:19:15 +08:00
# define RDMA0_SOUT_DPI0 0x2
2018-08-09 10:15:36 +08:00
# define RDMA0_SOUT_DPI1 0x3
2018-08-09 10:15:37 +08:00
# define RDMA0_SOUT_DSI1 0x1
2018-06-20 16:19:16 +08:00
# define RDMA0_SOUT_DSI2 0x4
2018-06-20 16:19:17 +08:00
# define RDMA0_SOUT_DSI3 0x5
2018-06-20 16:19:14 +08:00
# define RDMA1_SOUT_DPI0 0x2
2018-06-20 16:19:18 +08:00
# define RDMA1_SOUT_DPI1 0x3
2018-06-20 16:19:19 +08:00
# define RDMA1_SOUT_DSI1 0x1
2018-06-20 16:19:20 +08:00
# define RDMA1_SOUT_DSI2 0x4
2018-06-20 16:19:21 +08:00
# define RDMA1_SOUT_DSI3 0x5
2018-06-20 16:19:22 +08:00
# define RDMA2_SOUT_DPI0 0x2
2018-06-20 16:19:23 +08:00
# define RDMA2_SOUT_DPI1 0x3
2018-06-20 16:19:24 +08:00
# define RDMA2_SOUT_DSI1 0x1
2018-06-20 16:19:25 +08:00
# define RDMA2_SOUT_DSI2 0x4
2018-06-20 16:19:26 +08:00
# define RDMA2_SOUT_DSI3 0x5
2016-01-04 18:36:34 +01:00
# define DPI0_SEL_IN_RDMA1 0x1
2018-06-20 16:19:22 +08:00
# define DPI0_SEL_IN_RDMA2 0x3
2018-06-20 16:19:18 +08:00
# define DPI1_SEL_IN_RDMA1 (0x1 << 8)
2018-06-20 16:19:23 +08:00
# define DPI1_SEL_IN_RDMA2 (0x3 << 8)
2018-08-09 10:15:38 +08:00
# define DSI0_SEL_IN_RDMA1 0x1
2018-08-09 10:15:39 +08:00
# define DSI0_SEL_IN_RDMA2 0x4
2018-06-20 16:19:19 +08:00
# define DSI1_SEL_IN_RDMA1 0x1
2018-06-20 16:19:24 +08:00
# define DSI1_SEL_IN_RDMA2 0x4
2018-06-20 16:19:20 +08:00
# define DSI2_SEL_IN_RDMA1 (0x1 << 16)
2018-06-20 16:19:25 +08:00
# define DSI2_SEL_IN_RDMA2 (0x4 << 16)
2018-06-20 16:19:21 +08:00
# define DSI3_SEL_IN_RDMA1 (0x1 << 16)
2018-06-20 16:19:26 +08:00
# define DSI3_SEL_IN_RDMA2 (0x4 << 16)
2016-01-04 18:36:34 +01:00
# define COLOR1_SEL_IN_OVL1 0x1
2017-03-31 19:30:33 +08:00
# define OVL_MOUT_EN_RDMA 0x1
# define BLS_TO_DSI_RDMA1_TO_DPI1 0x8
# define DSI_SEL_IN_BLS 0x0
2016-01-04 18:36:34 +01:00
struct mtk_disp_mutex {
int id ;
bool claimed ;
} ;
struct mtk_ddp {
struct device * dev ;
struct clk * clk ;
void __iomem * regs ;
struct mtk_disp_mutex mutex [ 10 ] ;
2017-03-31 19:30:30 +08:00
const unsigned int * mutex_mod ;
2016-01-04 18:36:34 +01:00
} ;
2017-03-31 19:30:39 +08: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 16:19:31 +08: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 19:30:30 +08:00
static const unsigned int mt8173_mutex_mod [ DDP_COMPONENT_ID_MAX ] = {
2018-06-20 16:19:05 +08:00
[ DDP_COMPONENT_AAL0 ] = MT8173_MUTEX_MOD_DISP_AAL ,
2017-03-31 19:30:30 +08: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 16:19:06 +08:00
[ DDP_COMPONENT_OD0 ] = MT8173_MUTEX_MOD_DISP_OD ,
2017-03-31 19:30:30 +08: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 18:36:34 +01: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 19:30:33 +08: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 16:19:06 +08:00
} else if ( cur = = DDP_COMPONENT_OD0 & & next = = DDP_COMPONENT_RDMA0 ) {
2016-01-04 18:36:34 +01: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 16:19:13 +08: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 16:19:15 +08: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 10:15:36 +08: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 10:15:37 +08: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 16:19:16 +08: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 16:19:17 +08: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 16:19:19 +08: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 16:19:20 +08: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 16:19:21 +08: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 18:36:34 +01:00
} else if ( cur = = DDP_COMPONENT_RDMA1 & & next = = DDP_COMPONENT_DPI0 ) {
2018-06-20 16:19:14 +08:00
* addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN ;
value = RDMA1_SOUT_DPI0 ;
2018-06-20 16:19:18 +08: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 16:19:22 +08: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 16:19:23 +08: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 16:19:24 +08: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 16:19:25 +08: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 16:19:26 +08: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 18:36:34 +01: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 16:19:18 +08: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 10:15:38 +08: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 16:19:19 +08: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 16:19:20 +08: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 16:19:21 +08: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 16:19:22 +08: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 16:19:23 +08: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 10:15:39 +08: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 16:19:24 +08:00
} else if ( cur = = DDP_COMPONENT_RDMA2 & & next = = DDP_COMPONENT_DSI1 ) {
2018-08-09 10:15:49 +08:00
* addr = DISP_REG_CONFIG_DSIO_SEL_IN ;
2018-06-20 16:19:24 +08:00
value = DSI1_SEL_IN_RDMA2 ;
2018-06-20 16:19:25 +08: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 16:19:26 +08: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 18:36:34 +01: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 19:30:33 +08: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 18:36:34 +01:00
} else {
value = 0 ;
}
return value ;
}
2017-03-31 19:30:33 +08:00
static void mtk_ddp_sout_sel ( void __iomem * config_regs ,
enum mtk_ddp_comp_id cur ,
enum mtk_ddp_comp_id next )
{
if ( cur = = DDP_COMPONENT_BLS & & next = = DDP_COMPONENT_DSI0 )
writel_relaxed ( BLS_TO_DSI_RDMA1_TO_DPI1 ,
config_regs + DISP_REG_CONFIG_OUT_SEL ) ;
}
2016-01-04 18:36:34 +01: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 19:30:33 +08:00
mtk_ddp_sout_sel ( config_regs , cur , next ) ;
2016-01-04 18:36:34 +01: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 ;
2018-06-20 16:19:04 +08:00
unsigned int offset ;
2016-01-04 18:36:34 +01:00
WARN_ON ( & ddp - > mutex [ mutex - > id ] ! = mutex ) ;
switch ( id ) {
case DDP_COMPONENT_DSI0 :
reg = MUTEX_SOF_DSI0 ;
break ;
case DDP_COMPONENT_DSI1 :
reg = MUTEX_SOF_DSI0 ;
break ;
2018-06-20 16:19:28 +08:00
case DDP_COMPONENT_DSI2 :
reg = MUTEX_SOF_DSI2 ;
break ;
2018-06-20 16:19:29 +08:00
case DDP_COMPONENT_DSI3 :
reg = MUTEX_SOF_DSI3 ;
break ;
2016-01-04 18:36:34 +01:00
case DDP_COMPONENT_DPI0 :
reg = MUTEX_SOF_DPI0 ;
break ;
2018-06-20 16:19:27 +08:00
case DDP_COMPONENT_DPI1 :
reg = MUTEX_SOF_DPI1 ;
break ;
2016-01-04 18:36:34 +01:00
default :
2018-06-20 16:19:04 +08:00
if ( ddp - > mutex_mod [ id ] < 32 ) {
offset = DISP_REG_MUTEX_MOD ( mutex - > id ) ;
reg = readl_relaxed ( ddp - > regs + offset ) ;
reg | = 1 < < ddp - > mutex_mod [ id ] ;
writel_relaxed ( reg , ddp - > regs + offset ) ;
} else {
offset = DISP_REG_MUTEX_MOD2 ( mutex - > id ) ;
reg = readl_relaxed ( ddp - > regs + offset ) ;
reg | = 1 < < ( ddp - > mutex_mod [ id ] - 32 ) ;
writel_relaxed ( reg , ddp - > regs + offset ) ;
}
2016-01-04 18:36:34 +01:00
return ;
}
writel_relaxed ( reg , ddp - > regs + DISP_REG_MUTEX_SOF ( mutex - > id ) ) ;
}
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 16:19:04 +08:00
unsigned int offset ;
2016-01-04 18:36:34 +01:00
WARN_ON ( & ddp - > mutex [ mutex - > id ] ! = mutex ) ;
switch ( id ) {
case DDP_COMPONENT_DSI0 :
case DDP_COMPONENT_DSI1 :
2018-06-20 16:19:28 +08:00
case DDP_COMPONENT_DSI2 :
2018-06-20 16:19:29 +08:00
case DDP_COMPONENT_DSI3 :
2016-01-04 18:36:34 +01:00
case DDP_COMPONENT_DPI0 :
2018-06-20 16:19:27 +08:00
case DDP_COMPONENT_DPI1 :
2016-01-04 18:36:34 +01:00
writel_relaxed ( MUTEX_SOF_SINGLE_MODE ,
ddp - > regs + DISP_REG_MUTEX_SOF ( mutex - > id ) ) ;
break ;
default :
2018-06-20 16:19:04 +08:00
if ( ddp - > mutex_mod [ id ] < 32 ) {
offset = DISP_REG_MUTEX_MOD ( mutex - > id ) ;
reg = readl_relaxed ( ddp - > regs + offset ) ;
reg & = ~ ( 1 < < ddp - > mutex_mod [ id ] ) ;
writel_relaxed ( reg , ddp - > regs + offset ) ;
} else {
offset = DISP_REG_MUTEX_MOD2 ( mutex - > id ) ;
reg = readl_relaxed ( ddp - > regs + offset ) ;
reg & = ~ ( 1 < < ( ddp - > mutex_mod [ id ] - 32 ) ) ;
writel_relaxed ( reg , ddp - > regs + offset ) ;
}
2016-01-04 18:36:34 +01: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 19:30:31 +08: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 18:36:34 +01: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 ;
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 ) ;
}
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 ) ;
}
2017-03-31 19:30:30 +08:00
ddp - > mutex_mod = of_device_get_match_data ( dev ) ;
2016-01-04 18:36:34 +01:00
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 [ ] = {
2017-03-31 19:30:39 +08:00
{ . compatible = " mediatek,mt2701-disp-mutex " , . data = mt2701_mutex_mod } ,
2018-06-20 16:19:31 +08:00
{ . compatible = " mediatek,mt2712-disp-mutex " , . data = mt2712_mutex_mod } ,
2017-03-31 19:30:30 +08:00
{ . compatible = " mediatek,mt8173-disp-mutex " , . data = mt8173_mutex_mod } ,
2016-01-04 18:36:34 +01: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 ,
} ,
} ;