xref: /openbmc/linux/drivers/gpu/drm/mediatek/mtk_dpi.c (revision 1188f7f111c61394ec56beb8e30322305a8220b6)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29e629c17SJie Qiu /*
39e629c17SJie Qiu  * Copyright (c) 2014 MediaTek Inc.
49e629c17SJie Qiu  * Author: Jie Qiu <jie.qiu@mediatek.com>
59e629c17SJie Qiu  */
69aef5867SSam Ravnborg 
79aef5867SSam Ravnborg #include <linux/clk.h>
89e629c17SJie Qiu #include <linux/component.h>
99aef5867SSam Ravnborg #include <linux/interrupt.h>
109aef5867SSam Ravnborg #include <linux/kernel.h>
1172bd9ea3SVille Syrjälä #include <linux/media-bus-format.h>
129e629c17SJie Qiu #include <linux/of.h>
139e629c17SJie Qiu #include <linux/of_graph.h>
146bd4763fSJitao Shi #include <linux/pinctrl/consumer.h>
159aef5867SSam Ravnborg #include <linux/platform_device.h>
1662fc5cd1SXinlei Lee #include <linux/soc/mediatek/mtk-mmsys.h>
179e629c17SJie Qiu #include <linux/types.h>
189aef5867SSam Ravnborg 
1972ac6969SSatendra Singh Thakur #include <video/videomode.h>
209e629c17SJie Qiu 
219aef5867SSam Ravnborg #include <drm/drm_atomic_helper.h>
22ee68c743SBoris Brezillon #include <drm/drm_bridge.h>
23f0119514SHsin-Yi Wang #include <drm/drm_bridge_connector.h>
249aef5867SSam Ravnborg #include <drm/drm_crtc.h>
255e4cb0afSDave Airlie #include <drm/drm_edid.h>
269aef5867SSam Ravnborg #include <drm/drm_of.h>
27b534c4f5SThomas Zimmermann #include <drm/drm_simple_kms_helper.h>
289aef5867SSam Ravnborg 
291d33f13aSCK Hu #include "mtk_disp_drv.h"
309e629c17SJie Qiu #include "mtk_dpi_regs.h"
319e629c17SJie Qiu #include "mtk_drm_ddp_comp.h"
3262fc5cd1SXinlei Lee #include "mtk_drm_drv.h"
339e629c17SJie Qiu 
349e629c17SJie Qiu enum mtk_dpi_out_bit_num {
359e629c17SJie Qiu 	MTK_DPI_OUT_BIT_NUM_8BITS,
369e629c17SJie Qiu 	MTK_DPI_OUT_BIT_NUM_10BITS,
379e629c17SJie Qiu 	MTK_DPI_OUT_BIT_NUM_12BITS,
389e629c17SJie Qiu 	MTK_DPI_OUT_BIT_NUM_16BITS
399e629c17SJie Qiu };
409e629c17SJie Qiu 
419e629c17SJie Qiu enum mtk_dpi_out_yc_map {
429e629c17SJie Qiu 	MTK_DPI_OUT_YC_MAP_RGB,
439e629c17SJie Qiu 	MTK_DPI_OUT_YC_MAP_CYCY,
449e629c17SJie Qiu 	MTK_DPI_OUT_YC_MAP_YCYC,
459e629c17SJie Qiu 	MTK_DPI_OUT_YC_MAP_CY,
469e629c17SJie Qiu 	MTK_DPI_OUT_YC_MAP_YC
479e629c17SJie Qiu };
489e629c17SJie Qiu 
499e629c17SJie Qiu enum mtk_dpi_out_channel_swap {
509e629c17SJie Qiu 	MTK_DPI_OUT_CHANNEL_SWAP_RGB,
519e629c17SJie Qiu 	MTK_DPI_OUT_CHANNEL_SWAP_GBR,
529e629c17SJie Qiu 	MTK_DPI_OUT_CHANNEL_SWAP_BRG,
539e629c17SJie Qiu 	MTK_DPI_OUT_CHANNEL_SWAP_RBG,
549e629c17SJie Qiu 	MTK_DPI_OUT_CHANNEL_SWAP_GRB,
559e629c17SJie Qiu 	MTK_DPI_OUT_CHANNEL_SWAP_BGR
569e629c17SJie Qiu };
579e629c17SJie Qiu 
589e629c17SJie Qiu enum mtk_dpi_out_color_format {
599e629c17SJie Qiu 	MTK_DPI_COLOR_FORMAT_RGB,
60b992131aSBo-Chen Chen 	MTK_DPI_COLOR_FORMAT_YCBCR_422
619e629c17SJie Qiu };
629e629c17SJie Qiu 
639e629c17SJie Qiu struct mtk_dpi {
649e629c17SJie Qiu 	struct drm_encoder encoder;
65f89c696eSEnric Balletbo i Serra 	struct drm_bridge bridge;
668b465f01SEnric Balletbo i Serra 	struct drm_bridge *next_bridge;
67f0119514SHsin-Yi Wang 	struct drm_connector *connector;
689e629c17SJie Qiu 	void __iomem *regs;
699e629c17SJie Qiu 	struct device *dev;
7062fc5cd1SXinlei Lee 	struct device *mmsys_dev;
719e629c17SJie Qiu 	struct clk *engine_clk;
729e629c17SJie Qiu 	struct clk *pixel_clk;
739e629c17SJie Qiu 	struct clk *tvd_clk;
749e629c17SJie Qiu 	int irq;
759e629c17SJie Qiu 	struct drm_display_mode mode;
760ace4b99Schunhui dai 	const struct mtk_dpi_conf *conf;
779e629c17SJie Qiu 	enum mtk_dpi_out_color_format color_format;
789e629c17SJie Qiu 	enum mtk_dpi_out_yc_map yc_map;
799e629c17SJie Qiu 	enum mtk_dpi_out_bit_num bit_num;
809e629c17SJie Qiu 	enum mtk_dpi_out_channel_swap channel_swap;
816bd4763fSJitao Shi 	struct pinctrl *pinctrl;
826bd4763fSJitao Shi 	struct pinctrl_state *pins_gpio;
836bd4763fSJitao Shi 	struct pinctrl_state *pins_dpi;
846385ed8eSRex-BC Chen 	u32 output_fmt;
854e90a6ebSchunhui dai 	int refcount;
869e629c17SJie Qiu };
879e629c17SJie Qiu 
bridge_to_dpi(struct drm_bridge * b)88f89c696eSEnric Balletbo i Serra static inline struct mtk_dpi *bridge_to_dpi(struct drm_bridge *b)
899e629c17SJie Qiu {
90f89c696eSEnric Balletbo i Serra 	return container_of(b, struct mtk_dpi, bridge);
919e629c17SJie Qiu }
929e629c17SJie Qiu 
939e629c17SJie Qiu enum mtk_dpi_polarity {
949e629c17SJie Qiu 	MTK_DPI_POLARITY_RISING,
959e629c17SJie Qiu 	MTK_DPI_POLARITY_FALLING,
969e629c17SJie Qiu };
979e629c17SJie Qiu 
989e629c17SJie Qiu struct mtk_dpi_polarities {
999e629c17SJie Qiu 	enum mtk_dpi_polarity de_pol;
1009e629c17SJie Qiu 	enum mtk_dpi_polarity ck_pol;
1019e629c17SJie Qiu 	enum mtk_dpi_polarity hsync_pol;
1029e629c17SJie Qiu 	enum mtk_dpi_polarity vsync_pol;
1039e629c17SJie Qiu };
1049e629c17SJie Qiu 
1059e629c17SJie Qiu struct mtk_dpi_sync_param {
1069e629c17SJie Qiu 	u32 sync_width;
1079e629c17SJie Qiu 	u32 front_porch;
1089e629c17SJie Qiu 	u32 back_porch;
1099e629c17SJie Qiu 	bool shift_half_line;
1109e629c17SJie Qiu };
1119e629c17SJie Qiu 
1129e629c17SJie Qiu struct mtk_dpi_yc_limit {
1139e629c17SJie Qiu 	u16 y_top;
1149e629c17SJie Qiu 	u16 y_bottom;
1159e629c17SJie Qiu 	u16 c_top;
1169e629c17SJie Qiu 	u16 c_bottom;
1179e629c17SJie Qiu };
1189e629c17SJie Qiu 
1190bf0cb60SBo-Chen Chen /**
1200bf0cb60SBo-Chen Chen  * struct mtk_dpi_conf - Configuration of mediatek dpi.
1210bf0cb60SBo-Chen Chen  * @cal_factor: Callback function to calculate factor value.
1220bf0cb60SBo-Chen Chen  * @reg_h_fre_con: Register address of frequency control.
1230bf0cb60SBo-Chen Chen  * @max_clock_khz: Max clock frequency supported for this SoCs in khz units.
1240bf0cb60SBo-Chen Chen  * @edge_sel_en: Enable of edge selection.
1250bf0cb60SBo-Chen Chen  * @output_fmts: Array of supported output formats.
1260bf0cb60SBo-Chen Chen  * @num_output_fmts: Quantity of supported output formats.
127cf060519SGuillaume Ranquet  * @is_ck_de_pol: Support CK/DE polarity.
1283145095fSGuillaume Ranquet  * @swap_input_support: Support input swap function.
129c83da623SBo-Chen Chen  * @support_direct_pin: IP supports direct connection to dpi panels.
1302587d895SBo-Chen Chen  * @input_2pixel: Input pixel of dp_intf is 2 pixel per round, so enable this
1312587d895SBo-Chen Chen  *		  config to enable this feature.
132a519e22bSGuillaume Ranquet  * @dimension_mask: Mask used for HWIDTH, HPORCH, VSYNC_WIDTH and VSYNC_PORCH
133a519e22bSGuillaume Ranquet  *		    (no shift).
134e373924dSGuillaume Ranquet  * @hvsize_mask: Mask of HSIZE and VSIZE mask (no shift).
13548fb81a2SGuillaume Ranquet  * @channel_swap_shift: Shift value of channel swap.
1364e28119bSGuillaume Ranquet  * @yuv422_en_bit: Enable bit of yuv422.
137091e5e00SGuillaume Ranquet  * @csc_enable_bit: Enable bit of CSC.
13849ecbb78SBo-Chen Chen  * @pixels_per_iter: Quantity of transferred pixels per iteration.
13962fc5cd1SXinlei Lee  * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.
1400bf0cb60SBo-Chen Chen  */
1410ace4b99Schunhui dai struct mtk_dpi_conf {
14255c78aa5Schunhui dai 	unsigned int (*cal_factor)(int clock);
1430ace4b99Schunhui dai 	u32 reg_h_fre_con;
14444b07120SRex-BC Chen 	u32 max_clock_khz;
14579080159Schunhui dai 	bool edge_sel_en;
146be63f6e8SRex-BC Chen 	const u32 *output_fmts;
147be63f6e8SRex-BC Chen 	u32 num_output_fmts;
148cf060519SGuillaume Ranquet 	bool is_ck_de_pol;
1493145095fSGuillaume Ranquet 	bool swap_input_support;
150c83da623SBo-Chen Chen 	bool support_direct_pin;
1512587d895SBo-Chen Chen 	bool input_2pixel;
152a519e22bSGuillaume Ranquet 	u32 dimension_mask;
153e373924dSGuillaume Ranquet 	u32 hvsize_mask;
15448fb81a2SGuillaume Ranquet 	u32 channel_swap_shift;
1554e28119bSGuillaume Ranquet 	u32 yuv422_en_bit;
156091e5e00SGuillaume Ranquet 	u32 csc_enable_bit;
15749ecbb78SBo-Chen Chen 	u32 pixels_per_iter;
15862fc5cd1SXinlei Lee 	bool edge_cfg_in_mmsys;
1590ace4b99Schunhui dai };
1600ace4b99Schunhui dai 
mtk_dpi_mask(struct mtk_dpi * dpi,u32 offset,u32 val,u32 mask)1619e629c17SJie Qiu static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
1629e629c17SJie Qiu {
1639e629c17SJie Qiu 	u32 tmp = readl(dpi->regs + offset) & ~mask;
1649e629c17SJie Qiu 
1659e629c17SJie Qiu 	tmp |= (val & mask);
1669e629c17SJie Qiu 	writel(tmp, dpi->regs + offset);
1679e629c17SJie Qiu }
1689e629c17SJie Qiu 
mtk_dpi_sw_reset(struct mtk_dpi * dpi,bool reset)1699e629c17SJie Qiu static void mtk_dpi_sw_reset(struct mtk_dpi *dpi, bool reset)
1709e629c17SJie Qiu {
1719e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_RET, reset ? RST : 0, RST);
1729e629c17SJie Qiu }
1739e629c17SJie Qiu 
mtk_dpi_enable(struct mtk_dpi * dpi)1749e629c17SJie Qiu static void mtk_dpi_enable(struct mtk_dpi *dpi)
1759e629c17SJie Qiu {
1769e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_EN, EN, EN);
1779e629c17SJie Qiu }
1789e629c17SJie Qiu 
mtk_dpi_disable(struct mtk_dpi * dpi)1799e629c17SJie Qiu static void mtk_dpi_disable(struct mtk_dpi *dpi)
1809e629c17SJie Qiu {
1819e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_EN, 0, EN);
1829e629c17SJie Qiu }
1839e629c17SJie Qiu 
mtk_dpi_config_hsync(struct mtk_dpi * dpi,struct mtk_dpi_sync_param * sync)1849e629c17SJie Qiu static void mtk_dpi_config_hsync(struct mtk_dpi *dpi,
1859e629c17SJie Qiu 				 struct mtk_dpi_sync_param *sync)
1869e629c17SJie Qiu {
187a519e22bSGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_TGEN_HWIDTH, sync->sync_width << HPW,
188a519e22bSGuillaume Ranquet 		     dpi->conf->dimension_mask << HPW);
189a519e22bSGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->back_porch << HBP,
190a519e22bSGuillaume Ranquet 		     dpi->conf->dimension_mask << HBP);
1919e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->front_porch << HFP,
192a519e22bSGuillaume Ranquet 		     dpi->conf->dimension_mask << HFP);
1939e629c17SJie Qiu }
1949e629c17SJie Qiu 
mtk_dpi_config_vsync(struct mtk_dpi * dpi,struct mtk_dpi_sync_param * sync,u32 width_addr,u32 porch_addr)1959e629c17SJie Qiu static void mtk_dpi_config_vsync(struct mtk_dpi *dpi,
1969e629c17SJie Qiu 				 struct mtk_dpi_sync_param *sync,
1979e629c17SJie Qiu 				 u32 width_addr, u32 porch_addr)
1989e629c17SJie Qiu {
1999e629c17SJie Qiu 	mtk_dpi_mask(dpi, width_addr,
2009e629c17SJie Qiu 		     sync->shift_half_line << VSYNC_HALF_LINE_SHIFT,
2019e629c17SJie Qiu 		     VSYNC_HALF_LINE_MASK);
202a519e22bSGuillaume Ranquet 	mtk_dpi_mask(dpi, width_addr,
203a519e22bSGuillaume Ranquet 		     sync->sync_width << VSYNC_WIDTH_SHIFT,
204a519e22bSGuillaume Ranquet 		     dpi->conf->dimension_mask << VSYNC_WIDTH_SHIFT);
2059e629c17SJie Qiu 	mtk_dpi_mask(dpi, porch_addr,
2069e629c17SJie Qiu 		     sync->back_porch << VSYNC_BACK_PORCH_SHIFT,
207a519e22bSGuillaume Ranquet 		     dpi->conf->dimension_mask << VSYNC_BACK_PORCH_SHIFT);
2089e629c17SJie Qiu 	mtk_dpi_mask(dpi, porch_addr,
2099e629c17SJie Qiu 		     sync->front_porch << VSYNC_FRONT_PORCH_SHIFT,
210a519e22bSGuillaume Ranquet 		     dpi->conf->dimension_mask << VSYNC_FRONT_PORCH_SHIFT);
2119e629c17SJie Qiu }
2129e629c17SJie Qiu 
mtk_dpi_config_vsync_lodd(struct mtk_dpi * dpi,struct mtk_dpi_sync_param * sync)2139e629c17SJie Qiu static void mtk_dpi_config_vsync_lodd(struct mtk_dpi *dpi,
2149e629c17SJie Qiu 				      struct mtk_dpi_sync_param *sync)
2159e629c17SJie Qiu {
2169e629c17SJie Qiu 	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH, DPI_TGEN_VPORCH);
2179e629c17SJie Qiu }
2189e629c17SJie Qiu 
mtk_dpi_config_vsync_leven(struct mtk_dpi * dpi,struct mtk_dpi_sync_param * sync)2199e629c17SJie Qiu static void mtk_dpi_config_vsync_leven(struct mtk_dpi *dpi,
2209e629c17SJie Qiu 				       struct mtk_dpi_sync_param *sync)
2219e629c17SJie Qiu {
2229e629c17SJie Qiu 	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_LEVEN,
2239e629c17SJie Qiu 			     DPI_TGEN_VPORCH_LEVEN);
2249e629c17SJie Qiu }
2259e629c17SJie Qiu 
mtk_dpi_config_vsync_rodd(struct mtk_dpi * dpi,struct mtk_dpi_sync_param * sync)2269e629c17SJie Qiu static void mtk_dpi_config_vsync_rodd(struct mtk_dpi *dpi,
2279e629c17SJie Qiu 				      struct mtk_dpi_sync_param *sync)
2289e629c17SJie Qiu {
2299e629c17SJie Qiu 	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_RODD,
2309e629c17SJie Qiu 			     DPI_TGEN_VPORCH_RODD);
2319e629c17SJie Qiu }
2329e629c17SJie Qiu 
mtk_dpi_config_vsync_reven(struct mtk_dpi * dpi,struct mtk_dpi_sync_param * sync)2339e629c17SJie Qiu static void mtk_dpi_config_vsync_reven(struct mtk_dpi *dpi,
2349e629c17SJie Qiu 				       struct mtk_dpi_sync_param *sync)
2359e629c17SJie Qiu {
2369e629c17SJie Qiu 	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_REVEN,
2379e629c17SJie Qiu 			     DPI_TGEN_VPORCH_REVEN);
2389e629c17SJie Qiu }
2399e629c17SJie Qiu 
mtk_dpi_config_pol(struct mtk_dpi * dpi,struct mtk_dpi_polarities * dpi_pol)2409e629c17SJie Qiu static void mtk_dpi_config_pol(struct mtk_dpi *dpi,
2419e629c17SJie Qiu 			       struct mtk_dpi_polarities *dpi_pol)
2429e629c17SJie Qiu {
2439e629c17SJie Qiu 	unsigned int pol;
244cf060519SGuillaume Ranquet 	unsigned int mask;
2459e629c17SJie Qiu 
246cf060519SGuillaume Ranquet 	mask = HSYNC_POL | VSYNC_POL;
247cf060519SGuillaume Ranquet 	pol = (dpi_pol->hsync_pol == MTK_DPI_POLARITY_RISING ? 0 : HSYNC_POL) |
2489e629c17SJie Qiu 	      (dpi_pol->vsync_pol == MTK_DPI_POLARITY_RISING ? 0 : VSYNC_POL);
249cf060519SGuillaume Ranquet 	if (dpi->conf->is_ck_de_pol) {
250cf060519SGuillaume Ranquet 		mask |= CK_POL | DE_POL;
251cf060519SGuillaume Ranquet 		pol |= (dpi_pol->ck_pol == MTK_DPI_POLARITY_RISING ?
252cf060519SGuillaume Ranquet 			0 : CK_POL) |
253cf060519SGuillaume Ranquet 		       (dpi_pol->de_pol == MTK_DPI_POLARITY_RISING ?
254cf060519SGuillaume Ranquet 			0 : DE_POL);
255cf060519SGuillaume Ranquet 	}
256cf060519SGuillaume Ranquet 
257cf060519SGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, pol, mask);
2589e629c17SJie Qiu }
2599e629c17SJie Qiu 
mtk_dpi_config_3d(struct mtk_dpi * dpi,bool en_3d)2609e629c17SJie Qiu static void mtk_dpi_config_3d(struct mtk_dpi *dpi, bool en_3d)
2619e629c17SJie Qiu {
2629e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_CON, en_3d ? TDFP_EN : 0, TDFP_EN);
2639e629c17SJie Qiu }
2649e629c17SJie Qiu 
mtk_dpi_config_interface(struct mtk_dpi * dpi,bool inter)2659e629c17SJie Qiu static void mtk_dpi_config_interface(struct mtk_dpi *dpi, bool inter)
2669e629c17SJie Qiu {
2679e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_CON, inter ? INTL_EN : 0, INTL_EN);
2689e629c17SJie Qiu }
2699e629c17SJie Qiu 
mtk_dpi_config_fb_size(struct mtk_dpi * dpi,u32 width,u32 height)2709e629c17SJie Qiu static void mtk_dpi_config_fb_size(struct mtk_dpi *dpi, u32 width, u32 height)
2719e629c17SJie Qiu {
272e373924dSGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_SIZE, width << HSIZE,
273e373924dSGuillaume Ranquet 		     dpi->conf->hvsize_mask << HSIZE);
274e373924dSGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_SIZE, height << VSIZE,
275e373924dSGuillaume Ranquet 		     dpi->conf->hvsize_mask << VSIZE);
2769e629c17SJie Qiu }
2779e629c17SJie Qiu 
mtk_dpi_config_channel_limit(struct mtk_dpi * dpi)2784393c74aSBo-Chen Chen static void mtk_dpi_config_channel_limit(struct mtk_dpi *dpi)
2799e629c17SJie Qiu {
2804393c74aSBo-Chen Chen 	struct mtk_dpi_yc_limit limit;
2814393c74aSBo-Chen Chen 
2824393c74aSBo-Chen Chen 	if (drm_default_rgb_quant_range(&dpi->mode) ==
2834393c74aSBo-Chen Chen 	    HDMI_QUANTIZATION_RANGE_LIMITED) {
2844393c74aSBo-Chen Chen 		limit.y_bottom = 0x10;
2854393c74aSBo-Chen Chen 		limit.y_top = 0xfe0;
2864393c74aSBo-Chen Chen 		limit.c_bottom = 0x10;
2874393c74aSBo-Chen Chen 		limit.c_top = 0xfe0;
2884393c74aSBo-Chen Chen 	} else {
2894393c74aSBo-Chen Chen 		limit.y_bottom = 0;
2904393c74aSBo-Chen Chen 		limit.y_top = 0xfff;
2914393c74aSBo-Chen Chen 		limit.c_bottom = 0;
2924393c74aSBo-Chen Chen 		limit.c_top = 0xfff;
2934393c74aSBo-Chen Chen 	}
2944393c74aSBo-Chen Chen 
2954393c74aSBo-Chen Chen 	mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit.y_bottom << Y_LIMINT_BOT,
2969e629c17SJie Qiu 		     Y_LIMINT_BOT_MASK);
2974393c74aSBo-Chen Chen 	mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit.y_top << Y_LIMINT_TOP,
2989e629c17SJie Qiu 		     Y_LIMINT_TOP_MASK);
2994393c74aSBo-Chen Chen 	mtk_dpi_mask(dpi, DPI_C_LIMIT, limit.c_bottom << C_LIMIT_BOT,
3009e629c17SJie Qiu 		     C_LIMIT_BOT_MASK);
3014393c74aSBo-Chen Chen 	mtk_dpi_mask(dpi, DPI_C_LIMIT, limit.c_top << C_LIMIT_TOP,
3029e629c17SJie Qiu 		     C_LIMIT_TOP_MASK);
3039e629c17SJie Qiu }
3049e629c17SJie Qiu 
mtk_dpi_config_bit_num(struct mtk_dpi * dpi,enum mtk_dpi_out_bit_num num)3059e629c17SJie Qiu static void mtk_dpi_config_bit_num(struct mtk_dpi *dpi,
3069e629c17SJie Qiu 				   enum mtk_dpi_out_bit_num num)
3079e629c17SJie Qiu {
3089e629c17SJie Qiu 	u32 val;
3099e629c17SJie Qiu 
3109e629c17SJie Qiu 	switch (num) {
3119e629c17SJie Qiu 	case MTK_DPI_OUT_BIT_NUM_8BITS:
3129e629c17SJie Qiu 		val = OUT_BIT_8;
3139e629c17SJie Qiu 		break;
3149e629c17SJie Qiu 	case MTK_DPI_OUT_BIT_NUM_10BITS:
3159e629c17SJie Qiu 		val = OUT_BIT_10;
3169e629c17SJie Qiu 		break;
3179e629c17SJie Qiu 	case MTK_DPI_OUT_BIT_NUM_12BITS:
3189e629c17SJie Qiu 		val = OUT_BIT_12;
3199e629c17SJie Qiu 		break;
3209e629c17SJie Qiu 	case MTK_DPI_OUT_BIT_NUM_16BITS:
3219e629c17SJie Qiu 		val = OUT_BIT_16;
3229e629c17SJie Qiu 		break;
3239e629c17SJie Qiu 	default:
3249e629c17SJie Qiu 		val = OUT_BIT_8;
3259e629c17SJie Qiu 		break;
3269e629c17SJie Qiu 	}
3279e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << OUT_BIT,
3289e629c17SJie Qiu 		     OUT_BIT_MASK);
3299e629c17SJie Qiu }
3309e629c17SJie Qiu 
mtk_dpi_config_yc_map(struct mtk_dpi * dpi,enum mtk_dpi_out_yc_map map)3319e629c17SJie Qiu static void mtk_dpi_config_yc_map(struct mtk_dpi *dpi,
3329e629c17SJie Qiu 				  enum mtk_dpi_out_yc_map map)
3339e629c17SJie Qiu {
3349e629c17SJie Qiu 	u32 val;
3359e629c17SJie Qiu 
3369e629c17SJie Qiu 	switch (map) {
3379e629c17SJie Qiu 	case MTK_DPI_OUT_YC_MAP_RGB:
3389e629c17SJie Qiu 		val = YC_MAP_RGB;
3399e629c17SJie Qiu 		break;
3409e629c17SJie Qiu 	case MTK_DPI_OUT_YC_MAP_CYCY:
3419e629c17SJie Qiu 		val = YC_MAP_CYCY;
3429e629c17SJie Qiu 		break;
3439e629c17SJie Qiu 	case MTK_DPI_OUT_YC_MAP_YCYC:
3449e629c17SJie Qiu 		val = YC_MAP_YCYC;
3459e629c17SJie Qiu 		break;
3469e629c17SJie Qiu 	case MTK_DPI_OUT_YC_MAP_CY:
3479e629c17SJie Qiu 		val = YC_MAP_CY;
3489e629c17SJie Qiu 		break;
3499e629c17SJie Qiu 	case MTK_DPI_OUT_YC_MAP_YC:
3509e629c17SJie Qiu 		val = YC_MAP_YC;
3519e629c17SJie Qiu 		break;
3529e629c17SJie Qiu 	default:
3539e629c17SJie Qiu 		val = YC_MAP_RGB;
3549e629c17SJie Qiu 		break;
3559e629c17SJie Qiu 	}
3569e629c17SJie Qiu 
3579e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << YC_MAP, YC_MAP_MASK);
3589e629c17SJie Qiu }
3599e629c17SJie Qiu 
mtk_dpi_config_channel_swap(struct mtk_dpi * dpi,enum mtk_dpi_out_channel_swap swap)3609e629c17SJie Qiu static void mtk_dpi_config_channel_swap(struct mtk_dpi *dpi,
3619e629c17SJie Qiu 					enum mtk_dpi_out_channel_swap swap)
3629e629c17SJie Qiu {
3639e629c17SJie Qiu 	u32 val;
3649e629c17SJie Qiu 
3659e629c17SJie Qiu 	switch (swap) {
3669e629c17SJie Qiu 	case MTK_DPI_OUT_CHANNEL_SWAP_RGB:
3679e629c17SJie Qiu 		val = SWAP_RGB;
3689e629c17SJie Qiu 		break;
3699e629c17SJie Qiu 	case MTK_DPI_OUT_CHANNEL_SWAP_GBR:
3709e629c17SJie Qiu 		val = SWAP_GBR;
3719e629c17SJie Qiu 		break;
3729e629c17SJie Qiu 	case MTK_DPI_OUT_CHANNEL_SWAP_BRG:
3739e629c17SJie Qiu 		val = SWAP_BRG;
3749e629c17SJie Qiu 		break;
3759e629c17SJie Qiu 	case MTK_DPI_OUT_CHANNEL_SWAP_RBG:
3769e629c17SJie Qiu 		val = SWAP_RBG;
3779e629c17SJie Qiu 		break;
3789e629c17SJie Qiu 	case MTK_DPI_OUT_CHANNEL_SWAP_GRB:
3799e629c17SJie Qiu 		val = SWAP_GRB;
3809e629c17SJie Qiu 		break;
3819e629c17SJie Qiu 	case MTK_DPI_OUT_CHANNEL_SWAP_BGR:
3829e629c17SJie Qiu 		val = SWAP_BGR;
3839e629c17SJie Qiu 		break;
3849e629c17SJie Qiu 	default:
3859e629c17SJie Qiu 		val = SWAP_RGB;
3869e629c17SJie Qiu 		break;
3879e629c17SJie Qiu 	}
3889e629c17SJie Qiu 
38948fb81a2SGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING,
39048fb81a2SGuillaume Ranquet 		     val << dpi->conf->channel_swap_shift,
39148fb81a2SGuillaume Ranquet 		     CH_SWAP_MASK << dpi->conf->channel_swap_shift);
3929e629c17SJie Qiu }
3939e629c17SJie Qiu 
mtk_dpi_config_yuv422_enable(struct mtk_dpi * dpi,bool enable)3949e629c17SJie Qiu static void mtk_dpi_config_yuv422_enable(struct mtk_dpi *dpi, bool enable)
3959e629c17SJie Qiu {
3964e28119bSGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_CON, enable ? dpi->conf->yuv422_en_bit : 0,
3974e28119bSGuillaume Ranquet 		     dpi->conf->yuv422_en_bit);
3989e629c17SJie Qiu }
3999e629c17SJie Qiu 
mtk_dpi_config_csc_enable(struct mtk_dpi * dpi,bool enable)4009e629c17SJie Qiu static void mtk_dpi_config_csc_enable(struct mtk_dpi *dpi, bool enable)
4019e629c17SJie Qiu {
402091e5e00SGuillaume Ranquet 	mtk_dpi_mask(dpi, DPI_CON, enable ? dpi->conf->csc_enable_bit : 0,
403091e5e00SGuillaume Ranquet 		     dpi->conf->csc_enable_bit);
4049e629c17SJie Qiu }
4059e629c17SJie Qiu 
mtk_dpi_config_swap_input(struct mtk_dpi * dpi,bool enable)4069e629c17SJie Qiu static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)
4079e629c17SJie Qiu {
4089e629c17SJie Qiu 	mtk_dpi_mask(dpi, DPI_CON, enable ? IN_RB_SWAP : 0, IN_RB_SWAP);
4099e629c17SJie Qiu }
4109e629c17SJie Qiu 
mtk_dpi_config_2n_h_fre(struct mtk_dpi * dpi)4119e629c17SJie Qiu static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)
4129e629c17SJie Qiu {
4130ace4b99Schunhui dai 	mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
4149e629c17SJie Qiu }
4159e629c17SJie Qiu 
mtk_dpi_config_disable_edge(struct mtk_dpi * dpi)41679080159Schunhui dai static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
41779080159Schunhui dai {
41879080159Schunhui dai 	if (dpi->conf->edge_sel_en)
41979080159Schunhui dai 		mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
42079080159Schunhui dai }
42179080159Schunhui dai 
mtk_dpi_config_color_format(struct mtk_dpi * dpi,enum mtk_dpi_out_color_format format)4229e629c17SJie Qiu static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
4239e629c17SJie Qiu 					enum mtk_dpi_out_color_format format)
4249e629c17SJie Qiu {
425b992131aSBo-Chen Chen 	mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB);
426b992131aSBo-Chen Chen 
427b992131aSBo-Chen Chen 	if (format == MTK_DPI_COLOR_FORMAT_YCBCR_422) {
4289e629c17SJie Qiu 		mtk_dpi_config_yuv422_enable(dpi, true);
4299e629c17SJie Qiu 		mtk_dpi_config_csc_enable(dpi, true);
430b992131aSBo-Chen Chen 
431b992131aSBo-Chen Chen 		/*
432b992131aSBo-Chen Chen 		 * If height is smaller than 720, we need to use RGB_TO_BT601
433b992131aSBo-Chen Chen 		 * to transfer to yuv422. Otherwise, we use RGB_TO_JPEG.
434b992131aSBo-Chen Chen 		 */
435b992131aSBo-Chen Chen 		mtk_dpi_mask(dpi, DPI_MATRIX_SET, dpi->mode.hdisplay <= 720 ?
436b992131aSBo-Chen Chen 			     MATRIX_SEL_RGB_TO_BT601 : MATRIX_SEL_RGB_TO_JPEG,
437b992131aSBo-Chen Chen 			     INT_MATRIX_SEL_MASK);
4389e629c17SJie Qiu 	} else {
4399e629c17SJie Qiu 		mtk_dpi_config_yuv422_enable(dpi, false);
4409e629c17SJie Qiu 		mtk_dpi_config_csc_enable(dpi, false);
4413145095fSGuillaume Ranquet 		if (dpi->conf->swap_input_support)
4429e629c17SJie Qiu 			mtk_dpi_config_swap_input(dpi, false);
4439e629c17SJie Qiu 	}
4449e629c17SJie Qiu }
4459e629c17SJie Qiu 
mtk_dpi_dual_edge(struct mtk_dpi * dpi)4466385ed8eSRex-BC Chen static void mtk_dpi_dual_edge(struct mtk_dpi *dpi)
4476385ed8eSRex-BC Chen {
4486385ed8eSRex-BC Chen 	if ((dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE) ||
4496385ed8eSRex-BC Chen 	    (dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_BE)) {
4506385ed8eSRex-BC Chen 		mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE,
4516385ed8eSRex-BC Chen 			     DDR_EN | DDR_4PHASE);
4526385ed8eSRex-BC Chen 		mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING,
4536385ed8eSRex-BC Chen 			     dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE ?
4546385ed8eSRex-BC Chen 			     EDGE_SEL : 0, EDGE_SEL);
45562fc5cd1SXinlei Lee 		if (dpi->conf->edge_cfg_in_mmsys)
45662fc5cd1SXinlei Lee 			mtk_mmsys_ddp_dpi_fmt_config(dpi->mmsys_dev, MTK_DPI_RGB888_DDR_CON);
4576385ed8eSRex-BC Chen 	} else {
4586385ed8eSRex-BC Chen 		mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE, 0);
45962fc5cd1SXinlei Lee 		if (dpi->conf->edge_cfg_in_mmsys)
46062fc5cd1SXinlei Lee 			mtk_mmsys_ddp_dpi_fmt_config(dpi->mmsys_dev, MTK_DPI_RGB888_SDR_CON);
4616385ed8eSRex-BC Chen 	}
4626385ed8eSRex-BC Chen }
4636385ed8eSRex-BC Chen 
mtk_dpi_power_off(struct mtk_dpi * dpi)4644e90a6ebSchunhui dai static void mtk_dpi_power_off(struct mtk_dpi *dpi)
4659e629c17SJie Qiu {
4664e90a6ebSchunhui dai 	if (WARN_ON(dpi->refcount == 0))
4679e629c17SJie Qiu 		return;
4689e629c17SJie Qiu 
4694e90a6ebSchunhui dai 	if (--dpi->refcount != 0)
4709e629c17SJie Qiu 		return;
4719e629c17SJie Qiu 
4729e629c17SJie Qiu 	mtk_dpi_disable(dpi);
4739e629c17SJie Qiu 	clk_disable_unprepare(dpi->pixel_clk);
4749e629c17SJie Qiu 	clk_disable_unprepare(dpi->engine_clk);
4759e629c17SJie Qiu }
4769e629c17SJie Qiu 
mtk_dpi_power_on(struct mtk_dpi * dpi)4774e90a6ebSchunhui dai static int mtk_dpi_power_on(struct mtk_dpi *dpi)
4789e629c17SJie Qiu {
4799e629c17SJie Qiu 	int ret;
4809e629c17SJie Qiu 
4814e90a6ebSchunhui dai 	if (++dpi->refcount != 1)
4829e629c17SJie Qiu 		return 0;
4839e629c17SJie Qiu 
4849e629c17SJie Qiu 	ret = clk_prepare_enable(dpi->engine_clk);
4859e629c17SJie Qiu 	if (ret) {
4869e629c17SJie Qiu 		dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret);
4874e90a6ebSchunhui dai 		goto err_refcount;
4889e629c17SJie Qiu 	}
4899e629c17SJie Qiu 
4909e629c17SJie Qiu 	ret = clk_prepare_enable(dpi->pixel_clk);
4919e629c17SJie Qiu 	if (ret) {
4929e629c17SJie Qiu 		dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret);
4939e629c17SJie Qiu 		goto err_pixel;
4949e629c17SJie Qiu 	}
4959e629c17SJie Qiu 
4969e629c17SJie Qiu 	return 0;
4979e629c17SJie Qiu 
4989e629c17SJie Qiu err_pixel:
4999e629c17SJie Qiu 	clk_disable_unprepare(dpi->engine_clk);
5004e90a6ebSchunhui dai err_refcount:
5014e90a6ebSchunhui dai 	dpi->refcount--;
5029e629c17SJie Qiu 	return ret;
5039e629c17SJie Qiu }
5049e629c17SJie Qiu 
mtk_dpi_set_display_mode(struct mtk_dpi * dpi,struct drm_display_mode * mode)5059e629c17SJie Qiu static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
5069e629c17SJie Qiu 				    struct drm_display_mode *mode)
5079e629c17SJie Qiu {
5089e629c17SJie Qiu 	struct mtk_dpi_polarities dpi_pol;
5099e629c17SJie Qiu 	struct mtk_dpi_sync_param hsync;
5109e629c17SJie Qiu 	struct mtk_dpi_sync_param vsync_lodd = { 0 };
5119e629c17SJie Qiu 	struct mtk_dpi_sync_param vsync_leven = { 0 };
5129e629c17SJie Qiu 	struct mtk_dpi_sync_param vsync_rodd = { 0 };
5139e629c17SJie Qiu 	struct mtk_dpi_sync_param vsync_reven = { 0 };
51472ac6969SSatendra Singh Thakur 	struct videomode vm = { 0 };
5159e629c17SJie Qiu 	unsigned long pll_rate;
5169e629c17SJie Qiu 	unsigned int factor;
5179e629c17SJie Qiu 
5180d220079SJunzhi Zhao 	/* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
51955c78aa5Schunhui dai 	factor = dpi->conf->cal_factor(mode->clock);
52072ac6969SSatendra Singh Thakur 	drm_display_mode_to_videomode(mode, &vm);
52172ac6969SSatendra Singh Thakur 	pll_rate = vm.pixelclock * factor;
5229e629c17SJie Qiu 
5239e629c17SJie Qiu 	dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n",
52472ac6969SSatendra Singh Thakur 		pll_rate, vm.pixelclock);
5259e629c17SJie Qiu 
5269e629c17SJie Qiu 	clk_set_rate(dpi->tvd_clk, pll_rate);
5279e629c17SJie Qiu 	pll_rate = clk_get_rate(dpi->tvd_clk);
5289e629c17SJie Qiu 
52949ecbb78SBo-Chen Chen 	/*
53049ecbb78SBo-Chen Chen 	 * Depending on the IP version, we may output a different amount of
53149ecbb78SBo-Chen Chen 	 * pixels for each iteration: divide the clock by this number and
53249ecbb78SBo-Chen Chen 	 * adjust the display porches accordingly.
53349ecbb78SBo-Chen Chen 	 */
53472ac6969SSatendra Singh Thakur 	vm.pixelclock = pll_rate / factor;
53549ecbb78SBo-Chen Chen 	vm.pixelclock /= dpi->conf->pixels_per_iter;
53649ecbb78SBo-Chen Chen 
5376385ed8eSRex-BC Chen 	if ((dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE) ||
5386385ed8eSRex-BC Chen 	    (dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_BE))
5396385ed8eSRex-BC Chen 		clk_set_rate(dpi->pixel_clk, vm.pixelclock * 2);
5406385ed8eSRex-BC Chen 	else
54172ac6969SSatendra Singh Thakur 		clk_set_rate(dpi->pixel_clk, vm.pixelclock);
5426385ed8eSRex-BC Chen 
5436385ed8eSRex-BC Chen 
54472ac6969SSatendra Singh Thakur 	vm.pixelclock = clk_get_rate(dpi->pixel_clk);
5459e629c17SJie Qiu 
5469e629c17SJie Qiu 	dev_dbg(dpi->dev, "Got  PLL %lu Hz, pixel clock %lu Hz\n",
54772ac6969SSatendra Singh Thakur 		pll_rate, vm.pixelclock);
5489e629c17SJie Qiu 
5499e629c17SJie Qiu 	dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING;
5509e629c17SJie Qiu 	dpi_pol.de_pol = MTK_DPI_POLARITY_RISING;
55172ac6969SSatendra Singh Thakur 	dpi_pol.hsync_pol = vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ?
5529e629c17SJie Qiu 			    MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING;
55372ac6969SSatendra Singh Thakur 	dpi_pol.vsync_pol = vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ?
5549e629c17SJie Qiu 			    MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING;
55549ecbb78SBo-Chen Chen 
55649ecbb78SBo-Chen Chen 	/*
55749ecbb78SBo-Chen Chen 	 * Depending on the IP version, we may output a different amount of
55849ecbb78SBo-Chen Chen 	 * pixels for each iteration: divide the clock by this number and
55949ecbb78SBo-Chen Chen 	 * adjust the display porches accordingly.
56049ecbb78SBo-Chen Chen 	 */
56149ecbb78SBo-Chen Chen 	hsync.sync_width = vm.hsync_len / dpi->conf->pixels_per_iter;
56249ecbb78SBo-Chen Chen 	hsync.back_porch = vm.hback_porch / dpi->conf->pixels_per_iter;
56349ecbb78SBo-Chen Chen 	hsync.front_porch = vm.hfront_porch / dpi->conf->pixels_per_iter;
56449ecbb78SBo-Chen Chen 
5659e629c17SJie Qiu 	hsync.shift_half_line = false;
56672ac6969SSatendra Singh Thakur 	vsync_lodd.sync_width = vm.vsync_len;
56772ac6969SSatendra Singh Thakur 	vsync_lodd.back_porch = vm.vback_porch;
56872ac6969SSatendra Singh Thakur 	vsync_lodd.front_porch = vm.vfront_porch;
5699e629c17SJie Qiu 	vsync_lodd.shift_half_line = false;
5709e629c17SJie Qiu 
57172ac6969SSatendra Singh Thakur 	if (vm.flags & DISPLAY_FLAGS_INTERLACED &&
5729e629c17SJie Qiu 	    mode->flags & DRM_MODE_FLAG_3D_MASK) {
5739e629c17SJie Qiu 		vsync_leven = vsync_lodd;
5749e629c17SJie Qiu 		vsync_rodd = vsync_lodd;
5759e629c17SJie Qiu 		vsync_reven = vsync_lodd;
5769e629c17SJie Qiu 		vsync_leven.shift_half_line = true;
5779e629c17SJie Qiu 		vsync_reven.shift_half_line = true;
57872ac6969SSatendra Singh Thakur 	} else if (vm.flags & DISPLAY_FLAGS_INTERLACED &&
5799e629c17SJie Qiu 		   !(mode->flags & DRM_MODE_FLAG_3D_MASK)) {
5809e629c17SJie Qiu 		vsync_leven = vsync_lodd;
5819e629c17SJie Qiu 		vsync_leven.shift_half_line = true;
58272ac6969SSatendra Singh Thakur 	} else if (!(vm.flags & DISPLAY_FLAGS_INTERLACED) &&
5839e629c17SJie Qiu 		   mode->flags & DRM_MODE_FLAG_3D_MASK) {
5849e629c17SJie Qiu 		vsync_rodd = vsync_lodd;
5859e629c17SJie Qiu 	}
5869e629c17SJie Qiu 	mtk_dpi_sw_reset(dpi, true);
5879e629c17SJie Qiu 	mtk_dpi_config_pol(dpi, &dpi_pol);
5889e629c17SJie Qiu 
5899e629c17SJie Qiu 	mtk_dpi_config_hsync(dpi, &hsync);
5909e629c17SJie Qiu 	mtk_dpi_config_vsync_lodd(dpi, &vsync_lodd);
5919e629c17SJie Qiu 	mtk_dpi_config_vsync_rodd(dpi, &vsync_rodd);
5929e629c17SJie Qiu 	mtk_dpi_config_vsync_leven(dpi, &vsync_leven);
5939e629c17SJie Qiu 	mtk_dpi_config_vsync_reven(dpi, &vsync_reven);
5949e629c17SJie Qiu 
5959e629c17SJie Qiu 	mtk_dpi_config_3d(dpi, !!(mode->flags & DRM_MODE_FLAG_3D_MASK));
59672ac6969SSatendra Singh Thakur 	mtk_dpi_config_interface(dpi, !!(vm.flags &
59772ac6969SSatendra Singh Thakur 					 DISPLAY_FLAGS_INTERLACED));
59872ac6969SSatendra Singh Thakur 	if (vm.flags & DISPLAY_FLAGS_INTERLACED)
59972ac6969SSatendra Singh Thakur 		mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive >> 1);
6009e629c17SJie Qiu 	else
60172ac6969SSatendra Singh Thakur 		mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive);
6029e629c17SJie Qiu 
6034393c74aSBo-Chen Chen 	mtk_dpi_config_channel_limit(dpi);
6049e629c17SJie Qiu 	mtk_dpi_config_bit_num(dpi, dpi->bit_num);
6059e629c17SJie Qiu 	mtk_dpi_config_channel_swap(dpi, dpi->channel_swap);
6069e629c17SJie Qiu 	mtk_dpi_config_color_format(dpi, dpi->color_format);
607c83da623SBo-Chen Chen 	if (dpi->conf->support_direct_pin) {
608c83da623SBo-Chen Chen 		mtk_dpi_config_yc_map(dpi, dpi->yc_map);
6099e629c17SJie Qiu 		mtk_dpi_config_2n_h_fre(dpi);
6106385ed8eSRex-BC Chen 		mtk_dpi_dual_edge(dpi);
61179080159Schunhui dai 		mtk_dpi_config_disable_edge(dpi);
612c83da623SBo-Chen Chen 	}
6132587d895SBo-Chen Chen 	if (dpi->conf->input_2pixel) {
6142587d895SBo-Chen Chen 		mtk_dpi_mask(dpi, DPI_CON, DPINTF_INPUT_2P_EN,
6152587d895SBo-Chen Chen 			     DPINTF_INPUT_2P_EN);
6162587d895SBo-Chen Chen 	}
6179e629c17SJie Qiu 	mtk_dpi_sw_reset(dpi, false);
6189e629c17SJie Qiu 
6199e629c17SJie Qiu 	return 0;
6209e629c17SJie Qiu }
6219e629c17SJie Qiu 
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)622ec8747c5SRex-BC Chen static u32 *mtk_dpi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
623ec8747c5SRex-BC Chen 						      struct drm_bridge_state *bridge_state,
624ec8747c5SRex-BC Chen 						      struct drm_crtc_state *crtc_state,
625ec8747c5SRex-BC Chen 						      struct drm_connector_state *conn_state,
626ec8747c5SRex-BC Chen 						      unsigned int *num_output_fmts)
627ec8747c5SRex-BC Chen {
628ec8747c5SRex-BC Chen 	struct mtk_dpi *dpi = bridge_to_dpi(bridge);
629ec8747c5SRex-BC Chen 	u32 *output_fmts;
630ec8747c5SRex-BC Chen 
631ec8747c5SRex-BC Chen 	*num_output_fmts = 0;
632ec8747c5SRex-BC Chen 
633ec8747c5SRex-BC Chen 	if (!dpi->conf->output_fmts) {
634ec8747c5SRex-BC Chen 		dev_err(dpi->dev, "output_fmts should not be null\n");
635ec8747c5SRex-BC Chen 		return NULL;
636ec8747c5SRex-BC Chen 	}
637ec8747c5SRex-BC Chen 
638ec8747c5SRex-BC Chen 	output_fmts = kcalloc(dpi->conf->num_output_fmts, sizeof(*output_fmts),
639ec8747c5SRex-BC Chen 			     GFP_KERNEL);
640ec8747c5SRex-BC Chen 	if (!output_fmts)
641ec8747c5SRex-BC Chen 		return NULL;
642ec8747c5SRex-BC Chen 
643ec8747c5SRex-BC Chen 	*num_output_fmts = dpi->conf->num_output_fmts;
644ec8747c5SRex-BC Chen 
645ec8747c5SRex-BC Chen 	memcpy(output_fmts, dpi->conf->output_fmts,
646ec8747c5SRex-BC Chen 	       sizeof(*output_fmts) * dpi->conf->num_output_fmts);
647ec8747c5SRex-BC Chen 
648ec8747c5SRex-BC Chen 	return output_fmts;
649ec8747c5SRex-BC Chen }
650ec8747c5SRex-BC Chen 
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)651ec8747c5SRex-BC Chen static u32 *mtk_dpi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
652ec8747c5SRex-BC Chen 						     struct drm_bridge_state *bridge_state,
653ec8747c5SRex-BC Chen 						     struct drm_crtc_state *crtc_state,
654ec8747c5SRex-BC Chen 						     struct drm_connector_state *conn_state,
655ec8747c5SRex-BC Chen 						     u32 output_fmt,
656ec8747c5SRex-BC Chen 						     unsigned int *num_input_fmts)
657ec8747c5SRex-BC Chen {
658ec8747c5SRex-BC Chen 	u32 *input_fmts;
659ec8747c5SRex-BC Chen 
660ec8747c5SRex-BC Chen 	*num_input_fmts = 0;
661ec8747c5SRex-BC Chen 
662ec8747c5SRex-BC Chen 	input_fmts = kcalloc(1, sizeof(*input_fmts),
663ec8747c5SRex-BC Chen 			     GFP_KERNEL);
664ec8747c5SRex-BC Chen 	if (!input_fmts)
665ec8747c5SRex-BC Chen 		return NULL;
666ec8747c5SRex-BC Chen 
667ec8747c5SRex-BC Chen 	*num_input_fmts = 1;
668ec8747c5SRex-BC Chen 	input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
669ec8747c5SRex-BC Chen 
670ec8747c5SRex-BC Chen 	return input_fmts;
671ec8747c5SRex-BC Chen }
672ec8747c5SRex-BC Chen 
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)673ec8747c5SRex-BC Chen static int mtk_dpi_bridge_atomic_check(struct drm_bridge *bridge,
674ec8747c5SRex-BC Chen 				       struct drm_bridge_state *bridge_state,
675ec8747c5SRex-BC Chen 				       struct drm_crtc_state *crtc_state,
676ec8747c5SRex-BC Chen 				       struct drm_connector_state *conn_state)
677ec8747c5SRex-BC Chen {
678e062233cSFrank Wunderlich 	struct mtk_dpi *dpi = bridge_to_dpi(bridge);
679ec8747c5SRex-BC Chen 	unsigned int out_bus_format;
680ec8747c5SRex-BC Chen 
681ec8747c5SRex-BC Chen 	out_bus_format = bridge_state->output_bus_cfg.format;
682ec8747c5SRex-BC Chen 
6836b57ba32SHsin-Yi Wang 	if (out_bus_format == MEDIA_BUS_FMT_FIXED)
6846b57ba32SHsin-Yi Wang 		if (dpi->conf->num_output_fmts)
6856b57ba32SHsin-Yi Wang 			out_bus_format = dpi->conf->output_fmts[0];
6866b57ba32SHsin-Yi Wang 
687ec8747c5SRex-BC Chen 	dev_dbg(dpi->dev, "input format 0x%04x, output format 0x%04x\n",
688ec8747c5SRex-BC Chen 		bridge_state->input_bus_cfg.format,
689ec8747c5SRex-BC Chen 		bridge_state->output_bus_cfg.format);
690ec8747c5SRex-BC Chen 
691ec8747c5SRex-BC Chen 	dpi->output_fmt = out_bus_format;
692ec8747c5SRex-BC Chen 	dpi->bit_num = MTK_DPI_OUT_BIT_NUM_8BITS;
693ec8747c5SRex-BC Chen 	dpi->channel_swap = MTK_DPI_OUT_CHANNEL_SWAP_RGB;
694ec8747c5SRex-BC Chen 	dpi->yc_map = MTK_DPI_OUT_YC_MAP_RGB;
695b992131aSBo-Chen Chen 	if (out_bus_format == MEDIA_BUS_FMT_YUYV8_1X16)
696b992131aSBo-Chen Chen 		dpi->color_format = MTK_DPI_COLOR_FORMAT_YCBCR_422;
697b992131aSBo-Chen Chen 	else
698ec8747c5SRex-BC Chen 		dpi->color_format = MTK_DPI_COLOR_FORMAT_RGB;
699ec8747c5SRex-BC Chen 
700ec8747c5SRex-BC Chen 	return 0;
701ec8747c5SRex-BC Chen }
702ec8747c5SRex-BC Chen 
mtk_dpi_bridge_attach(struct drm_bridge * bridge,enum drm_bridge_attach_flags flags)703f89c696eSEnric Balletbo i Serra static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,
704f89c696eSEnric Balletbo i Serra 				 enum drm_bridge_attach_flags flags)
7059e629c17SJie Qiu {
706f89c696eSEnric Balletbo i Serra 	struct mtk_dpi *dpi = bridge_to_dpi(bridge);
707f89c696eSEnric Balletbo i Serra 
708f89c696eSEnric Balletbo i Serra 	return drm_bridge_attach(bridge->encoder, dpi->next_bridge,
709f89c696eSEnric Balletbo i Serra 				 &dpi->bridge, flags);
710f89c696eSEnric Balletbo i Serra }
711f89c696eSEnric Balletbo i Serra 
mtk_dpi_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)712f89c696eSEnric Balletbo i Serra static void mtk_dpi_bridge_mode_set(struct drm_bridge *bridge,
713f89c696eSEnric Balletbo i Serra 				const struct drm_display_mode *mode,
714f89c696eSEnric Balletbo i Serra 				const struct drm_display_mode *adjusted_mode)
715f89c696eSEnric Balletbo i Serra {
716f89c696eSEnric Balletbo i Serra 	struct mtk_dpi *dpi = bridge_to_dpi(bridge);
7179e629c17SJie Qiu 
7189e629c17SJie Qiu 	drm_mode_copy(&dpi->mode, adjusted_mode);
7199e629c17SJie Qiu }
7209e629c17SJie Qiu 
mtk_dpi_bridge_disable(struct drm_bridge * bridge)721f89c696eSEnric Balletbo i Serra static void mtk_dpi_bridge_disable(struct drm_bridge *bridge)
7229e629c17SJie Qiu {
723f89c696eSEnric Balletbo i Serra 	struct mtk_dpi *dpi = bridge_to_dpi(bridge);
7249e629c17SJie Qiu 
7254e90a6ebSchunhui dai 	mtk_dpi_power_off(dpi);
726ff446c0fSXinlei Lee 
727ff446c0fSXinlei Lee 	if (dpi->pinctrl && dpi->pins_gpio)
728ff446c0fSXinlei Lee 		pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
7299e629c17SJie Qiu }
7309e629c17SJie Qiu 
mtk_dpi_bridge_enable(struct drm_bridge * bridge)731f89c696eSEnric Balletbo i Serra static void mtk_dpi_bridge_enable(struct drm_bridge *bridge)
7329e629c17SJie Qiu {
733f89c696eSEnric Balletbo i Serra 	struct mtk_dpi *dpi = bridge_to_dpi(bridge);
7349e629c17SJie Qiu 
735ff446c0fSXinlei Lee 	if (dpi->pinctrl && dpi->pins_dpi)
736ff446c0fSXinlei Lee 		pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
737ff446c0fSXinlei Lee 
7384e90a6ebSchunhui dai 	mtk_dpi_power_on(dpi);
7399e629c17SJie Qiu 	mtk_dpi_set_display_mode(dpi, &dpi->mode);
740aed61ef6SGuillaume Ranquet 	mtk_dpi_enable(dpi);
7419e629c17SJie Qiu }
7429e629c17SJie Qiu 
74344b07120SRex-BC Chen 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)74444b07120SRex-BC Chen mtk_dpi_bridge_mode_valid(struct drm_bridge *bridge,
74544b07120SRex-BC Chen 			  const struct drm_display_info *info,
74644b07120SRex-BC Chen 			  const struct drm_display_mode *mode)
74744b07120SRex-BC Chen {
74844b07120SRex-BC Chen 	struct mtk_dpi *dpi = bridge_to_dpi(bridge);
74944b07120SRex-BC Chen 
75044b07120SRex-BC Chen 	if (mode->clock > dpi->conf->max_clock_khz)
75144b07120SRex-BC Chen 		return MODE_CLOCK_HIGH;
75244b07120SRex-BC Chen 
75344b07120SRex-BC Chen 	return MODE_OK;
75444b07120SRex-BC Chen }
75544b07120SRex-BC Chen 
756f89c696eSEnric Balletbo i Serra static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = {
757f89c696eSEnric Balletbo i Serra 	.attach = mtk_dpi_bridge_attach,
758f89c696eSEnric Balletbo i Serra 	.mode_set = mtk_dpi_bridge_mode_set,
75944b07120SRex-BC Chen 	.mode_valid = mtk_dpi_bridge_mode_valid,
760f89c696eSEnric Balletbo i Serra 	.disable = mtk_dpi_bridge_disable,
761f89c696eSEnric Balletbo i Serra 	.enable = mtk_dpi_bridge_enable,
762ec8747c5SRex-BC Chen 	.atomic_check = mtk_dpi_bridge_atomic_check,
763ec8747c5SRex-BC Chen 	.atomic_get_output_bus_fmts = mtk_dpi_bridge_atomic_get_output_bus_fmts,
764ec8747c5SRex-BC Chen 	.atomic_get_input_bus_fmts = mtk_dpi_bridge_atomic_get_input_bus_fmts,
765ec8747c5SRex-BC Chen 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
766ec8747c5SRex-BC Chen 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
767ec8747c5SRex-BC Chen 	.atomic_reset = drm_atomic_helper_bridge_reset,
7689e629c17SJie Qiu };
7699e629c17SJie Qiu 
mtk_dpi_start(struct device * dev)7701d33f13aSCK Hu void mtk_dpi_start(struct device *dev)
7719e629c17SJie Qiu {
7724d510659SCK Hu 	struct mtk_dpi *dpi = dev_get_drvdata(dev);
7739e629c17SJie Qiu 
7744e90a6ebSchunhui dai 	mtk_dpi_power_on(dpi);
7759e629c17SJie Qiu }
7769e629c17SJie Qiu 
mtk_dpi_stop(struct device * dev)7771d33f13aSCK Hu void mtk_dpi_stop(struct device *dev)
7789e629c17SJie Qiu {
7794d510659SCK Hu 	struct mtk_dpi *dpi = dev_get_drvdata(dev);
7809e629c17SJie Qiu 
7814e90a6ebSchunhui dai 	mtk_dpi_power_off(dpi);
7829e629c17SJie Qiu }
7839e629c17SJie Qiu 
mtk_dpi_bind(struct device * dev,struct device * master,void * data)7849e629c17SJie Qiu static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
7859e629c17SJie Qiu {
7869e629c17SJie Qiu 	struct mtk_dpi *dpi = dev_get_drvdata(dev);
7879e629c17SJie Qiu 	struct drm_device *drm_dev = data;
78862fc5cd1SXinlei Lee 	struct mtk_drm_private *priv = drm_dev->dev_private;
7899e629c17SJie Qiu 	int ret;
7909e629c17SJie Qiu 
79162fc5cd1SXinlei Lee 	dpi->mmsys_dev = priv->mmsys_dev;
792b534c4f5SThomas Zimmermann 	ret = drm_simple_encoder_init(drm_dev, &dpi->encoder,
793b534c4f5SThomas Zimmermann 				      DRM_MODE_ENCODER_TMDS);
7949e629c17SJie Qiu 	if (ret) {
7959e629c17SJie Qiu 		dev_err(dev, "Failed to initialize decoder: %d\n", ret);
796ff139560SCK Hu 		return ret;
7979e629c17SJie Qiu 	}
7989e629c17SJie Qiu 
799ff139560SCK Hu 	dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->dev);
8009e629c17SJie Qiu 
801f0119514SHsin-Yi Wang 	ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL,
802f0119514SHsin-Yi Wang 				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
803fb8d617fSLaurent Pinchart 	if (ret)
8049e629c17SJie Qiu 		goto err_cleanup;
8059e629c17SJie Qiu 
806f0119514SHsin-Yi Wang 	dpi->connector = drm_bridge_connector_init(drm_dev, &dpi->encoder);
807f0119514SHsin-Yi Wang 	if (IS_ERR(dpi->connector)) {
808f0119514SHsin-Yi Wang 		dev_err(dev, "Unable to create bridge connector\n");
809f0119514SHsin-Yi Wang 		ret = PTR_ERR(dpi->connector);
810f0119514SHsin-Yi Wang 		goto err_cleanup;
811f0119514SHsin-Yi Wang 	}
812f0119514SHsin-Yi Wang 	drm_connector_attach_encoder(dpi->connector, &dpi->encoder);
813f0119514SHsin-Yi Wang 
8149e629c17SJie Qiu 	return 0;
8159e629c17SJie Qiu 
8169e629c17SJie Qiu err_cleanup:
8179e629c17SJie Qiu 	drm_encoder_cleanup(&dpi->encoder);
8189e629c17SJie Qiu 	return ret;
8199e629c17SJie Qiu }
8209e629c17SJie Qiu 
mtk_dpi_unbind(struct device * dev,struct device * master,void * data)8219e629c17SJie Qiu static void mtk_dpi_unbind(struct device *dev, struct device *master,
8229e629c17SJie Qiu 			   void *data)
8239e629c17SJie Qiu {
8249e629c17SJie Qiu 	struct mtk_dpi *dpi = dev_get_drvdata(dev);
8259e629c17SJie Qiu 
8269e629c17SJie Qiu 	drm_encoder_cleanup(&dpi->encoder);
8279e629c17SJie Qiu }
8289e629c17SJie Qiu 
8299e629c17SJie Qiu static const struct component_ops mtk_dpi_component_ops = {
8309e629c17SJie Qiu 	.bind = mtk_dpi_bind,
8319e629c17SJie Qiu 	.unbind = mtk_dpi_unbind,
8329e629c17SJie Qiu };
8339e629c17SJie Qiu 
mt8173_calculate_factor(int clock)83455c78aa5Schunhui dai static unsigned int mt8173_calculate_factor(int clock)
83555c78aa5Schunhui dai {
83655c78aa5Schunhui dai 	if (clock <= 27000)
83755c78aa5Schunhui dai 		return 3 << 4;
83855c78aa5Schunhui dai 	else if (clock <= 84000)
83955c78aa5Schunhui dai 		return 3 << 3;
84055c78aa5Schunhui dai 	else if (clock <= 167000)
84155c78aa5Schunhui dai 		return 3 << 2;
84255c78aa5Schunhui dai 	else
84355c78aa5Schunhui dai 		return 3 << 1;
84455c78aa5Schunhui dai }
84555c78aa5Schunhui dai 
mt2701_calculate_factor(int clock)846d08b5ab9Schunhui dai static unsigned int mt2701_calculate_factor(int clock)
847d08b5ab9Schunhui dai {
848d08b5ab9Schunhui dai 	if (clock <= 64000)
849d08b5ab9Schunhui dai 		return 4;
8508eeb3946SWangyan Wang 	else if (clock <= 128000)
851d08b5ab9Schunhui dai 		return 2;
8528eeb3946SWangyan Wang 	else
8538eeb3946SWangyan Wang 		return 1;
854d08b5ab9Schunhui dai }
855d08b5ab9Schunhui dai 
mt8183_calculate_factor(int clock)856b4720944SJitao Shi static unsigned int mt8183_calculate_factor(int clock)
857b4720944SJitao Shi {
858b4720944SJitao Shi 	if (clock <= 27000)
859b4720944SJitao Shi 		return 8;
860b4720944SJitao Shi 	else if (clock <= 167000)
861b4720944SJitao Shi 		return 4;
862b4720944SJitao Shi 	else
863b4720944SJitao Shi 		return 2;
864b4720944SJitao Shi }
865b4720944SJitao Shi 
mt8195_dpintf_calculate_factor(int clock)866d86c1568SGuillaume Ranquet static unsigned int mt8195_dpintf_calculate_factor(int clock)
867d86c1568SGuillaume Ranquet {
868d86c1568SGuillaume Ranquet 	if (clock < 70000)
869d86c1568SGuillaume Ranquet 		return 4;
870d86c1568SGuillaume Ranquet 	else if (clock < 200000)
871d86c1568SGuillaume Ranquet 		return 2;
872d86c1568SGuillaume Ranquet 	else
873d86c1568SGuillaume Ranquet 		return 1;
874d86c1568SGuillaume Ranquet }
875d86c1568SGuillaume Ranquet 
876be63f6e8SRex-BC Chen static const u32 mt8173_output_fmts[] = {
877be63f6e8SRex-BC Chen 	MEDIA_BUS_FMT_RGB888_1X24,
878be63f6e8SRex-BC Chen };
879be63f6e8SRex-BC Chen 
880be63f6e8SRex-BC Chen static const u32 mt8183_output_fmts[] = {
881be63f6e8SRex-BC Chen 	MEDIA_BUS_FMT_RGB888_2X12_LE,
882be63f6e8SRex-BC Chen 	MEDIA_BUS_FMT_RGB888_2X12_BE,
883be63f6e8SRex-BC Chen };
884be63f6e8SRex-BC Chen 
885d86c1568SGuillaume Ranquet static const u32 mt8195_output_fmts[] = {
886d86c1568SGuillaume Ranquet 	MEDIA_BUS_FMT_RGB888_1X24,
887d86c1568SGuillaume Ranquet 	MEDIA_BUS_FMT_YUYV8_1X16,
888d86c1568SGuillaume Ranquet };
889d86c1568SGuillaume Ranquet 
8900ace4b99Schunhui dai static const struct mtk_dpi_conf mt8173_conf = {
89155c78aa5Schunhui dai 	.cal_factor = mt8173_calculate_factor,
8920ace4b99Schunhui dai 	.reg_h_fre_con = 0xe0,
89344b07120SRex-BC Chen 	.max_clock_khz = 300000,
894be63f6e8SRex-BC Chen 	.output_fmts = mt8173_output_fmts,
895be63f6e8SRex-BC Chen 	.num_output_fmts = ARRAY_SIZE(mt8173_output_fmts),
89649ecbb78SBo-Chen Chen 	.pixels_per_iter = 1,
897cf060519SGuillaume Ranquet 	.is_ck_de_pol = true,
8983145095fSGuillaume Ranquet 	.swap_input_support = true,
899c83da623SBo-Chen Chen 	.support_direct_pin = true,
900a519e22bSGuillaume Ranquet 	.dimension_mask = HPW_MASK,
901e373924dSGuillaume Ranquet 	.hvsize_mask = HSIZE_MASK,
90248fb81a2SGuillaume Ranquet 	.channel_swap_shift = CH_SWAP,
9034e28119bSGuillaume Ranquet 	.yuv422_en_bit = YUV422_EN,
904091e5e00SGuillaume Ranquet 	.csc_enable_bit = CSC_ENABLE,
9050ace4b99Schunhui dai };
9060ace4b99Schunhui dai 
907d08b5ab9Schunhui dai static const struct mtk_dpi_conf mt2701_conf = {
908d08b5ab9Schunhui dai 	.cal_factor = mt2701_calculate_factor,
909d08b5ab9Schunhui dai 	.reg_h_fre_con = 0xb0,
910d08b5ab9Schunhui dai 	.edge_sel_en = true,
91144b07120SRex-BC Chen 	.max_clock_khz = 150000,
912be63f6e8SRex-BC Chen 	.output_fmts = mt8173_output_fmts,
913be63f6e8SRex-BC Chen 	.num_output_fmts = ARRAY_SIZE(mt8173_output_fmts),
91449ecbb78SBo-Chen Chen 	.pixels_per_iter = 1,
915cf060519SGuillaume Ranquet 	.is_ck_de_pol = true,
9163145095fSGuillaume Ranquet 	.swap_input_support = true,
917c83da623SBo-Chen Chen 	.support_direct_pin = true,
918a519e22bSGuillaume Ranquet 	.dimension_mask = HPW_MASK,
919e373924dSGuillaume Ranquet 	.hvsize_mask = HSIZE_MASK,
92048fb81a2SGuillaume Ranquet 	.channel_swap_shift = CH_SWAP,
9214e28119bSGuillaume Ranquet 	.yuv422_en_bit = YUV422_EN,
922091e5e00SGuillaume Ranquet 	.csc_enable_bit = CSC_ENABLE,
923d08b5ab9Schunhui dai };
924d08b5ab9Schunhui dai 
925b4720944SJitao Shi static const struct mtk_dpi_conf mt8183_conf = {
926b4720944SJitao Shi 	.cal_factor = mt8183_calculate_factor,
927b4720944SJitao Shi 	.reg_h_fre_con = 0xe0,
92844b07120SRex-BC Chen 	.max_clock_khz = 100000,
929be63f6e8SRex-BC Chen 	.output_fmts = mt8183_output_fmts,
930be63f6e8SRex-BC Chen 	.num_output_fmts = ARRAY_SIZE(mt8183_output_fmts),
93149ecbb78SBo-Chen Chen 	.pixels_per_iter = 1,
932cf060519SGuillaume Ranquet 	.is_ck_de_pol = true,
9333145095fSGuillaume Ranquet 	.swap_input_support = true,
934c83da623SBo-Chen Chen 	.support_direct_pin = true,
935a519e22bSGuillaume Ranquet 	.dimension_mask = HPW_MASK,
936e373924dSGuillaume Ranquet 	.hvsize_mask = HSIZE_MASK,
93748fb81a2SGuillaume Ranquet 	.channel_swap_shift = CH_SWAP,
9384e28119bSGuillaume Ranquet 	.yuv422_en_bit = YUV422_EN,
939091e5e00SGuillaume Ranquet 	.csc_enable_bit = CSC_ENABLE,
940b4720944SJitao Shi };
941b4720944SJitao Shi 
942e15b0e6dSXinlei Lee static const struct mtk_dpi_conf mt8186_conf = {
943e15b0e6dSXinlei Lee 	.cal_factor = mt8183_calculate_factor,
944e15b0e6dSXinlei Lee 	.reg_h_fre_con = 0xe0,
945e15b0e6dSXinlei Lee 	.max_clock_khz = 150000,
946e15b0e6dSXinlei Lee 	.output_fmts = mt8183_output_fmts,
947e15b0e6dSXinlei Lee 	.num_output_fmts = ARRAY_SIZE(mt8183_output_fmts),
948e15b0e6dSXinlei Lee 	.edge_cfg_in_mmsys = true,
949e15b0e6dSXinlei Lee 	.pixels_per_iter = 1,
950e15b0e6dSXinlei Lee 	.is_ck_de_pol = true,
951e15b0e6dSXinlei Lee 	.swap_input_support = true,
952e15b0e6dSXinlei Lee 	.support_direct_pin = true,
953e15b0e6dSXinlei Lee 	.dimension_mask = HPW_MASK,
954e15b0e6dSXinlei Lee 	.hvsize_mask = HSIZE_MASK,
955e15b0e6dSXinlei Lee 	.channel_swap_shift = CH_SWAP,
956e15b0e6dSXinlei Lee 	.yuv422_en_bit = YUV422_EN,
957e15b0e6dSXinlei Lee 	.csc_enable_bit = CSC_ENABLE,
958e15b0e6dSXinlei Lee };
959e15b0e6dSXinlei Lee 
96038eaef2dSRex-BC Chen static const struct mtk_dpi_conf mt8192_conf = {
96138eaef2dSRex-BC Chen 	.cal_factor = mt8183_calculate_factor,
96238eaef2dSRex-BC Chen 	.reg_h_fre_con = 0xe0,
96338eaef2dSRex-BC Chen 	.max_clock_khz = 150000,
9647112e0b0SNícolas F. R. A. Prado 	.output_fmts = mt8183_output_fmts,
9657112e0b0SNícolas F. R. A. Prado 	.num_output_fmts = ARRAY_SIZE(mt8183_output_fmts),
96649ecbb78SBo-Chen Chen 	.pixels_per_iter = 1,
967cf060519SGuillaume Ranquet 	.is_ck_de_pol = true,
9683145095fSGuillaume Ranquet 	.swap_input_support = true,
969c83da623SBo-Chen Chen 	.support_direct_pin = true,
970a519e22bSGuillaume Ranquet 	.dimension_mask = HPW_MASK,
971e373924dSGuillaume Ranquet 	.hvsize_mask = HSIZE_MASK,
97248fb81a2SGuillaume Ranquet 	.channel_swap_shift = CH_SWAP,
9734e28119bSGuillaume Ranquet 	.yuv422_en_bit = YUV422_EN,
974091e5e00SGuillaume Ranquet 	.csc_enable_bit = CSC_ENABLE,
97538eaef2dSRex-BC Chen };
97638eaef2dSRex-BC Chen 
977d86c1568SGuillaume Ranquet static const struct mtk_dpi_conf mt8195_dpintf_conf = {
978d86c1568SGuillaume Ranquet 	.cal_factor = mt8195_dpintf_calculate_factor,
979d86c1568SGuillaume Ranquet 	.max_clock_khz = 600000,
980d86c1568SGuillaume Ranquet 	.output_fmts = mt8195_output_fmts,
981d86c1568SGuillaume Ranquet 	.num_output_fmts = ARRAY_SIZE(mt8195_output_fmts),
982d86c1568SGuillaume Ranquet 	.pixels_per_iter = 4,
983d86c1568SGuillaume Ranquet 	.input_2pixel = true,
984d86c1568SGuillaume Ranquet 	.dimension_mask = DPINTF_HPW_MASK,
985d86c1568SGuillaume Ranquet 	.hvsize_mask = DPINTF_HSIZE_MASK,
986d86c1568SGuillaume Ranquet 	.channel_swap_shift = DPINTF_CH_SWAP,
987d86c1568SGuillaume Ranquet 	.yuv422_en_bit = DPINTF_YUV422_EN,
988d86c1568SGuillaume Ranquet 	.csc_enable_bit = DPINTF_CSC_ENABLE,
9899e629c17SJie Qiu };
9909e629c17SJie Qiu 
mtk_dpi_probe(struct platform_device * pdev)9919e629c17SJie Qiu static int mtk_dpi_probe(struct platform_device *pdev)
9929e629c17SJie Qiu {
9939e629c17SJie Qiu 	struct device *dev = &pdev->dev;
9949e629c17SJie Qiu 	struct mtk_dpi *dpi;
9959e629c17SJie Qiu 	int ret;
9969e629c17SJie Qiu 
9979e629c17SJie Qiu 	dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
9989e629c17SJie Qiu 	if (!dpi)
9999e629c17SJie Qiu 		return -ENOMEM;
10009e629c17SJie Qiu 
10019e629c17SJie Qiu 	dpi->dev = dev;
10020ace4b99Schunhui dai 	dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
10036385ed8eSRex-BC Chen 	dpi->output_fmt = MEDIA_BUS_FMT_RGB888_1X24;
10049e629c17SJie Qiu 
10056bd4763fSJitao Shi 	dpi->pinctrl = devm_pinctrl_get(&pdev->dev);
10066bd4763fSJitao Shi 	if (IS_ERR(dpi->pinctrl)) {
10076bd4763fSJitao Shi 		dpi->pinctrl = NULL;
10086bd4763fSJitao Shi 		dev_dbg(&pdev->dev, "Cannot find pinctrl!\n");
10096bd4763fSJitao Shi 	}
10106bd4763fSJitao Shi 	if (dpi->pinctrl) {
10116bd4763fSJitao Shi 		dpi->pins_gpio = pinctrl_lookup_state(dpi->pinctrl, "sleep");
10126bd4763fSJitao Shi 		if (IS_ERR(dpi->pins_gpio)) {
10136bd4763fSJitao Shi 			dpi->pins_gpio = NULL;
10146bd4763fSJitao Shi 			dev_dbg(&pdev->dev, "Cannot find pinctrl idle!\n");
10156bd4763fSJitao Shi 		}
10166bd4763fSJitao Shi 		if (dpi->pins_gpio)
10176bd4763fSJitao Shi 			pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
10186bd4763fSJitao Shi 
10196bd4763fSJitao Shi 		dpi->pins_dpi = pinctrl_lookup_state(dpi->pinctrl, "default");
10206bd4763fSJitao Shi 		if (IS_ERR(dpi->pins_dpi)) {
10216bd4763fSJitao Shi 			dpi->pins_dpi = NULL;
10226bd4763fSJitao Shi 			dev_dbg(&pdev->dev, "Cannot find pinctrl active!\n");
10236bd4763fSJitao Shi 		}
10246bd4763fSJitao Shi 	}
10254f109879SAngeloGioacchino Del Regno 	dpi->regs = devm_platform_ioremap_resource(pdev, 0);
1026be471406SAngeloGioacchino Del Regno 	if (IS_ERR(dpi->regs))
1027be471406SAngeloGioacchino Del Regno 		return dev_err_probe(dev, PTR_ERR(dpi->regs),
1028be471406SAngeloGioacchino Del Regno 				     "Failed to ioremap mem resource\n");
10299e629c17SJie Qiu 
10309e629c17SJie Qiu 	dpi->engine_clk = devm_clk_get(dev, "engine");
1031be471406SAngeloGioacchino Del Regno 	if (IS_ERR(dpi->engine_clk))
1032be471406SAngeloGioacchino Del Regno 		return dev_err_probe(dev, PTR_ERR(dpi->engine_clk),
1033be471406SAngeloGioacchino Del Regno 				     "Failed to get engine clock\n");
10349e629c17SJie Qiu 
10359e629c17SJie Qiu 	dpi->pixel_clk = devm_clk_get(dev, "pixel");
1036be471406SAngeloGioacchino Del Regno 	if (IS_ERR(dpi->pixel_clk))
1037be471406SAngeloGioacchino Del Regno 		return dev_err_probe(dev, PTR_ERR(dpi->pixel_clk),
1038be471406SAngeloGioacchino Del Regno 				     "Failed to get pixel clock\n");
10399e629c17SJie Qiu 
10409e629c17SJie Qiu 	dpi->tvd_clk = devm_clk_get(dev, "pll");
1041be471406SAngeloGioacchino Del Regno 	if (IS_ERR(dpi->tvd_clk))
1042be471406SAngeloGioacchino Del Regno 		return dev_err_probe(dev, PTR_ERR(dpi->tvd_clk),
1043be471406SAngeloGioacchino Del Regno 				     "Failed to get tvdpll clock\n");
10449e629c17SJie Qiu 
10459e629c17SJie Qiu 	dpi->irq = platform_get_irq(pdev, 0);
104661a97decSRuan Jinjie 	if (dpi->irq < 0)
104761a97decSRuan Jinjie 		return dpi->irq;
10489e629c17SJie Qiu 
1049846a7ae1SAngeloGioacchino Del Regno 	dpi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
1050846a7ae1SAngeloGioacchino Del Regno 	if (IS_ERR(dpi->next_bridge))
1051846a7ae1SAngeloGioacchino Del Regno 		return dev_err_probe(dev, PTR_ERR(dpi->next_bridge),
1052846a7ae1SAngeloGioacchino Del Regno 				     "Failed to get bridge\n");
10539e629c17SJie Qiu 
10548b465f01SEnric Balletbo i Serra 	dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node);
10559e629c17SJie Qiu 
10569e629c17SJie Qiu 	platform_set_drvdata(pdev, dpi);
10579e629c17SJie Qiu 
1058f89c696eSEnric Balletbo i Serra 	dpi->bridge.funcs = &mtk_dpi_bridge_funcs;
1059f89c696eSEnric Balletbo i Serra 	dpi->bridge.of_node = dev->of_node;
1060f89c696eSEnric Balletbo i Serra 	dpi->bridge.type = DRM_MODE_CONNECTOR_DPI;
1061f89c696eSEnric Balletbo i Serra 
106247d4bb6bSAngeloGioacchino Del Regno 	ret = devm_drm_bridge_add(dev, &dpi->bridge);
106347d4bb6bSAngeloGioacchino Del Regno 	if (ret)
106447d4bb6bSAngeloGioacchino Del Regno 		return ret;
1065f89c696eSEnric Balletbo i Serra 
10669e629c17SJie Qiu 	ret = component_add(dev, &mtk_dpi_component_ops);
1067be471406SAngeloGioacchino Del Regno 	if (ret)
1068be471406SAngeloGioacchino Del Regno 		return dev_err_probe(dev, ret, "Failed to add component.\n");
10699e629c17SJie Qiu 
10709e629c17SJie Qiu 	return 0;
10719e629c17SJie Qiu }
10729e629c17SJie Qiu 
mtk_dpi_remove(struct platform_device * pdev)107390c95c38SAngeloGioacchino Del Regno static void mtk_dpi_remove(struct platform_device *pdev)
10749e629c17SJie Qiu {
10759e629c17SJie Qiu 	component_del(&pdev->dev, &mtk_dpi_component_ops);
10769e629c17SJie Qiu }
10779e629c17SJie Qiu 
10789e629c17SJie Qiu static const struct of_device_id mtk_dpi_of_ids[] = {
107961d9afafSAngeloGioacchino Del Regno 	{ .compatible = "mediatek,mt2701-dpi", .data = &mt2701_conf },
108061d9afafSAngeloGioacchino Del Regno 	{ .compatible = "mediatek,mt8173-dpi", .data = &mt8173_conf },
108161d9afafSAngeloGioacchino Del Regno 	{ .compatible = "mediatek,mt8183-dpi", .data = &mt8183_conf },
108261d9afafSAngeloGioacchino Del Regno 	{ .compatible = "mediatek,mt8186-dpi", .data = &mt8186_conf },
1083*f3e63240SHsiao Chien Sung 	{ .compatible = "mediatek,mt8188-dp-intf", .data = &mt8195_dpintf_conf },
108461d9afafSAngeloGioacchino Del Regno 	{ .compatible = "mediatek,mt8192-dpi", .data = &mt8192_conf },
108561d9afafSAngeloGioacchino Del Regno 	{ .compatible = "mediatek,mt8195-dp-intf", .data = &mt8195_dpintf_conf },
108661d9afafSAngeloGioacchino Del Regno 	{ /* sentinel */ },
10879e629c17SJie Qiu };
1088fdcbe17cSBoris Brezillon MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids);
10899e629c17SJie Qiu 
10909e629c17SJie Qiu struct platform_driver mtk_dpi_driver = {
10919e629c17SJie Qiu 	.probe = mtk_dpi_probe,
109290c95c38SAngeloGioacchino Del Regno 	.remove_new = mtk_dpi_remove,
10939e629c17SJie Qiu 	.driver = {
10949e629c17SJie Qiu 		.name = "mediatek-dpi",
10959e629c17SJie Qiu 		.of_match_table = mtk_dpi_of_ids,
10969e629c17SJie Qiu 	},
10979e629c17SJie Qiu };
1098