brintos

brintos / linux-shallow public Read only

0
0
Text · 29.4 KiB · a08d206 Raw
1110 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2014 MediaTek Inc.4 * Author: Jie Qiu <jie.qiu@mediatek.com>5 */6 7#include <linux/clk.h>8#include <linux/component.h>9#include <linux/interrupt.h>10#include <linux/kernel.h>11#include <linux/media-bus-format.h>12#include <linux/of.h>13#include <linux/of_graph.h>14#include <linux/pinctrl/consumer.h>15#include <linux/platform_device.h>16#include <linux/soc/mediatek/mtk-mmsys.h>17#include <linux/types.h>18 19#include <video/videomode.h>20 21#include <drm/drm_atomic_helper.h>22#include <drm/drm_bridge.h>23#include <drm/drm_bridge_connector.h>24#include <drm/drm_crtc.h>25#include <drm/drm_edid.h>26#include <drm/drm_of.h>27#include <drm/drm_simple_kms_helper.h>28 29#include "mtk_ddp_comp.h"30#include "mtk_disp_drv.h"31#include "mtk_dpi_regs.h"32#include "mtk_drm_drv.h"33 34enum mtk_dpi_out_bit_num {35	MTK_DPI_OUT_BIT_NUM_8BITS,36	MTK_DPI_OUT_BIT_NUM_10BITS,37	MTK_DPI_OUT_BIT_NUM_12BITS,38	MTK_DPI_OUT_BIT_NUM_16BITS39};40 41enum mtk_dpi_out_yc_map {42	MTK_DPI_OUT_YC_MAP_RGB,43	MTK_DPI_OUT_YC_MAP_CYCY,44	MTK_DPI_OUT_YC_MAP_YCYC,45	MTK_DPI_OUT_YC_MAP_CY,46	MTK_DPI_OUT_YC_MAP_YC47};48 49enum mtk_dpi_out_channel_swap {50	MTK_DPI_OUT_CHANNEL_SWAP_RGB,51	MTK_DPI_OUT_CHANNEL_SWAP_GBR,52	MTK_DPI_OUT_CHANNEL_SWAP_BRG,53	MTK_DPI_OUT_CHANNEL_SWAP_RBG,54	MTK_DPI_OUT_CHANNEL_SWAP_GRB,55	MTK_DPI_OUT_CHANNEL_SWAP_BGR56};57 58enum mtk_dpi_out_color_format {59	MTK_DPI_COLOR_FORMAT_RGB,60	MTK_DPI_COLOR_FORMAT_YCBCR_42261};62 63struct mtk_dpi {64	struct drm_encoder encoder;65	struct drm_bridge bridge;66	struct drm_bridge *next_bridge;67	struct drm_connector *connector;68	void __iomem *regs;69	struct device *dev;70	struct device *mmsys_dev;71	struct clk *engine_clk;72	struct clk *pixel_clk;73	struct clk *tvd_clk;74	int irq;75	struct drm_display_mode mode;76	const struct mtk_dpi_conf *conf;77	enum mtk_dpi_out_color_format color_format;78	enum mtk_dpi_out_yc_map yc_map;79	enum mtk_dpi_out_bit_num bit_num;80	enum mtk_dpi_out_channel_swap channel_swap;81	struct pinctrl *pinctrl;82	struct pinctrl_state *pins_gpio;83	struct pinctrl_state *pins_dpi;84	u32 output_fmt;85	int refcount;86};87 88static inline struct mtk_dpi *bridge_to_dpi(struct drm_bridge *b)89{90	return container_of(b, struct mtk_dpi, bridge);91}92 93enum mtk_dpi_polarity {94	MTK_DPI_POLARITY_RISING,95	MTK_DPI_POLARITY_FALLING,96};97 98struct mtk_dpi_polarities {99	enum mtk_dpi_polarity de_pol;100	enum mtk_dpi_polarity ck_pol;101	enum mtk_dpi_polarity hsync_pol;102	enum mtk_dpi_polarity vsync_pol;103};104 105struct mtk_dpi_sync_param {106	u32 sync_width;107	u32 front_porch;108	u32 back_porch;109	bool shift_half_line;110};111 112struct mtk_dpi_yc_limit {113	u16 y_top;114	u16 y_bottom;115	u16 c_top;116	u16 c_bottom;117};118 119/**120 * struct mtk_dpi_conf - Configuration of mediatek dpi.121 * @cal_factor: Callback function to calculate factor value.122 * @reg_h_fre_con: Register address of frequency control.123 * @max_clock_khz: Max clock frequency supported for this SoCs in khz units.124 * @edge_sel_en: Enable of edge selection.125 * @output_fmts: Array of supported output formats.126 * @num_output_fmts: Quantity of supported output formats.127 * @is_ck_de_pol: Support CK/DE polarity.128 * @swap_input_support: Support input swap function.129 * @support_direct_pin: IP supports direct connection to dpi panels.130 * @input_2pixel: Input pixel of dp_intf is 2 pixel per round, so enable this131 *		  config to enable this feature.132 * @dimension_mask: Mask used for HWIDTH, HPORCH, VSYNC_WIDTH and VSYNC_PORCH133 *		    (no shift).134 * @hvsize_mask: Mask of HSIZE and VSIZE mask (no shift).135 * @channel_swap_shift: Shift value of channel swap.136 * @yuv422_en_bit: Enable bit of yuv422.137 * @csc_enable_bit: Enable bit of CSC.138 * @pixels_per_iter: Quantity of transferred pixels per iteration.139 * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS.140 */141struct mtk_dpi_conf {142	unsigned int (*cal_factor)(int clock);143	u32 reg_h_fre_con;144	u32 max_clock_khz;145	bool edge_sel_en;146	const u32 *output_fmts;147	u32 num_output_fmts;148	bool is_ck_de_pol;149	bool swap_input_support;150	bool support_direct_pin;151	bool input_2pixel;152	u32 dimension_mask;153	u32 hvsize_mask;154	u32 channel_swap_shift;155	u32 yuv422_en_bit;156	u32 csc_enable_bit;157	u32 pixels_per_iter;158	bool edge_cfg_in_mmsys;159};160 161static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)162{163	u32 tmp = readl(dpi->regs + offset) & ~mask;164 165	tmp |= (val & mask);166	writel(tmp, dpi->regs + offset);167}168 169static void mtk_dpi_sw_reset(struct mtk_dpi *dpi, bool reset)170{171	mtk_dpi_mask(dpi, DPI_RET, reset ? RST : 0, RST);172}173 174static void mtk_dpi_enable(struct mtk_dpi *dpi)175{176	mtk_dpi_mask(dpi, DPI_EN, EN, EN);177}178 179static void mtk_dpi_disable(struct mtk_dpi *dpi)180{181	mtk_dpi_mask(dpi, DPI_EN, 0, EN);182}183 184static void mtk_dpi_config_hsync(struct mtk_dpi *dpi,185				 struct mtk_dpi_sync_param *sync)186{187	mtk_dpi_mask(dpi, DPI_TGEN_HWIDTH, sync->sync_width << HPW,188		     dpi->conf->dimension_mask << HPW);189	mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->back_porch << HBP,190		     dpi->conf->dimension_mask << HBP);191	mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->front_porch << HFP,192		     dpi->conf->dimension_mask << HFP);193}194 195static void mtk_dpi_config_vsync(struct mtk_dpi *dpi,196				 struct mtk_dpi_sync_param *sync,197				 u32 width_addr, u32 porch_addr)198{199	mtk_dpi_mask(dpi, width_addr,200		     sync->shift_half_line << VSYNC_HALF_LINE_SHIFT,201		     VSYNC_HALF_LINE_MASK);202	mtk_dpi_mask(dpi, width_addr,203		     sync->sync_width << VSYNC_WIDTH_SHIFT,204		     dpi->conf->dimension_mask << VSYNC_WIDTH_SHIFT);205	mtk_dpi_mask(dpi, porch_addr,206		     sync->back_porch << VSYNC_BACK_PORCH_SHIFT,207		     dpi->conf->dimension_mask << VSYNC_BACK_PORCH_SHIFT);208	mtk_dpi_mask(dpi, porch_addr,209		     sync->front_porch << VSYNC_FRONT_PORCH_SHIFT,210		     dpi->conf->dimension_mask << VSYNC_FRONT_PORCH_SHIFT);211}212 213static void mtk_dpi_config_vsync_lodd(struct mtk_dpi *dpi,214				      struct mtk_dpi_sync_param *sync)215{216	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH, DPI_TGEN_VPORCH);217}218 219static void mtk_dpi_config_vsync_leven(struct mtk_dpi *dpi,220				       struct mtk_dpi_sync_param *sync)221{222	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_LEVEN,223			     DPI_TGEN_VPORCH_LEVEN);224}225 226static void mtk_dpi_config_vsync_rodd(struct mtk_dpi *dpi,227				      struct mtk_dpi_sync_param *sync)228{229	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_RODD,230			     DPI_TGEN_VPORCH_RODD);231}232 233static void mtk_dpi_config_vsync_reven(struct mtk_dpi *dpi,234				       struct mtk_dpi_sync_param *sync)235{236	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_REVEN,237			     DPI_TGEN_VPORCH_REVEN);238}239 240static void mtk_dpi_config_pol(struct mtk_dpi *dpi,241			       struct mtk_dpi_polarities *dpi_pol)242{243	unsigned int pol;244	unsigned int mask;245 246	mask = HSYNC_POL | VSYNC_POL;247	pol = (dpi_pol->hsync_pol == MTK_DPI_POLARITY_RISING ? 0 : HSYNC_POL) |248	      (dpi_pol->vsync_pol == MTK_DPI_POLARITY_RISING ? 0 : VSYNC_POL);249	if (dpi->conf->is_ck_de_pol) {250		mask |= CK_POL | DE_POL;251		pol |= (dpi_pol->ck_pol == MTK_DPI_POLARITY_RISING ?252			0 : CK_POL) |253		       (dpi_pol->de_pol == MTK_DPI_POLARITY_RISING ?254			0 : DE_POL);255	}256 257	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, pol, mask);258}259 260static void mtk_dpi_config_3d(struct mtk_dpi *dpi, bool en_3d)261{262	mtk_dpi_mask(dpi, DPI_CON, en_3d ? TDFP_EN : 0, TDFP_EN);263}264 265static void mtk_dpi_config_interface(struct mtk_dpi *dpi, bool inter)266{267	mtk_dpi_mask(dpi, DPI_CON, inter ? INTL_EN : 0, INTL_EN);268}269 270static void mtk_dpi_config_fb_size(struct mtk_dpi *dpi, u32 width, u32 height)271{272	mtk_dpi_mask(dpi, DPI_SIZE, width << HSIZE,273		     dpi->conf->hvsize_mask << HSIZE);274	mtk_dpi_mask(dpi, DPI_SIZE, height << VSIZE,275		     dpi->conf->hvsize_mask << VSIZE);276}277 278static void mtk_dpi_config_channel_limit(struct mtk_dpi *dpi)279{280	struct mtk_dpi_yc_limit limit;281 282	if (drm_default_rgb_quant_range(&dpi->mode) ==283	    HDMI_QUANTIZATION_RANGE_LIMITED) {284		limit.y_bottom = 0x10;285		limit.y_top = 0xfe0;286		limit.c_bottom = 0x10;287		limit.c_top = 0xfe0;288	} else {289		limit.y_bottom = 0;290		limit.y_top = 0xfff;291		limit.c_bottom = 0;292		limit.c_top = 0xfff;293	}294 295	mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit.y_bottom << Y_LIMINT_BOT,296		     Y_LIMINT_BOT_MASK);297	mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit.y_top << Y_LIMINT_TOP,298		     Y_LIMINT_TOP_MASK);299	mtk_dpi_mask(dpi, DPI_C_LIMIT, limit.c_bottom << C_LIMIT_BOT,300		     C_LIMIT_BOT_MASK);301	mtk_dpi_mask(dpi, DPI_C_LIMIT, limit.c_top << C_LIMIT_TOP,302		     C_LIMIT_TOP_MASK);303}304 305static void mtk_dpi_config_bit_num(struct mtk_dpi *dpi,306				   enum mtk_dpi_out_bit_num num)307{308	u32 val;309 310	switch (num) {311	case MTK_DPI_OUT_BIT_NUM_8BITS:312		val = OUT_BIT_8;313		break;314	case MTK_DPI_OUT_BIT_NUM_10BITS:315		val = OUT_BIT_10;316		break;317	case MTK_DPI_OUT_BIT_NUM_12BITS:318		val = OUT_BIT_12;319		break;320	case MTK_DPI_OUT_BIT_NUM_16BITS:321		val = OUT_BIT_16;322		break;323	default:324		val = OUT_BIT_8;325		break;326	}327	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << OUT_BIT,328		     OUT_BIT_MASK);329}330 331static void mtk_dpi_config_yc_map(struct mtk_dpi *dpi,332				  enum mtk_dpi_out_yc_map map)333{334	u32 val;335 336	switch (map) {337	case MTK_DPI_OUT_YC_MAP_RGB:338		val = YC_MAP_RGB;339		break;340	case MTK_DPI_OUT_YC_MAP_CYCY:341		val = YC_MAP_CYCY;342		break;343	case MTK_DPI_OUT_YC_MAP_YCYC:344		val = YC_MAP_YCYC;345		break;346	case MTK_DPI_OUT_YC_MAP_CY:347		val = YC_MAP_CY;348		break;349	case MTK_DPI_OUT_YC_MAP_YC:350		val = YC_MAP_YC;351		break;352	default:353		val = YC_MAP_RGB;354		break;355	}356 357	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << YC_MAP, YC_MAP_MASK);358}359 360static void mtk_dpi_config_channel_swap(struct mtk_dpi *dpi,361					enum mtk_dpi_out_channel_swap swap)362{363	u32 val;364 365	switch (swap) {366	case MTK_DPI_OUT_CHANNEL_SWAP_RGB:367		val = SWAP_RGB;368		break;369	case MTK_DPI_OUT_CHANNEL_SWAP_GBR:370		val = SWAP_GBR;371		break;372	case MTK_DPI_OUT_CHANNEL_SWAP_BRG:373		val = SWAP_BRG;374		break;375	case MTK_DPI_OUT_CHANNEL_SWAP_RBG:376		val = SWAP_RBG;377		break;378	case MTK_DPI_OUT_CHANNEL_SWAP_GRB:379		val = SWAP_GRB;380		break;381	case MTK_DPI_OUT_CHANNEL_SWAP_BGR:382		val = SWAP_BGR;383		break;384	default:385		val = SWAP_RGB;386		break;387	}388 389	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING,390		     val << dpi->conf->channel_swap_shift,391		     CH_SWAP_MASK << dpi->conf->channel_swap_shift);392}393 394static void mtk_dpi_config_yuv422_enable(struct mtk_dpi *dpi, bool enable)395{396	mtk_dpi_mask(dpi, DPI_CON, enable ? dpi->conf->yuv422_en_bit : 0,397		     dpi->conf->yuv422_en_bit);398}399 400static void mtk_dpi_config_csc_enable(struct mtk_dpi *dpi, bool enable)401{402	mtk_dpi_mask(dpi, DPI_CON, enable ? dpi->conf->csc_enable_bit : 0,403		     dpi->conf->csc_enable_bit);404}405 406static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)407{408	mtk_dpi_mask(dpi, DPI_CON, enable ? IN_RB_SWAP : 0, IN_RB_SWAP);409}410 411static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)412{413	mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);414}415 416static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)417{418	if (dpi->conf->edge_sel_en)419		mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);420}421 422static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,423					enum mtk_dpi_out_color_format format)424{425	mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB);426 427	if (format == MTK_DPI_COLOR_FORMAT_YCBCR_422) {428		mtk_dpi_config_yuv422_enable(dpi, true);429		mtk_dpi_config_csc_enable(dpi, true);430 431		/*432		 * If height is smaller than 720, we need to use RGB_TO_BT601433		 * to transfer to yuv422. Otherwise, we use RGB_TO_JPEG.434		 */435		mtk_dpi_mask(dpi, DPI_MATRIX_SET, dpi->mode.hdisplay <= 720 ?436			     MATRIX_SEL_RGB_TO_BT601 : MATRIX_SEL_RGB_TO_JPEG,437			     INT_MATRIX_SEL_MASK);438	} else {439		mtk_dpi_config_yuv422_enable(dpi, false);440		mtk_dpi_config_csc_enable(dpi, false);441		if (dpi->conf->swap_input_support)442			mtk_dpi_config_swap_input(dpi, false);443	}444}445 446static void mtk_dpi_dual_edge(struct mtk_dpi *dpi)447{448	if ((dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE) ||449	    (dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_BE)) {450		mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE,451			     DDR_EN | DDR_4PHASE);452		mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING,453			     dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE ?454			     EDGE_SEL : 0, EDGE_SEL);455		if (dpi->conf->edge_cfg_in_mmsys)456			mtk_mmsys_ddp_dpi_fmt_config(dpi->mmsys_dev, MTK_DPI_RGB888_DDR_CON);457	} else {458		mtk_dpi_mask(dpi, DPI_DDR_SETTING, DDR_EN | DDR_4PHASE, 0);459		if (dpi->conf->edge_cfg_in_mmsys)460			mtk_mmsys_ddp_dpi_fmt_config(dpi->mmsys_dev, MTK_DPI_RGB888_SDR_CON);461	}462}463 464static void mtk_dpi_power_off(struct mtk_dpi *dpi)465{466	if (WARN_ON(dpi->refcount == 0))467		return;468 469	if (--dpi->refcount != 0)470		return;471 472	mtk_dpi_disable(dpi);473	clk_disable_unprepare(dpi->pixel_clk);474	clk_disable_unprepare(dpi->engine_clk);475}476 477static int mtk_dpi_power_on(struct mtk_dpi *dpi)478{479	int ret;480 481	if (++dpi->refcount != 1)482		return 0;483 484	ret = clk_prepare_enable(dpi->engine_clk);485	if (ret) {486		dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret);487		goto err_refcount;488	}489 490	ret = clk_prepare_enable(dpi->pixel_clk);491	if (ret) {492		dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret);493		goto err_pixel;494	}495 496	return 0;497 498err_pixel:499	clk_disable_unprepare(dpi->engine_clk);500err_refcount:501	dpi->refcount--;502	return ret;503}504 505static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,506				    struct drm_display_mode *mode)507{508	struct mtk_dpi_polarities dpi_pol;509	struct mtk_dpi_sync_param hsync;510	struct mtk_dpi_sync_param vsync_lodd = { 0 };511	struct mtk_dpi_sync_param vsync_leven = { 0 };512	struct mtk_dpi_sync_param vsync_rodd = { 0 };513	struct mtk_dpi_sync_param vsync_reven = { 0 };514	struct videomode vm = { 0 };515	unsigned long pll_rate;516	unsigned int factor;517 518	/* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */519	factor = dpi->conf->cal_factor(mode->clock);520	drm_display_mode_to_videomode(mode, &vm);521	pll_rate = vm.pixelclock * factor;522 523	dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n",524		pll_rate, vm.pixelclock);525 526	clk_set_rate(dpi->tvd_clk, pll_rate);527	pll_rate = clk_get_rate(dpi->tvd_clk);528 529	/*530	 * Depending on the IP version, we may output a different amount of531	 * pixels for each iteration: divide the clock by this number and532	 * adjust the display porches accordingly.533	 */534	vm.pixelclock = pll_rate / factor;535	vm.pixelclock /= dpi->conf->pixels_per_iter;536 537	if ((dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_LE) ||538	    (dpi->output_fmt == MEDIA_BUS_FMT_RGB888_2X12_BE))539		clk_set_rate(dpi->pixel_clk, vm.pixelclock * 2);540	else541		clk_set_rate(dpi->pixel_clk, vm.pixelclock);542 543 544	vm.pixelclock = clk_get_rate(dpi->pixel_clk);545 546	dev_dbg(dpi->dev, "Got  PLL %lu Hz, pixel clock %lu Hz\n",547		pll_rate, vm.pixelclock);548 549	dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING;550	dpi_pol.de_pol = MTK_DPI_POLARITY_RISING;551	dpi_pol.hsync_pol = vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ?552			    MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING;553	dpi_pol.vsync_pol = vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ?554			    MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING;555 556	/*557	 * Depending on the IP version, we may output a different amount of558	 * pixels for each iteration: divide the clock by this number and559	 * adjust the display porches accordingly.560	 */561	hsync.sync_width = vm.hsync_len / dpi->conf->pixels_per_iter;562	hsync.back_porch = vm.hback_porch / dpi->conf->pixels_per_iter;563	hsync.front_porch = vm.hfront_porch / dpi->conf->pixels_per_iter;564 565	hsync.shift_half_line = false;566	vsync_lodd.sync_width = vm.vsync_len;567	vsync_lodd.back_porch = vm.vback_porch;568	vsync_lodd.front_porch = vm.vfront_porch;569	vsync_lodd.shift_half_line = false;570 571	if (vm.flags & DISPLAY_FLAGS_INTERLACED &&572	    mode->flags & DRM_MODE_FLAG_3D_MASK) {573		vsync_leven = vsync_lodd;574		vsync_rodd = vsync_lodd;575		vsync_reven = vsync_lodd;576		vsync_leven.shift_half_line = true;577		vsync_reven.shift_half_line = true;578	} else if (vm.flags & DISPLAY_FLAGS_INTERLACED &&579		   !(mode->flags & DRM_MODE_FLAG_3D_MASK)) {580		vsync_leven = vsync_lodd;581		vsync_leven.shift_half_line = true;582	} else if (!(vm.flags & DISPLAY_FLAGS_INTERLACED) &&583		   mode->flags & DRM_MODE_FLAG_3D_MASK) {584		vsync_rodd = vsync_lodd;585	}586	mtk_dpi_sw_reset(dpi, true);587	mtk_dpi_config_pol(dpi, &dpi_pol);588 589	mtk_dpi_config_hsync(dpi, &hsync);590	mtk_dpi_config_vsync_lodd(dpi, &vsync_lodd);591	mtk_dpi_config_vsync_rodd(dpi, &vsync_rodd);592	mtk_dpi_config_vsync_leven(dpi, &vsync_leven);593	mtk_dpi_config_vsync_reven(dpi, &vsync_reven);594 595	mtk_dpi_config_3d(dpi, !!(mode->flags & DRM_MODE_FLAG_3D_MASK));596	mtk_dpi_config_interface(dpi, !!(vm.flags &597					 DISPLAY_FLAGS_INTERLACED));598	if (vm.flags & DISPLAY_FLAGS_INTERLACED)599		mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive >> 1);600	else601		mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive);602 603	mtk_dpi_config_channel_limit(dpi);604	mtk_dpi_config_bit_num(dpi, dpi->bit_num);605	mtk_dpi_config_channel_swap(dpi, dpi->channel_swap);606	mtk_dpi_config_color_format(dpi, dpi->color_format);607	if (dpi->conf->support_direct_pin) {608		mtk_dpi_config_yc_map(dpi, dpi->yc_map);609		mtk_dpi_config_2n_h_fre(dpi);610		mtk_dpi_dual_edge(dpi);611		mtk_dpi_config_disable_edge(dpi);612	}613	if (dpi->conf->input_2pixel) {614		mtk_dpi_mask(dpi, DPI_CON, DPINTF_INPUT_2P_EN,615			     DPINTF_INPUT_2P_EN);616	}617	mtk_dpi_sw_reset(dpi, false);618 619	return 0;620}621 622static u32 *mtk_dpi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,623						      struct drm_bridge_state *bridge_state,624						      struct drm_crtc_state *crtc_state,625						      struct drm_connector_state *conn_state,626						      unsigned int *num_output_fmts)627{628	struct mtk_dpi *dpi = bridge_to_dpi(bridge);629	u32 *output_fmts;630 631	*num_output_fmts = 0;632 633	if (!dpi->conf->output_fmts) {634		dev_err(dpi->dev, "output_fmts should not be null\n");635		return NULL;636	}637 638	output_fmts = kcalloc(dpi->conf->num_output_fmts, sizeof(*output_fmts),639			     GFP_KERNEL);640	if (!output_fmts)641		return NULL;642 643	*num_output_fmts = dpi->conf->num_output_fmts;644 645	memcpy(output_fmts, dpi->conf->output_fmts,646	       sizeof(*output_fmts) * dpi->conf->num_output_fmts);647 648	return output_fmts;649}650 651static u32 *mtk_dpi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,652						     struct drm_bridge_state *bridge_state,653						     struct drm_crtc_state *crtc_state,654						     struct drm_connector_state *conn_state,655						     u32 output_fmt,656						     unsigned int *num_input_fmts)657{658	u32 *input_fmts;659 660	*num_input_fmts = 0;661 662	input_fmts = kcalloc(1, sizeof(*input_fmts),663			     GFP_KERNEL);664	if (!input_fmts)665		return NULL;666 667	*num_input_fmts = 1;668	input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;669 670	return input_fmts;671}672 673static int mtk_dpi_bridge_atomic_check(struct drm_bridge *bridge,674				       struct drm_bridge_state *bridge_state,675				       struct drm_crtc_state *crtc_state,676				       struct drm_connector_state *conn_state)677{678	struct mtk_dpi *dpi = bridge_to_dpi(bridge);679	unsigned int out_bus_format;680 681	out_bus_format = bridge_state->output_bus_cfg.format;682 683	if (out_bus_format == MEDIA_BUS_FMT_FIXED)684		if (dpi->conf->num_output_fmts)685			out_bus_format = dpi->conf->output_fmts[0];686 687	dev_dbg(dpi->dev, "input format 0x%04x, output format 0x%04x\n",688		bridge_state->input_bus_cfg.format,689		bridge_state->output_bus_cfg.format);690 691	dpi->output_fmt = out_bus_format;692	dpi->bit_num = MTK_DPI_OUT_BIT_NUM_8BITS;693	dpi->channel_swap = MTK_DPI_OUT_CHANNEL_SWAP_RGB;694	dpi->yc_map = MTK_DPI_OUT_YC_MAP_RGB;695	if (out_bus_format == MEDIA_BUS_FMT_YUYV8_1X16)696		dpi->color_format = MTK_DPI_COLOR_FORMAT_YCBCR_422;697	else698		dpi->color_format = MTK_DPI_COLOR_FORMAT_RGB;699 700	return 0;701}702 703static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,704				 enum drm_bridge_attach_flags flags)705{706	struct mtk_dpi *dpi = bridge_to_dpi(bridge);707 708	return drm_bridge_attach(bridge->encoder, dpi->next_bridge,709				 &dpi->bridge, flags);710}711 712static void mtk_dpi_bridge_mode_set(struct drm_bridge *bridge,713				const struct drm_display_mode *mode,714				const struct drm_display_mode *adjusted_mode)715{716	struct mtk_dpi *dpi = bridge_to_dpi(bridge);717 718	drm_mode_copy(&dpi->mode, adjusted_mode);719}720 721static void mtk_dpi_bridge_disable(struct drm_bridge *bridge)722{723	struct mtk_dpi *dpi = bridge_to_dpi(bridge);724 725	mtk_dpi_power_off(dpi);726 727	if (dpi->pinctrl && dpi->pins_gpio)728		pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);729}730 731static void mtk_dpi_bridge_enable(struct drm_bridge *bridge)732{733	struct mtk_dpi *dpi = bridge_to_dpi(bridge);734 735	if (dpi->pinctrl && dpi->pins_dpi)736		pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);737 738	mtk_dpi_power_on(dpi);739	mtk_dpi_set_display_mode(dpi, &dpi->mode);740	mtk_dpi_enable(dpi);741}742 743static enum drm_mode_status744mtk_dpi_bridge_mode_valid(struct drm_bridge *bridge,745			  const struct drm_display_info *info,746			  const struct drm_display_mode *mode)747{748	struct mtk_dpi *dpi = bridge_to_dpi(bridge);749 750	if (mode->clock > dpi->conf->max_clock_khz)751		return MODE_CLOCK_HIGH;752 753	return MODE_OK;754}755 756static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = {757	.attach = mtk_dpi_bridge_attach,758	.mode_set = mtk_dpi_bridge_mode_set,759	.mode_valid = mtk_dpi_bridge_mode_valid,760	.disable = mtk_dpi_bridge_disable,761	.enable = mtk_dpi_bridge_enable,762	.atomic_check = mtk_dpi_bridge_atomic_check,763	.atomic_get_output_bus_fmts = mtk_dpi_bridge_atomic_get_output_bus_fmts,764	.atomic_get_input_bus_fmts = mtk_dpi_bridge_atomic_get_input_bus_fmts,765	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,766	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,767	.atomic_reset = drm_atomic_helper_bridge_reset,768};769 770void mtk_dpi_start(struct device *dev)771{772	struct mtk_dpi *dpi = dev_get_drvdata(dev);773 774	mtk_dpi_power_on(dpi);775}776 777void mtk_dpi_stop(struct device *dev)778{779	struct mtk_dpi *dpi = dev_get_drvdata(dev);780 781	mtk_dpi_power_off(dpi);782}783 784unsigned int mtk_dpi_encoder_index(struct device *dev)785{786	struct mtk_dpi *dpi = dev_get_drvdata(dev);787	unsigned int encoder_index = drm_encoder_index(&dpi->encoder);788 789	dev_dbg(dev, "encoder index:%d\n", encoder_index);790	return encoder_index;791}792 793static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)794{795	struct mtk_dpi *dpi = dev_get_drvdata(dev);796	struct drm_device *drm_dev = data;797	struct mtk_drm_private *priv = drm_dev->dev_private;798	int ret;799 800	dpi->mmsys_dev = priv->mmsys_dev;801	ret = drm_simple_encoder_init(drm_dev, &dpi->encoder,802				      DRM_MODE_ENCODER_TMDS);803	if (ret) {804		dev_err(dev, "Failed to initialize decoder: %d\n", ret);805		return ret;806	}807 808	ret = mtk_find_possible_crtcs(drm_dev, dpi->dev);809	if (ret < 0)810		goto err_cleanup;811	dpi->encoder.possible_crtcs = ret;812 813	ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL,814				DRM_BRIDGE_ATTACH_NO_CONNECTOR);815	if (ret)816		goto err_cleanup;817 818	dpi->connector = drm_bridge_connector_init(drm_dev, &dpi->encoder);819	if (IS_ERR(dpi->connector)) {820		dev_err(dev, "Unable to create bridge connector\n");821		ret = PTR_ERR(dpi->connector);822		goto err_cleanup;823	}824	drm_connector_attach_encoder(dpi->connector, &dpi->encoder);825 826	return 0;827 828err_cleanup:829	drm_encoder_cleanup(&dpi->encoder);830	return ret;831}832 833static void mtk_dpi_unbind(struct device *dev, struct device *master,834			   void *data)835{836	struct mtk_dpi *dpi = dev_get_drvdata(dev);837 838	drm_encoder_cleanup(&dpi->encoder);839}840 841static const struct component_ops mtk_dpi_component_ops = {842	.bind = mtk_dpi_bind,843	.unbind = mtk_dpi_unbind,844};845 846static unsigned int mt8173_calculate_factor(int clock)847{848	if (clock <= 27000)849		return 3 << 4;850	else if (clock <= 84000)851		return 3 << 3;852	else if (clock <= 167000)853		return 3 << 2;854	else855		return 3 << 1;856}857 858static unsigned int mt2701_calculate_factor(int clock)859{860	if (clock <= 64000)861		return 4;862	else if (clock <= 128000)863		return 2;864	else865		return 1;866}867 868static unsigned int mt8183_calculate_factor(int clock)869{870	if (clock <= 27000)871		return 8;872	else if (clock <= 167000)873		return 4;874	else875		return 2;876}877 878static unsigned int mt8195_dpintf_calculate_factor(int clock)879{880	if (clock < 70000)881		return 4;882	else if (clock < 200000)883		return 2;884	else885		return 1;886}887 888static const u32 mt8173_output_fmts[] = {889	MEDIA_BUS_FMT_RGB888_1X24,890};891 892static const u32 mt8183_output_fmts[] = {893	MEDIA_BUS_FMT_RGB888_2X12_LE,894	MEDIA_BUS_FMT_RGB888_2X12_BE,895};896 897static const u32 mt8195_output_fmts[] = {898	MEDIA_BUS_FMT_RGB888_1X24,899	MEDIA_BUS_FMT_YUYV8_1X16,900};901 902static const struct mtk_dpi_conf mt8173_conf = {903	.cal_factor = mt8173_calculate_factor,904	.reg_h_fre_con = 0xe0,905	.max_clock_khz = 300000,906	.output_fmts = mt8173_output_fmts,907	.num_output_fmts = ARRAY_SIZE(mt8173_output_fmts),908	.pixels_per_iter = 1,909	.is_ck_de_pol = true,910	.swap_input_support = true,911	.support_direct_pin = true,912	.dimension_mask = HPW_MASK,913	.hvsize_mask = HSIZE_MASK,914	.channel_swap_shift = CH_SWAP,915	.yuv422_en_bit = YUV422_EN,916	.csc_enable_bit = CSC_ENABLE,917};918 919static const struct mtk_dpi_conf mt2701_conf = {920	.cal_factor = mt2701_calculate_factor,921	.reg_h_fre_con = 0xb0,922	.edge_sel_en = true,923	.max_clock_khz = 150000,924	.output_fmts = mt8173_output_fmts,925	.num_output_fmts = ARRAY_SIZE(mt8173_output_fmts),926	.pixels_per_iter = 1,927	.is_ck_de_pol = true,928	.swap_input_support = true,929	.support_direct_pin = true,930	.dimension_mask = HPW_MASK,931	.hvsize_mask = HSIZE_MASK,932	.channel_swap_shift = CH_SWAP,933	.yuv422_en_bit = YUV422_EN,934	.csc_enable_bit = CSC_ENABLE,935};936 937static const struct mtk_dpi_conf mt8183_conf = {938	.cal_factor = mt8183_calculate_factor,939	.reg_h_fre_con = 0xe0,940	.max_clock_khz = 100000,941	.output_fmts = mt8183_output_fmts,942	.num_output_fmts = ARRAY_SIZE(mt8183_output_fmts),943	.pixels_per_iter = 1,944	.is_ck_de_pol = true,945	.swap_input_support = true,946	.support_direct_pin = true,947	.dimension_mask = HPW_MASK,948	.hvsize_mask = HSIZE_MASK,949	.channel_swap_shift = CH_SWAP,950	.yuv422_en_bit = YUV422_EN,951	.csc_enable_bit = CSC_ENABLE,952};953 954static const struct mtk_dpi_conf mt8186_conf = {955	.cal_factor = mt8183_calculate_factor,956	.reg_h_fre_con = 0xe0,957	.max_clock_khz = 150000,958	.output_fmts = mt8183_output_fmts,959	.num_output_fmts = ARRAY_SIZE(mt8183_output_fmts),960	.edge_cfg_in_mmsys = true,961	.pixels_per_iter = 1,962	.is_ck_de_pol = true,963	.swap_input_support = true,964	.support_direct_pin = true,965	.dimension_mask = HPW_MASK,966	.hvsize_mask = HSIZE_MASK,967	.channel_swap_shift = CH_SWAP,968	.yuv422_en_bit = YUV422_EN,969	.csc_enable_bit = CSC_ENABLE,970};971 972static const struct mtk_dpi_conf mt8192_conf = {973	.cal_factor = mt8183_calculate_factor,974	.reg_h_fre_con = 0xe0,975	.max_clock_khz = 150000,976	.output_fmts = mt8183_output_fmts,977	.num_output_fmts = ARRAY_SIZE(mt8183_output_fmts),978	.pixels_per_iter = 1,979	.is_ck_de_pol = true,980	.swap_input_support = true,981	.support_direct_pin = true,982	.dimension_mask = HPW_MASK,983	.hvsize_mask = HSIZE_MASK,984	.channel_swap_shift = CH_SWAP,985	.yuv422_en_bit = YUV422_EN,986	.csc_enable_bit = CSC_ENABLE,987};988 989static const struct mtk_dpi_conf mt8195_dpintf_conf = {990	.cal_factor = mt8195_dpintf_calculate_factor,991	.max_clock_khz = 600000,992	.output_fmts = mt8195_output_fmts,993	.num_output_fmts = ARRAY_SIZE(mt8195_output_fmts),994	.pixels_per_iter = 4,995	.input_2pixel = true,996	.dimension_mask = DPINTF_HPW_MASK,997	.hvsize_mask = DPINTF_HSIZE_MASK,998	.channel_swap_shift = DPINTF_CH_SWAP,999	.yuv422_en_bit = DPINTF_YUV422_EN,1000	.csc_enable_bit = DPINTF_CSC_ENABLE,1001};1002 1003static int mtk_dpi_probe(struct platform_device *pdev)1004{1005	struct device *dev = &pdev->dev;1006	struct mtk_dpi *dpi;1007	int ret;1008 1009	dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);1010	if (!dpi)1011		return -ENOMEM;1012 1013	dpi->dev = dev;1014	dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);1015	dpi->output_fmt = MEDIA_BUS_FMT_RGB888_1X24;1016 1017	dpi->pinctrl = devm_pinctrl_get(&pdev->dev);1018	if (IS_ERR(dpi->pinctrl)) {1019		dpi->pinctrl = NULL;1020		dev_dbg(&pdev->dev, "Cannot find pinctrl!\n");1021	}1022	if (dpi->pinctrl) {1023		dpi->pins_gpio = pinctrl_lookup_state(dpi->pinctrl, "sleep");1024		if (IS_ERR(dpi->pins_gpio)) {1025			dpi->pins_gpio = NULL;1026			dev_dbg(&pdev->dev, "Cannot find pinctrl idle!\n");1027		}1028		if (dpi->pins_gpio)1029			pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);1030 1031		dpi->pins_dpi = pinctrl_lookup_state(dpi->pinctrl, "default");1032		if (IS_ERR(dpi->pins_dpi)) {1033			dpi->pins_dpi = NULL;1034			dev_dbg(&pdev->dev, "Cannot find pinctrl active!\n");1035		}1036	}1037	dpi->regs = devm_platform_ioremap_resource(pdev, 0);1038	if (IS_ERR(dpi->regs))1039		return dev_err_probe(dev, PTR_ERR(dpi->regs),1040				     "Failed to ioremap mem resource\n");1041 1042	dpi->engine_clk = devm_clk_get(dev, "engine");1043	if (IS_ERR(dpi->engine_clk))1044		return dev_err_probe(dev, PTR_ERR(dpi->engine_clk),1045				     "Failed to get engine clock\n");1046 1047	dpi->pixel_clk = devm_clk_get(dev, "pixel");1048	if (IS_ERR(dpi->pixel_clk))1049		return dev_err_probe(dev, PTR_ERR(dpi->pixel_clk),1050				     "Failed to get pixel clock\n");1051 1052	dpi->tvd_clk = devm_clk_get(dev, "pll");1053	if (IS_ERR(dpi->tvd_clk))1054		return dev_err_probe(dev, PTR_ERR(dpi->tvd_clk),1055				     "Failed to get tvdpll clock\n");1056 1057	dpi->irq = platform_get_irq(pdev, 0);1058	if (dpi->irq < 0)1059		return dpi->irq;1060 1061	dpi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);1062	if (IS_ERR(dpi->next_bridge))1063		return dev_err_probe(dev, PTR_ERR(dpi->next_bridge),1064				     "Failed to get bridge\n");1065 1066	dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node);1067 1068	platform_set_drvdata(pdev, dpi);1069 1070	dpi->bridge.funcs = &mtk_dpi_bridge_funcs;1071	dpi->bridge.of_node = dev->of_node;1072	dpi->bridge.type = DRM_MODE_CONNECTOR_DPI;1073 1074	ret = devm_drm_bridge_add(dev, &dpi->bridge);1075	if (ret)1076		return ret;1077 1078	ret = component_add(dev, &mtk_dpi_component_ops);1079	if (ret)1080		return dev_err_probe(dev, ret, "Failed to add component.\n");1081 1082	return 0;1083}1084 1085static void mtk_dpi_remove(struct platform_device *pdev)1086{1087	component_del(&pdev->dev, &mtk_dpi_component_ops);1088}1089 1090static const struct of_device_id mtk_dpi_of_ids[] = {1091	{ .compatible = "mediatek,mt2701-dpi", .data = &mt2701_conf },1092	{ .compatible = "mediatek,mt8173-dpi", .data = &mt8173_conf },1093	{ .compatible = "mediatek,mt8183-dpi", .data = &mt8183_conf },1094	{ .compatible = "mediatek,mt8186-dpi", .data = &mt8186_conf },1095	{ .compatible = "mediatek,mt8188-dp-intf", .data = &mt8195_dpintf_conf },1096	{ .compatible = "mediatek,mt8192-dpi", .data = &mt8192_conf },1097	{ .compatible = "mediatek,mt8195-dp-intf", .data = &mt8195_dpintf_conf },1098	{ /* sentinel */ },1099};1100MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids);1101 1102struct platform_driver mtk_dpi_driver = {1103	.probe = mtk_dpi_probe,1104	.remove_new = mtk_dpi_remove,1105	.driver = {1106		.name = "mediatek-dpi",1107		.of_match_table = mtk_dpi_of_ids,1108	},1109};1110