2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-01-04 20:36:36 +03:00
/*
* Copyright ( c ) 2014 MediaTek Inc .
* Author : Jie Qiu < jie . qiu @ mediatek . com >
*/
2019-07-16 09:42:20 +03:00
# include <linux/clk.h>
2016-01-04 20:36:36 +03:00
# include <linux/component.h>
2019-07-16 09:42:20 +03:00
# include <linux/interrupt.h>
# include <linux/kernel.h>
2016-01-04 20:36:36 +03:00
# include <linux/of.h>
2018-10-03 06:41:42 +03:00
# include <linux/of_device.h>
2020-04-15 04:13:19 +03:00
# include <linux/of_gpio.h>
2016-01-04 20:36:36 +03:00
# include <linux/of_graph.h>
2020-04-15 04:13:19 +03:00
# include <linux/pinctrl/consumer.h>
2019-07-16 09:42:20 +03:00
# include <linux/platform_device.h>
2016-01-04 20:36:36 +03:00
# include <linux/types.h>
2019-07-16 09:42:20 +03:00
2018-03-31 17:47:58 +03:00
# include <video/videomode.h>
2016-01-04 20:36:36 +03:00
2019-07-16 09:42:20 +03:00
# include <drm/drm_atomic_helper.h>
2019-08-26 18:26:29 +03:00
# include <drm/drm_bridge.h>
2020-12-03 11:24:45 +03:00
# include <drm/drm_bridge_connector.h>
2019-07-16 09:42:20 +03:00
# include <drm/drm_crtc.h>
# include <drm/drm_of.h>
2020-03-05 18:59:38 +03:00
# include <drm/drm_simple_kms_helper.h>
2019-07-16 09:42:20 +03:00
2020-10-12 06:50:47 +03:00
# include "mtk_disp_drv.h"
2016-01-04 20:36:36 +03:00
# include "mtk_dpi_regs.h"
# include "mtk_drm_ddp_comp.h"
enum mtk_dpi_out_bit_num {
MTK_DPI_OUT_BIT_NUM_8BITS ,
MTK_DPI_OUT_BIT_NUM_10BITS ,
MTK_DPI_OUT_BIT_NUM_12BITS ,
MTK_DPI_OUT_BIT_NUM_16BITS
} ;
enum mtk_dpi_out_yc_map {
MTK_DPI_OUT_YC_MAP_RGB ,
MTK_DPI_OUT_YC_MAP_CYCY ,
MTK_DPI_OUT_YC_MAP_YCYC ,
MTK_DPI_OUT_YC_MAP_CY ,
MTK_DPI_OUT_YC_MAP_YC
} ;
enum mtk_dpi_out_channel_swap {
MTK_DPI_OUT_CHANNEL_SWAP_RGB ,
MTK_DPI_OUT_CHANNEL_SWAP_GBR ,
MTK_DPI_OUT_CHANNEL_SWAP_BRG ,
MTK_DPI_OUT_CHANNEL_SWAP_RBG ,
MTK_DPI_OUT_CHANNEL_SWAP_GRB ,
MTK_DPI_OUT_CHANNEL_SWAP_BGR
} ;
enum mtk_dpi_out_color_format {
2022-07-05 13:25:26 +03:00
MTK_DPI_COLOR_FORMAT_RGB ,
MTK_DPI_COLOR_FORMAT_YCBCR_422
2016-01-04 20:36:36 +03:00
} ;
struct mtk_dpi {
struct drm_encoder encoder ;
2020-08-26 11:53:17 +03:00
struct drm_bridge bridge ;
2020-08-26 11:53:16 +03:00
struct drm_bridge * next_bridge ;
2020-12-03 11:24:45 +03:00
struct drm_connector * connector ;
2016-01-04 20:36:36 +03:00
void __iomem * regs ;
struct device * dev ;
struct clk * engine_clk ;
struct clk * pixel_clk ;
struct clk * tvd_clk ;
int irq ;
struct drm_display_mode mode ;
2018-10-03 06:41:42 +03:00
const struct mtk_dpi_conf * conf ;
2016-01-04 20:36:36 +03:00
enum mtk_dpi_out_color_format color_format ;
enum mtk_dpi_out_yc_map yc_map ;
enum mtk_dpi_out_bit_num bit_num ;
enum mtk_dpi_out_channel_swap channel_swap ;
2020-04-15 04:13:19 +03:00
struct pinctrl * pinctrl ;
struct pinctrl_state * pins_gpio ;
struct pinctrl_state * pins_dpi ;
2021-05-26 11:52:17 +03:00
u32 output_fmt ;
2018-10-03 06:41:41 +03:00
int refcount ;
2016-01-04 20:36:36 +03:00
} ;
2020-08-26 11:53:17 +03:00
static inline struct mtk_dpi * bridge_to_dpi ( struct drm_bridge * b )
2016-01-04 20:36:36 +03:00
{
2020-08-26 11:53:17 +03:00
return container_of ( b , struct mtk_dpi , bridge ) ;
2016-01-04 20:36:36 +03:00
}
enum mtk_dpi_polarity {
MTK_DPI_POLARITY_RISING ,
MTK_DPI_POLARITY_FALLING ,
} ;
struct mtk_dpi_polarities {
enum mtk_dpi_polarity de_pol ;
enum mtk_dpi_polarity ck_pol ;
enum mtk_dpi_polarity hsync_pol ;
enum mtk_dpi_polarity vsync_pol ;
} ;
struct mtk_dpi_sync_param {
u32 sync_width ;
u32 front_porch ;
u32 back_porch ;
bool shift_half_line ;
} ;
struct mtk_dpi_yc_limit {
u16 y_top ;
u16 y_bottom ;
u16 c_top ;
u16 c_bottom ;
} ;
2022-07-01 06:58:32 +03:00
/**
* struct mtk_dpi_conf - Configuration of mediatek dpi .
* @ cal_factor : Callback function to calculate factor value .
* @ reg_h_fre_con : Register address of frequency control .
* @ max_clock_khz : Max clock frequency supported for this SoCs in khz units .
* @ edge_sel_en : Enable of edge selection .
* @ output_fmts : Array of supported output formats .
* @ num_output_fmts : Quantity of supported output formats .
2022-07-01 06:58:35 +03:00
* @ is_ck_de_pol : Support CK / DE polarity .
2022-07-01 06:58:36 +03:00
* @ swap_input_support : Support input swap function .
2022-07-01 06:58:37 +03:00
* @ dimension_mask : Mask used for HWIDTH , HPORCH , VSYNC_WIDTH and VSYNC_PORCH
* ( no shift ) .
2022-07-01 06:58:38 +03:00
* @ hvsize_mask : Mask of HSIZE and VSIZE mask ( no shift ) .
2022-07-01 06:58:39 +03:00
* @ channel_swap_shift : Shift value of channel swap .
2022-07-01 06:58:40 +03:00
* @ yuv422_en_bit : Enable bit of yuv422 .
2022-07-01 06:58:41 +03:00
* @ csc_enable_bit : Enable bit of CSC .
2022-07-01 06:58:32 +03:00
*/
2018-10-03 06:41:42 +03:00
struct mtk_dpi_conf {
2018-10-03 06:41:44 +03:00
unsigned int ( * cal_factor ) ( int clock ) ;
2018-10-03 06:41:42 +03:00
u32 reg_h_fre_con ;
2021-03-18 08:40:55 +03:00
u32 max_clock_khz ;
2018-10-03 06:41:43 +03:00
bool edge_sel_en ;
2021-05-26 11:52:18 +03:00
const u32 * output_fmts ;
u32 num_output_fmts ;
2022-07-01 06:58:35 +03:00
bool is_ck_de_pol ;
2022-07-01 06:58:36 +03:00
bool swap_input_support ;
2022-07-01 06:58:37 +03:00
u32 dimension_mask ;
2022-07-01 06:58:38 +03:00
u32 hvsize_mask ;
2022-07-01 06:58:39 +03:00
u32 channel_swap_shift ;
2022-07-01 06:58:40 +03:00
u32 yuv422_en_bit ;
2022-07-01 06:58:41 +03:00
u32 csc_enable_bit ;
2018-10-03 06:41:42 +03:00
} ;
2016-01-04 20:36:36 +03:00
static void mtk_dpi_mask ( struct mtk_dpi * dpi , u32 offset , u32 val , u32 mask )
{
u32 tmp = readl ( dpi - > regs + offset ) & ~ mask ;
tmp | = ( val & mask ) ;
writel ( tmp , dpi - > regs + offset ) ;
}
static void mtk_dpi_sw_reset ( struct mtk_dpi * dpi , bool reset )
{
mtk_dpi_mask ( dpi , DPI_RET , reset ? RST : 0 , RST ) ;
}
static void mtk_dpi_enable ( struct mtk_dpi * dpi )
{
mtk_dpi_mask ( dpi , DPI_EN , EN , EN ) ;
}
static void mtk_dpi_disable ( struct mtk_dpi * dpi )
{
mtk_dpi_mask ( dpi , DPI_EN , 0 , EN ) ;
}
static void mtk_dpi_config_hsync ( struct mtk_dpi * dpi ,
struct mtk_dpi_sync_param * sync )
{
2022-07-01 06:58:37 +03:00
mtk_dpi_mask ( dpi , DPI_TGEN_HWIDTH , sync - > sync_width < < HPW ,
dpi - > conf - > dimension_mask < < HPW ) ;
mtk_dpi_mask ( dpi , DPI_TGEN_HPORCH , sync - > back_porch < < HBP ,
dpi - > conf - > dimension_mask < < HBP ) ;
2016-01-04 20:36:36 +03:00
mtk_dpi_mask ( dpi , DPI_TGEN_HPORCH , sync - > front_porch < < HFP ,
2022-07-01 06:58:37 +03:00
dpi - > conf - > dimension_mask < < HFP ) ;
2016-01-04 20:36:36 +03:00
}
static void mtk_dpi_config_vsync ( struct mtk_dpi * dpi ,
struct mtk_dpi_sync_param * sync ,
u32 width_addr , u32 porch_addr )
{
mtk_dpi_mask ( dpi , width_addr ,
sync - > shift_half_line < < VSYNC_HALF_LINE_SHIFT ,
VSYNC_HALF_LINE_MASK ) ;
2022-07-01 06:58:37 +03:00
mtk_dpi_mask ( dpi , width_addr ,
sync - > sync_width < < VSYNC_WIDTH_SHIFT ,
dpi - > conf - > dimension_mask < < VSYNC_WIDTH_SHIFT ) ;
2016-01-04 20:36:36 +03:00
mtk_dpi_mask ( dpi , porch_addr ,
sync - > back_porch < < VSYNC_BACK_PORCH_SHIFT ,
2022-07-01 06:58:37 +03:00
dpi - > conf - > dimension_mask < < VSYNC_BACK_PORCH_SHIFT ) ;
2016-01-04 20:36:36 +03:00
mtk_dpi_mask ( dpi , porch_addr ,
sync - > front_porch < < VSYNC_FRONT_PORCH_SHIFT ,
2022-07-01 06:58:37 +03:00
dpi - > conf - > dimension_mask < < VSYNC_FRONT_PORCH_SHIFT ) ;
2016-01-04 20:36:36 +03:00
}
static void mtk_dpi_config_vsync_lodd ( struct mtk_dpi * dpi ,
struct mtk_dpi_sync_param * sync )
{
mtk_dpi_config_vsync ( dpi , sync , DPI_TGEN_VWIDTH , DPI_TGEN_VPORCH ) ;
}
static void mtk_dpi_config_vsync_leven ( struct mtk_dpi * dpi ,
struct mtk_dpi_sync_param * sync )
{
mtk_dpi_config_vsync ( dpi , sync , DPI_TGEN_VWIDTH_LEVEN ,
DPI_TGEN_VPORCH_LEVEN ) ;
}
static void mtk_dpi_config_vsync_rodd ( struct mtk_dpi * dpi ,
struct mtk_dpi_sync_param * sync )
{
mtk_dpi_config_vsync ( dpi , sync , DPI_TGEN_VWIDTH_RODD ,
DPI_TGEN_VPORCH_RODD ) ;
}
static void mtk_dpi_config_vsync_reven ( struct mtk_dpi * dpi ,
struct mtk_dpi_sync_param * sync )
{
mtk_dpi_config_vsync ( dpi , sync , DPI_TGEN_VWIDTH_REVEN ,
DPI_TGEN_VPORCH_REVEN ) ;
}
static void mtk_dpi_config_pol ( struct mtk_dpi * dpi ,
struct mtk_dpi_polarities * dpi_pol )
{
unsigned int pol ;
2022-07-01 06:58:35 +03:00
unsigned int mask ;
2016-01-04 20:36:36 +03:00
2022-07-01 06:58:35 +03:00
mask = HSYNC_POL | VSYNC_POL ;
pol = ( dpi_pol - > hsync_pol = = MTK_DPI_POLARITY_RISING ? 0 : HSYNC_POL ) |
2016-01-04 20:36:36 +03:00
( dpi_pol - > vsync_pol = = MTK_DPI_POLARITY_RISING ? 0 : VSYNC_POL ) ;
2022-07-01 06:58:35 +03:00
if ( dpi - > conf - > is_ck_de_pol ) {
mask | = CK_POL | DE_POL ;
pol | = ( dpi_pol - > ck_pol = = MTK_DPI_POLARITY_RISING ?
0 : CK_POL ) |
( dpi_pol - > de_pol = = MTK_DPI_POLARITY_RISING ?
0 : DE_POL ) ;
}
mtk_dpi_mask ( dpi , DPI_OUTPUT_SETTING , pol , mask ) ;
2016-01-04 20:36:36 +03:00
}
static void mtk_dpi_config_3d ( struct mtk_dpi * dpi , bool en_3d )
{
mtk_dpi_mask ( dpi , DPI_CON , en_3d ? TDFP_EN : 0 , TDFP_EN ) ;
}
static void mtk_dpi_config_interface ( struct mtk_dpi * dpi , bool inter )
{
mtk_dpi_mask ( dpi , DPI_CON , inter ? INTL_EN : 0 , INTL_EN ) ;
}
static void mtk_dpi_config_fb_size ( struct mtk_dpi * dpi , u32 width , u32 height )
{
2022-07-01 06:58:38 +03:00
mtk_dpi_mask ( dpi , DPI_SIZE , width < < HSIZE ,
dpi - > conf - > hvsize_mask < < HSIZE ) ;
mtk_dpi_mask ( dpi , DPI_SIZE , height < < VSIZE ,
dpi - > conf - > hvsize_mask < < VSIZE ) ;
2016-01-04 20:36:36 +03:00
}
2022-07-01 06:58:34 +03:00
static void mtk_dpi_config_channel_limit ( struct mtk_dpi * dpi )
2016-01-04 20:36:36 +03:00
{
2022-07-01 06:58:34 +03:00
struct mtk_dpi_yc_limit limit ;
if ( drm_default_rgb_quant_range ( & dpi - > mode ) = =
HDMI_QUANTIZATION_RANGE_LIMITED ) {
limit . y_bottom = 0x10 ;
limit . y_top = 0xfe0 ;
limit . c_bottom = 0x10 ;
limit . c_top = 0xfe0 ;
} else {
limit . y_bottom = 0 ;
limit . y_top = 0xfff ;
limit . c_bottom = 0 ;
limit . c_top = 0xfff ;
}
mtk_dpi_mask ( dpi , DPI_Y_LIMIT , limit . y_bottom < < Y_LIMINT_BOT ,
2016-01-04 20:36:36 +03:00
Y_LIMINT_BOT_MASK ) ;
2022-07-01 06:58:34 +03:00
mtk_dpi_mask ( dpi , DPI_Y_LIMIT , limit . y_top < < Y_LIMINT_TOP ,
2016-01-04 20:36:36 +03:00
Y_LIMINT_TOP_MASK ) ;
2022-07-01 06:58:34 +03:00
mtk_dpi_mask ( dpi , DPI_C_LIMIT , limit . c_bottom < < C_LIMIT_BOT ,
2016-01-04 20:36:36 +03:00
C_LIMIT_BOT_MASK ) ;
2022-07-01 06:58:34 +03:00
mtk_dpi_mask ( dpi , DPI_C_LIMIT , limit . c_top < < C_LIMIT_TOP ,
2016-01-04 20:36:36 +03:00
C_LIMIT_TOP_MASK ) ;
}
static void mtk_dpi_config_bit_num ( struct mtk_dpi * dpi ,
enum mtk_dpi_out_bit_num num )
{
u32 val ;
switch ( num ) {
case MTK_DPI_OUT_BIT_NUM_8BITS :
val = OUT_BIT_8 ;
break ;
case MTK_DPI_OUT_BIT_NUM_10BITS :
val = OUT_BIT_10 ;
break ;
case MTK_DPI_OUT_BIT_NUM_12BITS :
val = OUT_BIT_12 ;
break ;
case MTK_DPI_OUT_BIT_NUM_16BITS :
val = OUT_BIT_16 ;
break ;
default :
val = OUT_BIT_8 ;
break ;
}
mtk_dpi_mask ( dpi , DPI_OUTPUT_SETTING , val < < OUT_BIT ,
OUT_BIT_MASK ) ;
}
static void mtk_dpi_config_yc_map ( struct mtk_dpi * dpi ,
enum mtk_dpi_out_yc_map map )
{
u32 val ;
switch ( map ) {
case MTK_DPI_OUT_YC_MAP_RGB :
val = YC_MAP_RGB ;
break ;
case MTK_DPI_OUT_YC_MAP_CYCY :
val = YC_MAP_CYCY ;
break ;
case MTK_DPI_OUT_YC_MAP_YCYC :
val = YC_MAP_YCYC ;
break ;
case MTK_DPI_OUT_YC_MAP_CY :
val = YC_MAP_CY ;
break ;
case MTK_DPI_OUT_YC_MAP_YC :
val = YC_MAP_YC ;
break ;
default :
val = YC_MAP_RGB ;
break ;
}
mtk_dpi_mask ( dpi , DPI_OUTPUT_SETTING , val < < YC_MAP , YC_MAP_MASK ) ;
}
static void mtk_dpi_config_channel_swap ( struct mtk_dpi * dpi ,
enum mtk_dpi_out_channel_swap swap )
{
u32 val ;
switch ( swap ) {
case MTK_DPI_OUT_CHANNEL_SWAP_RGB :
val = SWAP_RGB ;
break ;
case MTK_DPI_OUT_CHANNEL_SWAP_GBR :
val = SWAP_GBR ;
break ;
case MTK_DPI_OUT_CHANNEL_SWAP_BRG :
val = SWAP_BRG ;
break ;
case MTK_DPI_OUT_CHANNEL_SWAP_RBG :
val = SWAP_RBG ;
break ;
case MTK_DPI_OUT_CHANNEL_SWAP_GRB :
val = SWAP_GRB ;
break ;
case MTK_DPI_OUT_CHANNEL_SWAP_BGR :
val = SWAP_BGR ;
break ;
default :
val = SWAP_RGB ;
break ;
}
2022-07-01 06:58:39 +03:00
mtk_dpi_mask ( dpi , DPI_OUTPUT_SETTING ,
val < < dpi - > conf - > channel_swap_shift ,
CH_SWAP_MASK < < dpi - > conf - > channel_swap_shift ) ;
2016-01-04 20:36:36 +03:00
}
static void mtk_dpi_config_yuv422_enable ( struct mtk_dpi * dpi , bool enable )
{
2022-07-01 06:58:40 +03:00
mtk_dpi_mask ( dpi , DPI_CON , enable ? dpi - > conf - > yuv422_en_bit : 0 ,
dpi - > conf - > yuv422_en_bit ) ;
2016-01-04 20:36:36 +03:00
}
static void mtk_dpi_config_csc_enable ( struct mtk_dpi * dpi , bool enable )
{
2022-07-01 06:58:41 +03:00
mtk_dpi_mask ( dpi , DPI_CON , enable ? dpi - > conf - > csc_enable_bit : 0 ,
dpi - > conf - > csc_enable_bit ) ;
2016-01-04 20:36:36 +03:00
}
static void mtk_dpi_config_swap_input ( struct mtk_dpi * dpi , bool enable )
{
mtk_dpi_mask ( dpi , DPI_CON , enable ? IN_RB_SWAP : 0 , IN_RB_SWAP ) ;
}
static void mtk_dpi_config_2n_h_fre ( struct mtk_dpi * dpi )
{
2018-10-03 06:41:42 +03:00
mtk_dpi_mask ( dpi , dpi - > conf - > reg_h_fre_con , H_FRE_2N , H_FRE_2N ) ;
2016-01-04 20:36:36 +03:00
}
2018-10-03 06:41:43 +03:00
static void mtk_dpi_config_disable_edge ( struct mtk_dpi * dpi )
{
if ( dpi - > conf - > edge_sel_en )
mtk_dpi_mask ( dpi , dpi - > conf - > reg_h_fre_con , 0 , EDGE_SEL_EN ) ;
}
2016-01-04 20:36:36 +03:00
static void mtk_dpi_config_color_format ( struct mtk_dpi * dpi ,
enum mtk_dpi_out_color_format format )
{
2022-07-01 06:58:33 +03:00
mtk_dpi_config_channel_swap ( dpi , MTK_DPI_OUT_CHANNEL_SWAP_RGB ) ;
2022-07-05 13:25:26 +03:00
if ( format = = MTK_DPI_COLOR_FORMAT_YCBCR_422 ) {
mtk_dpi_config_yuv422_enable ( dpi , true ) ;
mtk_dpi_config_csc_enable ( dpi , true ) ;
/*
* If height is smaller than 720 , we need to use RGB_TO_BT601
* to transfer to yuv422 . Otherwise , we use RGB_TO_JPEG .
*/
mtk_dpi_mask ( dpi , DPI_MATRIX_SET , dpi - > mode . hdisplay < = 720 ?
MATRIX_SEL_RGB_TO_BT601 : MATRIX_SEL_RGB_TO_JPEG ,
INT_MATRIX_SEL_MASK ) ;
} else {
mtk_dpi_config_yuv422_enable ( dpi , false ) ;
mtk_dpi_config_csc_enable ( dpi , false ) ;
if ( dpi - > conf - > swap_input_support )
mtk_dpi_config_swap_input ( dpi , false ) ;
}
2016-01-04 20:36:36 +03:00
}
2021-05-26 11:52:17 +03:00
static void mtk_dpi_dual_edge ( struct mtk_dpi * dpi )
{
if ( ( dpi - > output_fmt = = MEDIA_BUS_FMT_RGB888_2X12_LE ) | |
( dpi - > output_fmt = = MEDIA_BUS_FMT_RGB888_2X12_BE ) ) {
mtk_dpi_mask ( dpi , DPI_DDR_SETTING , DDR_EN | DDR_4PHASE ,
DDR_EN | DDR_4PHASE ) ;
mtk_dpi_mask ( dpi , DPI_OUTPUT_SETTING ,
dpi - > output_fmt = = MEDIA_BUS_FMT_RGB888_2X12_LE ?
EDGE_SEL : 0 , EDGE_SEL ) ;
} else {
mtk_dpi_mask ( dpi , DPI_DDR_SETTING , DDR_EN | DDR_4PHASE , 0 ) ;
}
}
2018-10-03 06:41:41 +03:00
static void mtk_dpi_power_off ( struct mtk_dpi * dpi )
2016-01-04 20:36:36 +03:00
{
2018-10-03 06:41:41 +03:00
if ( WARN_ON ( dpi - > refcount = = 0 ) )
2016-01-04 20:36:36 +03:00
return ;
2018-10-03 06:41:41 +03:00
if ( - - dpi - > refcount ! = 0 )
2016-01-04 20:36:36 +03:00
return ;
2020-04-15 04:13:19 +03:00
if ( dpi - > pinctrl & & dpi - > pins_gpio )
pinctrl_select_state ( dpi - > pinctrl , dpi - > pins_gpio ) ;
2016-01-04 20:36:36 +03:00
mtk_dpi_disable ( dpi ) ;
clk_disable_unprepare ( dpi - > pixel_clk ) ;
clk_disable_unprepare ( dpi - > engine_clk ) ;
}
2018-10-03 06:41:41 +03:00
static int mtk_dpi_power_on ( struct mtk_dpi * dpi )
2016-01-04 20:36:36 +03:00
{
int ret ;
2018-10-03 06:41:41 +03:00
if ( + + dpi - > refcount ! = 1 )
2016-01-04 20:36:36 +03:00
return 0 ;
ret = clk_prepare_enable ( dpi - > engine_clk ) ;
if ( ret ) {
dev_err ( dpi - > dev , " Failed to enable engine clock: %d \n " , ret ) ;
2018-10-03 06:41:41 +03:00
goto err_refcount ;
2016-01-04 20:36:36 +03:00
}
ret = clk_prepare_enable ( dpi - > pixel_clk ) ;
if ( ret ) {
dev_err ( dpi - > dev , " Failed to enable pixel clock: %d \n " , ret ) ;
goto err_pixel ;
}
2020-04-15 04:13:19 +03:00
if ( dpi - > pinctrl & & dpi - > pins_dpi )
pinctrl_select_state ( dpi - > pinctrl , dpi - > pins_dpi ) ;
2016-01-04 20:36:36 +03:00
return 0 ;
err_pixel :
clk_disable_unprepare ( dpi - > engine_clk ) ;
2018-10-03 06:41:41 +03:00
err_refcount :
dpi - > refcount - - ;
2016-01-04 20:36:36 +03:00
return ret ;
}
static int mtk_dpi_set_display_mode ( struct mtk_dpi * dpi ,
struct drm_display_mode * mode )
{
struct mtk_dpi_polarities dpi_pol ;
struct mtk_dpi_sync_param hsync ;
struct mtk_dpi_sync_param vsync_lodd = { 0 } ;
struct mtk_dpi_sync_param vsync_leven = { 0 } ;
struct mtk_dpi_sync_param vsync_rodd = { 0 } ;
struct mtk_dpi_sync_param vsync_reven = { 0 } ;
2018-03-31 17:47:58 +03:00
struct videomode vm = { 0 } ;
2016-01-04 20:36:36 +03:00
unsigned long pll_rate ;
unsigned int factor ;
2016-09-29 06:02:15 +03:00
/* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
2018-10-03 06:41:44 +03:00
factor = dpi - > conf - > cal_factor ( mode - > clock ) ;
2018-03-31 17:47:58 +03:00
drm_display_mode_to_videomode ( mode , & vm ) ;
pll_rate = vm . pixelclock * factor ;
2016-01-04 20:36:36 +03:00
dev_dbg ( dpi - > dev , " Want PLL %lu Hz, pixel clock %lu Hz \n " ,
2018-03-31 17:47:58 +03:00
pll_rate , vm . pixelclock ) ;
2016-01-04 20:36:36 +03:00
clk_set_rate ( dpi - > tvd_clk , pll_rate ) ;
pll_rate = clk_get_rate ( dpi - > tvd_clk ) ;
2018-03-31 17:47:58 +03:00
vm . pixelclock = pll_rate / factor ;
2021-05-26 11:52:17 +03:00
if ( ( dpi - > output_fmt = = MEDIA_BUS_FMT_RGB888_2X12_LE ) | |
( dpi - > output_fmt = = MEDIA_BUS_FMT_RGB888_2X12_BE ) )
clk_set_rate ( dpi - > pixel_clk , vm . pixelclock * 2 ) ;
else
clk_set_rate ( dpi - > pixel_clk , vm . pixelclock ) ;
2018-03-31 17:47:58 +03:00
vm . pixelclock = clk_get_rate ( dpi - > pixel_clk ) ;
2016-01-04 20:36:36 +03:00
dev_dbg ( dpi - > dev , " Got PLL %lu Hz, pixel clock %lu Hz \n " ,
2018-03-31 17:47:58 +03:00
pll_rate , vm . pixelclock ) ;
2016-01-04 20:36:36 +03:00
dpi_pol . ck_pol = MTK_DPI_POLARITY_FALLING ;
dpi_pol . de_pol = MTK_DPI_POLARITY_RISING ;
2018-03-31 17:47:58 +03:00
dpi_pol . hsync_pol = vm . flags & DISPLAY_FLAGS_HSYNC_HIGH ?
2016-01-04 20:36:36 +03:00
MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING ;
2018-03-31 17:47:58 +03:00
dpi_pol . vsync_pol = vm . flags & DISPLAY_FLAGS_VSYNC_HIGH ?
2016-01-04 20:36:36 +03:00
MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING ;
2018-03-31 17:47:58 +03:00
hsync . sync_width = vm . hsync_len ;
hsync . back_porch = vm . hback_porch ;
hsync . front_porch = vm . hfront_porch ;
2016-01-04 20:36:36 +03:00
hsync . shift_half_line = false ;
2018-03-31 17:47:58 +03:00
vsync_lodd . sync_width = vm . vsync_len ;
vsync_lodd . back_porch = vm . vback_porch ;
vsync_lodd . front_porch = vm . vfront_porch ;
2016-01-04 20:36:36 +03:00
vsync_lodd . shift_half_line = false ;
2018-03-31 17:47:58 +03:00
if ( vm . flags & DISPLAY_FLAGS_INTERLACED & &
2016-01-04 20:36:36 +03:00
mode - > flags & DRM_MODE_FLAG_3D_MASK ) {
vsync_leven = vsync_lodd ;
vsync_rodd = vsync_lodd ;
vsync_reven = vsync_lodd ;
vsync_leven . shift_half_line = true ;
vsync_reven . shift_half_line = true ;
2018-03-31 17:47:58 +03:00
} else if ( vm . flags & DISPLAY_FLAGS_INTERLACED & &
2016-01-04 20:36:36 +03:00
! ( mode - > flags & DRM_MODE_FLAG_3D_MASK ) ) {
vsync_leven = vsync_lodd ;
vsync_leven . shift_half_line = true ;
2018-03-31 17:47:58 +03:00
} else if ( ! ( vm . flags & DISPLAY_FLAGS_INTERLACED ) & &
2016-01-04 20:36:36 +03:00
mode - > flags & DRM_MODE_FLAG_3D_MASK ) {
vsync_rodd = vsync_lodd ;
}
mtk_dpi_sw_reset ( dpi , true ) ;
mtk_dpi_config_pol ( dpi , & dpi_pol ) ;
mtk_dpi_config_hsync ( dpi , & hsync ) ;
mtk_dpi_config_vsync_lodd ( dpi , & vsync_lodd ) ;
mtk_dpi_config_vsync_rodd ( dpi , & vsync_rodd ) ;
mtk_dpi_config_vsync_leven ( dpi , & vsync_leven ) ;
mtk_dpi_config_vsync_reven ( dpi , & vsync_reven ) ;
mtk_dpi_config_3d ( dpi , ! ! ( mode - > flags & DRM_MODE_FLAG_3D_MASK ) ) ;
2018-03-31 17:47:58 +03:00
mtk_dpi_config_interface ( dpi , ! ! ( vm . flags &
DISPLAY_FLAGS_INTERLACED ) ) ;
if ( vm . flags & DISPLAY_FLAGS_INTERLACED )
mtk_dpi_config_fb_size ( dpi , vm . hactive , vm . vactive > > 1 ) ;
2016-01-04 20:36:36 +03:00
else
2018-03-31 17:47:58 +03:00
mtk_dpi_config_fb_size ( dpi , vm . hactive , vm . vactive ) ;
2016-01-04 20:36:36 +03:00
2022-07-01 06:58:34 +03:00
mtk_dpi_config_channel_limit ( dpi ) ;
2016-01-04 20:36:36 +03:00
mtk_dpi_config_bit_num ( dpi , dpi - > bit_num ) ;
mtk_dpi_config_channel_swap ( dpi , dpi - > channel_swap ) ;
mtk_dpi_config_yc_map ( dpi , dpi - > yc_map ) ;
mtk_dpi_config_color_format ( dpi , dpi - > color_format ) ;
mtk_dpi_config_2n_h_fre ( dpi ) ;
2021-05-26 11:52:17 +03:00
mtk_dpi_dual_edge ( dpi ) ;
2018-10-03 06:41:43 +03:00
mtk_dpi_config_disable_edge ( dpi ) ;
2016-01-04 20:36:36 +03:00
mtk_dpi_sw_reset ( dpi , false ) ;
return 0 ;
}
2021-05-26 11:52:19 +03:00
static u32 * mtk_dpi_bridge_atomic_get_output_bus_fmts ( struct drm_bridge * bridge ,
struct drm_bridge_state * bridge_state ,
struct drm_crtc_state * crtc_state ,
struct drm_connector_state * conn_state ,
unsigned int * num_output_fmts )
{
struct mtk_dpi * dpi = bridge_to_dpi ( bridge ) ;
u32 * output_fmts ;
* num_output_fmts = 0 ;
if ( ! dpi - > conf - > output_fmts ) {
dev_err ( dpi - > dev , " output_fmts should not be null \n " ) ;
return NULL ;
}
output_fmts = kcalloc ( dpi - > conf - > num_output_fmts , sizeof ( * output_fmts ) ,
GFP_KERNEL ) ;
if ( ! output_fmts )
return NULL ;
* num_output_fmts = dpi - > conf - > num_output_fmts ;
memcpy ( output_fmts , dpi - > conf - > output_fmts ,
sizeof ( * output_fmts ) * dpi - > conf - > num_output_fmts ) ;
return output_fmts ;
}
static u32 * mtk_dpi_bridge_atomic_get_input_bus_fmts ( struct drm_bridge * bridge ,
struct drm_bridge_state * bridge_state ,
struct drm_crtc_state * crtc_state ,
struct drm_connector_state * conn_state ,
u32 output_fmt ,
unsigned int * num_input_fmts )
{
u32 * input_fmts ;
* num_input_fmts = 0 ;
input_fmts = kcalloc ( 1 , sizeof ( * input_fmts ) ,
GFP_KERNEL ) ;
if ( ! input_fmts )
return NULL ;
* num_input_fmts = 1 ;
input_fmts [ 0 ] = MEDIA_BUS_FMT_RGB888_1X24 ;
return input_fmts ;
}
static int mtk_dpi_bridge_atomic_check ( struct drm_bridge * bridge ,
struct drm_bridge_state * bridge_state ,
struct drm_crtc_state * crtc_state ,
struct drm_connector_state * conn_state )
{
2021-07-12 11:07:36 +03:00
struct mtk_dpi * dpi = bridge_to_dpi ( bridge ) ;
2021-05-26 11:52:19 +03:00
unsigned int out_bus_format ;
out_bus_format = bridge_state - > output_bus_cfg . format ;
2021-07-12 12:46:57 +03:00
if ( out_bus_format = = MEDIA_BUS_FMT_FIXED )
if ( dpi - > conf - > num_output_fmts )
out_bus_format = dpi - > conf - > output_fmts [ 0 ] ;
2021-05-26 11:52:19 +03:00
dev_dbg ( dpi - > dev , " input format 0x%04x, output format 0x%04x \n " ,
bridge_state - > input_bus_cfg . format ,
bridge_state - > output_bus_cfg . format ) ;
dpi - > output_fmt = out_bus_format ;
dpi - > bit_num = MTK_DPI_OUT_BIT_NUM_8BITS ;
dpi - > channel_swap = MTK_DPI_OUT_CHANNEL_SWAP_RGB ;
dpi - > yc_map = MTK_DPI_OUT_YC_MAP_RGB ;
2022-07-05 13:25:26 +03:00
if ( out_bus_format = = MEDIA_BUS_FMT_YUYV8_1X16 )
dpi - > color_format = MTK_DPI_COLOR_FORMAT_YCBCR_422 ;
else
dpi - > color_format = MTK_DPI_COLOR_FORMAT_RGB ;
2021-05-26 11:52:19 +03:00
return 0 ;
}
2020-08-26 11:53:17 +03:00
static int mtk_dpi_bridge_attach ( struct drm_bridge * bridge ,
enum drm_bridge_attach_flags flags )
2016-01-04 20:36:36 +03:00
{
2020-08-26 11:53:17 +03:00
struct mtk_dpi * dpi = bridge_to_dpi ( bridge ) ;
return drm_bridge_attach ( bridge - > encoder , dpi - > next_bridge ,
& dpi - > bridge , flags ) ;
}
static void mtk_dpi_bridge_mode_set ( struct drm_bridge * bridge ,
const struct drm_display_mode * mode ,
const struct drm_display_mode * adjusted_mode )
{
struct mtk_dpi * dpi = bridge_to_dpi ( bridge ) ;
2016-01-04 20:36:36 +03:00
drm_mode_copy ( & dpi - > mode , adjusted_mode ) ;
}
2020-08-26 11:53:17 +03:00
static void mtk_dpi_bridge_disable ( struct drm_bridge * bridge )
2016-01-04 20:36:36 +03:00
{
2020-08-26 11:53:17 +03:00
struct mtk_dpi * dpi = bridge_to_dpi ( bridge ) ;
2016-01-04 20:36:36 +03:00
2018-10-03 06:41:41 +03:00
mtk_dpi_power_off ( dpi ) ;
2016-01-04 20:36:36 +03:00
}
2020-08-26 11:53:17 +03:00
static void mtk_dpi_bridge_enable ( struct drm_bridge * bridge )
2016-01-04 20:36:36 +03:00
{
2020-08-26 11:53:17 +03:00
struct mtk_dpi * dpi = bridge_to_dpi ( bridge ) ;
2016-01-04 20:36:36 +03:00
2018-10-03 06:41:41 +03:00
mtk_dpi_power_on ( dpi ) ;
2016-01-04 20:36:36 +03:00
mtk_dpi_set_display_mode ( dpi , & dpi - > mode ) ;
2022-07-01 06:58:44 +03:00
mtk_dpi_enable ( dpi ) ;
2016-01-04 20:36:36 +03:00
}
2021-03-18 08:40:55 +03:00
static enum drm_mode_status
mtk_dpi_bridge_mode_valid ( struct drm_bridge * bridge ,
const struct drm_display_info * info ,
const struct drm_display_mode * mode )
{
struct mtk_dpi * dpi = bridge_to_dpi ( bridge ) ;
if ( mode - > clock > dpi - > conf - > max_clock_khz )
return MODE_CLOCK_HIGH ;
return MODE_OK ;
}
2020-08-26 11:53:17 +03:00
static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = {
. attach = mtk_dpi_bridge_attach ,
. mode_set = mtk_dpi_bridge_mode_set ,
2021-03-18 08:40:55 +03:00
. mode_valid = mtk_dpi_bridge_mode_valid ,
2020-08-26 11:53:17 +03:00
. disable = mtk_dpi_bridge_disable ,
. enable = mtk_dpi_bridge_enable ,
2021-05-26 11:52:19 +03:00
. atomic_check = mtk_dpi_bridge_atomic_check ,
. atomic_get_output_bus_fmts = mtk_dpi_bridge_atomic_get_output_bus_fmts ,
. atomic_get_input_bus_fmts = mtk_dpi_bridge_atomic_get_input_bus_fmts ,
. atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_bridge_destroy_state ,
. atomic_reset = drm_atomic_helper_bridge_reset ,
2016-01-04 20:36:36 +03:00
} ;
2020-10-12 06:50:47 +03:00
void mtk_dpi_start ( struct device * dev )
2016-01-04 20:36:36 +03:00
{
2020-10-12 10:54:26 +03:00
struct mtk_dpi * dpi = dev_get_drvdata ( dev ) ;
2016-01-04 20:36:36 +03:00
2018-10-03 06:41:41 +03:00
mtk_dpi_power_on ( dpi ) ;
2016-01-04 20:36:36 +03:00
}
2020-10-12 06:50:47 +03:00
void mtk_dpi_stop ( struct device * dev )
2016-01-04 20:36:36 +03:00
{
2020-10-12 10:54:26 +03:00
struct mtk_dpi * dpi = dev_get_drvdata ( dev ) ;
2016-01-04 20:36:36 +03:00
2018-10-03 06:41:41 +03:00
mtk_dpi_power_off ( dpi ) ;
2016-01-04 20:36:36 +03:00
}
static int mtk_dpi_bind ( struct device * dev , struct device * master , void * data )
{
struct mtk_dpi * dpi = dev_get_drvdata ( dev ) ;
struct drm_device * drm_dev = data ;
int ret ;
2020-03-05 18:59:38 +03:00
ret = drm_simple_encoder_init ( drm_dev , & dpi - > encoder ,
DRM_MODE_ENCODER_TMDS ) ;
2016-01-04 20:36:36 +03:00
if ( ret ) {
dev_err ( dev , " Failed to initialize decoder: %d \n " , ret ) ;
2020-10-13 09:15:10 +03:00
return ret ;
2016-01-04 20:36:36 +03:00
}
2020-10-13 09:15:10 +03:00
dpi - > encoder . possible_crtcs = mtk_drm_find_possible_crtc_by_comp ( drm_dev , dpi - > dev ) ;
2016-01-04 20:36:36 +03:00
2020-12-03 11:24:45 +03:00
ret = drm_bridge_attach ( & dpi - > encoder , & dpi - > bridge , NULL ,
DRM_BRIDGE_ATTACH_NO_CONNECTOR ) ;
2021-03-24 00:50:08 +03:00
if ( ret )
2016-01-04 20:36:36 +03:00
goto err_cleanup ;
2020-12-03 11:24:45 +03:00
dpi - > connector = drm_bridge_connector_init ( drm_dev , & dpi - > encoder ) ;
if ( IS_ERR ( dpi - > connector ) ) {
dev_err ( dev , " Unable to create bridge connector \n " ) ;
ret = PTR_ERR ( dpi - > connector ) ;
goto err_cleanup ;
}
drm_connector_attach_encoder ( dpi - > connector , & dpi - > encoder ) ;
2016-01-04 20:36:36 +03:00
return 0 ;
err_cleanup :
drm_encoder_cleanup ( & dpi - > encoder ) ;
return ret ;
}
static void mtk_dpi_unbind ( struct device * dev , struct device * master ,
void * data )
{
struct mtk_dpi * dpi = dev_get_drvdata ( dev ) ;
drm_encoder_cleanup ( & dpi - > encoder ) ;
}
static const struct component_ops mtk_dpi_component_ops = {
. bind = mtk_dpi_bind ,
. unbind = mtk_dpi_unbind ,
} ;
2018-10-03 06:41:44 +03:00
static unsigned int mt8173_calculate_factor ( int clock )
{
if ( clock < = 27000 )
return 3 < < 4 ;
else if ( clock < = 84000 )
return 3 < < 3 ;
else if ( clock < = 167000 )
return 3 < < 2 ;
else
return 3 < < 1 ;
}
2018-10-03 06:41:46 +03:00
static unsigned int mt2701_calculate_factor ( int clock )
{
if ( clock < = 64000 )
return 4 ;
2019-04-09 09:53:05 +03:00
else if ( clock < = 128000 )
2018-10-03 06:41:46 +03:00
return 2 ;
2019-04-09 09:53:05 +03:00
else
return 1 ;
2018-10-03 06:41:46 +03:00
}
2020-02-25 12:40:56 +03:00
static unsigned int mt8183_calculate_factor ( int clock )
{
if ( clock < = 27000 )
return 8 ;
else if ( clock < = 167000 )
return 4 ;
else
return 2 ;
}
2021-05-26 11:52:18 +03:00
static const u32 mt8173_output_fmts [ ] = {
MEDIA_BUS_FMT_RGB888_1X24 ,
} ;
static const u32 mt8183_output_fmts [ ] = {
MEDIA_BUS_FMT_RGB888_2X12_LE ,
MEDIA_BUS_FMT_RGB888_2X12_BE ,
} ;
2018-10-03 06:41:42 +03:00
static const struct mtk_dpi_conf mt8173_conf = {
2018-10-03 06:41:44 +03:00
. cal_factor = mt8173_calculate_factor ,
2018-10-03 06:41:42 +03:00
. reg_h_fre_con = 0xe0 ,
2021-03-18 08:40:55 +03:00
. max_clock_khz = 300000 ,
2021-05-26 11:52:18 +03:00
. output_fmts = mt8173_output_fmts ,
. num_output_fmts = ARRAY_SIZE ( mt8173_output_fmts ) ,
2022-07-01 06:58:35 +03:00
. is_ck_de_pol = true ,
2022-07-01 06:58:36 +03:00
. swap_input_support = true ,
2022-07-01 06:58:37 +03:00
. dimension_mask = HPW_MASK ,
2022-07-01 06:58:38 +03:00
. hvsize_mask = HSIZE_MASK ,
2022-07-01 06:58:39 +03:00
. channel_swap_shift = CH_SWAP ,
2022-07-01 06:58:40 +03:00
. yuv422_en_bit = YUV422_EN ,
2022-07-01 06:58:41 +03:00
. csc_enable_bit = CSC_ENABLE ,
2018-10-03 06:41:42 +03:00
} ;
2018-10-03 06:41:46 +03:00
static const struct mtk_dpi_conf mt2701_conf = {
. cal_factor = mt2701_calculate_factor ,
. reg_h_fre_con = 0xb0 ,
. edge_sel_en = true ,
2021-03-18 08:40:55 +03:00
. max_clock_khz = 150000 ,
2021-05-26 11:52:18 +03:00
. output_fmts = mt8173_output_fmts ,
. num_output_fmts = ARRAY_SIZE ( mt8173_output_fmts ) ,
2022-07-01 06:58:35 +03:00
. is_ck_de_pol = true ,
2022-07-01 06:58:36 +03:00
. swap_input_support = true ,
2022-07-01 06:58:37 +03:00
. dimension_mask = HPW_MASK ,
2022-07-01 06:58:38 +03:00
. hvsize_mask = HSIZE_MASK ,
2022-07-01 06:58:39 +03:00
. channel_swap_shift = CH_SWAP ,
2022-07-01 06:58:40 +03:00
. yuv422_en_bit = YUV422_EN ,
2022-07-01 06:58:41 +03:00
. csc_enable_bit = CSC_ENABLE ,
2018-10-03 06:41:46 +03:00
} ;
2020-02-25 12:40:56 +03:00
static const struct mtk_dpi_conf mt8183_conf = {
. cal_factor = mt8183_calculate_factor ,
. reg_h_fre_con = 0xe0 ,
2021-03-18 08:40:55 +03:00
. max_clock_khz = 100000 ,
2021-05-26 11:52:18 +03:00
. output_fmts = mt8183_output_fmts ,
. num_output_fmts = ARRAY_SIZE ( mt8183_output_fmts ) ,
2022-07-01 06:58:35 +03:00
. is_ck_de_pol = true ,
2022-07-01 06:58:36 +03:00
. swap_input_support = true ,
2022-07-01 06:58:37 +03:00
. dimension_mask = HPW_MASK ,
2022-07-01 06:58:38 +03:00
. hvsize_mask = HSIZE_MASK ,
2022-07-01 06:58:39 +03:00
. channel_swap_shift = CH_SWAP ,
2022-07-01 06:58:40 +03:00
. yuv422_en_bit = YUV422_EN ,
2022-07-01 06:58:41 +03:00
. csc_enable_bit = CSC_ENABLE ,
2020-02-25 12:40:56 +03:00
} ;
2021-03-18 08:40:56 +03:00
static const struct mtk_dpi_conf mt8192_conf = {
. cal_factor = mt8183_calculate_factor ,
. reg_h_fre_con = 0xe0 ,
. max_clock_khz = 150000 ,
2022-04-08 04:39:50 +03:00
. output_fmts = mt8183_output_fmts ,
. num_output_fmts = ARRAY_SIZE ( mt8183_output_fmts ) ,
2022-07-01 06:58:35 +03:00
. is_ck_de_pol = true ,
2022-07-01 06:58:36 +03:00
. swap_input_support = true ,
2022-07-01 06:58:37 +03:00
. dimension_mask = HPW_MASK ,
2022-07-01 06:58:38 +03:00
. hvsize_mask = HSIZE_MASK ,
2022-07-01 06:58:39 +03:00
. channel_swap_shift = CH_SWAP ,
2022-07-01 06:58:40 +03:00
. yuv422_en_bit = YUV422_EN ,
2022-07-01 06:58:41 +03:00
. csc_enable_bit = CSC_ENABLE ,
2021-03-18 08:40:56 +03:00
} ;
2016-01-04 20:36:36 +03:00
static int mtk_dpi_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct mtk_dpi * dpi ;
struct resource * mem ;
int ret ;
dpi = devm_kzalloc ( dev , sizeof ( * dpi ) , GFP_KERNEL ) ;
if ( ! dpi )
return - ENOMEM ;
dpi - > dev = dev ;
2018-10-03 06:41:42 +03:00
dpi - > conf = ( struct mtk_dpi_conf * ) of_device_get_match_data ( dev ) ;
2021-05-26 11:52:17 +03:00
dpi - > output_fmt = MEDIA_BUS_FMT_RGB888_1X24 ;
2016-01-04 20:36:36 +03:00
2020-04-15 04:13:19 +03:00
dpi - > pinctrl = devm_pinctrl_get ( & pdev - > dev ) ;
if ( IS_ERR ( dpi - > pinctrl ) ) {
dpi - > pinctrl = NULL ;
dev_dbg ( & pdev - > dev , " Cannot find pinctrl! \n " ) ;
}
if ( dpi - > pinctrl ) {
dpi - > pins_gpio = pinctrl_lookup_state ( dpi - > pinctrl , " sleep " ) ;
if ( IS_ERR ( dpi - > pins_gpio ) ) {
dpi - > pins_gpio = NULL ;
dev_dbg ( & pdev - > dev , " Cannot find pinctrl idle! \n " ) ;
}
if ( dpi - > pins_gpio )
pinctrl_select_state ( dpi - > pinctrl , dpi - > pins_gpio ) ;
dpi - > pins_dpi = pinctrl_lookup_state ( dpi - > pinctrl , " default " ) ;
if ( IS_ERR ( dpi - > pins_dpi ) ) {
dpi - > pins_dpi = NULL ;
dev_dbg ( & pdev - > dev , " Cannot find pinctrl active! \n " ) ;
}
}
2016-01-04 20:36:36 +03:00
mem = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
dpi - > regs = devm_ioremap_resource ( dev , mem ) ;
if ( IS_ERR ( dpi - > regs ) ) {
ret = PTR_ERR ( dpi - > regs ) ;
dev_err ( dev , " Failed to ioremap mem resource: %d \n " , ret ) ;
return ret ;
}
dpi - > engine_clk = devm_clk_get ( dev , " engine " ) ;
if ( IS_ERR ( dpi - > engine_clk ) ) {
ret = PTR_ERR ( dpi - > engine_clk ) ;
2020-03-25 20:31:19 +03:00
if ( ret ! = - EPROBE_DEFER )
dev_err ( dev , " Failed to get engine clock: %d \n " , ret ) ;
2016-01-04 20:36:36 +03:00
return ret ;
}
dpi - > pixel_clk = devm_clk_get ( dev , " pixel " ) ;
if ( IS_ERR ( dpi - > pixel_clk ) ) {
ret = PTR_ERR ( dpi - > pixel_clk ) ;
2020-03-25 20:31:19 +03:00
if ( ret ! = - EPROBE_DEFER )
dev_err ( dev , " Failed to get pixel clock: %d \n " , ret ) ;
2016-01-04 20:36:36 +03:00
return ret ;
}
dpi - > tvd_clk = devm_clk_get ( dev , " pll " ) ;
if ( IS_ERR ( dpi - > tvd_clk ) ) {
ret = PTR_ERR ( dpi - > tvd_clk ) ;
2020-03-25 20:31:19 +03:00
if ( ret ! = - EPROBE_DEFER )
dev_err ( dev , " Failed to get tvdpll clock: %d \n " , ret ) ;
2016-01-04 20:36:36 +03:00
return ret ;
}
dpi - > irq = platform_get_irq ( pdev , 0 ) ;
2021-03-13 10:48:02 +03:00
if ( dpi - > irq < = 0 )
2016-01-04 20:36:36 +03:00
return - EINVAL ;
2018-10-03 06:41:45 +03:00
ret = drm_of_find_panel_or_bridge ( dev - > of_node , 0 , 0 ,
2020-08-26 11:53:16 +03:00
NULL , & dpi - > next_bridge ) ;
2018-10-03 06:41:45 +03:00
if ( ret )
return ret ;
2016-01-04 20:36:36 +03:00
2020-08-26 11:53:16 +03:00
dev_info ( dev , " Found bridge node: %pOF \n " , dpi - > next_bridge - > of_node ) ;
2016-01-04 20:36:36 +03:00
platform_set_drvdata ( pdev , dpi ) ;
2020-08-26 11:53:17 +03:00
dpi - > bridge . funcs = & mtk_dpi_bridge_funcs ;
dpi - > bridge . of_node = dev - > of_node ;
dpi - > bridge . type = DRM_MODE_CONNECTOR_DPI ;
drm_bridge_add ( & dpi - > bridge ) ;
2016-01-04 20:36:36 +03:00
ret = component_add ( dev , & mtk_dpi_component_ops ) ;
if ( ret ) {
2020-08-26 11:53:17 +03:00
drm_bridge_remove ( & dpi - > bridge ) ;
2016-01-04 20:36:36 +03:00
dev_err ( dev , " Failed to add component: %d \n " , ret ) ;
return ret ;
}
return 0 ;
}
static int mtk_dpi_remove ( struct platform_device * pdev )
{
2020-08-26 11:53:17 +03:00
struct mtk_dpi * dpi = platform_get_drvdata ( pdev ) ;
2016-01-04 20:36:36 +03:00
component_del ( & pdev - > dev , & mtk_dpi_component_ops ) ;
2020-08-26 11:53:17 +03:00
drm_bridge_remove ( & dpi - > bridge ) ;
2016-01-04 20:36:36 +03:00
return 0 ;
}
static const struct of_device_id mtk_dpi_of_ids [ ] = {
2018-10-03 06:41:46 +03:00
{ . compatible = " mediatek,mt2701-dpi " ,
. data = & mt2701_conf ,
} ,
2018-10-03 06:41:42 +03:00
{ . compatible = " mediatek,mt8173-dpi " ,
. data = & mt8173_conf ,
} ,
2020-02-25 12:40:56 +03:00
{ . compatible = " mediatek,mt8183-dpi " ,
. data = & mt8183_conf ,
} ,
2021-03-18 08:40:56 +03:00
{ . compatible = " mediatek,mt8192-dpi " ,
. data = & mt8192_conf ,
} ,
2018-10-03 06:41:42 +03:00
{ } ,
2016-01-04 20:36:36 +03:00
} ;
2021-02-03 14:07:17 +03:00
MODULE_DEVICE_TABLE ( of , mtk_dpi_of_ids ) ;
2016-01-04 20:36:36 +03:00
struct platform_driver mtk_dpi_driver = {
. probe = mtk_dpi_probe ,
. remove = mtk_dpi_remove ,
. driver = {
. name = " mediatek-dpi " ,
. of_match_table = mtk_dpi_of_ids ,
} ,
} ;