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