Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.1-rc3 790 lines 20 kB view raw
1/* 2 * Copyright (c) 2014 MediaTek Inc. 3 * Author: Jie Qiu <jie.qiu@mediatek.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14#include <drm/drmP.h> 15#include <drm/drm_crtc.h> 16#include <drm/drm_atomic_helper.h> 17#include <drm/drm_of.h> 18#include <linux/kernel.h> 19#include <linux/component.h> 20#include <linux/platform_device.h> 21#include <linux/of.h> 22#include <linux/of_device.h> 23#include <linux/of_graph.h> 24#include <linux/interrupt.h> 25#include <linux/types.h> 26#include <linux/clk.h> 27#include <video/videomode.h> 28 29#include "mtk_dpi_regs.h" 30#include "mtk_drm_ddp_comp.h" 31 32enum mtk_dpi_out_bit_num { 33 MTK_DPI_OUT_BIT_NUM_8BITS, 34 MTK_DPI_OUT_BIT_NUM_10BITS, 35 MTK_DPI_OUT_BIT_NUM_12BITS, 36 MTK_DPI_OUT_BIT_NUM_16BITS 37}; 38 39enum mtk_dpi_out_yc_map { 40 MTK_DPI_OUT_YC_MAP_RGB, 41 MTK_DPI_OUT_YC_MAP_CYCY, 42 MTK_DPI_OUT_YC_MAP_YCYC, 43 MTK_DPI_OUT_YC_MAP_CY, 44 MTK_DPI_OUT_YC_MAP_YC 45}; 46 47enum mtk_dpi_out_channel_swap { 48 MTK_DPI_OUT_CHANNEL_SWAP_RGB, 49 MTK_DPI_OUT_CHANNEL_SWAP_GBR, 50 MTK_DPI_OUT_CHANNEL_SWAP_BRG, 51 MTK_DPI_OUT_CHANNEL_SWAP_RBG, 52 MTK_DPI_OUT_CHANNEL_SWAP_GRB, 53 MTK_DPI_OUT_CHANNEL_SWAP_BGR 54}; 55 56enum mtk_dpi_out_color_format { 57 MTK_DPI_COLOR_FORMAT_RGB, 58 MTK_DPI_COLOR_FORMAT_RGB_FULL, 59 MTK_DPI_COLOR_FORMAT_YCBCR_444, 60 MTK_DPI_COLOR_FORMAT_YCBCR_422, 61 MTK_DPI_COLOR_FORMAT_XV_YCC, 62 MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL, 63 MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL 64}; 65 66struct mtk_dpi { 67 struct mtk_ddp_comp ddp_comp; 68 struct drm_encoder encoder; 69 struct drm_bridge *bridge; 70 void __iomem *regs; 71 struct device *dev; 72 struct clk *engine_clk; 73 struct clk *pixel_clk; 74 struct clk *tvd_clk; 75 int irq; 76 struct drm_display_mode mode; 77 const struct mtk_dpi_conf *conf; 78 enum mtk_dpi_out_color_format color_format; 79 enum mtk_dpi_out_yc_map yc_map; 80 enum mtk_dpi_out_bit_num bit_num; 81 enum mtk_dpi_out_channel_swap channel_swap; 82 int refcount; 83}; 84 85static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e) 86{ 87 return container_of(e, struct mtk_dpi, encoder); 88} 89 90enum mtk_dpi_polarity { 91 MTK_DPI_POLARITY_RISING, 92 MTK_DPI_POLARITY_FALLING, 93}; 94 95struct mtk_dpi_polarities { 96 enum mtk_dpi_polarity de_pol; 97 enum mtk_dpi_polarity ck_pol; 98 enum mtk_dpi_polarity hsync_pol; 99 enum mtk_dpi_polarity vsync_pol; 100}; 101 102struct mtk_dpi_sync_param { 103 u32 sync_width; 104 u32 front_porch; 105 u32 back_porch; 106 bool shift_half_line; 107}; 108 109struct mtk_dpi_yc_limit { 110 u16 y_top; 111 u16 y_bottom; 112 u16 c_top; 113 u16 c_bottom; 114}; 115 116struct mtk_dpi_conf { 117 unsigned int (*cal_factor)(int clock); 118 u32 reg_h_fre_con; 119 bool edge_sel_en; 120}; 121 122static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) 123{ 124 u32 tmp = readl(dpi->regs + offset) & ~mask; 125 126 tmp |= (val & mask); 127 writel(tmp, dpi->regs + offset); 128} 129 130static void mtk_dpi_sw_reset(struct mtk_dpi *dpi, bool reset) 131{ 132 mtk_dpi_mask(dpi, DPI_RET, reset ? RST : 0, RST); 133} 134 135static void mtk_dpi_enable(struct mtk_dpi *dpi) 136{ 137 mtk_dpi_mask(dpi, DPI_EN, EN, EN); 138} 139 140static void mtk_dpi_disable(struct mtk_dpi *dpi) 141{ 142 mtk_dpi_mask(dpi, DPI_EN, 0, EN); 143} 144 145static void mtk_dpi_config_hsync(struct mtk_dpi *dpi, 146 struct mtk_dpi_sync_param *sync) 147{ 148 mtk_dpi_mask(dpi, DPI_TGEN_HWIDTH, 149 sync->sync_width << HPW, HPW_MASK); 150 mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, 151 sync->back_porch << HBP, HBP_MASK); 152 mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->front_porch << HFP, 153 HFP_MASK); 154} 155 156static void mtk_dpi_config_vsync(struct mtk_dpi *dpi, 157 struct mtk_dpi_sync_param *sync, 158 u32 width_addr, u32 porch_addr) 159{ 160 mtk_dpi_mask(dpi, width_addr, 161 sync->sync_width << VSYNC_WIDTH_SHIFT, 162 VSYNC_WIDTH_MASK); 163 mtk_dpi_mask(dpi, width_addr, 164 sync->shift_half_line << VSYNC_HALF_LINE_SHIFT, 165 VSYNC_HALF_LINE_MASK); 166 mtk_dpi_mask(dpi, porch_addr, 167 sync->back_porch << VSYNC_BACK_PORCH_SHIFT, 168 VSYNC_BACK_PORCH_MASK); 169 mtk_dpi_mask(dpi, porch_addr, 170 sync->front_porch << VSYNC_FRONT_PORCH_SHIFT, 171 VSYNC_FRONT_PORCH_MASK); 172} 173 174static void mtk_dpi_config_vsync_lodd(struct mtk_dpi *dpi, 175 struct mtk_dpi_sync_param *sync) 176{ 177 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH, DPI_TGEN_VPORCH); 178} 179 180static void mtk_dpi_config_vsync_leven(struct mtk_dpi *dpi, 181 struct mtk_dpi_sync_param *sync) 182{ 183 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_LEVEN, 184 DPI_TGEN_VPORCH_LEVEN); 185} 186 187static void mtk_dpi_config_vsync_rodd(struct mtk_dpi *dpi, 188 struct mtk_dpi_sync_param *sync) 189{ 190 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_RODD, 191 DPI_TGEN_VPORCH_RODD); 192} 193 194static void mtk_dpi_config_vsync_reven(struct mtk_dpi *dpi, 195 struct mtk_dpi_sync_param *sync) 196{ 197 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_REVEN, 198 DPI_TGEN_VPORCH_REVEN); 199} 200 201static void mtk_dpi_config_pol(struct mtk_dpi *dpi, 202 struct mtk_dpi_polarities *dpi_pol) 203{ 204 unsigned int pol; 205 206 pol = (dpi_pol->ck_pol == MTK_DPI_POLARITY_RISING ? 0 : CK_POL) | 207 (dpi_pol->de_pol == MTK_DPI_POLARITY_RISING ? 0 : DE_POL) | 208 (dpi_pol->hsync_pol == MTK_DPI_POLARITY_RISING ? 0 : HSYNC_POL) | 209 (dpi_pol->vsync_pol == MTK_DPI_POLARITY_RISING ? 0 : VSYNC_POL); 210 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, pol, 211 CK_POL | DE_POL | HSYNC_POL | VSYNC_POL); 212} 213 214static void mtk_dpi_config_3d(struct mtk_dpi *dpi, bool en_3d) 215{ 216 mtk_dpi_mask(dpi, DPI_CON, en_3d ? TDFP_EN : 0, TDFP_EN); 217} 218 219static void mtk_dpi_config_interface(struct mtk_dpi *dpi, bool inter) 220{ 221 mtk_dpi_mask(dpi, DPI_CON, inter ? INTL_EN : 0, INTL_EN); 222} 223 224static void mtk_dpi_config_fb_size(struct mtk_dpi *dpi, u32 width, u32 height) 225{ 226 mtk_dpi_mask(dpi, DPI_SIZE, width << HSIZE, HSIZE_MASK); 227 mtk_dpi_mask(dpi, DPI_SIZE, height << VSIZE, VSIZE_MASK); 228} 229 230static void mtk_dpi_config_channel_limit(struct mtk_dpi *dpi, 231 struct mtk_dpi_yc_limit *limit) 232{ 233 mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit->y_bottom << Y_LIMINT_BOT, 234 Y_LIMINT_BOT_MASK); 235 mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit->y_top << Y_LIMINT_TOP, 236 Y_LIMINT_TOP_MASK); 237 mtk_dpi_mask(dpi, DPI_C_LIMIT, limit->c_bottom << C_LIMIT_BOT, 238 C_LIMIT_BOT_MASK); 239 mtk_dpi_mask(dpi, DPI_C_LIMIT, limit->c_top << C_LIMIT_TOP, 240 C_LIMIT_TOP_MASK); 241} 242 243static void mtk_dpi_config_bit_num(struct mtk_dpi *dpi, 244 enum mtk_dpi_out_bit_num num) 245{ 246 u32 val; 247 248 switch (num) { 249 case MTK_DPI_OUT_BIT_NUM_8BITS: 250 val = OUT_BIT_8; 251 break; 252 case MTK_DPI_OUT_BIT_NUM_10BITS: 253 val = OUT_BIT_10; 254 break; 255 case MTK_DPI_OUT_BIT_NUM_12BITS: 256 val = OUT_BIT_12; 257 break; 258 case MTK_DPI_OUT_BIT_NUM_16BITS: 259 val = OUT_BIT_16; 260 break; 261 default: 262 val = OUT_BIT_8; 263 break; 264 } 265 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << OUT_BIT, 266 OUT_BIT_MASK); 267} 268 269static void mtk_dpi_config_yc_map(struct mtk_dpi *dpi, 270 enum mtk_dpi_out_yc_map map) 271{ 272 u32 val; 273 274 switch (map) { 275 case MTK_DPI_OUT_YC_MAP_RGB: 276 val = YC_MAP_RGB; 277 break; 278 case MTK_DPI_OUT_YC_MAP_CYCY: 279 val = YC_MAP_CYCY; 280 break; 281 case MTK_DPI_OUT_YC_MAP_YCYC: 282 val = YC_MAP_YCYC; 283 break; 284 case MTK_DPI_OUT_YC_MAP_CY: 285 val = YC_MAP_CY; 286 break; 287 case MTK_DPI_OUT_YC_MAP_YC: 288 val = YC_MAP_YC; 289 break; 290 default: 291 val = YC_MAP_RGB; 292 break; 293 } 294 295 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << YC_MAP, YC_MAP_MASK); 296} 297 298static void mtk_dpi_config_channel_swap(struct mtk_dpi *dpi, 299 enum mtk_dpi_out_channel_swap swap) 300{ 301 u32 val; 302 303 switch (swap) { 304 case MTK_DPI_OUT_CHANNEL_SWAP_RGB: 305 val = SWAP_RGB; 306 break; 307 case MTK_DPI_OUT_CHANNEL_SWAP_GBR: 308 val = SWAP_GBR; 309 break; 310 case MTK_DPI_OUT_CHANNEL_SWAP_BRG: 311 val = SWAP_BRG; 312 break; 313 case MTK_DPI_OUT_CHANNEL_SWAP_RBG: 314 val = SWAP_RBG; 315 break; 316 case MTK_DPI_OUT_CHANNEL_SWAP_GRB: 317 val = SWAP_GRB; 318 break; 319 case MTK_DPI_OUT_CHANNEL_SWAP_BGR: 320 val = SWAP_BGR; 321 break; 322 default: 323 val = SWAP_RGB; 324 break; 325 } 326 327 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << CH_SWAP, CH_SWAP_MASK); 328} 329 330static void mtk_dpi_config_yuv422_enable(struct mtk_dpi *dpi, bool enable) 331{ 332 mtk_dpi_mask(dpi, DPI_CON, enable ? YUV422_EN : 0, YUV422_EN); 333} 334 335static void mtk_dpi_config_csc_enable(struct mtk_dpi *dpi, bool enable) 336{ 337 mtk_dpi_mask(dpi, DPI_CON, enable ? CSC_ENABLE : 0, CSC_ENABLE); 338} 339 340static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable) 341{ 342 mtk_dpi_mask(dpi, DPI_CON, enable ? IN_RB_SWAP : 0, IN_RB_SWAP); 343} 344 345static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi) 346{ 347 mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); 348} 349 350static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi) 351{ 352 if (dpi->conf->edge_sel_en) 353 mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN); 354} 355 356static void mtk_dpi_config_color_format(struct mtk_dpi *dpi, 357 enum mtk_dpi_out_color_format format) 358{ 359 if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_444) || 360 (format == MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL)) { 361 mtk_dpi_config_yuv422_enable(dpi, false); 362 mtk_dpi_config_csc_enable(dpi, true); 363 mtk_dpi_config_swap_input(dpi, false); 364 mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_BGR); 365 } else if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_422) || 366 (format == MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL)) { 367 mtk_dpi_config_yuv422_enable(dpi, true); 368 mtk_dpi_config_csc_enable(dpi, true); 369 mtk_dpi_config_swap_input(dpi, true); 370 mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); 371 } else { 372 mtk_dpi_config_yuv422_enable(dpi, false); 373 mtk_dpi_config_csc_enable(dpi, false); 374 mtk_dpi_config_swap_input(dpi, false); 375 mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); 376 } 377} 378 379static void mtk_dpi_power_off(struct mtk_dpi *dpi) 380{ 381 if (WARN_ON(dpi->refcount == 0)) 382 return; 383 384 if (--dpi->refcount != 0) 385 return; 386 387 mtk_dpi_disable(dpi); 388 clk_disable_unprepare(dpi->pixel_clk); 389 clk_disable_unprepare(dpi->engine_clk); 390} 391 392static int mtk_dpi_power_on(struct mtk_dpi *dpi) 393{ 394 int ret; 395 396 if (++dpi->refcount != 1) 397 return 0; 398 399 ret = clk_prepare_enable(dpi->engine_clk); 400 if (ret) { 401 dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret); 402 goto err_refcount; 403 } 404 405 ret = clk_prepare_enable(dpi->pixel_clk); 406 if (ret) { 407 dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret); 408 goto err_pixel; 409 } 410 411 mtk_dpi_enable(dpi); 412 return 0; 413 414err_pixel: 415 clk_disable_unprepare(dpi->engine_clk); 416err_refcount: 417 dpi->refcount--; 418 return ret; 419} 420 421static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, 422 struct drm_display_mode *mode) 423{ 424 struct mtk_dpi_yc_limit limit; 425 struct mtk_dpi_polarities dpi_pol; 426 struct mtk_dpi_sync_param hsync; 427 struct mtk_dpi_sync_param vsync_lodd = { 0 }; 428 struct mtk_dpi_sync_param vsync_leven = { 0 }; 429 struct mtk_dpi_sync_param vsync_rodd = { 0 }; 430 struct mtk_dpi_sync_param vsync_reven = { 0 }; 431 struct videomode vm = { 0 }; 432 unsigned long pll_rate; 433 unsigned int factor; 434 435 /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */ 436 factor = dpi->conf->cal_factor(mode->clock); 437 drm_display_mode_to_videomode(mode, &vm); 438 pll_rate = vm.pixelclock * factor; 439 440 dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n", 441 pll_rate, vm.pixelclock); 442 443 clk_set_rate(dpi->tvd_clk, pll_rate); 444 pll_rate = clk_get_rate(dpi->tvd_clk); 445 446 vm.pixelclock = pll_rate / factor; 447 clk_set_rate(dpi->pixel_clk, vm.pixelclock); 448 vm.pixelclock = clk_get_rate(dpi->pixel_clk); 449 450 dev_dbg(dpi->dev, "Got PLL %lu Hz, pixel clock %lu Hz\n", 451 pll_rate, vm.pixelclock); 452 453 limit.c_bottom = 0x0010; 454 limit.c_top = 0x0FE0; 455 limit.y_bottom = 0x0010; 456 limit.y_top = 0x0FE0; 457 458 dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING; 459 dpi_pol.de_pol = MTK_DPI_POLARITY_RISING; 460 dpi_pol.hsync_pol = vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? 461 MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING; 462 dpi_pol.vsync_pol = vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? 463 MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING; 464 hsync.sync_width = vm.hsync_len; 465 hsync.back_porch = vm.hback_porch; 466 hsync.front_porch = vm.hfront_porch; 467 hsync.shift_half_line = false; 468 vsync_lodd.sync_width = vm.vsync_len; 469 vsync_lodd.back_porch = vm.vback_porch; 470 vsync_lodd.front_porch = vm.vfront_porch; 471 vsync_lodd.shift_half_line = false; 472 473 if (vm.flags & DISPLAY_FLAGS_INTERLACED && 474 mode->flags & DRM_MODE_FLAG_3D_MASK) { 475 vsync_leven = vsync_lodd; 476 vsync_rodd = vsync_lodd; 477 vsync_reven = vsync_lodd; 478 vsync_leven.shift_half_line = true; 479 vsync_reven.shift_half_line = true; 480 } else if (vm.flags & DISPLAY_FLAGS_INTERLACED && 481 !(mode->flags & DRM_MODE_FLAG_3D_MASK)) { 482 vsync_leven = vsync_lodd; 483 vsync_leven.shift_half_line = true; 484 } else if (!(vm.flags & DISPLAY_FLAGS_INTERLACED) && 485 mode->flags & DRM_MODE_FLAG_3D_MASK) { 486 vsync_rodd = vsync_lodd; 487 } 488 mtk_dpi_sw_reset(dpi, true); 489 mtk_dpi_config_pol(dpi, &dpi_pol); 490 491 mtk_dpi_config_hsync(dpi, &hsync); 492 mtk_dpi_config_vsync_lodd(dpi, &vsync_lodd); 493 mtk_dpi_config_vsync_rodd(dpi, &vsync_rodd); 494 mtk_dpi_config_vsync_leven(dpi, &vsync_leven); 495 mtk_dpi_config_vsync_reven(dpi, &vsync_reven); 496 497 mtk_dpi_config_3d(dpi, !!(mode->flags & DRM_MODE_FLAG_3D_MASK)); 498 mtk_dpi_config_interface(dpi, !!(vm.flags & 499 DISPLAY_FLAGS_INTERLACED)); 500 if (vm.flags & DISPLAY_FLAGS_INTERLACED) 501 mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive >> 1); 502 else 503 mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive); 504 505 mtk_dpi_config_channel_limit(dpi, &limit); 506 mtk_dpi_config_bit_num(dpi, dpi->bit_num); 507 mtk_dpi_config_channel_swap(dpi, dpi->channel_swap); 508 mtk_dpi_config_yc_map(dpi, dpi->yc_map); 509 mtk_dpi_config_color_format(dpi, dpi->color_format); 510 mtk_dpi_config_2n_h_fre(dpi); 511 mtk_dpi_config_disable_edge(dpi); 512 mtk_dpi_sw_reset(dpi, false); 513 514 return 0; 515} 516 517static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder) 518{ 519 drm_encoder_cleanup(encoder); 520} 521 522static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = { 523 .destroy = mtk_dpi_encoder_destroy, 524}; 525 526static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder *encoder, 527 const struct drm_display_mode *mode, 528 struct drm_display_mode *adjusted_mode) 529{ 530 return true; 531} 532 533static void mtk_dpi_encoder_mode_set(struct drm_encoder *encoder, 534 struct drm_display_mode *mode, 535 struct drm_display_mode *adjusted_mode) 536{ 537 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 538 539 drm_mode_copy(&dpi->mode, adjusted_mode); 540} 541 542static void mtk_dpi_encoder_disable(struct drm_encoder *encoder) 543{ 544 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 545 546 mtk_dpi_power_off(dpi); 547} 548 549static void mtk_dpi_encoder_enable(struct drm_encoder *encoder) 550{ 551 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 552 553 mtk_dpi_power_on(dpi); 554 mtk_dpi_set_display_mode(dpi, &dpi->mode); 555} 556 557static int mtk_dpi_atomic_check(struct drm_encoder *encoder, 558 struct drm_crtc_state *crtc_state, 559 struct drm_connector_state *conn_state) 560{ 561 return 0; 562} 563 564static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs = { 565 .mode_fixup = mtk_dpi_encoder_mode_fixup, 566 .mode_set = mtk_dpi_encoder_mode_set, 567 .disable = mtk_dpi_encoder_disable, 568 .enable = mtk_dpi_encoder_enable, 569 .atomic_check = mtk_dpi_atomic_check, 570}; 571 572static void mtk_dpi_start(struct mtk_ddp_comp *comp) 573{ 574 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); 575 576 mtk_dpi_power_on(dpi); 577} 578 579static void mtk_dpi_stop(struct mtk_ddp_comp *comp) 580{ 581 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); 582 583 mtk_dpi_power_off(dpi); 584} 585 586static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = { 587 .start = mtk_dpi_start, 588 .stop = mtk_dpi_stop, 589}; 590 591static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) 592{ 593 struct mtk_dpi *dpi = dev_get_drvdata(dev); 594 struct drm_device *drm_dev = data; 595 int ret; 596 597 ret = mtk_ddp_comp_register(drm_dev, &dpi->ddp_comp); 598 if (ret < 0) { 599 dev_err(dev, "Failed to register component %pOF: %d\n", 600 dev->of_node, ret); 601 return ret; 602 } 603 604 ret = drm_encoder_init(drm_dev, &dpi->encoder, &mtk_dpi_encoder_funcs, 605 DRM_MODE_ENCODER_TMDS, NULL); 606 if (ret) { 607 dev_err(dev, "Failed to initialize decoder: %d\n", ret); 608 goto err_unregister; 609 } 610 drm_encoder_helper_add(&dpi->encoder, &mtk_dpi_encoder_helper_funcs); 611 612 /* Currently DPI0 is fixed to be driven by OVL1 */ 613 dpi->encoder.possible_crtcs = BIT(1); 614 615 ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL); 616 if (ret) { 617 dev_err(dev, "Failed to attach bridge: %d\n", ret); 618 goto err_cleanup; 619 } 620 621 dpi->bit_num = MTK_DPI_OUT_BIT_NUM_8BITS; 622 dpi->channel_swap = MTK_DPI_OUT_CHANNEL_SWAP_RGB; 623 dpi->yc_map = MTK_DPI_OUT_YC_MAP_RGB; 624 dpi->color_format = MTK_DPI_COLOR_FORMAT_RGB; 625 626 return 0; 627 628err_cleanup: 629 drm_encoder_cleanup(&dpi->encoder); 630err_unregister: 631 mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp); 632 return ret; 633} 634 635static void mtk_dpi_unbind(struct device *dev, struct device *master, 636 void *data) 637{ 638 struct mtk_dpi *dpi = dev_get_drvdata(dev); 639 struct drm_device *drm_dev = data; 640 641 drm_encoder_cleanup(&dpi->encoder); 642 mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp); 643} 644 645static const struct component_ops mtk_dpi_component_ops = { 646 .bind = mtk_dpi_bind, 647 .unbind = mtk_dpi_unbind, 648}; 649 650static unsigned int mt8173_calculate_factor(int clock) 651{ 652 if (clock <= 27000) 653 return 3 << 4; 654 else if (clock <= 84000) 655 return 3 << 3; 656 else if (clock <= 167000) 657 return 3 << 2; 658 else 659 return 3 << 1; 660} 661 662static unsigned int mt2701_calculate_factor(int clock) 663{ 664 if (clock <= 64000) 665 return 16; 666 else if (clock <= 128000) 667 return 8; 668 else if (clock <= 256000) 669 return 4; 670 else 671 return 2; 672} 673 674static const struct mtk_dpi_conf mt8173_conf = { 675 .cal_factor = mt8173_calculate_factor, 676 .reg_h_fre_con = 0xe0, 677}; 678 679static const struct mtk_dpi_conf mt2701_conf = { 680 .cal_factor = mt2701_calculate_factor, 681 .reg_h_fre_con = 0xb0, 682 .edge_sel_en = true, 683}; 684 685static int mtk_dpi_probe(struct platform_device *pdev) 686{ 687 struct device *dev = &pdev->dev; 688 struct mtk_dpi *dpi; 689 struct resource *mem; 690 int comp_id; 691 int ret; 692 693 dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); 694 if (!dpi) 695 return -ENOMEM; 696 697 dpi->dev = dev; 698 dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev); 699 700 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 701 dpi->regs = devm_ioremap_resource(dev, mem); 702 if (IS_ERR(dpi->regs)) { 703 ret = PTR_ERR(dpi->regs); 704 dev_err(dev, "Failed to ioremap mem resource: %d\n", ret); 705 return ret; 706 } 707 708 dpi->engine_clk = devm_clk_get(dev, "engine"); 709 if (IS_ERR(dpi->engine_clk)) { 710 ret = PTR_ERR(dpi->engine_clk); 711 dev_err(dev, "Failed to get engine clock: %d\n", ret); 712 return ret; 713 } 714 715 dpi->pixel_clk = devm_clk_get(dev, "pixel"); 716 if (IS_ERR(dpi->pixel_clk)) { 717 ret = PTR_ERR(dpi->pixel_clk); 718 dev_err(dev, "Failed to get pixel clock: %d\n", ret); 719 return ret; 720 } 721 722 dpi->tvd_clk = devm_clk_get(dev, "pll"); 723 if (IS_ERR(dpi->tvd_clk)) { 724 ret = PTR_ERR(dpi->tvd_clk); 725 dev_err(dev, "Failed to get tvdpll clock: %d\n", ret); 726 return ret; 727 } 728 729 dpi->irq = platform_get_irq(pdev, 0); 730 if (dpi->irq <= 0) { 731 dev_err(dev, "Failed to get irq: %d\n", dpi->irq); 732 return -EINVAL; 733 } 734 735 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, 736 NULL, &dpi->bridge); 737 if (ret) 738 return ret; 739 740 dev_info(dev, "Found bridge node: %pOF\n", dpi->bridge->of_node); 741 742 comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI); 743 if (comp_id < 0) { 744 dev_err(dev, "Failed to identify by alias: %d\n", comp_id); 745 return comp_id; 746 } 747 748 ret = mtk_ddp_comp_init(dev, dev->of_node, &dpi->ddp_comp, comp_id, 749 &mtk_dpi_funcs); 750 if (ret) { 751 dev_err(dev, "Failed to initialize component: %d\n", ret); 752 return ret; 753 } 754 755 platform_set_drvdata(pdev, dpi); 756 757 ret = component_add(dev, &mtk_dpi_component_ops); 758 if (ret) { 759 dev_err(dev, "Failed to add component: %d\n", ret); 760 return ret; 761 } 762 763 return 0; 764} 765 766static int mtk_dpi_remove(struct platform_device *pdev) 767{ 768 component_del(&pdev->dev, &mtk_dpi_component_ops); 769 770 return 0; 771} 772 773static const struct of_device_id mtk_dpi_of_ids[] = { 774 { .compatible = "mediatek,mt2701-dpi", 775 .data = &mt2701_conf, 776 }, 777 { .compatible = "mediatek,mt8173-dpi", 778 .data = &mt8173_conf, 779 }, 780 { }, 781}; 782 783struct platform_driver mtk_dpi_driver = { 784 .probe = mtk_dpi_probe, 785 .remove = mtk_dpi_remove, 786 .driver = { 787 .name = "mediatek-dpi", 788 .of_match_table = mtk_dpi_of_ids, 789 }, 790};