linux/drivers/gpu/drm/bridge/chrontel-ch7033.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Chrontel CH7033 Video Encoder Driver
   4 *
   5 * Copyright (C) 2019,2020 Lubomir Rintel
   6 */
   7
   8#include <linux/gpio/consumer.h>
   9#include <linux/module.h>
  10#include <linux/regmap.h>
  11
  12#include <drm/drm_atomic_helper.h>
  13#include <drm/drm_bridge.h>
  14#include <drm/drm_edid.h>
  15#include <drm/drm_of.h>
  16#include <drm/drm_print.h>
  17#include <drm/drm_probe_helper.h>
  18
  19/* Page 0, Register 0x07 */
  20enum {
  21        DRI_PD          = BIT(3),
  22        IO_PD           = BIT(5),
  23};
  24
  25/* Page 0, Register 0x08 */
  26enum {
  27        DRI_PDDRI       = GENMASK(7, 4),
  28        PDDAC           = GENMASK(3, 1),
  29        PANEN           = BIT(0),
  30};
  31
  32/* Page 0, Register 0x09 */
  33enum {
  34        DPD             = BIT(7),
  35        GCKOFF          = BIT(6),
  36        TV_BP           = BIT(5),
  37        SCLPD           = BIT(4),
  38        SDPD            = BIT(3),
  39        VGA_PD          = BIT(2),
  40        HDBKPD          = BIT(1),
  41        HDMI_PD         = BIT(0),
  42};
  43
  44/* Page 0, Register 0x0a */
  45enum {
  46        MEMINIT         = BIT(7),
  47        MEMIDLE         = BIT(6),
  48        MEMPD           = BIT(5),
  49        STOP            = BIT(4),
  50        LVDS_PD         = BIT(3),
  51        HD_DVIB         = BIT(2),
  52        HDCP_PD         = BIT(1),
  53        MCU_PD          = BIT(0),
  54};
  55
  56/* Page 0, Register 0x18 */
  57enum {
  58        IDF             = GENMASK(7, 4),
  59        INTEN           = BIT(3),
  60        SWAP            = GENMASK(2, 0),
  61};
  62
  63enum {
  64        BYTE_SWAP_RGB   = 0,
  65        BYTE_SWAP_RBG   = 1,
  66        BYTE_SWAP_GRB   = 2,
  67        BYTE_SWAP_GBR   = 3,
  68        BYTE_SWAP_BRG   = 4,
  69        BYTE_SWAP_BGR   = 5,
  70};
  71
  72/* Page 0, Register 0x19 */
  73enum {
  74        HPO_I           = BIT(5),
  75        VPO_I           = BIT(4),
  76        DEPO_I          = BIT(3),
  77        CRYS_EN         = BIT(2),
  78        GCLKFREQ        = GENMASK(2, 0),
  79};
  80
  81/* Page 0, Register 0x2e */
  82enum {
  83        HFLIP           = BIT(7),
  84        VFLIP           = BIT(6),
  85        DEPO_O          = BIT(5),
  86        HPO_O           = BIT(4),
  87        VPO_O           = BIT(3),
  88        TE              = GENMASK(2, 0),
  89};
  90
  91/* Page 0, Register 0x2b */
  92enum {
  93        SWAPS           = GENMASK(7, 4),
  94        VFMT            = GENMASK(3, 0),
  95};
  96
  97/* Page 0, Register 0x54 */
  98enum {
  99        COMP_BP         = BIT(7),
 100        DAC_EN_T        = BIT(6),
 101        HWO_HDMI_HI     = GENMASK(5, 3),
 102        HOO_HDMI_HI     = GENMASK(2, 0),
 103};
 104
 105/* Page 0, Register 0x57 */
 106enum {
 107        FLDSEN          = BIT(7),
 108        VWO_HDMI_HI     = GENMASK(5, 3),
 109        VOO_HDMI_HI     = GENMASK(2, 0),
 110};
 111
 112/* Page 0, Register 0x7e */
 113enum {
 114        HDMI_LVDS_SEL   = BIT(7),
 115        DE_GEN          = BIT(6),
 116        PWM_INDEX_HI    = BIT(5),
 117        USE_DE          = BIT(4),
 118        R_INT           = GENMASK(3, 0),
 119};
 120
 121/* Page 1, Register 0x07 */
 122enum {
 123        BPCKSEL         = BIT(7),
 124        DRI_CMFB_EN     = BIT(6),
 125        CEC_PUEN        = BIT(5),
 126        CEC_T           = BIT(3),
 127        CKINV           = BIT(2),
 128        CK_TVINV        = BIT(1),
 129        DRI_CKS2        = BIT(0),
 130};
 131
 132/* Page 1, Register 0x08 */
 133enum {
 134        DACG            = BIT(6),
 135        DACKTST         = BIT(5),
 136        DEDGEB          = BIT(4),
 137        SYO             = BIT(3),
 138        DRI_IT_LVDS     = GENMASK(2, 1),
 139        DISPON          = BIT(0),
 140};
 141
 142/* Page 1, Register 0x0c */
 143enum {
 144        DRI_PLL_CP      = GENMASK(7, 6),
 145        DRI_PLL_DIVSEL  = BIT(5),
 146        DRI_PLL_N1_1    = BIT(4),
 147        DRI_PLL_N1_0    = BIT(3),
 148        DRI_PLL_N3_1    = BIT(2),
 149        DRI_PLL_N3_0    = BIT(1),
 150        DRI_PLL_CKTSTEN = BIT(0),
 151};
 152
 153/* Page 1, Register 0x6b */
 154enum {
 155        VCO3CS          = GENMASK(7, 6),
 156        ICPGBK2_0       = GENMASK(5, 3),
 157        DRI_VCO357SC    = BIT(2),
 158        PDPLL2          = BIT(1),
 159        DRI_PD_SER      = BIT(0),
 160};
 161
 162/* Page 1, Register 0x6c */
 163enum {
 164        PLL2N11         = GENMASK(7, 4),
 165        PLL2N5_4        = BIT(3),
 166        PLL2N5_TOP      = BIT(2),
 167        DRI_PLL_PD      = BIT(1),
 168        PD_I2CM         = BIT(0),
 169};
 170
 171/* Page 3, Register 0x28 */
 172enum {
 173        DIFF_EN         = GENMASK(7, 6),
 174        CORREC_EN       = GENMASK(5, 4),
 175        VGACLK_BP       = BIT(3),
 176        HM_LV_SEL       = BIT(2),
 177        HD_VGA_SEL      = BIT(1),
 178};
 179
 180/* Page 3, Register 0x2a */
 181enum {
 182        LVDSCLK_BP      = BIT(7),
 183        HDTVCLK_BP      = BIT(6),
 184        HDMICLK_BP      = BIT(5),
 185        HDTV_BP         = BIT(4),
 186        HDMI_BP         = BIT(3),
 187        THRWL           = GENMASK(2, 0),
 188};
 189
 190/* Page 4, Register 0x52 */
 191enum {
 192        PGM_ARSTB       = BIT(7),
 193        MCU_ARSTB       = BIT(6),
 194        MCU_RETB        = BIT(2),
 195        RESETIB         = BIT(1),
 196        RESETDB         = BIT(0),
 197};
 198
 199struct ch7033_priv {
 200        struct regmap *regmap;
 201        struct drm_bridge *next_bridge;
 202        struct drm_bridge bridge;
 203        struct drm_connector connector;
 204};
 205
 206#define conn_to_ch7033_priv(x) \
 207        container_of(x, struct ch7033_priv, connector)
 208#define bridge_to_ch7033_priv(x) \
 209        container_of(x, struct ch7033_priv, bridge)
 210
 211
 212static enum drm_connector_status ch7033_connector_detect(
 213        struct drm_connector *connector, bool force)
 214{
 215        struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
 216
 217        return drm_bridge_detect(priv->next_bridge);
 218}
 219
 220static const struct drm_connector_funcs ch7033_connector_funcs = {
 221        .reset = drm_atomic_helper_connector_reset,
 222        .fill_modes = drm_helper_probe_single_connector_modes,
 223        .detect = ch7033_connector_detect,
 224        .destroy = drm_connector_cleanup,
 225        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 226        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 227};
 228
 229static int ch7033_connector_get_modes(struct drm_connector *connector)
 230{
 231        struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
 232        struct edid *edid;
 233        int ret;
 234
 235        edid = drm_bridge_get_edid(priv->next_bridge, connector);
 236        drm_connector_update_edid_property(connector, edid);
 237        if (edid) {
 238                ret = drm_add_edid_modes(connector, edid);
 239                kfree(edid);
 240        } else {
 241                ret = drm_add_modes_noedid(connector, 1920, 1080);
 242                drm_set_preferred_mode(connector, 1024, 768);
 243        }
 244
 245        return ret;
 246}
 247
 248static struct drm_encoder *ch7033_connector_best_encoder(
 249                        struct drm_connector *connector)
 250{
 251        struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
 252
 253        return priv->bridge.encoder;
 254}
 255
 256static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = {
 257        .get_modes = ch7033_connector_get_modes,
 258        .best_encoder = ch7033_connector_best_encoder,
 259};
 260
 261static void ch7033_hpd_event(void *arg, enum drm_connector_status status)
 262{
 263        struct ch7033_priv *priv = arg;
 264
 265        if (priv->bridge.dev)
 266                drm_helper_hpd_irq_event(priv->connector.dev);
 267}
 268
 269static int ch7033_bridge_attach(struct drm_bridge *bridge,
 270                                enum drm_bridge_attach_flags flags)
 271{
 272        struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
 273        struct drm_connector *connector = &priv->connector;
 274        int ret;
 275
 276        ret = drm_bridge_attach(bridge->encoder, priv->next_bridge, bridge,
 277                                DRM_BRIDGE_ATTACH_NO_CONNECTOR);
 278        if (ret)
 279                return ret;
 280
 281        if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
 282                return 0;
 283
 284        if (priv->next_bridge->ops & DRM_BRIDGE_OP_DETECT) {
 285                connector->polled = DRM_CONNECTOR_POLL_HPD;
 286        } else {
 287                connector->polled = DRM_CONNECTOR_POLL_CONNECT |
 288                                    DRM_CONNECTOR_POLL_DISCONNECT;
 289        }
 290
 291        if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD) {
 292                drm_bridge_hpd_enable(priv->next_bridge, ch7033_hpd_event,
 293                                      priv);
 294        }
 295
 296        drm_connector_helper_add(connector,
 297                                 &ch7033_connector_helper_funcs);
 298        ret = drm_connector_init_with_ddc(bridge->dev, &priv->connector,
 299                                          &ch7033_connector_funcs,
 300                                          priv->next_bridge->type,
 301                                          priv->next_bridge->ddc);
 302        if (ret) {
 303                DRM_ERROR("Failed to initialize connector\n");
 304                return ret;
 305        }
 306
 307        return drm_connector_attach_encoder(&priv->connector, bridge->encoder);
 308}
 309
 310static void ch7033_bridge_detach(struct drm_bridge *bridge)
 311{
 312        struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
 313
 314        if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD)
 315                drm_bridge_hpd_disable(priv->next_bridge);
 316        drm_connector_cleanup(&priv->connector);
 317}
 318
 319static enum drm_mode_status ch7033_bridge_mode_valid(struct drm_bridge *bridge,
 320                                     const struct drm_display_info *info,
 321                                     const struct drm_display_mode *mode)
 322{
 323        if (mode->clock > 165000)
 324                return MODE_CLOCK_HIGH;
 325        if (mode->hdisplay >= 1920)
 326                return MODE_BAD_HVALUE;
 327        if (mode->vdisplay >= 1080)
 328                return MODE_BAD_VVALUE;
 329        return MODE_OK;
 330}
 331
 332static void ch7033_bridge_disable(struct drm_bridge *bridge)
 333{
 334        struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
 335
 336        regmap_write(priv->regmap, 0x03, 0x04);
 337        regmap_update_bits(priv->regmap, 0x52, RESETDB, 0x00);
 338}
 339
 340static void ch7033_bridge_enable(struct drm_bridge *bridge)
 341{
 342        struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
 343
 344        regmap_write(priv->regmap, 0x03, 0x04);
 345        regmap_update_bits(priv->regmap, 0x52, RESETDB, RESETDB);
 346}
 347
 348static void ch7033_bridge_mode_set(struct drm_bridge *bridge,
 349                                   const struct drm_display_mode *mode,
 350                                   const struct drm_display_mode *adjusted_mode)
 351{
 352        struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
 353        int hbporch = mode->hsync_start - mode->hdisplay;
 354        int hsynclen = mode->hsync_end - mode->hsync_start;
 355        int vbporch = mode->vsync_start - mode->vdisplay;
 356        int vsynclen = mode->vsync_end - mode->vsync_start;
 357
 358        /*
 359         * Page 4
 360         */
 361        regmap_write(priv->regmap, 0x03, 0x04);
 362
 363        /* Turn everything off to set all the registers to their defaults. */
 364        regmap_write(priv->regmap, 0x52, 0x00);
 365        /* Bring I/O block up. */
 366        regmap_write(priv->regmap, 0x52, RESETIB);
 367
 368        /*
 369         * Page 0
 370         */
 371        regmap_write(priv->regmap, 0x03, 0x00);
 372
 373        /* Bring up parts we need from the power down. */
 374        regmap_update_bits(priv->regmap, 0x07, DRI_PD | IO_PD, 0);
 375        regmap_update_bits(priv->regmap, 0x08, DRI_PDDRI | PDDAC | PANEN, 0);
 376        regmap_update_bits(priv->regmap, 0x09, DPD | GCKOFF |
 377                                               HDMI_PD | VGA_PD, 0);
 378        regmap_update_bits(priv->regmap, 0x0a, HD_DVIB, 0);
 379
 380        /* Horizontal input timing. */
 381        regmap_write(priv->regmap, 0x0b, (mode->htotal >> 8) << 3 |
 382                                         (mode->hdisplay >> 8));
 383        regmap_write(priv->regmap, 0x0c, mode->hdisplay);
 384        regmap_write(priv->regmap, 0x0d, mode->htotal);
 385        regmap_write(priv->regmap, 0x0e, (hsynclen >> 8) << 3 |
 386                                         (hbporch >> 8));
 387        regmap_write(priv->regmap, 0x0f, hbporch);
 388        regmap_write(priv->regmap, 0x10, hsynclen);
 389
 390        /* Vertical input timing. */
 391        regmap_write(priv->regmap, 0x11, (mode->vtotal >> 8) << 3 |
 392                                         (mode->vdisplay >> 8));
 393        regmap_write(priv->regmap, 0x12, mode->vdisplay);
 394        regmap_write(priv->regmap, 0x13, mode->vtotal);
 395        regmap_write(priv->regmap, 0x14, ((vsynclen >> 8) << 3) |
 396                                         (vbporch >> 8));
 397        regmap_write(priv->regmap, 0x15, vbporch);
 398        regmap_write(priv->regmap, 0x16, vsynclen);
 399
 400        /* Input color swap. */
 401        regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR);
 402
 403        /* Input clock and sync polarity. */
 404        regmap_update_bits(priv->regmap, 0x19, 0x1, mode->clock >> 16);
 405        regmap_update_bits(priv->regmap, 0x19, HPO_I | VPO_I | GCLKFREQ,
 406                           (mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_I : 0 |
 407                           (mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_I : 0 |
 408                           mode->clock >> 16);
 409        regmap_write(priv->regmap, 0x1a, mode->clock >> 8);
 410        regmap_write(priv->regmap, 0x1b, mode->clock);
 411
 412        /* Horizontal output timing. */
 413        regmap_write(priv->regmap, 0x1f, (mode->htotal >> 8) << 3 |
 414                                         (mode->hdisplay >> 8));
 415        regmap_write(priv->regmap, 0x20, mode->hdisplay);
 416        regmap_write(priv->regmap, 0x21, mode->htotal);
 417
 418        /* Vertical output timing. */
 419        regmap_write(priv->regmap, 0x25, (mode->vtotal >> 8) << 3 |
 420                                         (mode->vdisplay >> 8));
 421        regmap_write(priv->regmap, 0x26, mode->vdisplay);
 422        regmap_write(priv->regmap, 0x27, mode->vtotal);
 423
 424        /* VGA channel bypass */
 425        regmap_update_bits(priv->regmap, 0x2b, VFMT, 9);
 426
 427        /* Output sync polarity. */
 428        regmap_update_bits(priv->regmap, 0x2e, HPO_O | VPO_O,
 429                           (mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_O : 0 |
 430                           (mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_O : 0);
 431
 432        /* HDMI horizontal output timing. */
 433        regmap_update_bits(priv->regmap, 0x54, HWO_HDMI_HI | HOO_HDMI_HI,
 434                                               (hsynclen >> 8) << 3 |
 435                                               (hbporch >> 8));
 436        regmap_write(priv->regmap, 0x55, hbporch);
 437        regmap_write(priv->regmap, 0x56, hsynclen);
 438
 439        /* HDMI vertical output timing. */
 440        regmap_update_bits(priv->regmap, 0x57, VWO_HDMI_HI | VOO_HDMI_HI,
 441                                               (vsynclen >> 8) << 3 |
 442                                               (vbporch >> 8));
 443        regmap_write(priv->regmap, 0x58, vbporch);
 444        regmap_write(priv->regmap, 0x59, vsynclen);
 445
 446        /* Pick HDMI, not LVDS. */
 447        regmap_update_bits(priv->regmap, 0x7e, HDMI_LVDS_SEL, HDMI_LVDS_SEL);
 448
 449        /*
 450         * Page 1
 451         */
 452        regmap_write(priv->regmap, 0x03, 0x01);
 453
 454        /* No idea what these do, but VGA is wobbly and blinky without them. */
 455        regmap_update_bits(priv->regmap, 0x07, CKINV, CKINV);
 456        regmap_update_bits(priv->regmap, 0x08, DISPON, DISPON);
 457
 458        /* DRI PLL */
 459        regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_DIVSEL, DRI_PLL_DIVSEL);
 460        if (mode->clock <= 40000) {
 461                regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
 462                                                       DRI_PLL_N1_0 |
 463                                                       DRI_PLL_N3_1 |
 464                                                       DRI_PLL_N3_0,
 465                                                       0);
 466        } else if (mode->clock < 80000) {
 467                regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
 468                                                       DRI_PLL_N1_0 |
 469                                                       DRI_PLL_N3_1 |
 470                                                       DRI_PLL_N3_0,
 471                                                       DRI_PLL_N3_0 |
 472                                                       DRI_PLL_N1_0);
 473        } else {
 474                regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
 475                                                       DRI_PLL_N1_0 |
 476                                                       DRI_PLL_N3_1 |
 477                                                       DRI_PLL_N3_0,
 478                                                       DRI_PLL_N3_1 |
 479                                                       DRI_PLL_N1_1);
 480        }
 481
 482        /* This seems to be color calibration for VGA. */
 483        regmap_write(priv->regmap, 0x64, 0x29); /* LSB Blue */
 484        regmap_write(priv->regmap, 0x65, 0x29); /* LSB Green */
 485        regmap_write(priv->regmap, 0x66, 0x29); /* LSB Red */
 486        regmap_write(priv->regmap, 0x67, 0x00); /* MSB Blue */
 487        regmap_write(priv->regmap, 0x68, 0x00); /* MSB Green */
 488        regmap_write(priv->regmap, 0x69, 0x00); /* MSB Red */
 489
 490        regmap_update_bits(priv->regmap, 0x6b, DRI_PD_SER, 0x00);
 491        regmap_update_bits(priv->regmap, 0x6c, DRI_PLL_PD, 0x00);
 492
 493        /*
 494         * Page 3
 495         */
 496        regmap_write(priv->regmap, 0x03, 0x03);
 497
 498        /* More bypasses and apparently another HDMI/LVDS selector. */
 499        regmap_update_bits(priv->regmap, 0x28, VGACLK_BP | HM_LV_SEL,
 500                                               VGACLK_BP | HM_LV_SEL);
 501        regmap_update_bits(priv->regmap, 0x2a, HDMICLK_BP | HDMI_BP,
 502                                               HDMICLK_BP | HDMI_BP);
 503
 504        /*
 505         * Page 4
 506         */
 507        regmap_write(priv->regmap, 0x03, 0x04);
 508
 509        /* Output clock. */
 510        regmap_write(priv->regmap, 0x10, mode->clock >> 16);
 511        regmap_write(priv->regmap, 0x11, mode->clock >> 8);
 512        regmap_write(priv->regmap, 0x12, mode->clock);
 513}
 514
 515static const struct drm_bridge_funcs ch7033_bridge_funcs = {
 516        .attach = ch7033_bridge_attach,
 517        .detach = ch7033_bridge_detach,
 518        .mode_valid = ch7033_bridge_mode_valid,
 519        .disable = ch7033_bridge_disable,
 520        .enable = ch7033_bridge_enable,
 521        .mode_set = ch7033_bridge_mode_set,
 522};
 523
 524static const struct regmap_config ch7033_regmap_config = {
 525        .reg_bits = 8,
 526        .val_bits = 8,
 527        .max_register = 0x7f,
 528};
 529
 530static int ch7033_probe(struct i2c_client *client,
 531                        const struct i2c_device_id *id)
 532{
 533        struct device *dev = &client->dev;
 534        struct ch7033_priv *priv;
 535        unsigned int val;
 536        int ret;
 537
 538        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 539        if (!priv)
 540                return -ENOMEM;
 541
 542        dev_set_drvdata(dev, priv);
 543
 544        ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL,
 545                                          &priv->next_bridge);
 546        if (ret)
 547                return ret;
 548
 549        priv->regmap = devm_regmap_init_i2c(client, &ch7033_regmap_config);
 550        if (IS_ERR(priv->regmap)) {
 551                dev_err(&client->dev, "regmap init failed\n");
 552                return PTR_ERR(priv->regmap);
 553        }
 554
 555        ret = regmap_read(priv->regmap, 0x00, &val);
 556        if (ret < 0) {
 557                dev_err(&client->dev, "error reading the model id: %d\n", ret);
 558                return ret;
 559        }
 560        if ((val & 0xf7) != 0x56) {
 561                dev_err(&client->dev, "the device is not a ch7033\n");
 562                return -ENODEV;
 563        }
 564
 565        regmap_write(priv->regmap, 0x03, 0x04);
 566        ret = regmap_read(priv->regmap, 0x51, &val);
 567        if (ret < 0) {
 568                dev_err(&client->dev, "error reading the model id: %d\n", ret);
 569                return ret;
 570        }
 571        if ((val & 0x0f) != 3) {
 572                dev_err(&client->dev, "unknown revision %u\n", val);
 573                return -ENODEV;
 574        }
 575
 576        INIT_LIST_HEAD(&priv->bridge.list);
 577        priv->bridge.funcs = &ch7033_bridge_funcs;
 578        priv->bridge.of_node = dev->of_node;
 579        drm_bridge_add(&priv->bridge);
 580
 581        dev_info(dev, "Chrontel CH7033 Video Encoder\n");
 582        return 0;
 583}
 584
 585static int ch7033_remove(struct i2c_client *client)
 586{
 587        struct device *dev = &client->dev;
 588        struct ch7033_priv *priv = dev_get_drvdata(dev);
 589
 590        drm_bridge_remove(&priv->bridge);
 591
 592        return 0;
 593}
 594
 595static const struct of_device_id ch7033_dt_ids[] = {
 596        { .compatible = "chrontel,ch7033", },
 597        { }
 598};
 599MODULE_DEVICE_TABLE(of, ch7033_dt_ids);
 600
 601static const struct i2c_device_id ch7033_ids[] = {
 602        { "ch7033", 0 },
 603        { }
 604};
 605MODULE_DEVICE_TABLE(i2c, ch7033_ids);
 606
 607static struct i2c_driver ch7033_driver = {
 608        .probe = ch7033_probe,
 609        .remove = ch7033_remove,
 610        .driver = {
 611                .name = "ch7033",
 612                .of_match_table = of_match_ptr(ch7033_dt_ids),
 613        },
 614        .id_table = ch7033_ids,
 615};
 616
 617module_i2c_driver(ch7033_driver);
 618
 619MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
 620MODULE_DESCRIPTION("Chrontel CH7033 Video Encoder Driver");
 621MODULE_LICENSE("GPL v2");
 622