Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Chrontel CH7033 Video Encoder Driver
0004  *
0005  * Copyright (C) 2019,2020 Lubomir Rintel
0006  */
0007 
0008 #include <linux/gpio/consumer.h>
0009 #include <linux/i2c.h>
0010 #include <linux/module.h>
0011 #include <linux/regmap.h>
0012 
0013 #include <drm/drm_atomic_helper.h>
0014 #include <drm/drm_bridge.h>
0015 #include <drm/drm_edid.h>
0016 #include <drm/drm_of.h>
0017 #include <drm/drm_print.h>
0018 #include <drm/drm_probe_helper.h>
0019 
0020 /* Page 0, Register 0x07 */
0021 enum {
0022     DRI_PD      = BIT(3),
0023     IO_PD       = BIT(5),
0024 };
0025 
0026 /* Page 0, Register 0x08 */
0027 enum {
0028     DRI_PDDRI   = GENMASK(7, 4),
0029     PDDAC       = GENMASK(3, 1),
0030     PANEN       = BIT(0),
0031 };
0032 
0033 /* Page 0, Register 0x09 */
0034 enum {
0035     DPD     = BIT(7),
0036     GCKOFF      = BIT(6),
0037     TV_BP       = BIT(5),
0038     SCLPD       = BIT(4),
0039     SDPD        = BIT(3),
0040     VGA_PD      = BIT(2),
0041     HDBKPD      = BIT(1),
0042     HDMI_PD     = BIT(0),
0043 };
0044 
0045 /* Page 0, Register 0x0a */
0046 enum {
0047     MEMINIT     = BIT(7),
0048     MEMIDLE     = BIT(6),
0049     MEMPD       = BIT(5),
0050     STOP        = BIT(4),
0051     LVDS_PD     = BIT(3),
0052     HD_DVIB     = BIT(2),
0053     HDCP_PD     = BIT(1),
0054     MCU_PD      = BIT(0),
0055 };
0056 
0057 /* Page 0, Register 0x18 */
0058 enum {
0059     IDF     = GENMASK(7, 4),
0060     INTEN       = BIT(3),
0061     SWAP        = GENMASK(2, 0),
0062 };
0063 
0064 enum {
0065     BYTE_SWAP_RGB   = 0,
0066     BYTE_SWAP_RBG   = 1,
0067     BYTE_SWAP_GRB   = 2,
0068     BYTE_SWAP_GBR   = 3,
0069     BYTE_SWAP_BRG   = 4,
0070     BYTE_SWAP_BGR   = 5,
0071 };
0072 
0073 /* Page 0, Register 0x19 */
0074 enum {
0075     HPO_I       = BIT(5),
0076     VPO_I       = BIT(4),
0077     DEPO_I      = BIT(3),
0078     CRYS_EN     = BIT(2),
0079     GCLKFREQ    = GENMASK(2, 0),
0080 };
0081 
0082 /* Page 0, Register 0x2e */
0083 enum {
0084     HFLIP       = BIT(7),
0085     VFLIP       = BIT(6),
0086     DEPO_O      = BIT(5),
0087     HPO_O       = BIT(4),
0088     VPO_O       = BIT(3),
0089     TE      = GENMASK(2, 0),
0090 };
0091 
0092 /* Page 0, Register 0x2b */
0093 enum {
0094     SWAPS       = GENMASK(7, 4),
0095     VFMT        = GENMASK(3, 0),
0096 };
0097 
0098 /* Page 0, Register 0x54 */
0099 enum {
0100     COMP_BP     = BIT(7),
0101     DAC_EN_T    = BIT(6),
0102     HWO_HDMI_HI = GENMASK(5, 3),
0103     HOO_HDMI_HI = GENMASK(2, 0),
0104 };
0105 
0106 /* Page 0, Register 0x57 */
0107 enum {
0108     FLDSEN      = BIT(7),
0109     VWO_HDMI_HI = GENMASK(5, 3),
0110     VOO_HDMI_HI = GENMASK(2, 0),
0111 };
0112 
0113 /* Page 0, Register 0x7e */
0114 enum {
0115     HDMI_LVDS_SEL   = BIT(7),
0116     DE_GEN      = BIT(6),
0117     PWM_INDEX_HI    = BIT(5),
0118     USE_DE      = BIT(4),
0119     R_INT       = GENMASK(3, 0),
0120 };
0121 
0122 /* Page 1, Register 0x07 */
0123 enum {
0124     BPCKSEL     = BIT(7),
0125     DRI_CMFB_EN = BIT(6),
0126     CEC_PUEN    = BIT(5),
0127     CEC_T       = BIT(3),
0128     CKINV       = BIT(2),
0129     CK_TVINV    = BIT(1),
0130     DRI_CKS2    = BIT(0),
0131 };
0132 
0133 /* Page 1, Register 0x08 */
0134 enum {
0135     DACG        = BIT(6),
0136     DACKTST     = BIT(5),
0137     DEDGEB      = BIT(4),
0138     SYO     = BIT(3),
0139     DRI_IT_LVDS = GENMASK(2, 1),
0140     DISPON      = BIT(0),
0141 };
0142 
0143 /* Page 1, Register 0x0c */
0144 enum {
0145     DRI_PLL_CP  = GENMASK(7, 6),
0146     DRI_PLL_DIVSEL  = BIT(5),
0147     DRI_PLL_N1_1    = BIT(4),
0148     DRI_PLL_N1_0    = BIT(3),
0149     DRI_PLL_N3_1    = BIT(2),
0150     DRI_PLL_N3_0    = BIT(1),
0151     DRI_PLL_CKTSTEN = BIT(0),
0152 };
0153 
0154 /* Page 1, Register 0x6b */
0155 enum {
0156     VCO3CS      = GENMASK(7, 6),
0157     ICPGBK2_0   = GENMASK(5, 3),
0158     DRI_VCO357SC    = BIT(2),
0159     PDPLL2      = BIT(1),
0160     DRI_PD_SER  = BIT(0),
0161 };
0162 
0163 /* Page 1, Register 0x6c */
0164 enum {
0165     PLL2N11     = GENMASK(7, 4),
0166     PLL2N5_4    = BIT(3),
0167     PLL2N5_TOP  = BIT(2),
0168     DRI_PLL_PD  = BIT(1),
0169     PD_I2CM     = BIT(0),
0170 };
0171 
0172 /* Page 3, Register 0x28 */
0173 enum {
0174     DIFF_EN     = GENMASK(7, 6),
0175     CORREC_EN   = GENMASK(5, 4),
0176     VGACLK_BP   = BIT(3),
0177     HM_LV_SEL   = BIT(2),
0178     HD_VGA_SEL  = BIT(1),
0179 };
0180 
0181 /* Page 3, Register 0x2a */
0182 enum {
0183     LVDSCLK_BP  = BIT(7),
0184     HDTVCLK_BP  = BIT(6),
0185     HDMICLK_BP  = BIT(5),
0186     HDTV_BP     = BIT(4),
0187     HDMI_BP     = BIT(3),
0188     THRWL       = GENMASK(2, 0),
0189 };
0190 
0191 /* Page 4, Register 0x52 */
0192 enum {
0193     PGM_ARSTB   = BIT(7),
0194     MCU_ARSTB   = BIT(6),
0195     MCU_RETB    = BIT(2),
0196     RESETIB     = BIT(1),
0197     RESETDB     = BIT(0),
0198 };
0199 
0200 struct ch7033_priv {
0201     struct regmap *regmap;
0202     struct drm_bridge *next_bridge;
0203     struct drm_bridge bridge;
0204     struct drm_connector connector;
0205 };
0206 
0207 #define conn_to_ch7033_priv(x) \
0208     container_of(x, struct ch7033_priv, connector)
0209 #define bridge_to_ch7033_priv(x) \
0210     container_of(x, struct ch7033_priv, bridge)
0211 
0212 
0213 static enum drm_connector_status ch7033_connector_detect(
0214     struct drm_connector *connector, bool force)
0215 {
0216     struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
0217 
0218     return drm_bridge_detect(priv->next_bridge);
0219 }
0220 
0221 static const struct drm_connector_funcs ch7033_connector_funcs = {
0222     .reset = drm_atomic_helper_connector_reset,
0223     .fill_modes = drm_helper_probe_single_connector_modes,
0224     .detect = ch7033_connector_detect,
0225     .destroy = drm_connector_cleanup,
0226     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0227     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0228 };
0229 
0230 static int ch7033_connector_get_modes(struct drm_connector *connector)
0231 {
0232     struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
0233     struct edid *edid;
0234     int ret;
0235 
0236     edid = drm_bridge_get_edid(priv->next_bridge, connector);
0237     drm_connector_update_edid_property(connector, edid);
0238     if (edid) {
0239         ret = drm_add_edid_modes(connector, edid);
0240         kfree(edid);
0241     } else {
0242         ret = drm_add_modes_noedid(connector, 1920, 1080);
0243         drm_set_preferred_mode(connector, 1024, 768);
0244     }
0245 
0246     return ret;
0247 }
0248 
0249 static struct drm_encoder *ch7033_connector_best_encoder(
0250             struct drm_connector *connector)
0251 {
0252     struct ch7033_priv *priv = conn_to_ch7033_priv(connector);
0253 
0254     return priv->bridge.encoder;
0255 }
0256 
0257 static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = {
0258     .get_modes = ch7033_connector_get_modes,
0259     .best_encoder = ch7033_connector_best_encoder,
0260 };
0261 
0262 static void ch7033_hpd_event(void *arg, enum drm_connector_status status)
0263 {
0264     struct ch7033_priv *priv = arg;
0265 
0266     if (priv->bridge.dev)
0267         drm_helper_hpd_irq_event(priv->connector.dev);
0268 }
0269 
0270 static int ch7033_bridge_attach(struct drm_bridge *bridge,
0271                 enum drm_bridge_attach_flags flags)
0272 {
0273     struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
0274     struct drm_connector *connector = &priv->connector;
0275     int ret;
0276 
0277     ret = drm_bridge_attach(bridge->encoder, priv->next_bridge, bridge,
0278                 DRM_BRIDGE_ATTACH_NO_CONNECTOR);
0279     if (ret)
0280         return ret;
0281 
0282     if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
0283         return 0;
0284 
0285     if (priv->next_bridge->ops & DRM_BRIDGE_OP_DETECT) {
0286         connector->polled = DRM_CONNECTOR_POLL_HPD;
0287     } else {
0288         connector->polled = DRM_CONNECTOR_POLL_CONNECT |
0289                     DRM_CONNECTOR_POLL_DISCONNECT;
0290     }
0291 
0292     if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD) {
0293         drm_bridge_hpd_enable(priv->next_bridge, ch7033_hpd_event,
0294                       priv);
0295     }
0296 
0297     drm_connector_helper_add(connector,
0298                  &ch7033_connector_helper_funcs);
0299     ret = drm_connector_init_with_ddc(bridge->dev, &priv->connector,
0300                       &ch7033_connector_funcs,
0301                       priv->next_bridge->type,
0302                       priv->next_bridge->ddc);
0303     if (ret) {
0304         DRM_ERROR("Failed to initialize connector\n");
0305         return ret;
0306     }
0307 
0308     return drm_connector_attach_encoder(&priv->connector, bridge->encoder);
0309 }
0310 
0311 static void ch7033_bridge_detach(struct drm_bridge *bridge)
0312 {
0313     struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
0314 
0315     if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD)
0316         drm_bridge_hpd_disable(priv->next_bridge);
0317     drm_connector_cleanup(&priv->connector);
0318 }
0319 
0320 static enum drm_mode_status ch7033_bridge_mode_valid(struct drm_bridge *bridge,
0321                      const struct drm_display_info *info,
0322                      const struct drm_display_mode *mode)
0323 {
0324     if (mode->clock > 165000)
0325         return MODE_CLOCK_HIGH;
0326     if (mode->hdisplay >= 1920)
0327         return MODE_BAD_HVALUE;
0328     if (mode->vdisplay >= 1080)
0329         return MODE_BAD_VVALUE;
0330     return MODE_OK;
0331 }
0332 
0333 static void ch7033_bridge_disable(struct drm_bridge *bridge)
0334 {
0335     struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
0336 
0337     regmap_write(priv->regmap, 0x03, 0x04);
0338     regmap_update_bits(priv->regmap, 0x52, RESETDB, 0x00);
0339 }
0340 
0341 static void ch7033_bridge_enable(struct drm_bridge *bridge)
0342 {
0343     struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
0344 
0345     regmap_write(priv->regmap, 0x03, 0x04);
0346     regmap_update_bits(priv->regmap, 0x52, RESETDB, RESETDB);
0347 }
0348 
0349 static void ch7033_bridge_mode_set(struct drm_bridge *bridge,
0350                    const struct drm_display_mode *mode,
0351                    const struct drm_display_mode *adjusted_mode)
0352 {
0353     struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);
0354     int hbporch = mode->hsync_start - mode->hdisplay;
0355     int hsynclen = mode->hsync_end - mode->hsync_start;
0356     int vbporch = mode->vsync_start - mode->vdisplay;
0357     int vsynclen = mode->vsync_end - mode->vsync_start;
0358 
0359     /*
0360      * Page 4
0361      */
0362     regmap_write(priv->regmap, 0x03, 0x04);
0363 
0364     /* Turn everything off to set all the registers to their defaults. */
0365     regmap_write(priv->regmap, 0x52, 0x00);
0366     /* Bring I/O block up. */
0367     regmap_write(priv->regmap, 0x52, RESETIB);
0368 
0369     /*
0370      * Page 0
0371      */
0372     regmap_write(priv->regmap, 0x03, 0x00);
0373 
0374     /* Bring up parts we need from the power down. */
0375     regmap_update_bits(priv->regmap, 0x07, DRI_PD | IO_PD, 0);
0376     regmap_update_bits(priv->regmap, 0x08, DRI_PDDRI | PDDAC | PANEN, 0);
0377     regmap_update_bits(priv->regmap, 0x09, DPD | GCKOFF |
0378                            HDMI_PD | VGA_PD, 0);
0379     regmap_update_bits(priv->regmap, 0x0a, HD_DVIB, 0);
0380 
0381     /* Horizontal input timing. */
0382     regmap_write(priv->regmap, 0x0b, (mode->htotal >> 8) << 3 |
0383                      (mode->hdisplay >> 8));
0384     regmap_write(priv->regmap, 0x0c, mode->hdisplay);
0385     regmap_write(priv->regmap, 0x0d, mode->htotal);
0386     regmap_write(priv->regmap, 0x0e, (hsynclen >> 8) << 3 |
0387                      (hbporch >> 8));
0388     regmap_write(priv->regmap, 0x0f, hbporch);
0389     regmap_write(priv->regmap, 0x10, hsynclen);
0390 
0391     /* Vertical input timing. */
0392     regmap_write(priv->regmap, 0x11, (mode->vtotal >> 8) << 3 |
0393                      (mode->vdisplay >> 8));
0394     regmap_write(priv->regmap, 0x12, mode->vdisplay);
0395     regmap_write(priv->regmap, 0x13, mode->vtotal);
0396     regmap_write(priv->regmap, 0x14, ((vsynclen >> 8) << 3) |
0397                      (vbporch >> 8));
0398     regmap_write(priv->regmap, 0x15, vbporch);
0399     regmap_write(priv->regmap, 0x16, vsynclen);
0400 
0401     /* Input color swap. */
0402     regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR);
0403 
0404     /* Input clock and sync polarity. */
0405     regmap_update_bits(priv->regmap, 0x19, 0x1, mode->clock >> 16);
0406     regmap_update_bits(priv->regmap, 0x19, HPO_I | VPO_I | GCLKFREQ,
0407                (mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_I : 0 |
0408                (mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_I : 0 |
0409                mode->clock >> 16);
0410     regmap_write(priv->regmap, 0x1a, mode->clock >> 8);
0411     regmap_write(priv->regmap, 0x1b, mode->clock);
0412 
0413     /* Horizontal output timing. */
0414     regmap_write(priv->regmap, 0x1f, (mode->htotal >> 8) << 3 |
0415                      (mode->hdisplay >> 8));
0416     regmap_write(priv->regmap, 0x20, mode->hdisplay);
0417     regmap_write(priv->regmap, 0x21, mode->htotal);
0418 
0419     /* Vertical output timing. */
0420     regmap_write(priv->regmap, 0x25, (mode->vtotal >> 8) << 3 |
0421                      (mode->vdisplay >> 8));
0422     regmap_write(priv->regmap, 0x26, mode->vdisplay);
0423     regmap_write(priv->regmap, 0x27, mode->vtotal);
0424 
0425     /* VGA channel bypass */
0426     regmap_update_bits(priv->regmap, 0x2b, VFMT, 9);
0427 
0428     /* Output sync polarity. */
0429     regmap_update_bits(priv->regmap, 0x2e, HPO_O | VPO_O,
0430                (mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_O : 0 |
0431                (mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_O : 0);
0432 
0433     /* HDMI horizontal output timing. */
0434     regmap_update_bits(priv->regmap, 0x54, HWO_HDMI_HI | HOO_HDMI_HI,
0435                            (hsynclen >> 8) << 3 |
0436                            (hbporch >> 8));
0437     regmap_write(priv->regmap, 0x55, hbporch);
0438     regmap_write(priv->regmap, 0x56, hsynclen);
0439 
0440     /* HDMI vertical output timing. */
0441     regmap_update_bits(priv->regmap, 0x57, VWO_HDMI_HI | VOO_HDMI_HI,
0442                            (vsynclen >> 8) << 3 |
0443                            (vbporch >> 8));
0444     regmap_write(priv->regmap, 0x58, vbporch);
0445     regmap_write(priv->regmap, 0x59, vsynclen);
0446 
0447     /* Pick HDMI, not LVDS. */
0448     regmap_update_bits(priv->regmap, 0x7e, HDMI_LVDS_SEL, HDMI_LVDS_SEL);
0449 
0450     /*
0451      * Page 1
0452      */
0453     regmap_write(priv->regmap, 0x03, 0x01);
0454 
0455     /* No idea what these do, but VGA is wobbly and blinky without them. */
0456     regmap_update_bits(priv->regmap, 0x07, CKINV, CKINV);
0457     regmap_update_bits(priv->regmap, 0x08, DISPON, DISPON);
0458 
0459     /* DRI PLL */
0460     regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_DIVSEL, DRI_PLL_DIVSEL);
0461     if (mode->clock <= 40000) {
0462         regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
0463                                DRI_PLL_N1_0 |
0464                                DRI_PLL_N3_1 |
0465                                DRI_PLL_N3_0,
0466                                0);
0467     } else if (mode->clock < 80000) {
0468         regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
0469                                DRI_PLL_N1_0 |
0470                                DRI_PLL_N3_1 |
0471                                DRI_PLL_N3_0,
0472                                DRI_PLL_N3_0 |
0473                                DRI_PLL_N1_0);
0474     } else {
0475         regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |
0476                                DRI_PLL_N1_0 |
0477                                DRI_PLL_N3_1 |
0478                                DRI_PLL_N3_0,
0479                                DRI_PLL_N3_1 |
0480                                DRI_PLL_N1_1);
0481     }
0482 
0483     /* This seems to be color calibration for VGA. */
0484     regmap_write(priv->regmap, 0x64, 0x29); /* LSB Blue */
0485     regmap_write(priv->regmap, 0x65, 0x29); /* LSB Green */
0486     regmap_write(priv->regmap, 0x66, 0x29); /* LSB Red */
0487     regmap_write(priv->regmap, 0x67, 0x00); /* MSB Blue */
0488     regmap_write(priv->regmap, 0x68, 0x00); /* MSB Green */
0489     regmap_write(priv->regmap, 0x69, 0x00); /* MSB Red */
0490 
0491     regmap_update_bits(priv->regmap, 0x6b, DRI_PD_SER, 0x00);
0492     regmap_update_bits(priv->regmap, 0x6c, DRI_PLL_PD, 0x00);
0493 
0494     /*
0495      * Page 3
0496      */
0497     regmap_write(priv->regmap, 0x03, 0x03);
0498 
0499     /* More bypasses and apparently another HDMI/LVDS selector. */
0500     regmap_update_bits(priv->regmap, 0x28, VGACLK_BP | HM_LV_SEL,
0501                            VGACLK_BP | HM_LV_SEL);
0502     regmap_update_bits(priv->regmap, 0x2a, HDMICLK_BP | HDMI_BP,
0503                            HDMICLK_BP | HDMI_BP);
0504 
0505     /*
0506      * Page 4
0507      */
0508     regmap_write(priv->regmap, 0x03, 0x04);
0509 
0510     /* Output clock. */
0511     regmap_write(priv->regmap, 0x10, mode->clock >> 16);
0512     regmap_write(priv->regmap, 0x11, mode->clock >> 8);
0513     regmap_write(priv->regmap, 0x12, mode->clock);
0514 }
0515 
0516 static const struct drm_bridge_funcs ch7033_bridge_funcs = {
0517     .attach = ch7033_bridge_attach,
0518     .detach = ch7033_bridge_detach,
0519     .mode_valid = ch7033_bridge_mode_valid,
0520     .disable = ch7033_bridge_disable,
0521     .enable = ch7033_bridge_enable,
0522     .mode_set = ch7033_bridge_mode_set,
0523 };
0524 
0525 static const struct regmap_config ch7033_regmap_config = {
0526     .reg_bits = 8,
0527     .val_bits = 8,
0528     .max_register = 0x7f,
0529 };
0530 
0531 static int ch7033_probe(struct i2c_client *client,
0532             const struct i2c_device_id *id)
0533 {
0534     struct device *dev = &client->dev;
0535     struct ch7033_priv *priv;
0536     unsigned int val;
0537     int ret;
0538 
0539     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0540     if (!priv)
0541         return -ENOMEM;
0542 
0543     dev_set_drvdata(dev, priv);
0544 
0545     ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL,
0546                       &priv->next_bridge);
0547     if (ret)
0548         return ret;
0549 
0550     priv->regmap = devm_regmap_init_i2c(client, &ch7033_regmap_config);
0551     if (IS_ERR(priv->regmap)) {
0552         dev_err(&client->dev, "regmap init failed\n");
0553         return PTR_ERR(priv->regmap);
0554     }
0555 
0556     ret = regmap_read(priv->regmap, 0x00, &val);
0557     if (ret < 0) {
0558         dev_err(&client->dev, "error reading the model id: %d\n", ret);
0559         return ret;
0560     }
0561     if ((val & 0xf7) != 0x56) {
0562         dev_err(&client->dev, "the device is not a ch7033\n");
0563         return -ENODEV;
0564     }
0565 
0566     regmap_write(priv->regmap, 0x03, 0x04);
0567     ret = regmap_read(priv->regmap, 0x51, &val);
0568     if (ret < 0) {
0569         dev_err(&client->dev, "error reading the model id: %d\n", ret);
0570         return ret;
0571     }
0572     if ((val & 0x0f) != 3) {
0573         dev_err(&client->dev, "unknown revision %u\n", val);
0574         return -ENODEV;
0575     }
0576 
0577     INIT_LIST_HEAD(&priv->bridge.list);
0578     priv->bridge.funcs = &ch7033_bridge_funcs;
0579     priv->bridge.of_node = dev->of_node;
0580     drm_bridge_add(&priv->bridge);
0581 
0582     dev_info(dev, "Chrontel CH7033 Video Encoder\n");
0583     return 0;
0584 }
0585 
0586 static int ch7033_remove(struct i2c_client *client)
0587 {
0588     struct device *dev = &client->dev;
0589     struct ch7033_priv *priv = dev_get_drvdata(dev);
0590 
0591     drm_bridge_remove(&priv->bridge);
0592 
0593     return 0;
0594 }
0595 
0596 static const struct of_device_id ch7033_dt_ids[] = {
0597     { .compatible = "chrontel,ch7033", },
0598     { }
0599 };
0600 MODULE_DEVICE_TABLE(of, ch7033_dt_ids);
0601 
0602 static const struct i2c_device_id ch7033_ids[] = {
0603     { "ch7033", 0 },
0604     { }
0605 };
0606 MODULE_DEVICE_TABLE(i2c, ch7033_ids);
0607 
0608 static struct i2c_driver ch7033_driver = {
0609     .probe = ch7033_probe,
0610     .remove = ch7033_remove,
0611     .driver = {
0612         .name = "ch7033",
0613         .of_match_table = of_match_ptr(ch7033_dt_ids),
0614     },
0615     .id_table = ch7033_ids,
0616 };
0617 
0618 module_i2c_driver(ch7033_driver);
0619 
0620 MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
0621 MODULE_DESCRIPTION("Chrontel CH7033 Video Encoder Driver");
0622 MODULE_LICENSE("GPL v2");